Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 4679 → Rev 4680

/contrib/media/updf/apps/kos_main.c
0,0 → 1,333
#include<menuet/os.h>
#define _WIN32
#include "fitz.h"
#include "mupdf.h"
#include "muxps.h"
#include "pdfapp.h"
 
 
 
static char Title[] = "some title";
static char * filename = "/hd0/1/yand.pdf";
static pdfapp_t gapp;
 
void f65(unsigned x, unsigned y, unsigned w, unsigned h, char *d) //Вывод картинки
{
asm ("nop"::"c"(w*65536+h), "d"(x*65536+y), "b"(d));
asm ("xor %eax, %eax");
asm ("movl %eax, %ebp");
asm ("pushl $32");
asm ("popl %esi");
asm ("int $0x40"::"a"(65));
 
}
 
struct blit_call
{
int dstx;
int dsty;
int w;
int h;
 
int srcx;
int srcy;
int srcw;
int srch;
 
unsigned char *d;
int stride;
};
 
void blit(int dstx, int dsty, int w, int h, int srcx, int srcy,int srcw, int srch, int stride, char *d) //Вызов сисфункции Blitter
{
 
struct blit_call image;
image.dstx=dstx;
image.dsty=dsty;
image.w=w;
image.h=h;
image.srcx=srcx;
image.srcy=srcy;
image.srcw=srcw;
image.srch=srch;
image.stride=stride;
image.d=d;
 
asm ("int $0x40"::"a"(73),"b"(0),"c"(&image));
 
}
 
void winwarn(pdfapp_t *app, char *msg)
{
fprintf(stderr, "mupdf: %s\n", msg);
}
 
void winerror(pdfapp_t *app, fz_error error)
{
fz_catch(error, "aborting");
exit(1);
}
 
char *winpassword(pdfapp_t *app, char *filename)
{
char *r = "";
return r;
}
 
 
void wincursor(pdfapp_t *app, int curs)
{
}
 
void wintitle(pdfapp_t *app, char *s)
{
 
sprintf(Title,"uPDF: %s", s);
}
 
void winhelp(pdfapp_t *app)
{
}
 
void winresize(pdfapp_t *app, int w, int h)
{
//here should be something!!!
}
 
 
void windocopy(pdfapp_t *app)
{
}
 
void winreloadfile(pdfapp_t *app)
{
pdfapp_close(app);
 
 
pdfapp_open(app, filename, 0, 1);
}
 
void winopenuri(pdfapp_t *app, char *buf)
{
/* here can be browser!
char *browser = getenv("BROWSER");
if (!browser)
browser = "open";
if (fork() == 0)
execlp(browser, browser, buf, (char*)0);
* */
}
 
 
 
void winclose(pdfapp_t *app)
{
pdfapp_close(&gapp);
__menuet__sys_exit();
}
 
void kol_paint_bar(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c)
{
asm ("int $0x40"::"a"(13), "b"(x*65536+w), "c"(y*65536+h), "d"(c));
}
 
 
static void winblit(pdfapp_t *app)
{
char yoba[32];
int x0 = gapp.panx;
int y0 = gapp.pany;
int x1 = gapp.panx + gapp.image->w;
int y1 = gapp.pany + gapp.image->h;
__menuet__debug_out(" Window blit\n");
/*
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);*/
if (gapp.image->h-y0 > 0) {
kol_paint_bar(0, gapp.image->h-y0, 590, 368, 0xEFEFEF);
}
/*kol_paint_bar(x1, 0, gapp.winw - x1, gapp.winh, 0x00FF00);
kol_paint_bar(0, 0, gapp.winw, y0, 0xFF0000);
kol_paint_bar(0, y1, gapp.winw, gapp.winh - y1, 0xFFFF);*/
 
/*XSetForeground(xdpy, xgc, xshcolor.pixel);
fillrect(x0+2, y1, gapp.image->w, 2);
fillrect(x1, y0+2, 2, gapp.image->h);*/
sprintf (yoba, "%d x %d, %d x %d \n", gapp.image->w, gapp.image->h, gapp.winw, gapp.winh);
__menuet__debug_out(yoba);
 
 
if (gapp.image->n == 4)
/*ximage_blit(xwin, xgc,
x0, y0,
gapp.image->samples,
0, 0,
gapp.image->w,
gapp.image->h,
gapp.image->w * gapp.image->n);*/
// f65(x0,y0+32,gapp.image->w,gapp.image->h,gapp.image->samples);
blit(6, 24, 588, 368, x0, y0,gapp.image->w, gapp.image->h, gapp.image->w * gapp.image->n, gapp.image->samples);
else if (gapp.image->n == 2)
{
int i = gapp.image->w*gapp.image->h;
unsigned char *color = malloc(i*4);
if (color != NULL)
{
unsigned char *s = gapp.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,
gapp.image->w,
gapp.image->h,
gapp.image->w * 4); */
//f65(x0,y0,gapp.image->w,gapp.image->h,color);
blit(6, 24, 588, 368, x0, y0,gapp.image->w, gapp.image->h, gapp.image->w * 4, color);
free(color);
}
}
__menuet__bar(0,0,600,20,0xFFFFFF);
__menuet__make_button(0,0,40,20,7,0x404040FF); //(posirion x, position y, width, height, id, color)
__menuet__write_text(5,4,0xFFFFFF,"Open",4);
__menuet__make_button(550,0,20,20,2,0x404040FF); //prev page
__menuet__write_text(555,3,0xFFFFFF,"<",1);
__menuet__make_button(570,0,20,20,3,0x404040FF); //nex page
__menuet__write_text(575,3,0xFFFFFF,">",1);
__menuet__make_button(40,0,20,20,4,0x404040FF); //show help
__menuet__write_text(45,3,0xFFFFFF,"?",1);
__menuet__make_button(60,0,20,20,5,0x404040FF); //magnify +
__menuet__write_text(65,3,0xFFFFFF,"+",1);
__menuet__make_button(80,0,20,20,6,0x404040FF); //magnify -
__menuet__write_text(85,3,0xFFFFFF,"-",1);
__menuet__make_button(570,20,20,20,8,0x404040FF); // move up
__menuet__write_text(575,3,0xFFFFFF,"^",1);
__menuet__make_button(570,360,20,20,9,0x404040FF); // move down
__menuet__write_text(575,363,0xFFFFFF,"v",1);
__menuet__make_button(100,0,20,20,10,0x404040FF); // rotate + 15 deg
__menuet__write_text(105,3,0xFFFFFF,"cw",1);
__menuet__make_button(120,0,20,20,11,0x404040FF); // rotate - 15 deg
__menuet__write_text(125,3,0xFFFFFF,"ccw",1);
}
 
void paint(void)
{
__menuet__window_redraw(1);
//__menuet__define_window(10,10,600,400,0x64CFCFCF,0x800000FF,Title);
__menuet__define_window(10,10,600,400,0x73CFCFCF,0x800000FF,Title);
__menuet__bar(0,0,600,400,0xFFFFFF);
winblit(&gapp);
__menuet__window_redraw(2);
}
 
void winrepaint(pdfapp_t *app)
{
winblit(&gapp);
}
 
void winrepaintsearch(pdfapp_t *app)
{
paint();
//search!
}
 
 
int main (void)
{
char* original_command_line = *(char**)0x1C;
__menuet__debug_out(original_command_line);
char buf[128];
int resolution = 72;
int pageno = 1;
__menuet__debug_out("\nStarted\n");
fz_accelerate();
__menuet__debug_out("PDF init\n");
pdfapp_init(&gapp);
gapp.scrw = 600;
gapp.scrh = 400;
gapp.resolution = resolution;
gapp.pageno = pageno;
__menuet__debug_out("PDF Open\n");
pdfapp_open(&gapp, original_command_line, 0, 0);
__menuet__debug_out("PDF Opened\n");
 
int i;
int butt;
__menuet__debug_out("Inital paint\n");
pdfapp_onresize(&gapp, 600, 400);
paint();
for(;;)
{
 
i=__menuet__wait_for_event();
butt = __menuet__get_button_id();
if (gapp.image)
{
gapp.shrinkwrap = 0;
}
switch(i)
{
case 1:
paint();
continue;
case 2:
buf[0]=__menuet__getkey();
pdfapp_onkey(&gapp, buf[0]);
continue;
case 3:
if(butt==1) __menuet__sys_exit();//browse file
if(butt==2) pdfapp_onkey(&gapp, '['); //previous page
if(butt==3) pdfapp_onkey(&gapp, ']'); __menuet__debug_out("\nStarted\n"); //next page
if(butt==4) pdfapp_onkey(&gapp, '?'); //show help window
if(butt==5) pdfapp_onkey(&gapp, '+'); //magnify +
if(butt==6) pdfapp_onkey(&gapp, '-'); //mag -
if(butt==7) ;//mag open file
if(butt==8) pdfapp_onkey(&gapp, 'j'); //move up
if(butt==9) pdfapp_onkey(&gapp, 'k'); //move down
if(butt==10) pdfapp_onkey(&gapp, 'a'); //rotate +15 deg
if(butt==11) pdfapp_onkey(&gapp, 's'); //rotate -15deg
continue;
}
}
return 0;
}
/contrib/media/updf/apps/man/mupdf.1
0,0 → 1,86
.TH MUPDF 1 "March 15, 2010"
.\" 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
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
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.
.SH SEE ALSO
.BR pdfclean (1),
.BR pdfdraw (1),
.BR pdfshow (1).
.SH AUTHOR
MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is Copyright 2006-2010 Artifex Software, Inc.
.PP
This manual page was written by Sebastian Rasmussen <sebras@hotmail.com>.
/contrib/media/updf/apps/man/pdfclean.1
0,0 → 1,39
.TH PDFCLEAN 1 "September 4, 2011"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
pdfclean \- pretty print, decompress and garbage collect PDF files
.SH SYNOPSIS
.B pdfclean
.RI [ options ]
.RI input.pdf
.RI [ output.pdf ]
.RI [ pages ]
.SH DESCRIPTION
.B pdfclean
pretty prints and rewrites the contents of a PDF file.
If no output file is specified, the new file will be written to "out.pdf" in
the current directory.
.PP
.SH OPTIONS
.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 ranges to clean.
.SH SEE ALSO
.BR mupdf (1),
.BR pdfdraw (1).
.BR pdfshow (1).
.SH AUTHOR
MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is Copyright 2006-2010 Artifex Software, Inc.
/contrib/media/updf/apps/man/pdfdraw.1
0,0 → 1,78
.TH PDFDRAW 1 "September 4, 2011"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
pdfdraw \- render PDF documents
.SH SYNOPSIS
.B pdfdraw
.RI [ options ]
.RI input.pdf
.RI [ pages]
.SH DESCRIPTION
.B pdfdraw
will render a PDF document to image files.
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 \-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 pdfclean (1).
.BR pdfshow (1).
.SH AUTHOR
MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is Copyright 2006-2010 Artifex Software, Inc.
/contrib/media/updf/apps/man/pdfshow.1
0,0 → 1,42
.TH PDFSHOW 1 "July 19, 2010"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
pdfshow \- show objects and streams that make up a PDF document
.SH SYNOPSIS
.B pdfshow
.RI [ options ]
.RI file.pdf
.RI [ xref ]
.RI [ trailer ]
.RI [ pages ]
.RI [ grep ]
.RI [ object-number... ]
.SH DESCRIPTION
.B pdfshow
pretty prints the objects and streams specified on the command line.
Streams are decoded and non-printable characters are represented
with a period.
Specify objects with their number.
The special names xref, trailer and pages will
respectively print the cross reference, trailer,
and the object numbers for all pages.
The special name grep will print all objects in the file
in a compact one-line format suitable for piping to grep.
.PP
.SH OPTIONS
.TP
.B \-b
Print streams as binary data and omit the object header.
.TP
.B \-e
Print streams in their original encoded form.
.TP
.B \-p password
Use the specified password if the file is encrypted.
.SH SEE ALSO
.BR mupdf (1),
.BR pdfclean (1).
.BR pdfdraw (1).
.SH AUTHOR
MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is copyright 2006-2010 Artifex Software, Inc.
/contrib/media/updf/apps/mupdf_icon_antialias.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/media/updf/apps/mupdf_icon_bitmap.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/media/updf/apps/pdfapp.c
0,0 → 1,1225
#include "fitz.h"
#include "mupdf.h"
#include "muxps.h"
#include "pdfapp.h"
 
#include <ctype.h> /* for tolower() */
 
#define ZOOMSTEP 1.142857
#define BEYOND_THRESHHOLD 40
 
enum panning
{
DONT_PAN = 0,
PAN_TO_TOP,
PAN_TO_BOTTOM
};
 
static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint);
 
static void pdfapp_warn(pdfapp_t *app, const char *fmt, ...)
{
char buf[1024];
va_list ap;
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
winwarn(app, buf);
}
 
static void pdfapp_error(pdfapp_t *app, fz_error error)
{
winerror(app, error);
}
 
char *pdfapp_version(pdfapp_t *app)
{
return
"MuPDF 0.9\n"
"Copyright 2006-2011 Artifex Sofware, 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-- shrinkwrap\n"
"r\t\t-- reload file\n"
". pgdn right space\t-- next page\n"
", pgup left b\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"
"123g\t\t-- go to page 123\n"
"/\t\t-- search 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"
;
}
 
void pdfapp_init(pdfapp_t *app)
{
memset(app, 0, sizeof(pdfapp_t));
app->scrw = 640;
app->scrh = 480;
app->resolution = 72;
}
 
void pdfapp_invert(pdfapp_t *app, fz_bbox rect)
{
unsigned char *p;
int x, y, n;
 
int x0 = CLAMP(rect.x0 - app->image->x, 0, app->image->w - 1);
int x1 = CLAMP(rect.x1 - app->image->x, 0, app->image->w - 1);
int y0 = CLAMP(rect.y0 - app->image->y, 0, app->image->h - 1);
int y1 = CLAMP(rect.y1 - app->image->y, 0, app->image->h - 1);
 
for (y = y0; y < y1; y++)
{
p = app->image->samples + (y * app->image->w + x0) * app->image->n;
for (x = x0; x < x1; x++)
{
for (n = app->image->n; n > 0; n--, p++)
*p = 255 - *p;
}
}
}
 
static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd)
{
fz_error error;
fz_stream *file;
char *password = "";
fz_obj *obj;
fz_obj *info;
 
/*
* Open PDF and load xref table
*/
__menuet__debug_out("FZ OPEN\n");
//file = fz_open_fd(fd);
__menuet__debug_out("FZ ready\n");
error = pdf_open_xref(&app->xref, filename, NULL);
if (error){
__menuet__debug_out("FZ can't open\n");
pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename));}
fz_close(file);
 
/*
* Handle encrypted PDF files
*/
/*
if (pdf_needs_password(app->xref))
{
int okay = pdf_authenticate_password(app->xref, password);
while (!okay)
{
password = winpassword(app, filename);
if (!password)
exit(1);
okay = pdf_authenticate_password(app->xref, password);
if (!okay)
pdfapp_warn(app, "Invalid password.");
}
}
* */
 
/*
* Load meta information
*/
 
/*
app->outline = pdf_load_outline(app->xref);
 
app->doctitle = filename;
if (strrchr(app->doctitle, '\\'))
app->doctitle = strrchr(app->doctitle, '\\') + 1;
if (strrchr(app->doctitle, '/'))
app->doctitle = strrchr(app->doctitle, '/') + 1;
info = fz_dict_gets(app->xref->trailer, "Info");
if (info)
{
obj = fz_dict_gets(info, "Title");
if (obj)
app->doctitle = pdf_to_utf8(obj);
} */
 
/*
* Start at first page
*/
__menuet__debug_out("Start at first page\n");
 
error = pdf_load_page_tree(app->xref);
if (error) {
__menuet__debug_out("Can't load tree\n");
pdfapp_error(app, fz_rethrow(error, "cannot load page tree"));}
 
__menuet__debug_out("Page counter\n");
app->pagecount = pdf_count_pages(app->xref);
__menuet__debug_out("All is set!\n");
}
 
static void pdfapp_open_xps(pdfapp_t *app, char *filename, int fd)
{
fz_error error;
fz_stream *file;
 
file = fz_open_fd(fd);
error = xps_open_stream(&app->xps, file);
if (error)
pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename));
fz_close(file);
 
app->doctitle = filename;
 
app->pagecount = xps_count_pages(app->xps);
}
 
void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload)
{
if (strstr(filename, ".xps") || strstr(filename, ".XPS") || strstr(filename, ".rels"))
pdfapp_open_xps(app, filename, fd);
else
pdfapp_open_pdf(app, filename, fd);
 
app->cache = fz_new_glyph_cache();
 
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);
}
 
void pdfapp_close(pdfapp_t *app)
{
if (app->cache)
fz_free_glyph_cache(app->cache);
app->cache = NULL;
 
if (app->image)
fz_drop_pixmap(app->image);
app->image = NULL;
 
if (app->outline)
pdf_free_outline(app->outline);
app->outline = NULL;
 
if (app->xref)
{
if (app->xref->store)
pdf_free_store(app->xref->store);
app->xref->store = NULL;
 
pdf_free_xref(app->xref);
app->xref = NULL;
}
 
if (app->xps)
{
xps_free_context(app->xps);
app->xps = NULL;
}
 
fz_flush_warnings();
}
 
static fz_matrix pdfapp_viewctm(pdfapp_t *app)
{
fz_matrix ctm;
ctm = fz_identity;
ctm = fz_concat(ctm, fz_translate(0, -app->page_bbox.y1));
if (app->xref)
ctm = fz_concat(ctm, fz_scale(app->resolution/72.0f, -app->resolution/72.0f));
else
ctm = fz_concat(ctm, fz_scale(app->resolution/96.0f, app->resolution/96.0f));
ctm = fz_concat(ctm, fz_rotate(app->rotate + app->page_rotate));
return ctm;
}
 
static void pdfapp_panview(pdfapp_t *app, int newx, int newy)
{
if (newx < 0)
newx = 0;
if (newy < 0)
newy = 0;
 
if (newx + app->image->w < app->winw)
newx = app->winw - app->image->w;
if (newy + app->image->h < app->winh)
newy = app->winh - app->image->h;
 
if (app->winw >= app->image->w)
newx = (app->winw - app->image->w) / 2;
if (app->winh >= app->image->h)
newy = (app->winh - app->image->h) / 2;
 
if (newx != app->panx || newy != app->pany)
winrepaint(app);
if (newy > app->image->h) {
 
app->pageno++;
if (app->pageno > app->pagecount)
app->pageno = app->pagecount;
 
 
newy = 0;
app->pany = newy;
pdfapp_showpage(app, 1, 1, 1);
}
 
app->panx = newx;
app->pany = newy;
}
 
static void pdfapp_loadpage_pdf(pdfapp_t *app)
{
pdf_page *page;
fz_error error;
fz_device *mdev;
 
error = pdf_load_page(&page, app->xref, app->pageno - 1);
if (error)
pdfapp_error(app, error);
 
app->page_bbox = page->mediabox;
app->page_rotate = page->rotate;
app->page_links = page->links;
page->links = NULL;
 
/* Create display list */
app->page_list = fz_new_display_list();
mdev = fz_new_list_device(app->page_list);
error = pdf_run_page(app->xref, page, mdev, fz_identity);
if (error)
{
error = fz_rethrow(error, "cannot draw page %d in '%s'", app->pageno, app->doctitle);
pdfapp_error(app, error);
}
fz_free_device(mdev);
 
pdf_free_page(page);
 
pdf_age_store(app->xref->store, 3);
}
 
static void pdfapp_loadpage_xps(pdfapp_t *app)
{
xps_page *page;
fz_device *mdev;
fz_error error;
 
error = xps_load_page(&page, app->xps, app->pageno - 1);
if (error)
pdfapp_error(app, fz_rethrow(error, "cannot load page %d in file '%s'", app->pageno, app->doctitle));
 
app->page_bbox.x0 = 0;
app->page_bbox.y0 = 0;
app->page_bbox.x1 = page->width;
app->page_bbox.y1 = page->height;
app->page_rotate = 0;
app->page_links = NULL;
 
/* Create display list */
app->page_list = fz_new_display_list();
mdev = fz_new_list_device(app->page_list);
app->xps->dev = mdev;
xps_parse_fixed_page(app->xps, fz_identity, page);
app->xps->dev = NULL;
fz_free_device(mdev);
 
xps_free_page(app->xps, page);
}
 
static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint)
{
char buf[256];
fz_device *idev;
fz_device *tdev;
fz_colorspace *colorspace;
fz_matrix ctm;
fz_bbox bbox;
 
wincursor(app, WAIT);
 
if (loadpage)
{
if (app->page_list)
fz_free_display_list(app->page_list);
if (app->page_text)
fz_free_text_span(app->page_text);
if (app->page_links)
pdf_free_link(app->page_links);
 
if (app->xref)
pdfapp_loadpage_pdf(app);
if (app->xps)
pdfapp_loadpage_xps(app);
 
/* Zero search hit position */
app->hit = -1;
app->hitlen = 0;
 
/* Extract text */
app->page_text = fz_new_text_span();
tdev = fz_new_text_device(app->page_text);
fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox);
fz_free_device(tdev);
}
 
if (drawpage)
{
sprintf(buf, "%s - %d/%d (%d dpi)", app->doctitle,
app->pageno, app->pagecount, app->resolution);
wintitle(app, buf);
 
ctm = pdfapp_viewctm(app);
bbox = fz_round_rect(fz_transform_rect(ctm, app->page_bbox));
 
/* Draw */
if (app->image)
fz_drop_pixmap(app->image);
if (app->grayscale)
colorspace = fz_device_gray;
else
//#ifdef _WIN32
colorspace = fz_device_bgr;
//#else
// colorspace = fz_device_rgb;
//#endif
app->image = fz_new_pixmap_with_rect(colorspace, bbox);
fz_clear_pixmap_with_color(app->image, 255);
idev = fz_new_draw_device(app->cache, app->image);
fz_execute_display_list(app->page_list, idev, ctm, bbox);
fz_free_device(idev);
}
 
if (repaint)
{
pdfapp_panview(app, app->panx, app->pany);
 
if (app->shrinkwrap)
{
__menuet__debug_out ("SHRINK\n");
int w = app->image->w;
int h = app->image->h;
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);
}
 
fz_flush_warnings();
}
 
static void pdfapp_gotouri(pdfapp_t *app, fz_obj *uri)
{
char *buf;
buf = fz_malloc(fz_to_str_len(uri) + 1);
memcpy(buf, fz_to_str_buf(uri), fz_to_str_len(uri));
buf[fz_to_str_len(uri)] = 0;
winopenuri(app, buf);
fz_free(buf);
}
 
static void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj)
{
int number;
 
number = pdf_find_page_number(app->xref, obj);
if (number < 0)
return;
 
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);
}
 
static inline fz_bbox bboxcharat(fz_text_span *span, int idx)
{
int ofs = 0;
while (span)
{
if (idx < ofs + span->len)
return span->text[idx - ofs].bbox;
if (span->eol)
{
if (idx == ofs + span->len)
return fz_empty_bbox;
ofs ++;
}
ofs += span->len;
span = span->next;
}
return fz_empty_bbox;
}
 
void pdfapp_inverthit(pdfapp_t *app)
{
fz_bbox hitbox, bbox;
fz_matrix ctm;
int i;
 
if (app->hit < 0)
return;
 
hitbox = fz_empty_bbox;
ctm = pdfapp_viewctm(app);
 
for (i = app->hit; i < app->hit + app->hitlen; i++)
{
bbox = bboxcharat(app->page_text, i);
if (fz_is_empty_rect(bbox))
{
if (!fz_is_empty_rect(hitbox))
pdfapp_invert(app, fz_transform_bbox(ctm, hitbox));
hitbox = fz_empty_bbox;
}
else
{
hitbox = fz_union_bbox(hitbox, bbox);
}
}
 
if (!fz_is_empty_rect(hitbox))
pdfapp_invert(app, fz_transform_bbox(ctm, hitbox));
}
 
static inline int charat(fz_text_span *span, int idx)
{
int ofs = 0;
while (span)
{
if (idx < ofs + span->len)
return span->text[idx - ofs].c;
if (span->eol)
{
if (idx == ofs + span->len)
return ' ';
ofs ++;
}
ofs += span->len;
span = span->next;
}
return 0;
}
 
static int textlen(fz_text_span *span)
{
int len = 0;
while (span)
{
len += span->len;
if (span->eol)
len ++;
span = span->next;
}
return len;
}
 
static int match(char *s, fz_text_span *span, int n)
{
int orig = n;
int c;
while ((c = *s++))
{
if (c == ' ' && charat(span, n) == ' ')
{
while (charat(span, n) == ' ')
n++;
}
else
{
if (tolower(c) != tolower(charat(span, n)))
return 0;
n++;
}
}
return n - orig;
}
 
static void pdfapp_searchforward(pdfapp_t *app, enum panning *panto)
{
int matchlen;
int test;
int len;
int startpage;
 
wincursor(app, WAIT);
 
startpage = app->pageno;
 
do
{
len = textlen(app->page_text);
 
if (app->hit >= 0)
test = app->hit + strlen(app->search);
else
test = 0;
 
while (test < len)
{
matchlen = match(app->search, app->page_text, test);
if (matchlen)
{
app->hit = test;
app->hitlen = matchlen;
wincursor(app, HAND);
winrepaint(app);
return;
}
test++;
}
 
app->pageno++;
if (app->pageno > app->pagecount)
app->pageno = 1;
 
pdfapp_showpage(app, 1, 0, 0);
*panto = PAN_TO_TOP;
 
} while (app->pageno != startpage);
 
if (app->pageno == startpage)
{
pdfapp_warn(app, "String '%s' not found.", app->search);
winrepaintsearch(app);
}
else
winrepaint(app);
 
wincursor(app, HAND);
}
 
static void pdfapp_searchbackward(pdfapp_t *app, enum panning *panto)
{
int matchlen;
int test;
int len;
int startpage;
 
wincursor(app, WAIT);
 
startpage = app->pageno;
 
do
{
len = textlen(app->page_text);
 
if (app->hit >= 0)
test = app->hit - 1;
else
test = len;
 
while (test >= 0)
{
matchlen = match(app->search, app->page_text, test);
if (matchlen)
{
app->hit = test;
app->hitlen = matchlen;
wincursor(app, HAND);
winrepaint(app);
return;
}
test--;
}
 
app->pageno--;
if (app->pageno < 1)
app->pageno = app->pagecount;
 
pdfapp_showpage(app, 1, 0, 0);
*panto = PAN_TO_BOTTOM;
 
} while (app->pageno != startpage);
 
if (app->pageno == startpage)
{
pdfapp_warn(app, "String '%s' not found.", app->search);
winrepaintsearch(app);
}
else
winrepaint(app);
 
wincursor(app, HAND);
}
 
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);
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 '?':
winhelp(app);
break;
 
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);
break;
case '-':
app->resolution /= ZOOMSTEP;
if (app->resolution < MINRES)
app->resolution = MINRES;
pdfapp_showpage(app, 0, 1, 1);
break;
 
case 'L':
app->rotate -= 90;
pdfapp_showpage(app, 0, 1, 1);
break;
case 'R':
app->rotate += 90;
pdfapp_showpage(app, 0, 1, 1);
break;
 
case 'c':
app->grayscale ^= 1;
pdfapp_showpage(app, 0, 1, 1);
break;
 
#ifndef NDEBUG
case 'a':
app->rotate -= 15;
pdfapp_showpage(app, 0, 1, 1);
break;
case 's':
app->rotate += 15;
pdfapp_showpage(app, 0, 1, 1);
break;
#endif
 
/*
* Pan view, but dont need to repaint image
*/
 
case 'w':
app->shrinkwrap = 1;
app->panx = app->pany = 0;
pdfapp_showpage(app, 0, 0, 1);
break;
 
case 'h':
app->panx += app->image->w / 10;
pdfapp_showpage(app, 0, 0, 1);
break;
 
case 'j':
app->pany -= app->image->h / 10;
pdfapp_showpage(app, 0, 0, 1);
break;
 
case 'k':
app->pany += app->image->h / 10;
pdfapp_showpage(app, 0, 0, 1);
break;
 
case 'l':
app->panx -= app->image->w / 10;
pdfapp_showpage(app, 0, 0, 1);
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;
 
/*
* 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':
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++;
break;
case '[':
panto = PAN_TO_TOP;
app->pageno--;
break;
 
 
case '<':
panto = PAN_TO_TOP;
app->pageno -= 10;
break;
case '>':
panto = PAN_TO_TOP;
app->pageno += 10;
break;
 
/*
* Reloading the file...
*/
 
case 'r':
panto = DONT_PAN;
oldpage = -1;
winreloadfile(app);
break;
 
/*
* Searching
*/
 
case '/':
app->isediting = 1;
app->search[0] = 0;
app->hit = -1;
app->hitlen = 0;
winrepaintsearch(app);
break;
 
case 'n':
pdfapp_searchforward(app, &panto);
loadpage = 0;
break;
 
case 'N':
pdfapp_searchbackward(app, &panto);
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);
}
}
 
void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state)
{
pdf_link *link;
fz_matrix ctm;
fz_point p;
 
p.x = x - app->panx + app->image->x;
p.y = y - app->pany + app->image->y;
 
ctm = pdfapp_viewctm(app);
ctm = fz_invert_matrix(ctm);
 
p = fz_transform_point(ctm, p);
 
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)
{
if (link->kind == PDF_LINK_URI)
pdfapp_gotouri(app, link->dest);
else if (link->kind == PDF_LINK_GOTO)
pdfapp_gotopage(app, fz_array_get(link->dest, 0)); /* [ pageobj ... ] */
return;
}
}
else
{
wincursor(app, ARROW);
}
 
if (state == 1)
{
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);
}
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 = MIN(app->selx, x) - app->panx + app->image->x;
app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x;
app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y;
app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y;
winrepaint(app);
if (app->selr.x0 < app->selr.x1 && app->selr.y0 < app->selr.y1)
windocopy(app);
}
if (app->ispanning)
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 + app->image->h < app->winh || newy > 0)
{
/* Yes. We can assume that deltay != 0 */
int deltay = y - app->sely;
/* Check whether the panning has occured 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 threshhold
*/
app->beyondy += deltay;
if (app->beyondy > BEYOND_THRESHHOLD)
{
if( app->pageno > 1 )
{
app->pageno--;
pdfapp_showpage(app, 1, 1, 1);
newy = -app->image->h;
}
app->beyondy = 0;
}
else if (app->beyondy < -BEYOND_THRESHHOLD)
{
if( app->pageno < app->pagecount )
{
app->pageno++;
pdfapp_showpage(app, 1, 1, 1);
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 = MIN(app->selx, x) - app->panx + app->image->x;
app->selr.x1 = MAX(app->selx, x) - app->panx + app->image->x;
app->selr.y0 = MIN(app->sely, y) - app->pany + app->image->y;
app->selr.y1 = MAX(app->sely, y) - app->pany + app->image->y;
winrepaint(app);
}
 
}
 
void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen)
{
fz_bbox hitbox;
fz_matrix ctm;
fz_text_span *span;
int c, i, p;
int seen;
 
int x0 = app->selr.x0;
int x1 = app->selr.x1;
int y0 = app->selr.y0;
int y1 = app->selr.y1;
 
ctm = pdfapp_viewctm(app);
 
p = 0;
for (span = app->page_text; span; span = span->next)
{
seen = 0;
 
for (i = 0; i < span->len; i++)
{
hitbox = fz_transform_bbox(ctm, span->text[i].bbox);
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;
}
}
 
if (seen && span->eol)
{
#ifdef _WIN32
if (p < ucslen - 1)
ucsbuf[p++] = '\r';
#endif
if (p < ucslen - 1)
ucsbuf[p++] = '\n';
}
}
 
ucsbuf[p] = 0;
}
/contrib/media/updf/apps/pdfapp.h
0,0 → 1,105
/*
* 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 };
 
extern void winwarn(pdfapp_t*, char *s);
extern void winerror(pdfapp_t*, fz_error error);
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 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*);
 
struct pdfapp_s
{
/* current document params */
char *doctitle;
pdf_xref *xref;
pdf_outline *outline;
xps_context *xps;
 
int pagecount;
fz_glyph_cache *cache;
 
/* current view params */
int resolution;
int rotate;
fz_pixmap *image;
int grayscale;
 
/* current page params */
int pageno;
fz_rect page_bbox;
float page_rotate;
fz_display_list *page_list;
fz_text_span *page_text;
pdf_link *page_links;
 
/* snapback history */
int hist[256];
int histlen;
int marks[10];
 
/* window system sizes */
int winw, winh;
int scrw, scrh;
int shrinkwrap;
 
/* 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_bbox selr;
 
/* search state */
int isediting;
char search[512];
int hit;
int hitlen;
 
/* client context storage */
void *userdata;
};
 
void pdfapp_init(pdfapp_t *app);
void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload);
void pdfapp_close(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_invert(pdfapp_t *app, fz_bbox rect);
void pdfapp_inverthit(pdfapp_t *app);
/contrib/media/updf/apps/pdfclean.c
0,0 → 1,775
/*
* 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 "fitz.h"
#include "mupdf.h"
 
static FILE *out = NULL;
 
static char *uselist = NULL;
static int *ofslist = NULL;
static int *genlist = NULL;
static int *renumbermap = NULL;
 
static int dogarbage = 0;
static int doexpand = 0;
static int doascii = 0;
 
static pdf_xref *xref = NULL;
 
void die(fz_error error)
{
fz_catch(error, "aborting");
if (xref)
pdf_free_xref(xref);
exit(1);
}
 
static void usage(void)
{
fprintf(stderr,
"usage: pdfclean [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 streams\n"
"\t-a\tascii hex encode binary streams\n"
"\tpages\tcomma separated list of ranges\n");
exit(1);
}
 
/*
* Garbage collect objects not reachable from the trailer.
*/
 
static void sweepref(fz_obj *ref);
 
static void sweepobj(fz_obj *obj)
{
int i;
 
if (fz_is_indirect(obj))
sweepref(obj);
 
else if (fz_is_dict(obj))
for (i = 0; i < fz_dict_len(obj); i++)
sweepobj(fz_dict_get_val(obj, i));
 
else if (fz_is_array(obj))
for (i = 0; i < fz_array_len(obj); i++)
sweepobj(fz_array_get(obj, i));
}
 
static void sweepref(fz_obj *obj)
{
int num = fz_to_num(obj);
int gen = fz_to_gen(obj);
 
if (num < 0 || num >= xref->len)
return;
if (uselist[num])
return;
 
uselist[num] = 1;
 
/* Bake in /Length in stream objects */
if (pdf_is_stream(xref, num, gen))
{
fz_obj *len = fz_dict_gets(obj, "Length");
if (fz_is_indirect(len))
{
uselist[fz_to_num(len)] = 0;
len = fz_resolve_indirect(len);
fz_dict_puts(obj, "Length", len);
}
}
 
sweepobj(fz_resolve_indirect(obj));
}
 
/*
* Scan for and remove duplicate objects (slow)
*/
 
static void removeduplicateobjs(void)
{
int num, other;
 
for (num = 1; num < xref->len; num++)
{
/* Only compare an object to objects preceeding it */
for (other = 1; other < num; other++)
{
fz_obj *a, *b;
 
if (num == other || !uselist[num] || !uselist[other])
continue;
 
/*
* Comparing stream objects data contents would take too long.
*
* pdf_is_stream calls pdf_cache_object and ensures
* that the xref table has the objects loaded.
*/
if (pdf_is_stream(xref, num, 0) || pdf_is_stream(xref, other, 0))
continue;
 
a = xref->table[num].obj;
b = xref->table[other].obj;
 
a = fz_resolve_indirect(a);
b = fz_resolve_indirect(b);
 
if (fz_objcmp(a, b))
continue;
 
/* Keep the lowest numbered object */
renumbermap[num] = MIN(num, other);
renumbermap[other] = MIN(num, other);
uselist[MAX(num, other)] = 0;
 
/* One duplicate was found, do not look for another */
break;
}
}
}
 
/*
* Renumber objects sequentially so the xref is more compact
*/
 
static void compactxref(void)
{
int num, newnum;
 
/*
* Update renumbermap in-place, clustering all used
* objects together at low object ids. Objects that
* already should be renumbered will have their new
* object ids be updated to reflect the compaction.
*/
 
newnum = 1;
for (num = 1; num < xref->len; num++)
{
if (uselist[num] && renumbermap[num] == num)
renumbermap[num] = newnum++;
else if (renumbermap[num] != num)
renumbermap[num] = renumbermap[renumbermap[num]];
}
}
 
/*
* Update indirect objects according to renumbering established when
* removing duplicate objects and compacting the xref.
*/
 
static void renumberobj(fz_obj *obj)
{
int i;
 
if (fz_is_dict(obj))
{
for (i = 0; i < fz_dict_len(obj); i++)
{
fz_obj *key = fz_dict_get_key(obj, i);
fz_obj *val = fz_dict_get_val(obj, i);
if (fz_is_indirect(val))
{
val = fz_new_indirect(renumbermap[fz_to_num(val)], 0, xref);
fz_dict_put(obj, key, val);
fz_drop_obj(val);
}
else
{
renumberobj(val);
}
}
}
 
else if (fz_is_array(obj))
{
for (i = 0; i < fz_array_len(obj); i++)
{
fz_obj *val = fz_array_get(obj, i);
if (fz_is_indirect(val))
{
val = fz_new_indirect(renumbermap[fz_to_num(val)], 0, xref);
fz_array_put(obj, i, val);
fz_drop_obj(val);
}
else
{
renumberobj(val);
}
}
}
}
 
static void renumberobjs(void)
{
pdf_xref_entry *oldxref;
int newlen;
int num;
 
/* Apply renumber map to indirect references in all objects in xref */
renumberobj(xref->trailer);
for (num = 0; num < xref->len; num++)
{
fz_obj *obj = xref->table[num].obj;
 
if (fz_is_indirect(obj))
{
obj = fz_new_indirect(renumbermap[fz_to_num(obj)], 0, xref);
pdf_update_object(xref, num, 0, obj);
fz_drop_obj(obj);
}
else
{
renumberobj(obj);
}
}
 
/* Create new table for the reordered, compacted xref */
oldxref = xref->table;
xref->table = fz_calloc(xref->len, sizeof(pdf_xref_entry));
xref->table[0] = oldxref[0];
 
/* Move used objects into the new compacted xref */
newlen = 0;
for (num = 1; num < xref->len; num++)
{
if (uselist[num])
{
if (newlen < renumbermap[num])
newlen = renumbermap[num];
xref->table[renumbermap[num]] = oldxref[num];
}
else
{
if (oldxref[num].obj)
fz_drop_obj(oldxref[num].obj);
}
}
 
fz_free(oldxref);
 
/* Update the used objects count in compacted xref */
xref->len = newlen + 1;
 
/* Update list of used objects to fit with compacted xref */
for (num = 1; num < xref->len; num++)
uselist[num] = 1;
}
 
/*
* Recreate page tree to only retain specified pages.
*/
 
static void retainpages(int argc, char **argv)
{
fz_error error;
fz_obj *oldroot, *root, *pages, *kids, *countobj, *parent;
 
/* Load the old page tree */
error = pdf_load_page_tree(xref);
if (error)
die(fz_rethrow(error, "cannot load page tree"));
 
/* Keep only pages/type entry to avoid references to unretained pages */
oldroot = fz_dict_gets(xref->trailer, "Root");
pages = fz_dict_gets(oldroot, "Pages");
 
root = fz_new_dict(2);
fz_dict_puts(root, "Type", fz_dict_gets(oldroot, "Type"));
fz_dict_puts(root, "Pages", fz_dict_gets(oldroot, "Pages"));
 
pdf_update_object(xref, fz_to_num(oldroot), fz_to_gen(oldroot), root);
 
fz_drop_obj(root);
 
/* Create a new kids array with only the pages we want to keep */
parent = fz_new_indirect(fz_to_num(pages), fz_to_gen(pages), xref);
kids = fz_new_array(1);
 
/* Retain pages specified */
while (argc - fz_optind)
{
int page, spage, epage;
char *spec, *dash;
char *pagelist = argv[fz_optind];
 
spec = fz_strsep(&pagelist, ",");
while (spec)
{
dash = strchr(spec, '-');
 
if (dash == spec)
spage = epage = pdf_count_pages(xref);
else
spage = epage = atoi(spec);
 
if (dash)
{
if (strlen(dash) > 1)
epage = atoi(dash + 1);
else
epage = pdf_count_pages(xref);
}
 
if (spage > epage)
page = spage, spage = epage, epage = page;
 
if (spage < 1)
spage = 1;
if (epage > pdf_count_pages(xref))
epage = pdf_count_pages(xref);
 
for (page = spage; page <= epage; page++)
{
fz_obj *pageobj = xref->page_objs[page-1];
fz_obj *pageref = xref->page_refs[page-1];
 
fz_dict_puts(pageobj, "Parent", parent);
 
/* Store page object in new kids array */
fz_array_push(kids, pageref);
}
 
spec = fz_strsep(&pagelist, ",");
}
 
fz_optind++;
}
 
fz_drop_obj(parent);
 
/* Update page count and kids array */
countobj = fz_new_int(fz_array_len(kids));
fz_dict_puts(pages, "Count", countobj);
fz_drop_obj(countobj);
fz_dict_puts(pages, "Kids", kids);
fz_drop_obj(kids);
}
 
/*
* Make sure we have loaded objects from object streams.
*/
 
static void preloadobjstms(void)
{
fz_error error;
fz_obj *obj;
int num;
 
for (num = 0; num < xref->len; num++)
{
if (xref->table[num].type == 'o')
{
error = pdf_load_object(&obj, xref, num, 0);
if (error)
die(error);
fz_drop_obj(obj);
}
}
}
 
/*
* Save streams and objects to the output
*/
 
static inline int isbinary(int c)
{
if (c == '\n' || c == '\r' || c == '\t')
return 0;
return c < 32 || c > 127;
}
 
static int isbinarystream(fz_buffer *buf)
{
int i;
for (i = 0; i < buf->len; i++)
if (isbinary(buf->data[i]))
return 1;
return 0;
}
 
static fz_buffer *hexbuf(unsigned char *p, int n)
{
static const char hex[16] = "0123456789abcdef";
fz_buffer *buf;
int x = 0;
 
buf = fz_new_buffer(n * 2 + (n / 32) + 2);
 
while (n--)
{
buf->data[buf->len++] = hex[*p >> 4];
buf->data[buf->len++] = hex[*p & 15];
if (++x == 32)
{
buf->data[buf->len++] = '\n';
x = 0;
}
p++;
}
 
buf->data[buf->len++] = '>';
buf->data[buf->len++] = '\n';
 
return buf;
}
 
static void addhexfilter(fz_obj *dict)
{
fz_obj *f, *dp, *newf, *newdp;
fz_obj *ahx, *nullobj;
 
ahx = fz_new_name("ASCIIHexDecode");
nullobj = fz_new_null();
newf = newdp = NULL;
 
f = fz_dict_gets(dict, "Filter");
dp = fz_dict_gets(dict, "DecodeParms");
 
if (fz_is_name(f))
{
newf = fz_new_array(2);
fz_array_push(newf, ahx);
fz_array_push(newf, f);
f = newf;
if (fz_is_dict(dp))
{
newdp = fz_new_array(2);
fz_array_push(newdp, nullobj);
fz_array_push(newdp, dp);
dp = newdp;
}
}
else if (fz_is_array(f))
{
fz_array_insert(f, ahx);
if (fz_is_array(dp))
fz_array_insert(dp, nullobj);
}
else
f = ahx;
 
fz_dict_puts(dict, "Filter", f);
if (dp)
fz_dict_puts(dict, "DecodeParms", dp);
 
fz_drop_obj(ahx);
fz_drop_obj(nullobj);
if (newf)
fz_drop_obj(newf);
if (newdp)
fz_drop_obj(newdp);
}
 
static void copystream(fz_obj *obj, int num, int gen)
{
fz_error error;
fz_buffer *buf, *tmp;
fz_obj *newlen;
 
error = pdf_load_raw_stream(&buf, xref, num, gen);
if (error)
die(error);
 
if (doascii && isbinarystream(buf))
{
tmp = hexbuf(buf->data, buf->len);
fz_drop_buffer(buf);
buf = tmp;
 
addhexfilter(obj);
 
newlen = fz_new_int(buf->len);
fz_dict_puts(obj, "Length", newlen);
fz_drop_obj(newlen);
}
 
fprintf(out, "%d %d obj\n", num, gen);
fz_fprint_obj(out, obj, !doexpand);
fprintf(out, "stream\n");
fwrite(buf->data, 1, buf->len, out);
fprintf(out, "endstream\nendobj\n\n");
 
fz_drop_buffer(buf);
}
 
static void expandstream(fz_obj *obj, int num, int gen)
{
fz_error error;
fz_buffer *buf, *tmp;
fz_obj *newlen;
 
error = pdf_load_stream(&buf, xref, num, gen);
if (error)
die(error);
 
fz_dict_dels(obj, "Filter");
fz_dict_dels(obj, "DecodeParms");
 
if (doascii && isbinarystream(buf))
{
tmp = hexbuf(buf->data, buf->len);
fz_drop_buffer(buf);
buf = tmp;
 
addhexfilter(obj);
}
 
newlen = fz_new_int(buf->len);
fz_dict_puts(obj, "Length", newlen);
fz_drop_obj(newlen);
 
fprintf(out, "%d %d obj\n", num, gen);
fz_fprint_obj(out, obj, !doexpand);
fprintf(out, "stream\n");
fwrite(buf->data, 1, buf->len, out);
fprintf(out, "endstream\nendobj\n\n");
 
fz_drop_buffer(buf);
}
 
static void writeobject(int num, int gen)
{
fz_error error;
fz_obj *obj;
fz_obj *type;
 
error = pdf_load_object(&obj, xref, num, gen);
if (error)
die(error);
 
/* skip ObjStm and XRef objects */
if (fz_is_dict(obj))
{
type = fz_dict_gets(obj, "Type");
if (fz_is_name(type) && !strcmp(fz_to_name(type), "ObjStm"))
{
uselist[num] = 0;
fz_drop_obj(obj);
return;
}
if (fz_is_name(type) && !strcmp(fz_to_name(type), "XRef"))
{
uselist[num] = 0;
fz_drop_obj(obj);
return;
}
}
 
if (!pdf_is_stream(xref, num, gen))
{
fprintf(out, "%d %d obj\n", num, gen);
fz_fprint_obj(out, obj, !doexpand);
fprintf(out, "endobj\n\n");
}
else
{
if (doexpand && !pdf_is_jpx_image(obj))
expandstream(obj, num, gen);
else
copystream(obj, num, gen);
}
 
fz_drop_obj(obj);
}
 
static void writexref(void)
{
fz_obj *trailer;
fz_obj *obj;
int startxref;
int num;
 
startxref = ftell(out);
 
fprintf(out, "xref\n0 %d\n", xref->len);
for (num = 0; num < xref->len; num++)
{
if (uselist[num])
fprintf(out, "%010d %05d n \n", ofslist[num], genlist[num]);
else
fprintf(out, "%010d %05d f \n", ofslist[num], genlist[num]);
}
fprintf(out, "\n");
 
trailer = fz_new_dict(5);
 
obj = fz_new_int(xref->len);
fz_dict_puts(trailer, "Size", obj);
fz_drop_obj(obj);
 
obj = fz_dict_gets(xref->trailer, "Info");
if (obj)
fz_dict_puts(trailer, "Info", obj);
 
obj = fz_dict_gets(xref->trailer, "Root");
if (obj)
fz_dict_puts(trailer, "Root", obj);
 
obj = fz_dict_gets(xref->trailer, "ID");
if (obj)
fz_dict_puts(trailer, "ID", obj);
 
fprintf(out, "trailer\n");
fz_fprint_obj(out, trailer, !doexpand);
fprintf(out, "\n");
 
fz_drop_obj(trailer);
 
fprintf(out, "startxref\n%d\n%%%%EOF\n", startxref);
}
 
static void writepdf(void)
{
int lastfree;
int num;
 
for (num = 0; num < xref->len; num++)
{
if (xref->table[num].type == 'f')
genlist[num] = xref->table[num].gen;
if (xref->table[num].type == 'n')
genlist[num] = xref->table[num].gen;
if (xref->table[num].type == 'o')
genlist[num] = 0;
 
if (dogarbage && !uselist[num])
continue;
 
if (xref->table[num].type == 'n' || xref->table[num].type == 'o')
{
uselist[num] = 1;
ofslist[num] = ftell(out);
writeobject(num, genlist[num]);
}
}
 
/* Construct linked list of free object slots */
lastfree = 0;
for (num = 0; num < xref->len; num++)
{
if (!uselist[num])
{
genlist[num]++;
ofslist[lastfree] = num;
lastfree = num;
}
}
 
writexref();
}
 
int main(int argc, char **argv)
{
fz_error error;
char *infile;
char *outfile = "out.pdf";
char *password = "";
int c, num;
int subset;
 
while ((c = fz_getopt(argc, argv, "adgp:")) != -1)
{
switch (c)
{
case 'p': password = fz_optarg; break;
case 'g': dogarbage ++; break;
case 'd': doexpand ++; break;
case 'a': doascii ++; 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;
 
error = pdf_open_xref(&xref, infile, password);
if (error)
die(fz_rethrow(error, "cannot open input file '%s'", infile));
 
out = fopen(outfile, "wb");
if (!out)
die(fz_throw("cannot open output file '%s'", outfile));
 
fprintf(out, "%%PDF-%d.%d\n", xref->version / 10, xref->version % 10);
fprintf(out, "%%\316\274\341\277\246\n\n");
 
uselist = fz_calloc(xref->len + 1, sizeof(char));
ofslist = fz_calloc(xref->len + 1, sizeof(int));
genlist = fz_calloc(xref->len + 1, sizeof(int));
renumbermap = fz_calloc(xref->len + 1, sizeof(int));
 
for (num = 0; num < xref->len; num++)
{
uselist[num] = 0;
ofslist[num] = 0;
genlist[num] = 0;
renumbermap[num] = num;
}
 
/* Make sure any objects hidden in compressed streams have been loaded */
preloadobjstms();
 
/* Only retain the specified subset of the pages */
if (subset)
retainpages(argc, argv);
 
/* Sweep & mark objects from the trailer */
if (dogarbage >= 1)
sweepobj(xref->trailer);
 
/* Coalesce and renumber duplicate objects */
if (dogarbage >= 3)
removeduplicateobjs();
 
/* Compact xref by renumbering and removing unused objects */
if (dogarbage >= 2)
compactxref();
 
/* Make renumbering affect all indirect references and update xref */
if (dogarbage >= 2)
renumberobjs();
 
writepdf();
 
if (fclose(out))
die(fz_throw("cannot close output file '%s'", outfile));
 
fz_free(uselist);
fz_free(ofslist);
fz_free(genlist);
fz_free(renumbermap);
 
pdf_free_xref(xref);
 
fz_flush_warnings();
 
return 0;
}
/contrib/media/updf/apps/pdfdraw.c
0,0 → 1,405
/*
* pdfdraw -- command line tool for drawing pdf documents
*/
 
#include "fitz.h"
#include "mupdf.h"
 
#ifdef _MSC_VER
#include <winsock2.h>
#else
#include <sys/time.h>
#endif
 
char *output = NULL;
float resolution = 72;
float rotation = 0;
 
int showxml = 0;
int showtext = 0;
int showtime = 0;
int showmd5 = 0;
int savealpha = 0;
int uselist = 1;
int alphabits = 8;
float gamma_value = 1;
int invert = 0;
 
fz_colorspace *colorspace;
fz_glyph_cache *glyphcache;
char *filename;
 
struct {
int count, total;
int min, max;
int minpage, maxpage;
} timing;
 
static void die(fz_error error)
{
fz_catch(error, "aborting");
exit(1);
}
 
static void usage(void)
{
fprintf(stderr,
"usage: pdfdraw [options] input.pdf [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-A\tdisable accelerated functions\n"
"\t-a\tsave alpha channel (only pam and png)\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)\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 gamma\tgamma correct output\n"
"\t-I\tinvert output\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 drawpage(pdf_xref *xref, int pagenum)
{
fz_error error;
pdf_page *page;
fz_display_list *list;
fz_device *dev;
int start;
 
if (showtime)
{
start = gettime();
}
 
error = pdf_load_page(&page, xref, pagenum - 1);
if (error)
die(fz_rethrow(error, "cannot load page %d in file '%s'", pagenum, filename));
 
list = NULL;
 
if (uselist)
{
list = fz_new_display_list();
dev = fz_new_list_device(list);
error = pdf_run_page(xref, page, dev, fz_identity);
if (error)
die(fz_rethrow(error, "cannot draw page %d in file '%s'", pagenum, filename));
fz_free_device(dev);
}
 
if (showxml)
{
dev = fz_new_trace_device();
printf("<page number=\"%d\">\n", pagenum);
if (list)
fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
else
pdf_run_page(xref, page, dev, fz_identity);
printf("</page>\n");
fz_free_device(dev);
}
 
if (showtext)
{
fz_text_span *text = fz_new_text_span();
dev = fz_new_text_device(text);
if (list)
fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
else
pdf_run_page(xref, page, dev, fz_identity);
fz_free_device(dev);
printf("[Page %d]\n", pagenum);
if (showtext > 1)
fz_debug_text_span_xml(text);
else
fz_debug_text_span(text);
printf("\n");
fz_free_text_span(text);
}
 
if (showmd5 || showtime)
printf("page %s %d", filename, pagenum);
 
if (output || showmd5 || showtime)
{
float zoom;
fz_matrix ctm;
fz_bbox bbox;
fz_pixmap *pix;
 
zoom = resolution / 72;
ctm = fz_translate(0, -page->mediabox.y1);
ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
ctm = fz_concat(ctm, fz_rotate(page->rotate));
ctm = fz_concat(ctm, fz_rotate(rotation));
bbox = fz_round_rect(fz_transform_rect(ctm, page->mediabox));
 
/* TODO: banded rendering and multi-page ppm */
 
pix = fz_new_pixmap_with_rect(colorspace, bbox);
 
if (savealpha)
fz_clear_pixmap(pix);
else
fz_clear_pixmap_with_color(pix, 255);
 
dev = fz_new_draw_device(glyphcache, pix);
if (list)
fz_execute_display_list(list, dev, ctm, bbox);
else
pdf_run_page(xref, page, dev, ctm);
fz_free_device(dev);
 
if (invert)
fz_invert_pixmap(pix);
if (gamma_value != 1)
fz_gamma_pixmap(pix, gamma_value);
 
if (output)
{
char buf[512];
sprintf(buf, output, pagenum);
if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm"))
fz_write_pnm(pix, buf);
else if (strstr(output, ".pam"))
fz_write_pam(pix, buf, savealpha);
else if (strstr(output, ".png"))
fz_write_png(pix, buf, savealpha);
else if (strstr(output, ".pbm")) {
fz_halftone *ht = fz_get_default_halftone(1);
fz_bitmap *bit = fz_halftone_pixmap(pix, ht);
fz_write_pbm(bit, buf);
fz_drop_bitmap(bit);
fz_drop_halftone(ht);
}
}
 
if (showmd5)
{
fz_md5 md5;
unsigned char digest[16];
int i;
 
fz_md5_init(&md5);
fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
fz_md5_final(&md5, digest);
 
printf(" ");
for (i = 0; i < 16; i++)
printf("%02x", digest[i]);
}
 
fz_drop_pixmap(pix);
}
 
if (list)
fz_free_display_list(list);
 
pdf_free_page(page);
 
if (showtime)
{
int end = gettime();
int diff = end - start;
 
if (diff < timing.min)
{
timing.min = diff;
timing.minpage = pagenum;
}
if (diff > timing.max)
{
timing.max = diff;
timing.maxpage = pagenum;
}
timing.total += diff;
timing.count ++;
 
printf(" %dms", diff);
}
 
if (showmd5 || showtime)
printf("\n");
 
pdf_age_store(xref->store, 3);
 
fz_flush_warnings();
}
 
static void drawrange(pdf_xref *xref, char *range)
{
int page, spage, epage;
char *spec, *dash;
 
spec = fz_strsep(&range, ",");
while (spec)
{
dash = strchr(spec, '-');
 
if (dash == spec)
spage = epage = pdf_count_pages(xref);
else
spage = epage = atoi(spec);
 
if (dash)
{
if (strlen(dash) > 1)
epage = atoi(dash + 1);
else
epage = pdf_count_pages(xref);
}
 
spage = CLAMP(spage, 1, pdf_count_pages(xref));
epage = CLAMP(epage, 1, pdf_count_pages(xref));
 
if (spage < epage)
for (page = spage; page <= epage; page++)
drawpage(xref, page);
else
for (page = spage; page >= epage; page--)
drawpage(xref, page);
 
spec = fz_strsep(&range, ",");
}
}
 
int main(int argc, char **argv)
{
char *password = "";
int grayscale = 0;
int accelerate = 1;
pdf_xref *xref;
fz_error error;
int c;
 
while ((c = fz_getopt(argc, argv, "o:p:r:R:Aab:dgmtx5G:I")) != -1)
{
switch (c)
{
case 'o': output = fz_optarg; break;
case 'p': password = fz_optarg; break;
case 'r': resolution = atof(fz_optarg); break;
case 'R': rotation = atof(fz_optarg); break;
case 'A': accelerate = 0; break;
case 'a': savealpha = 1; break;
case 'b': alphabits = atoi(fz_optarg); break;
case 'm': showtime++; break;
case 't': showtext++; break;
case 'x': showxml++; break;
case '5': showmd5++; break;
case 'g': grayscale++; break;
case 'd': uselist = 0; break;
case 'G': gamma_value = atof(fz_optarg); break;
case 'I': invert++; break;
default: usage(); break;
}
}
 
fz_set_aa_level(alphabits);
 
if (fz_optind == argc)
usage();
 
if (!showtext && !showxml && !showtime && !showmd5 && !output)
{
printf("nothing to do\n");
exit(0);
}
 
if (accelerate)
fz_accelerate();
 
glyphcache = fz_new_glyph_cache();
 
colorspace = fz_device_rgb;
if (grayscale)
colorspace = fz_device_gray;
if (output && strstr(output, ".pgm"))
colorspace = fz_device_gray;
if (output && strstr(output, ".ppm"))
colorspace = fz_device_rgb;
if (output && strstr(output, ".pbm"))
colorspace = fz_device_gray;
 
timing.count = 0;
timing.total = 0;
timing.min = 1 << 30;
timing.max = 0;
timing.minpage = 0;
timing.maxpage = 0;
 
if (showxml)
printf("<?xml version=\"1.0\"?>\n");
 
while (fz_optind < argc)
{
filename = argv[fz_optind++];
 
error = pdf_open_xref(&xref, filename, password);
if (error)
die(fz_rethrow(error, "cannot open document: %s", filename));
 
error = pdf_load_page_tree(xref);
if (error)
die(fz_rethrow(error, "cannot load page tree: %s", filename));
 
if (showxml)
printf("<document name=\"%s\">\n", filename);
 
if (fz_optind == argc || !isrange(argv[fz_optind]))
drawrange(xref, "1-");
if (fz_optind < argc && isrange(argv[fz_optind]))
drawrange(xref, argv[fz_optind++]);
 
if (showxml)
printf("</document>\n");
 
pdf_free_xref(xref);
}
 
if (showtime)
{
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);
}
 
fz_free_glyph_cache(glyphcache);
 
fz_flush_warnings();
 
return 0;
}
/contrib/media/updf/apps/pdfextract.c
0,0 → 1,222
/*
* pdfextract -- the ultimate way to extract images and fonts from pdfs
*/
 
#include "fitz.h"
#include "mupdf.h"
 
static pdf_xref *xref = NULL;
static int dorgb = 0;
 
void die(fz_error error)
{
fz_catch(error, "aborting");
if (xref)
pdf_free_xref(xref);
exit(1);
}
 
static void usage(void)
{
fprintf(stderr, "usage: pdfextract [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(fz_obj *obj)
{
fz_obj *type = fz_dict_gets(obj, "Subtype");
return fz_is_name(type) && !strcmp(fz_to_name(type), "Image");
}
 
static int isfontdesc(fz_obj *obj)
{
fz_obj *type = fz_dict_gets(obj, "Type");
return fz_is_name(type) && !strcmp(fz_to_name(type), "FontDescriptor");
}
 
static void saveimage(int num)
{
fz_error error;
fz_pixmap *img;
fz_obj *ref;
char name[1024];
 
ref = fz_new_indirect(num, 0, xref);
 
/* TODO: detect DCTD and save as jpeg */
 
error = pdf_load_image(&img, xref, ref);
if (error)
die(error);
 
if (dorgb && img->colorspace && img->colorspace != fz_device_rgb)
{
fz_pixmap *temp;
temp = fz_new_pixmap_with_rect(fz_device_rgb, fz_bound_pixmap(img));
fz_convert_pixmap(img, temp);
fz_drop_pixmap(img);
img = temp;
}
 
if (img->n <= 4)
{
sprintf(name, "img-%04d.png", num);
printf("extracting image %s\n", name);
fz_write_png(img, name, 0);
}
else
{
sprintf(name, "img-%04d.pam", num);
printf("extracting image %s\n", name);
fz_write_pam(img, name, 0);
}
 
fz_drop_pixmap(img);
fz_drop_obj(ref);
}
 
static void savefont(fz_obj *dict, int num)
{
fz_error error;
char name[1024];
char *subtype;
fz_buffer *buf;
fz_obj *stream = NULL;
fz_obj *obj;
char *ext = "";
FILE *f;
char *fontname = "font";
int n;
 
obj = fz_dict_gets(dict, "FontName");
if (obj)
fontname = fz_to_name(obj);
 
obj = fz_dict_gets(dict, "FontFile");
if (obj)
{
stream = obj;
ext = "pfa";
}
 
obj = fz_dict_gets(dict, "FontFile2");
if (obj)
{
stream = obj;
ext = "ttf";
}
 
obj = fz_dict_gets(dict, "FontFile3");
if (obj)
{
stream = obj;
 
obj = fz_dict_gets(obj, "Subtype");
if (obj && !fz_is_name(obj))
die(fz_throw("Invalid font descriptor subtype"));
 
subtype = fz_to_name(obj);
if (!strcmp(subtype, "Type1C"))
ext = "cff";
else if (!strcmp(subtype, "CIDFontType0C"))
ext = "cid";
else
die(fz_throw("Unhandled font type '%s'", subtype));
}
 
if (!stream)
{
fz_warn("Unhandled font type");
return;
}
 
buf = fz_new_buffer(0);
 
error = pdf_load_stream(&buf, xref, fz_to_num(stream), fz_to_gen(stream));
if (error)
die(error);
 
sprintf(name, "%s-%04d.%s", fontname, num, ext);
printf("extracting font %s\n", name);
 
f = fopen(name, "wb");
if (f == NULL)
die(fz_throw("Error creating font file"));
 
n = fwrite(buf->data, 1, buf->len, f);
if (n < buf->len)
die(fz_throw("Error writing font file"));
 
if (fclose(f) < 0)
die(fz_throw("Error closing font file"));
 
fz_drop_buffer(buf);
}
 
static void showobject(int num)
{
fz_error error;
fz_obj *obj;
 
if (!xref)
die(fz_throw("no file specified"));
 
error = pdf_load_object(&obj, xref, num, 0);
if (error)
die(error);
 
if (isimage(obj))
saveimage(num);
else if (isfontdesc(obj))
savefont(obj, num);
 
fz_drop_obj(obj);
}
 
int main(int argc, char **argv)
{
fz_error error;
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++];
error = pdf_open_xref(&xref, infile, password);
if (error)
die(fz_rethrow(error, "cannot open input file '%s'", infile));
 
if (fz_optind == argc)
{
for (o = 0; o < xref->len; o++)
showobject(o);
}
else
{
while (fz_optind < argc)
{
showobject(atoi(argv[fz_optind]));
fz_optind++;
}
}
 
pdf_free_xref(xref);
 
fz_flush_warnings();
 
return 0;
}
/contrib/media/updf/apps/pdfinfo.c
0,0 → 1,1011
/*
* Information tool.
* Print information about the input pdf.
*/
 
#include "fitz.h"
#include "mupdf.h"
 
pdf_xref *xref;
int pagecount;
 
void closexref(void);
 
void die(fz_error error)
{
fz_catch(error, "aborting");
closexref();
exit(1);
}
 
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;
fz_obj *pageref;
fz_obj *pageobj;
union {
struct {
fz_obj *obj;
} info;
struct {
fz_obj *obj;
} crypt;
struct {
fz_obj *obj;
fz_rect *bbox;
} dim;
struct {
fz_obj *obj;
fz_obj *subtype;
fz_obj *name;
} font;
struct {
fz_obj *obj;
fz_obj *width;
fz_obj *height;
fz_obj *bpc;
fz_obj *filter;
fz_obj *cs;
fz_obj *altcs;
} image;
struct {
fz_obj *obj;
fz_obj *type;
} shading;
struct {
fz_obj *obj;
fz_obj *type;
fz_obj *paint;
fz_obj *tiling;
fz_obj *shading;
} pattern;
struct {
fz_obj *obj;
fz_obj *groupsubtype;
fz_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_free_xref(xref);
xref = NULL;
}
 
if (dim)
{
for (i = 0; i < dims; i++)
fz_free(dim[i].u.dim.bbox);
fz_free(dim);
dim = NULL;
dims = 0;
}
 
if (font)
{
fz_free(font);
font = NULL;
fonts = 0;
}
 
if (image)
{
fz_free(image);
image = NULL;
images = 0;
}
 
if (shading)
{
fz_free(shading);
shading = NULL;
shadings = 0;
}
 
if (pattern)
{
fz_free(pattern);
pattern = NULL;
patterns = 0;
}
 
if (form)
{
fz_free(form);
form = NULL;
forms = 0;
}
 
if (psobj)
{
fz_free(psobj);
psobj = NULL;
psobjs = 0;
}
 
if (xref && xref->store)
{
pdf_free_store(xref->store);
xref->store = NULL;
}
}
 
static void
infousage(void)
{
fprintf(stderr,
"usage: pdfinfo [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)
{
fz_obj *obj;
 
printf("\nPDF-%d.%d\n", xref->version / 10, xref->version % 10);
 
obj = fz_dict_gets(xref->trailer, "Info");
if (obj)
{
printf("Info object (%d %d R):\n", fz_to_num(obj), fz_to_gen(obj));
fz_debug_obj(fz_resolve_indirect(obj));
}
 
obj = fz_dict_gets(xref->trailer, "Encrypt");
if (obj)
{
printf("\nEncryption object (%d %d R):\n", fz_to_num(obj), fz_to_gen(obj));
fz_debug_obj(fz_resolve_indirect(obj));
}
 
printf("\nPages: %d\n\n", pagecount);
}
 
static void
gatherdimensions(int page, fz_obj *pageref, fz_obj *pageobj)
{
fz_rect bbox;
fz_obj *obj;
int j;
 
obj = fz_dict_gets(pageobj, "MediaBox");
if (!fz_is_array(obj))
return;
 
bbox = pdf_to_rect(obj);
 
for (j = 0; j < dims; j++)
if (!memcmp(dim[j].u.dim.bbox, &bbox, sizeof (fz_rect)))
break;
 
if (j < dims)
return;
 
dims++;
 
dim = fz_realloc(dim, dims, sizeof(struct info));
dim[dims - 1].page = page;
dim[dims - 1].pageref = pageref;
dim[dims - 1].pageobj = pageobj;
dim[dims - 1].u.dim.bbox = fz_malloc(sizeof(fz_rect));
memcpy(dim[dims - 1].u.dim.bbox, &bbox, sizeof (fz_rect));
 
return;
}
 
static void
gatherfonts(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *fontdict = NULL;
fz_obj *subtype = NULL;
fz_obj *basefont = NULL;
fz_obj *name = NULL;
int k;
 
fontdict = fz_dict_get_val(dict, i);
if (!fz_is_dict(fontdict))
{
fz_warn("not a font dict (%d %d R)", fz_to_num(fontdict), fz_to_gen(fontdict));
continue;
}
 
subtype = fz_dict_gets(fontdict, "Subtype");
basefont = fz_dict_gets(fontdict, "BaseFont");
if (!basefont || fz_is_null(basefont))
name = fz_dict_gets(fontdict, "Name");
 
for (k = 0; k < fonts; k++)
if (!fz_objcmp(font[k].u.font.obj, fontdict))
break;
 
if (k < fonts)
continue;
 
fonts++;
 
font = fz_realloc(font, fonts, sizeof(struct info));
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, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *imagedict;
fz_obj *type;
fz_obj *width;
fz_obj *height;
fz_obj *bpc = NULL;
fz_obj *filter = NULL;
fz_obj *cs = NULL;
fz_obj *altcs;
int k;
 
imagedict = fz_dict_get_val(dict, i);
if (!fz_is_dict(imagedict))
{
fz_warn("not an image dict (%d %d R)", fz_to_num(imagedict), fz_to_gen(imagedict));
continue;
}
 
type = fz_dict_gets(imagedict, "Subtype");
if (strcmp(fz_to_name(type), "Image"))
continue;
 
filter = fz_dict_gets(imagedict, "Filter");
 
altcs = NULL;
cs = fz_dict_gets(imagedict, "ColorSpace");
if (fz_is_array(cs))
{
fz_obj *cses = cs;
 
cs = fz_array_get(cses, 0);
if (fz_is_name(cs) && (!strcmp(fz_to_name(cs), "DeviceN") || !strcmp(fz_to_name(cs), "Separation")))
{
altcs = fz_array_get(cses, 2);
if (fz_is_array(altcs))
altcs = fz_array_get(altcs, 0);
}
}
 
width = fz_dict_gets(imagedict, "Width");
height = fz_dict_gets(imagedict, "Height");
bpc = fz_dict_gets(imagedict, "BitsPerComponent");
 
for (k = 0; k < images; k++)
if (!fz_objcmp(image[k].u.image.obj, imagedict))
break;
 
if (k < images)
continue;
 
images++;
 
image = fz_realloc(image, images, sizeof(struct info));
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, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *xobjdict;
fz_obj *type;
fz_obj *subtype;
fz_obj *group;
fz_obj *groupsubtype;
fz_obj *reference;
int k;
 
xobjdict = fz_dict_get_val(dict, i);
if (!fz_is_dict(xobjdict))
{
fz_warn("not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict));
continue;
}
 
type = fz_dict_gets(xobjdict, "Subtype");
if (strcmp(fz_to_name(type), "Form"))
continue;
 
subtype = fz_dict_gets(xobjdict, "Subtype2");
if (!strcmp(fz_to_name(subtype), "PS"))
continue;
 
group = fz_dict_gets(xobjdict, "Group");
groupsubtype = fz_dict_gets(group, "S");
reference = fz_dict_gets(xobjdict, "Ref");
 
for (k = 0; k < forms; k++)
if (!fz_objcmp(form[k].u.form.obj, xobjdict))
break;
 
if (k < forms)
continue;
 
forms++;
 
form = fz_realloc(form, forms, sizeof(struct info));
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, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *xobjdict;
fz_obj *type;
fz_obj *subtype;
int k;
 
xobjdict = fz_dict_get_val(dict, i);
if (!fz_is_dict(xobjdict))
{
fz_warn("not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict));
continue;
}
 
type = fz_dict_gets(xobjdict, "Subtype");
subtype = fz_dict_gets(xobjdict, "Subtype2");
if (strcmp(fz_to_name(type), "PS") &&
(strcmp(fz_to_name(type), "Form") || strcmp(fz_to_name(subtype), "PS")))
continue;
 
for (k = 0; k < psobjs; k++)
if (!fz_objcmp(psobj[k].u.form.obj, xobjdict))
break;
 
if (k < psobjs)
continue;
 
psobjs++;
 
psobj = fz_realloc(psobj, psobjs, sizeof(struct info));
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, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *shade;
fz_obj *type;
int k;
 
shade = fz_dict_get_val(dict, i);
if (!fz_is_dict(shade))
{
fz_warn("not a shading dict (%d %d R)", fz_to_num(shade), fz_to_gen(shade));
continue;
}
 
type = fz_dict_gets(shade, "ShadingType");
if (!fz_is_int(type) || fz_to_int(type) < 1 || fz_to_int(type) > 7)
{
fz_warn("not a shading type (%d %d R)", fz_to_num(shade), fz_to_gen(shade));
type = NULL;
}
 
for (k = 0; k < shadings; k++)
if (!fz_objcmp(shading[k].u.shading.obj, shade))
break;
 
if (k < shadings)
continue;
 
shadings++;
 
shading = fz_realloc(shading, shadings, sizeof(struct info));
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, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict)
{
int i;
 
for (i = 0; i < fz_dict_len(dict); i++)
{
fz_obj *patterndict;
fz_obj *type;
fz_obj *paint = NULL;
fz_obj *tiling = NULL;
fz_obj *shading = NULL;
int k;
 
patterndict = fz_dict_get_val(dict, i);
if (!fz_is_dict(patterndict))
{
fz_warn("not a pattern dict (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict));
continue;
}
 
type = fz_dict_gets(patterndict, "PatternType");
if (!fz_is_int(type) || fz_to_int(type) < 1 || fz_to_int(type) > 2)
{
fz_warn("not a pattern type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict));
type = NULL;
}
 
if (fz_to_int(type) == 1)
{
paint = fz_dict_gets(patterndict, "PaintType");
if (!fz_is_int(paint) || fz_to_int(paint) < 1 || fz_to_int(paint) > 2)
{
fz_warn("not a pattern paint type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict));
paint = NULL;
}
 
tiling = fz_dict_gets(patterndict, "TilingType");
if (!fz_is_int(tiling) || fz_to_int(tiling) < 1 || fz_to_int(tiling) > 3)
{
fz_warn("not a pattern tiling type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict));
tiling = NULL;
}
}
else
{
shading = fz_dict_gets(patterndict, "Shading");
}
 
for (k = 0; k < patterns; k++)
if (!fz_objcmp(pattern[k].u.pattern.obj, patterndict))
break;
 
if (k < patterns)
continue;
 
patterns++;
 
pattern = fz_realloc(pattern, patterns, sizeof(struct info));
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, fz_obj *rsrc)
{
fz_obj *pageobj;
fz_obj *pageref;
fz_obj *font;
fz_obj *xobj;
fz_obj *shade;
fz_obj *pattern;
fz_obj *subrsrc;
int i;
 
pageobj = xref->page_objs[page-1];
pageref = xref->page_refs[page-1];
 
if (!pageobj)
die(fz_throw("cannot retrieve info from page %d", page));
 
font = fz_dict_gets(rsrc, "Font");
if (font)
{
gatherfonts(page, pageref, pageobj, font);
 
for (i = 0; i < fz_dict_len(font); i++)
{
fz_obj *obj = fz_dict_get_val(font, i);
 
subrsrc = fz_dict_gets(obj, "Resources");
if (subrsrc && fz_objcmp(rsrc, subrsrc))
gatherresourceinfo(page, subrsrc);
}
}
 
xobj = fz_dict_gets(rsrc, "XObject");
if (xobj)
{
gatherimages(page, pageref, pageobj, xobj);
gatherforms(page, pageref, pageobj, xobj);
gatherpsobjs(page, pageref, pageobj, xobj);
 
for (i = 0; i < fz_dict_len(xobj); i++)
{
fz_obj *obj = fz_dict_get_val(xobj, i);
subrsrc = fz_dict_gets(obj, "Resources");
if (subrsrc && fz_objcmp(rsrc, subrsrc))
gatherresourceinfo(page, subrsrc);
}
}
 
shade = fz_dict_gets(rsrc, "Shading");
if (shade)
gathershadings(page, pageref, pageobj, shade);
 
pattern = fz_dict_gets(rsrc, "Pattern");
if (pattern)
{
gatherpatterns(page, pageref, pageobj, pattern);
 
for (i = 0; i < fz_dict_len(pattern); i++)
{
fz_obj *obj = fz_dict_get_val(pattern, i);
subrsrc = fz_dict_gets(obj, "Resources");
if (subrsrc && fz_objcmp(rsrc, subrsrc))
gatherresourceinfo(page, subrsrc);
}
}
}
 
static void
gatherpageinfo(int page)
{
fz_obj *pageobj;
fz_obj *pageref;
fz_obj *rsrc;
 
pageobj = xref->page_objs[page-1];
pageref = xref->page_refs[page-1];
 
if (!pageobj)
die(fz_throw("cannot retrieve info from page %d", page));
 
gatherdimensions(page, pageref, pageobj);
 
rsrc = fz_dict_gets(pageobj, "Resources");
gatherresourceinfo(page, rsrc);
}
 
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,
fz_to_num(dim[i].pageref), fz_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,
fz_to_num(font[i].pageref), fz_to_gen(font[i].pageref),
fz_to_name(font[i].u.font.subtype),
fz_to_name(font[i].u.font.name),
fz_to_num(font[i].u.font.obj), fz_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,
fz_to_num(image[i].pageref), fz_to_gen(image[i].pageref));
 
if (fz_is_array(image[i].u.image.filter))
for (j = 0; j < fz_array_len(image[i].u.image.filter); j++)
{
fz_obj *obj = fz_array_get(image[i].u.image.filter, j);
char *filter = fz_strdup(fz_to_name(obj));
 
if (strstr(filter, "Decode"))
*(strstr(filter, "Decode")) = '\0';
 
printf("%s%s",
filter,
j == fz_array_len(image[i].u.image.filter) - 1 ? "" : " ");
fz_free(filter);
}
else if (image[i].u.image.filter)
{
fz_obj *obj = image[i].u.image.filter;
char *filter = fz_strdup(fz_to_name(obj));
 
if (strstr(filter, "Decode"))
*(strstr(filter, "Decode")) = '\0';
 
printf("%s", filter);
fz_free(filter);
}
else
printf("Raw");
 
if (image[i].u.image.cs)
{
cs = fz_strdup(fz_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(fz_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",
fz_to_int(image[i].u.image.width),
fz_to_int(image[i].u.image.height),
image[i].u.image.bpc ? fz_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 : "",
fz_to_num(image[i].u.image.obj), fz_to_gen(image[i].u.image.obj));
 
fz_free(cs);
fz_free(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,
fz_to_num(shading[i].pageref), fz_to_gen(shading[i].pageref),
shadingtype[fz_to_int(shading[i].u.shading.type)],
fz_to_num(shading[i].u.shading.obj), fz_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 (fz_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,
fz_to_num(pattern[i].pageref), fz_to_gen(pattern[i].pageref),
painttype[fz_to_int(pattern[i].u.pattern.paint)],
tilingtype[fz_to_int(pattern[i].u.pattern.tiling)],
fz_to_num(pattern[i].u.pattern.obj), fz_to_gen(pattern[i].u.pattern.obj));
}
else
{
printf(PAGE_FMT "Shading %d %d R (%d %d R)\n",
pattern[i].page,
fz_to_num(pattern[i].pageref), fz_to_gen(pattern[i].pageref),
fz_to_num(pattern[i].u.pattern.shading), fz_to_gen(pattern[i].u.pattern.shading),
fz_to_num(pattern[i].u.pattern.obj), fz_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,
fz_to_num(form[i].pageref), fz_to_gen(form[i].pageref),
form[i].u.form.groupsubtype ? " " : "",
form[i].u.form.groupsubtype ? fz_to_name(form[i].u.form.groupsubtype) : "",
form[i].u.form.groupsubtype ? " Group" : "",
form[i].u.form.reference ? " Reference" : "",
fz_to_num(form[i].u.form.obj), fz_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,
fz_to_num(psobj[i].pageref), fz_to_gen(psobj[i].pageref),
fz_to_num(psobj[i].u.form.obj), fz_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;
 
if (!xref)
infousage();
 
allpages = !strcmp(pagelist, "1-");
 
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;
 
if (spage < 1)
spage = 1;
if (epage > pagecount)
epage = pagecount;
if (spage > pagecount)
spage = pagecount;
 
if (allpages)
printf("Retrieving info from pages %d-%d...\n", spage, epage);
if (spage >= 1)
{
for (page = spage; page <= epage; page++)
{
gatherpageinfo(page);
if (!allpages)
{
printf("Page %d:\n", page);
printinfo(filename, show, page);
printf("\n");
}
}
}
 
spec = fz_strsep(&pagelist, ",");
}
 
if (allpages)
printinfo(filename, show, -1);
}
 
int main(int argc, char **argv)
{
enum { NO_FILE_OPENED, NO_INFO_GATHERED, INFO_SHOWN } state;
fz_error error;
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();
 
state = NO_FILE_OPENED;
while (fz_optind < argc)
{
if (strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF"))
{
if (state == NO_INFO_GATHERED)
{
showinfo(filename, show, "1-");
closexref();
}
 
closexref();
 
filename = argv[fz_optind];
printf("%s:\n", filename);
error = pdf_open_xref(&xref, filename, password);
if (error)
die(fz_rethrow(error, "cannot open input file '%s'", filename));
 
error = pdf_load_page_tree(xref);
if (error)
die(fz_rethrow(error, "cannot load page tree: %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();
 
return 0;
}
/contrib/media/updf/apps/pdfshow.c
0,0 → 1,240
/*
* pdfshow -- the ultimate pdf debugging tool
*/
 
#include "fitz.h"
#include "mupdf.h"
 
static pdf_xref *xref = NULL;
static int showbinary = 0;
static int showdecode = 1;
static int showcolumn;
 
void die(fz_error error)
{
fz_catch(error, "aborting");
if (xref)
pdf_free_xref(xref);
exit(1);
}
 
static void usage(void)
{
fprintf(stderr, "usage: pdfshow [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 (!xref)
die(fz_throw("no file specified"));
printf("trailer\n");
fz_debug_obj(xref->trailer);
printf("\n");
}
 
static void showxref(void)
{
if (!xref)
die(fz_throw("no file specified"));
pdf_debug_xref(xref);
printf("\n");
}
 
static void showpagetree(void)
{
fz_error error;
fz_obj *ref;
int count;
int i;
 
if (!xref)
die(fz_throw("no file specified"));
 
if (!xref->page_len)
{
error = pdf_load_page_tree(xref);
if (error)
die(fz_rethrow(error, "cannot load page tree"));
}
 
count = pdf_count_pages(xref);
for (i = 0; i < count; i++)
{
ref = xref->page_refs[i];
printf("page %d = %d %d R\n", i + 1, fz_to_num(ref), fz_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_error error;
fz_stream *stm;
unsigned char buf[2048];
int n;
 
showcolumn = 0;
 
if (showdecode)
error = pdf_open_stream(&stm, xref, num, gen);
else
error = pdf_open_raw_stream(&stm, xref, num, gen);
if (error)
die(error);
 
while (1)
{
n = fz_read(stm, buf, sizeof buf);
if (n < 0)
die(n);
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)
{
fz_error error;
fz_obj *obj;
 
if (!xref)
die(fz_throw("no file specified"));
 
error = pdf_load_object(&obj, xref, num, gen);
if (error)
die(error);
 
if (pdf_is_stream(xref, num, gen))
{
if (showbinary)
{
showstream(num, gen);
}
else
{
printf("%d %d obj\n", num, gen);
fz_debug_obj(obj);
printf("stream\n");
showstream(num, gen);
printf("endstream\n");
printf("endobj\n\n");
}
}
else
{
printf("%d %d obj\n", num, gen);
fz_debug_obj(obj);
printf("endobj\n\n");
}
 
fz_drop_obj(obj);
}
 
static void showgrep(char *filename)
{
fz_error error;
fz_obj *obj;
int i;
 
for (i = 0; i < xref->len; i++)
{
if (xref->table[i].type == 'n' || xref->table[i].type == 'o')
{
error = pdf_load_object(&obj, xref, i, 0);
if (error)
die(error);
 
fz_sort_dict(obj);
 
printf("%s:%d: ", filename, i);
fz_fprint_obj(stdout, obj, 1);
 
fz_drop_obj(obj);
}
}
 
printf("%s:trailer: ", filename);
fz_fprint_obj(stdout, xref->trailer, 1);
}
 
int main(int argc, char **argv)
{
char *password = NULL; /* don't throw errors if encrypted */
char *filename;
fz_error error;
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++];
error = pdf_open_xref(&xref, filename, password);
if (error)
die(fz_rethrow(error, "cannot open document: %s", filename));
 
if (fz_optind == argc)
showtrailer();
 
while (fz_optind < argc)
{
switch (argv[fz_optind][0])
{
case 't': showtrailer(); break;
case 'x': showxref(); break;
case 'p': showpagetree(); break;
case 'g': showgrep(filename); break;
default: showobject(atoi(argv[fz_optind]), 0); break;
}
fz_optind++;
}
 
pdf_free_xref(xref);
 
fz_flush_warnings();
 
return 0;
}
/contrib/media/updf/apps/win_main.c
0,0 → 1,895
#include "fitz.h"
#include "mupdf.h"
#include "muxps.h"
#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 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;
static LRESULT CALLBACK frameproc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK viewproc(HWND, UINT, WPARAM, LPARAM);
 
static int justcopied = 0;
 
static pdfapp_t gapp;
 
static wchar_t wbuf[1024];
static char filename[1024];
 
/*
* 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, 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, fz_error error)
{
char msgbuf[160 * 30];
int i;
 
/* TODO: redirect stderr to a log file and display here */
fz_catch(error, "displaying error message to user");
 
fz_strlcpy(msgbuf, "An error has occurred.\n\n", sizeof msgbuf);
for (i = 0; i < fz_get_error_count(); i++)
{
fz_strlcat(msgbuf, fz_get_error_line(i), sizeof msgbuf);
fz_strlcat(msgbuf, "\n", sizeof msgbuf);
}
 
MessageBoxA(hwndframe, msgbuf, "MuPDF: Error", MB_ICONERROR);
exit(1);
}
 
void win32error(char *msg)
{
LPSTR buf;
int code = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&buf, 0, NULL);
winerror(&gapp, fz_throw("%s:\n%s", msg, buf));
}
 
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)\0*.xps;*.pdf\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0All Files\0*\0\0";
ofn.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
return GetOpenFileNameW(&ofn);
}
 
static char pd_filename[256] = "The file is encrypted.";
static char pd_password[256] = "";
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;
GetDlgItemTextA(hwnd, 3, pd_password, sizeof pd_password);
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)
win32error("cannot create password dialog");
if (pd_okay)
return pd_password;
return NULL;
}
 
INT CALLBACK
dloginfoproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[256];
pdf_xref *xref = gapp.xref;
fz_obj *info, *obj;
 
switch(message)
{
case WM_INITDIALOG:
 
SetDlgItemTextW(hwnd, 0x10, wbuf);
 
if (!xref)
{
SetDlgItemTextA(hwnd, 0x11, "XPS");
SetDlgItemTextA(hwnd, 0x12, "None");
SetDlgItemTextA(hwnd, 0x13, "n/a");
return TRUE;
}
 
sprintf(buf, "PDF %d.%d", xref->version / 10, xref->version % 10);
SetDlgItemTextA(hwnd, 0x11, buf);
 
if (xref->crypt)
{
sprintf(buf, "Standard V%d %d-bit %s", pdf_get_crypt_revision(xref),
pdf_get_crypt_length(xref), pdf_get_crypt_method(xref));
SetDlgItemTextA(hwnd, 0x12, buf);
strcpy(buf, "");
if (pdf_has_permission(xref, PDF_PERM_PRINT))
strcat(buf, "print, ");
if (pdf_has_permission(xref, PDF_PERM_CHANGE))
strcat(buf, "modify, ");
if (pdf_has_permission(xref, PDF_PERM_COPY))
strcat(buf, "copy, ");
if (pdf_has_permission(xref, PDF_PERM_NOTES))
strcat(buf, "annotate, ");
if (strlen(buf) > 2)
buf[strlen(buf)-2] = 0;
else
strcpy(buf, "none");
SetDlgItemTextA(hwnd, 0x13, buf);
}
else
{
SetDlgItemTextA(hwnd, 0x12, "None");
SetDlgItemTextA(hwnd, 0x13, "n/a");
}
 
info = fz_dict_gets(xref->trailer, "Info");
if (!info)
return TRUE;
 
#define SETUCS(ID) \
{ \
unsigned short *ucs; \
ucs = pdf_to_ucs2(obj); \
SetDlgItemTextW(hwnd, ID, ucs); \
fz_free(ucs); \
}
 
if ((obj = fz_dict_gets(info, "Title")))
SETUCS(0x20);
if ((obj = fz_dict_gets(info, "Author")))
SETUCS(0x21);
if ((obj = fz_dict_gets(info, "Subject")))
SETUCS(0x22);
if ((obj = fz_dict_gets(info, "Keywords")))
SETUCS(0x23);
if ((obj = fz_dict_gets(info, "Creator")))
SETUCS(0x24);
if ((obj = fz_dict_gets(info, "Producer")))
SETUCS(0x25);
if ((obj = fz_dict_gets(info, "CreationDate")))
SETUCS(0x26);
if ((obj = fz_dict_gets(info, "ModDate")))
SETUCS(0x27);
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)
win32error("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)
win32error("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)
win32error("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)
win32error("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);
 
/* 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 != NULL);
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)
win32error("cannot create frame: %s");
 
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)
win32error("cannot create view: %s");
 
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)
{
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);
}
 
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 += 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 x0 = gapp.panx;
int y0 = gapp.pany;
int x1 = gapp.panx + gapp.image->w;
int y1 = gapp.pany + gapp.image->h;
RECT r;
 
if (gapp.image)
{
if (gapp.iscopying || justcopied)
{
pdfapp_invert(&gapp, gapp.selr);
justcopied = 1;
}
 
pdfapp_inverthit(&gapp);
 
dibinf->bmiHeader.biWidth = gapp.image->w;
dibinf->bmiHeader.biHeight = -gapp.image->h;
dibinf->bmiHeader.biSizeImage = gapp.image->h * 4;
 
if (gapp.image->n == 2)
{
int i = gapp.image->w * gapp.image->h;
unsigned char *color = malloc(i*4);
unsigned char *s = gapp.image->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, gapp.image->w, gapp.image->h,
0, 0, 0, gapp.image->h, color,
dibinf, DIB_RGB_COLORS);
free(color);
}
if (gapp.image->n == 4)
{
SetDIBitsToDevice(hdc,
gapp.panx, gapp.pany, gapp.image->w, gapp.image->h,
0, 0, 0, gapp.image->h, gapp.image->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);
}
 
/*
* 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)
{
int fd;
 
pdfapp_close(app);
 
fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666);
if (fd < 0)
winerror(&gapp, fz_throw("cannot reload file '%s'", filename));
 
pdfapp_open(app, filename, fd, 1);
}
 
void winopenuri(pdfapp_t *app, char *buf)
{
ShellExecuteA(hwndframe, "open", buf, 0, 0, SW_SHOWNORMAL);
}
 
void handlekey(int c)
{
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 && 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);
}
 
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);
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;
 
/* 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 fd;
int code;
 
fz_accelerate();
 
pdfapp_init(&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);
}
 
fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666);
if (fd < 0)
winerror(&gapp, fz_throw("cannot open file '%s'", filename));
 
code = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, filename, sizeof filename, NULL, NULL);
if (code == 0)
win32error("cannot convert filename to utf-8");
 
pdfapp_open(&gapp, filename, fd, 0);
 
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
 
pdfapp_close(&gapp);
 
return 0;
}
/contrib/media/updf/apps/win_res.rc
0,0 → 1,61
IDI_ICONAPP ICON "mupdf_icon_antialias.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_DLOGABOUT DIALOG 50, 50, 200, 220
STYLE 128 | 0x80000000
CAPTION " About MuPDF "
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Okay", 1, 200-10-50, 220-7-14, 50, 14, 0x50010001
LTEXT "<copyright>", 2, 10, 10, 180, 20, 0
LTEXT "<usage>", 3, 10, 35, 180, 160, 0
END
 
/contrib/media/updf/apps/x11_image.c
0,0 → 1,697
/*
* 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 "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);
 
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 (fz_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] == NULL) {
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 = MIN(srch - ay, HEIGHT);
for (ax = 0; ax < srcw; ax += WIDTH)
{
w = MIN(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++) {
dst[x] = 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,
};
/contrib/media/updf/apps/x11_main.c
0,0 → 1,629
#include "fitz.h"
#include "mupdf.h"
#include "muxps.h"
#include "pdfapp.h"
 
#include <menuet/os.h>
 
// #include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
 
 
 
#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);
 
static Display *xdpy;
static Atom XA_TARGETS;
static Atom XA_TIMESTAMP;
static Atom XA_UTF8_STRING;
static Atom WM_DELETE_WINDOW;
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;
static int justcopied = 0;
static int 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;
 
/*
* Dialog boxes
*/
 
void winwarn(pdfapp_t *app, char *msg)
{
fprintf(stderr, "mupdf: %s\n", msg);
}
 
void winerror(pdfapp_t *app, fz_error error)
{
fz_catch(error, "aborting");
exit(1);
}
 
char *winpassword(pdfapp_t *app, char *filename)
{
char *r = password;
password = NULL;
return r;
}
 
/*
* X11 magic
*/
 
static void winopen(void)
{
 
/*
xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy),
10, 10, 200, 100, 1,
ximage_get_depth(),
InputOutput,
ximage_get_visual(),
0,
NULL); */
__menuet__define_window(10,10,200,200,
0,0,0);
}
 
void winclose(pdfapp_t *app)
{
closing = 1;
}
 
void wincursor(pdfapp_t *app, int curs)
{
}
 
void wintitle(pdfapp_t *app, char *s)
{
}
 
void winhelp(pdfapp_t *app)
{
}
 
void winresize(pdfapp_t *app, int w, int h)
{
 
}
 
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 x0 = gapp.panx;
int y0 = gapp.pany;
int x1 = gapp.panx + gapp.image->w;
int y1 = gapp.pany + gapp.image->h;
 
XSetForeground(xdpy, xgc, xbgcolor.pixel);
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, gapp.image->w, 2);
fillrect(x1, y0+2, 2, gapp.image->h);
 
if (gapp.iscopying || justcopied)
{
pdfapp_invert(&gapp, gapp.selr);
justcopied = 1;
}
 
pdfapp_inverthit(&gapp);
 
if (gapp.image->n == 4)
ximage_blit(xwin, xgc,
x0, y0,
gapp.image->samples,
0, 0,
gapp.image->w,
gapp.image->h,
gapp.image->w * gapp.image->n);
else if (gapp.image->n == 2)
{
int i = gapp.image->w*gapp.image->h;
unsigned char *color = malloc(i*4);
if (color != NULL)
{
unsigned char *s = gapp.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,
gapp.image->w,
gapp.image->h,
gapp.image->w * 4);
free(color);
}
}
 
pdfapp_inverthit(&gapp);
 
if (gapp.iscopying || justcopied)
{
pdfapp_invert(&gapp, gapp.selr);
justcopied = 1;
}
 
winblitsearch(app);
}
 
void winrepaint(pdfapp_t *app)
{
dirty = 1;
}
 
void winrepaintsearch(pdfapp_t *app)
{
dirtysearch = 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);
 
printf("drawstring '%s'\n", s);
}
 
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 windocopy(pdfapp_t *app)
{
/* 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 += runetochar(utf8, &ucs);
 
if (ucs < 256)
*latin1++ = ucs;
else
*latin1++ = '?';
}
 
*utf8 = 0;
*latin1 = 0;
 
XSetSelectionOwner(xdpy, XA_PRIMARY, xwin, copytime);
 
justcopied = 1;*/
}
 
void onselreq(Window requestor, Atom selection, Atom target, Atom property, Time time)
{
/* XEvent nevt;
 
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;
printf(" -> targets\n");
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, SelectionNotify, &nevt);
* */
}
 
void winreloadfile(pdfapp_t *app)
{
int fd;
 
pdfapp_close(app);
 
fd = open(filename, O_BINARY | O_RDONLY, 0666);
if (fd < 0)
winerror(app, fz_throw("cannot reload file '%s'", filename));
 
pdfapp_open(app, filename, fd, 1);
}
 
void winopenuri(pdfapp_t *app, char *buf)
{
/*
char *browser = getenv("BROWSER");
if (!browser)
browser = "open";
if (fork() == 0)
execlp(browser, browser, buf, (char*)0);
* */
}
 
static void onkey(int c)
{
/* if (justcopied)
{
justcopied = 0;
winrepaint(&gapp);
}
* */
 
pdfapp_onkey(&gapp, c);
}
 
static void onmouse(int x, int y, int btn, int modifiers, int state)
{
/* 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");
fprintf(stderr, "\t-A\tdisable accelerated functions\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 = 72;
int pageno = 1;
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();
 
filename = argv[fz_optind++];
 
if (argc - fz_optind == 1)
pageno = atoi(argv[fz_optind++]);
 
if (accelerate)
fz_accelerate();
 
winopen();
 
pdfapp_init(&gapp);
gapp.scrw = DisplayWidth(xdpy, xscr);
gapp.scrh = DisplayHeight(xdpy, xscr);
gapp.resolution = resolution;
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);
 
FD_ZERO(&fds);
FD_SET(x11fd, &fds);
 
signal(SIGHUP, signal_handler);
 
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;
}
/contrib/media/updf/apps/xpsdraw.c
0,0 → 1,366
#include "fitz.h"
#include "muxps.h"
 
#ifdef _MSC_VER
#include <winsock2.h>
#else
#include <sys/time.h>
#endif
 
char *output = NULL;
float resolution = 72;
 
int showxml = 0;
int showtext = 0;
int showtime = 0;
int showmd5 = 0;
int savealpha = 0;
int uselist = 1;
 
fz_colorspace *colorspace;
fz_glyph_cache *glyphcache;
char *filename;
 
struct {
int count, total;
int min, max;
int minpage, maxpage;
} timing;
 
static void die(fz_error error)
{
fz_catch(error, "aborting");
exit(1);
}
 
static void usage(void)
{
fprintf(stderr,
"usage: xpsdraw [options] input.xps [pages]\n"
"\t-o -\toutput filename (%%d for page number)\n"
"\t\tsupported formats: pgm, ppm, pam, png\n"
"\t-r -\tresolution in dpi (default: 72)\n"
"\t-a\tsave alpha channel (only pam and png)\n"
"\t-g\trender in grayscale\n"
"\t-m\tshow timing information\n"
"\t-t\tshow text (-tt for xml)\n"
"\t-x\tshow display list\n"
"\t-d\tdisable use of display list\n"
"\t-5\tshow md5 checksums\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
xps_run_page(xps_context *ctx, xps_page *page, fz_device *dev, fz_matrix ctm)
{
ctx->dev = dev;
xps_parse_fixed_page(ctx, ctm, page);
ctx->dev = NULL;
}
 
static void drawpage(xps_context *ctx, int pagenum)
{
xps_page *page;
fz_display_list *list;
fz_device *dev;
int start;
int code;
 
if (showtime)
{
start = gettime();
}
 
code = xps_load_page(&page, ctx, pagenum - 1);
if (code)
die(fz_rethrow(code, "cannot load page %d in file '%s'", pagenum, filename));
 
list = NULL;
 
if (uselist)
{
list = fz_new_display_list();
dev = fz_new_list_device(list);
xps_run_page(ctx, page, dev, fz_identity);
fz_free_device(dev);
}
 
if (showxml)
{
dev = fz_new_trace_device();
printf("<page number=\"%d\">\n", pagenum);
if (list)
fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
else
xps_run_page(ctx, page, dev, fz_identity);
printf("</page>\n");
fz_free_device(dev);
}
 
if (showtext)
{
fz_text_span *text = fz_new_text_span();
dev = fz_new_text_device(text);
if (list)
fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
else
xps_run_page(ctx, page, dev, fz_identity);
fz_free_device(dev);
printf("[Page %d]\n", pagenum);
if (showtext > 1)
fz_debug_text_span_xml(text);
else
fz_debug_text_span(text);
printf("\n");
fz_free_text_span(text);
}
 
if (showmd5 || showtime)
printf("page %s %d", filename, pagenum);
 
if (output || showmd5 || showtime)
{
float zoom;
fz_matrix ctm;
fz_rect rect;
fz_bbox bbox;
fz_pixmap *pix;
 
rect.x0 = rect.y0 = 0;
rect.x1 = page->width;
rect.y1 = page->height;
 
zoom = resolution / 96;
ctm = fz_translate(0, -page->height);
ctm = fz_concat(ctm, fz_scale(zoom, zoom));
bbox = fz_round_rect(fz_transform_rect(ctm, rect));
 
/* TODO: banded rendering and multi-page ppm */
 
pix = fz_new_pixmap_with_rect(colorspace, bbox);
 
if (savealpha)
fz_clear_pixmap(pix);
else
fz_clear_pixmap_with_color(pix, 255);
 
dev = fz_new_draw_device(glyphcache, pix);
if (list)
fz_execute_display_list(list, dev, ctm, bbox);
else
xps_run_page(ctx, page, dev, ctm);
fz_free_device(dev);
 
if (output)
{
char buf[512];
sprintf(buf, output, pagenum);
if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm"))
fz_write_pnm(pix, buf);
else if (strstr(output, ".pam"))
fz_write_pam(pix, buf, savealpha);
else if (strstr(output, ".png"))
fz_write_png(pix, buf, savealpha);
}
 
if (showmd5)
{
fz_md5 md5;
unsigned char digest[16];
int i;
 
fz_md5_init(&md5);
fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
fz_md5_final(&md5, digest);
 
printf(" ");
for (i = 0; i < 16; i++)
printf("%02x", digest[i]);
}
 
fz_drop_pixmap(pix);
}
 
if (list)
fz_free_display_list(list);
 
if (showtime)
{
int end = gettime();
int diff = end - start;
 
if (diff < timing.min)
{
timing.min = diff;
timing.minpage = pagenum;
}
if (diff > timing.max)
{
timing.max = diff;
timing.maxpage = pagenum;
}
timing.total += diff;
timing.count ++;
 
printf(" %dms", diff);
}
 
if (showmd5 || showtime)
printf("\n");
}
 
static void drawrange(xps_context *ctx, char *range)
{
int page, spage, epage;
char *spec, *dash;
 
spec = fz_strsep(&range, ",");
while (spec)
{
dash = strchr(spec, '-');
 
if (dash == spec)
spage = epage = xps_count_pages(ctx);
else
spage = epage = atoi(spec);
 
if (dash)
{
if (strlen(dash) > 1)
epage = atoi(dash + 1);
else
epage = xps_count_pages(ctx);
}
 
spage = CLAMP(spage, 1, xps_count_pages(ctx));
epage = CLAMP(epage, 1, xps_count_pages(ctx));
 
if (spage < epage)
for (page = spage; page <= epage; page++)
drawpage(ctx, page);
else
for (page = spage; page >= epage; page--)
drawpage(ctx, page);
 
spec = fz_strsep(&range, ",");
}
}
 
int main(int argc, char **argv)
{
int grayscale = 0;
int accelerate = 1;
xps_context *ctx;
int code;
int c;
 
while ((c = fz_getopt(argc, argv, "o:p:r:Aadgmtx5")) != -1)
{
switch (c)
{
case 'o': output = fz_optarg; break;
case 'r': resolution = atof(fz_optarg); break;
case 'A': accelerate = 0; break;
case 'a': savealpha = 1; break;
case 'm': showtime++; break;
case 't': showtext++; break;
case 'x': showxml++; break;
case '5': showmd5++; break;
case 'g': grayscale++; break;
case 'd': uselist = 0; break;
default: usage(); break;
}
}
 
if (fz_optind == argc)
usage();
 
if (!showtext && !showxml && !showtime && !showmd5 && !output)
{
printf("nothing to do\n");
exit(0);
}
 
if (accelerate)
fz_accelerate();
 
glyphcache = fz_new_glyph_cache();
 
colorspace = fz_device_rgb;
if (grayscale)
colorspace = fz_device_gray;
if (output && strstr(output, ".pgm"))
colorspace = fz_device_gray;
if (output && strstr(output, ".ppm"))
colorspace = fz_device_rgb;
 
timing.count = 0;
timing.total = 0;
timing.min = 1 << 30;
timing.max = 0;
timing.minpage = 0;
timing.maxpage = 0;
 
if (showxml)
printf("<?xml version=\"1.0\"?>\n");
 
while (fz_optind < argc)
{
filename = argv[fz_optind++];
 
code = xps_open_file(&ctx, filename);
if (code)
die(fz_rethrow(code, "cannot open document: %s", filename));
 
if (showxml)
printf("<document name=\"%s\">\n", filename);
 
if (fz_optind == argc || !isrange(argv[fz_optind]))
drawrange(ctx, "1-");
if (fz_optind < argc && isrange(argv[fz_optind]))
drawrange(ctx, argv[fz_optind++]);
 
if (showxml)
printf("</document>\n");
 
xps_free_context(ctx);
}
 
if (showtime)
{
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);
}
 
fz_free_glyph_cache(glyphcache);
 
return 0;
}