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