Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4679 → Rev 4680

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