static void merge_range(const char *range) { int start, end, i, count; pdf_graft_map *graft_map; count = pdf_count_pages(ctx, doc_src); graft_map = pdf_new_graft_map(ctx, doc_des); fz_try(ctx) { while ((range = fz_parse_page_range(ctx, range, &start, &end, count))) { if (start < end) for (i = start; i <= end; ++i) page_merge(i, -1, graft_map); else for (i = start; i >= end; --i) page_merge(i, -1, graft_map); } } fz_always(ctx) { pdf_drop_graft_map(ctx, graft_map); } fz_catch(ctx) { fz_rethrow(ctx); } }
static int _pdf_doc_count_pages(const struct _pdf_doc *self) { if (self->xref) return pdf_count_pages(self->xref); return 0; }
int j_mu_count_pages(void* p_ctx, void* p_doc) { fz_context* ctx = (fz_context*) p_ctx; pdf_document* doc = (pdf_document*) p_doc; int n = pdf_count_pages(ctx, doc); return n; }
PDFDocument* PDFDocument::Open(const std::string& path, int page_cache_size) { fz_context* context = fz_new_context(nullptr, nullptr, FZ_STORE_DEFAULT); pdf_document* raw_pdf_document = nullptr; fz_try(context) { raw_pdf_document = pdf_open_document(context, path.c_str()); if ((raw_pdf_document == nullptr) || (!pdf_count_pages(context, raw_pdf_document))) { fz_throw( context, FZ_ERROR_GENERIC, const_cast<char*>("Cannot open document \"%s\""), path.c_str()); } } fz_catch(context) { if (raw_pdf_document != nullptr) { pdf_drop_document(context, raw_pdf_document); } fz_drop_context(context); return nullptr; } PDFDocument* document = new PDFDocument(page_cache_size); document->_fz_context = context; document->_pdf_document = raw_pdf_document; return document; }
int pdfsign_main(int argc, char **argv) { fz_context *ctx; pdf_document *doc; char *password = ""; int i, n, c; pdf_page *page = NULL; while ((c = fz_getopt(argc, argv, "p:")) != -1) { switch (c) { case 'p': password = fz_optarg; break; default: usage(); break; } } if (argc - fz_optind < 1) usage(); filename = argv[fz_optind++]; ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); if (!ctx) { fprintf(stderr, "cannot initialize context\n"); exit(1); } fz_var(page); doc = pdf_open_document(ctx, filename); fz_try(ctx) { if (pdf_needs_password(ctx, doc)) if (!pdf_authenticate_password(ctx, doc, password)) fz_warn(ctx, "cannot authenticate password: %s", filename); n = pdf_count_pages(ctx, doc); for (i = 0; i < n; ++i) { page = pdf_load_page(ctx, doc, i); verify_page(ctx, doc, i, page); fz_drop_page(ctx, (fz_page*)page); page = NULL; } } fz_always(ctx) pdf_drop_document(ctx, doc); fz_catch(ctx) { fz_drop_page(ctx, (fz_page*)page); fprintf(stderr, "error verify signatures: %s\n", fz_caught_message(ctx)); } fz_flush_warnings(ctx); fz_drop_context(ctx); return 0; }
static void showinfo(char *filename, int show, char *pagelist) { int page, spage, epage; char *spec, *dash; int allpages; int pagecount; if (!doc) infousage(); allpages = !strcmp(pagelist, "1-"); pagecount = pdf_count_pages(doc); spec = fz_strsep(&pagelist, ","); while (spec && pagecount) { 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; spage = fz_clampi(spage, 1, pagecount); epage = fz_clampi(epage, 1, pagecount); if (allpages) printf("Retrieving info from pages %d-%d...\n", spage, epage); for (page = spage; page <= epage; page++) { gatherpageinfo(page, show); if (!allpages) { printf("Page %d:\n", page); printinfo(filename, show, page); printf("\n"); } } spec = fz_strsep(&pagelist, ","); } if (allpages) printinfo(filename, show, -1); }
void pdf_insert_page(pdf_document *doc, pdf_page *page, int at) { fz_context *ctx = doc->ctx; int count = pdf_count_pages(doc); pdf_obj *parent, *kids; pdf_obj *page_ref; int i; page_ref = pdf_new_ref(doc, page->me); fz_try(ctx) { if (count == 0) { /* TODO: create new page tree? */ fz_throw(ctx, FZ_ERROR_GENERIC, "empty page tree, cannot insert page"); } else if (at >= count) { if (at > count) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot insert page beyond end of page tree"); /* append after last page */ pdf_lookup_page_loc(doc, count - 1, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert(kids, page_ref, i + 1); } else { /* insert before found page */ pdf_lookup_page_loc(doc, at, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert(kids, page_ref, i); } pdf_dict_puts(page->me, "Parent", parent); /* Adjust page counts */ while (parent) { int count = pdf_to_int(pdf_dict_gets(parent, "Count")); pdf_dict_puts_drop(parent, "Count", pdf_new_int(doc, count + 1)); parent = pdf_dict_gets(parent, "Parent"); } } fz_always(ctx) { pdf_drop_obj(page_ref); } fz_catch(ctx) { fz_rethrow(ctx); } }
static void wmupdf_convert_pages_to_forms(pdf_document *xref,fz_context *ctx,int *srcpageused) { int i,pagecount; pagecount = pdf_count_pages(xref); for (i=0;i<=pagecount;i++) if (srcpageused[i]) wmupdf_convert_single_page_to_form(xref,ctx,i); }
void juggler_page_tree_changed(juggler_t *juggler) { juggler->pagecount = pdf_count_pages(juggler->ctx, juggler->pdf); size_t i; for(i = 0; i < RENDER_BUFFER_COUNT; i++) juggler->rendered[i].samples = NULL; juggler->recent_rendered = 0; juggler->sizes = NULL; get_all_pages_size(juggler); }
JNIEXPORT int JNICALL Java_com_artifex_mupdf_MuPDFCore_openFile(JNIEnv * env, jobject thiz, jstring jfilename) { const char *filename; int pages = 0; filename = (*env)->GetStringUTFChars(env, jfilename, NULL); if (filename == NULL) { LOGE("Failed to get filename"); return 0; } /* 128 MB store for low memory devices. Tweak as necessary. */ ctx = fz_new_context(NULL, NULL, 128 << 20); if (!ctx) { LOGE("Failed to initialise context"); return 0; } xref = NULL; fz_try(ctx) { colorspace = fz_device_rgb; LOGE("Opening document..."); fz_try(ctx) { xref = pdf_open_document(ctx, filename); } fz_catch(ctx) { fz_throw(ctx, "Cannot open document: '%s'\n", filename); } pages = pdf_count_pages(xref); LOGE("Done! %d pages", pages); } fz_catch(ctx) { LOGE("Failed: %s", ctx->error->message); pdf_close_document(xref); xref = NULL; fz_free_context(ctx); ctx = NULL; } return pages; }
void benchfile(char *pdffilename, int loadonly, int pageNo) { pdf_document *xref = NULL; mstimer timer; int page_count; int curpage; fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); if (!ctx) { logbench("Error: fz_new_context() failed\n"); return; } logbench("Starting: %s\n", pdffilename); timerstart(&timer); fz_var(xref); fz_try(ctx) { xref = openxref(ctx, pdffilename); } fz_catch(ctx) { goto Exit; } timerstop(&timer); logbench("load: %.2f ms\n", timeinms(&timer)); page_count = pdf_count_pages(xref); logbench("page count: %d\n", page_count); if (loadonly) goto Exit; for (curpage = 1; curpage <= page_count; curpage++) { pdf_page *page; if ((-1 != pageNo) && (pageNo != curpage)) continue; page = benchloadpage(ctx, xref, curpage); if (page) { benchrenderpage(ctx, xref, page, curpage); pdf_free_page(xref, page); } } Exit: logbench("Finished: %s\n", pdffilename); pdf_close_document(xref); fz_free_context(ctx); }
static int showpages(fz_context *ctx, pdf_document *doc, fz_output *out, char *pagelist) { int page, spage, epage; char *spec, *dash; int pagecount; int ret = 0; if (!doc) infousage(); pagecount = pdf_count_pages(ctx, doc); spec = fz_strsep(&pagelist, ","); while (spec && pagecount) { 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; spage = fz_clampi(spage, 1, pagecount); epage = fz_clampi(epage, 1, pagecount); for (page = spage; page <= epage; page++) { ret |= showpage(ctx, doc, out, page); } spec = fz_strsep(&pagelist, ","); } return ret; }
static int showpages(fz_context *ctx, pdf_document *doc, fz_output *out, const char *pagelist) { int page, spage, epage; int pagecount; int ret = 0; if (!doc) infousage(); pagecount = pdf_count_pages(ctx, doc); while ((pagelist = fz_parse_page_range(ctx, pagelist, &spage, &epage, pagecount))) { if (spage > epage) page = spage, spage = epage, epage = page; for (page = spage; page <= epage; page++) ret |= showpage(ctx, doc, out, page); } return ret; }
pdf_document *openxref(fz_context *ctx, char *filename) { pdf_document *xref = pdf_open_document(ctx, filename); fz_try(ctx) { if (pdf_needs_password(xref)) { logbench("Warning: password protected document\n"); fz_throw(ctx, "document requires password"); } pdf_count_pages(xref); } fz_catch(ctx) { pdf_close_document(xref); fz_rethrow(ctx); } return xref; }
int pdfinfo_main(int argc, char **argv) { enum { NO_FILE_OPENED, NO_INFO_GATHERED, INFO_SHOWN } state; 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(); ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); if (!ctx) { fprintf(stderr, "cannot initialise context\n"); exit(1); } state = NO_FILE_OPENED; while (fz_optind < argc) { if (state == NO_FILE_OPENED || !arg_is_page_range(argv[fz_optind])) { if (state == NO_INFO_GATHERED) { showinfo(filename, show, "1-"); } closexref(); filename = argv[fz_optind]; printf("%s:\n", filename); doc = pdf_open_document_no_run(ctx, filename); if (pdf_needs_password(doc)) if (!pdf_authenticate_password(doc, password)) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", filename); pagecount = pdf_count_pages(doc); 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(); fz_free_context(ctx); return 0; }
static void retainpages(fz_context *ctx, globals *glo, int argc, char **argv) { pdf_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests; pdf_document *doc = glo->doc; int argidx = 0; pdf_obj *names_list = NULL; pdf_obj *outlines; int pagecount; int i; int *page_object_nums; /* Keep only pages/type and (reduced) dest entries to avoid * references to unretained pages */ oldroot = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); pages = pdf_dict_get(ctx, oldroot, PDF_NAME_Pages); olddests = pdf_load_name_tree(ctx, doc, PDF_NAME_Dests); outlines = pdf_dict_get(ctx, oldroot, PDF_NAME_Outlines); root = pdf_new_dict(ctx, doc, 3); pdf_dict_put(ctx, root, PDF_NAME_Type, pdf_dict_get(ctx, oldroot, PDF_NAME_Type)); pdf_dict_put(ctx, root, PDF_NAME_Pages, pdf_dict_get(ctx, oldroot, PDF_NAME_Pages)); pdf_dict_put(ctx, root, PDF_NAME_Outlines, outlines); pdf_update_object(ctx, doc, pdf_to_num(ctx, oldroot), root); /* Create a new kids array with only the pages we want to keep */ parent = pdf_new_indirect(ctx, doc, pdf_to_num(ctx, pages), pdf_to_gen(ctx, pages)); kids = pdf_new_array(ctx, doc, 1); /* Retain pages specified */ while (argc - argidx) { int page, spage, epage; char *spec, *dash; char *pagelist = argv[argidx]; pagecount = pdf_count_pages(ctx, doc); 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; } spage = fz_clampi(spage, 1, pagecount); epage = fz_clampi(epage, 1, pagecount); if (spage < epage) for (page = spage; page <= epage; ++page) retainpage(ctx, doc, parent, kids, page); else for (page = spage; page >= epage; --page) retainpage(ctx, doc, parent, kids, page); spec = fz_strsep(&pagelist, ","); } argidx++; } pdf_drop_obj(ctx, parent); /* Update page count and kids array */ countobj = pdf_new_int(ctx, doc, pdf_array_len(ctx, kids)); pdf_dict_put(ctx, pages, PDF_NAME_Count, countobj); pdf_drop_obj(ctx, countobj); pdf_dict_put(ctx, pages, PDF_NAME_Kids, kids); pdf_drop_obj(ctx, kids); /* Force the next call to pdf_count_pages to recount */ glo->doc->page_count = 0; pagecount = pdf_count_pages(ctx, doc); page_object_nums = fz_calloc(ctx, pagecount, sizeof(*page_object_nums)); for (i = 0; i < pagecount; i++) { pdf_obj *pageref = pdf_lookup_page_obj(ctx, doc, i); page_object_nums[i] = pdf_to_num(ctx, pageref); } /* If we had an old Dests tree (now reformed as an olddests * dictionary), keep any entries in there that point to * valid pages. This may mean we keep more than we need, but * it's safe at least. */ if (olddests) { pdf_obj *names = pdf_new_dict(ctx, doc, 1); pdf_obj *dests = pdf_new_dict(ctx, doc, 1); int len = pdf_dict_len(ctx, olddests); names_list = pdf_new_array(ctx, doc, 32); for (i = 0; i < len; i++) { pdf_obj *key = pdf_dict_get_key(ctx, olddests, i); pdf_obj *val = pdf_dict_get_val(ctx, olddests, i); pdf_obj *dest = pdf_dict_get(ctx, val, PDF_NAME_D); dest = pdf_array_get(ctx, dest ? dest : val, 0); if (dest_is_valid_page(ctx, dest, page_object_nums, pagecount)) { pdf_obj *key_str = pdf_new_string(ctx, doc, pdf_to_name(ctx, key), strlen(pdf_to_name(ctx, key))); pdf_array_push(ctx, names_list, key_str); pdf_array_push(ctx, names_list, val); pdf_drop_obj(ctx, key_str); } } pdf_dict_put(ctx, dests, PDF_NAME_Names, names_list); pdf_dict_put(ctx, names, PDF_NAME_Dests, dests); pdf_dict_put(ctx, root, PDF_NAME_Names, names); pdf_drop_obj(ctx, names); pdf_drop_obj(ctx, dests); pdf_drop_obj(ctx, olddests); } /* Edit each pages /Annot list to remove any links that point to * nowhere. */ for (i = 0; i < pagecount; i++) { pdf_obj *pageref = pdf_lookup_page_obj(ctx, doc, i); pdf_obj *pageobj = pdf_resolve_indirect(ctx, pageref); pdf_obj *annots = pdf_dict_get(ctx, pageobj, PDF_NAME_Annots); int len = pdf_array_len(ctx, annots); int j; for (j = 0; j < len; j++) { pdf_obj *o = pdf_array_get(ctx, annots, j); if (!pdf_name_eq(ctx, pdf_dict_get(ctx, o, PDF_NAME_Subtype), PDF_NAME_Link)) continue; if (!dest_is_valid(ctx, o, pagecount, page_object_nums, names_list)) { /* Remove this annotation */ pdf_array_delete(ctx, annots, j); j--; } } } if (strip_outlines(ctx, doc, outlines, pagecount, page_object_nums, names_list) == 0) { pdf_dict_del(ctx, root, PDF_NAME_Outlines); } fz_free(ctx, page_object_nums); pdf_drop_obj(ctx, names_list); pdf_drop_obj(ctx, root); }
static void retainpages(int argc, char **argv) { fz_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests; /* Keep only pages/type and (reduced) dest entries to avoid * references to unretained pages */ oldroot = fz_dict_gets(xref->trailer, "Root"); pages = fz_dict_gets(oldroot, "Pages"); olddests = pdf_load_name_tree(xref, "Dests"); root = fz_new_dict(ctx, 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(ctx, fz_to_num(pages), fz_to_gen(pages), xref); kids = fz_new_array(ctx, 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(ctx, fz_array_len(kids)); fz_dict_puts(pages, "Count", countobj); fz_drop_obj(countobj); fz_dict_puts(pages, "Kids", kids); fz_drop_obj(kids); /* Also preserve the (partial) Dests name tree */ if (olddests) { int i; fz_obj *names = fz_new_dict(ctx, 1); fz_obj *dests = fz_new_dict(ctx, 1); fz_obj *names_list = fz_new_array(ctx, 32); for (i = 0; i < fz_dict_len(olddests); i++) { fz_obj *key = fz_dict_get_key(olddests, i); fz_obj *val = fz_dict_get_val(olddests, i); fz_obj *key_str = fz_new_string(ctx, fz_to_name(key), strlen(fz_to_name(key))); fz_obj *dest = fz_dict_gets(val, "D"); dest = fz_array_get(dest ? dest : val, 0); if (fz_array_contains(fz_dict_gets(pages, "Kids"), dest)) { fz_array_push(names_list, key_str); fz_array_push(names_list, val); } fz_drop_obj(key_str); } root = fz_dict_gets(xref->trailer, "Root"); fz_dict_puts(dests, "Names", names_list); fz_dict_puts(names, "Dests", dests); fz_dict_puts(root, "Names", names); fz_drop_obj(names); fz_drop_obj(dests); fz_drop_obj(names_list); fz_drop_obj(olddests); } }
void pdf_insert_page(pdf_document *doc, pdf_page *page, int at) { fz_context *ctx = doc->ctx; int count = pdf_count_pages(doc); pdf_obj *parent, *kids; pdf_obj *page_ref; int i; page_ref = pdf_new_ref(doc, page->me); fz_try(ctx) { if (count == 0) { pdf_obj *root = pdf_dict_gets(pdf_trailer(doc), "Root"); parent = pdf_dict_gets(root, "Pages"); if (!parent) fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot find page tree"); kids = pdf_dict_gets(parent, "Kids"); if (!kids) fz_throw(doc->ctx, FZ_ERROR_GENERIC, "malformed page tree"); pdf_array_insert(kids, page_ref, 0); } else if (at >= count) { if (at == INT_MAX) at = count; if (at > count) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot insert page beyond end of page tree"); /* append after last page */ pdf_lookup_page_loc(doc, count - 1, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert(kids, page_ref, i + 1); } else { /* insert before found page */ pdf_lookup_page_loc(doc, at, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert(kids, page_ref, i); } pdf_dict_puts(page->me, "Parent", parent); /* Adjust page counts */ while (parent) { int count = pdf_to_int(pdf_dict_gets(parent, "Count")); pdf_dict_puts_drop(parent, "Count", pdf_new_int(doc, count + 1)); parent = pdf_dict_gets(parent, "Parent"); } } fz_always(ctx) { pdf_drop_obj(page_ref); } fz_catch(ctx) { fz_rethrow(ctx); } doc->page_count = 0; /* invalidate cached value */ }
static int wmupdf_pdfdoc_newpages(pdf_document *xref,fz_context *ctx,WPDFPAGEINFO *pageinfo, int use_forms,FILE *out) { static char *funcname="wmupdf_pdfdoc_newpages"; pdf_obj *root,*oldroot,*pages,*kids,*countobj,*parent,*olddests; pdf_obj *srcpageobj,*srcpagecontents; pdf_obj *destpageobj,*destpagecontents,*destpageresources; double srcx0,srcy0; int qref,i,i0,pagecount,srccount,destpageref,nbb; int *srcpageused; char *bigbuf; double srcpagerot; /* Avoid compiler warning */ destpageref = 0; destpageobj = NULL; srcx0=srcy0=0.; /* Keep only pages/type and (reduced) dest entries to avoid references to unretained pages */ pagecount = pdf_count_pages(xref); if (use_forms) { willus_mem_alloc_warn((void **)&srcpageused,sizeof(int)*(pagecount+1),funcname,10); /* Mark all source pages as "not done" */ for (i=0;i<=pagecount;i++) srcpageused[i]=0; nbb=4096; willus_mem_alloc_warn((void **)&bigbuf,nbb,funcname,10); bigbuf[0]='\0'; } oldroot = pdf_dict_gets(xref->trailer,"Root"); /* ** pages points to /Pages object in PDF file. ** Has: /Type /Pages, /Count <numpages>, /Kids [ obj obj obj obj ] */ pages = pdf_dict_gets(oldroot,"Pages"); olddests = pdf_load_name_tree(xref,"Dests"); /* ** Create new root object with only /Pages and /Type (and reduced dest entries) ** to avoid references to unretained pages. */ root = pdf_new_dict(ctx,4); pdf_dict_puts(root,"Type",pdf_dict_gets(oldroot,"Type")); pdf_dict_puts(root,"Pages",pages); pdf_update_object(xref,pdf_to_num(oldroot),root); pdf_drop_obj(root); /* Parent indirectly references the /Pages object in the file */ /* (Each new page we create has to point to this.) */ parent = pdf_new_indirect(ctx, pdf_to_num(pages), pdf_to_gen(pages), xref); /* Create a new kids array with only the pages we want to keep */ kids = pdf_new_array(ctx, 1); qref=0; /* Avoid compiler warnings */ destpageresources=NULL; destpagecontents=NULL; srcpagecontents=NULL; srcpagerot=0.; for (i=0;i<=pageinfo->boxes.n;i++) if (pageinfo->boxes.box[i].dstpage>0) break; if (i>0) { if (i<pageinfo->boxes.n) memmove(&pageinfo->boxes.box[0],&pageinfo->boxes.box[i],sizeof(WPDFBOX)*pageinfo->boxes.n-i); pageinfo->boxes.n -= i; } /* Walk through PFDBOXES array */ for (i=srccount=i0=0;i<=pageinfo->boxes.n;i++) { WPDFBOX *box; int j,k,newsrc; static char buf[512]; pdf_obj *s1indirect,*qindirect,*rotobj; static double cpm[3][3],m[3][3],m1[3][3]; static double xclip[4],yclip[4]; /* printf("box[%d]\n",i); if (i<pageinfo->boxes.n) { box=&pageinfo->boxes.box[i]; printf(" srcpage=%d, dstpage=%d\n",box->srcbox.pageno,box->dstpage); printf(" x0=%g, y0=%g\n",box->x0,box->y0); printf(" w=%g, h=%g\n",box->w,box->h); printf(" x1=%g, y1=%g\n",box->x1,box->y1); printf(" sr=%g, dr=%g\n",box->srcrot_deg,box->dstrot_deg); printf(" scale=%g\n",box->scale); } */ /* Check to see if we are done with an output page */ if (srccount>0 && (i==pageinfo->boxes.n || (i>0 && pageinfo->boxes.box[i].dstpage!=pageinfo->boxes.box[i-1].dstpage))) { pdf_obj *newpageref; /* ** Store destination page into document structure */ /* printf(" ADDING NEW PAGE. (srccount=%d)\n",srccount); */ if (use_forms) { pdf_obj *dest_stream; /* Create new object in document for destination page stream */ dest_stream = pdf_new_indirect(ctx,new_stream_object(xref,ctx,bigbuf), 0,(void *)xref); /* Store this into the destination page contents array */ pdf_array_push(destpagecontents,dest_stream); pdf_drop_obj(dest_stream); } newpageref=pdf_new_indirect(ctx,destpageref,0,(void *)xref); /* Reference parent list of pages */ pdf_dict_puts(destpageobj,"Parent",parent); pdf_dict_puts(destpageobj,"Contents",destpagecontents); pdf_dict_puts(destpageobj,"Resources",destpageresources); /* Store page object in document's kids array */ pdf_array_push(kids,newpageref); /* Update document with new page */ pdf_update_object(xref,destpageref,destpageobj); /* Clean up */ pdf_drop_obj(newpageref); pdf_drop_obj(destpageresources); pdf_drop_obj(destpagecontents); pdf_drop_obj(destpageobj); /* Reset source page and index to start of new destination page */ i0=i; srccount=0; } /* Quit loop if beyond last box */ if (i>=pageinfo->boxes.n) break; box=&pageinfo->boxes.box[i]; if (box->srcbox.pageno<1 || box->srcbox.pageno>pagecount) continue; /* Is this a source page we haven't processed yet (for this destination page)? */ for (newsrc=1,j=i0;j<i;j++) { if (pageinfo->boxes.box[j].srcbox.pageno==box->srcbox.pageno) { newsrc=0; break; } } if (newsrc) { double v[4]; srccount++; if (use_forms) srcpageused[box->srcbox.pageno]=1; /* printf(" NEW SOURCE PAGE (srccount=%d)\n",srccount); */ if (srccount==1) { /* ** Start a new destination page. ** ** Each new page object is a dict type with: ** /Type /Page ** /Contents (array of objects) ** /Resources (dict) ** /MediaBox [0 0 612 792] ** /Parent <PagesObj> ** [Can have /Rotate 90, for example.] ** */ /* printf(" (STARTING NEW DEST. PAGE)\n"); */ destpageobj=start_new_destpage(ctx,box->dst_width_pts,box->dst_height_pts); destpageresources=pdf_new_dict(ctx,1); if (use_forms) pdf_dict_puts(destpageresources,"XObject",pdf_new_dict(ctx,1)); destpageref=pdf_create_object(xref); destpagecontents=pdf_new_array(ctx,1); /* Init the destination page stream for forms */ if (use_forms) bigbuf[0]='\0'; } /* New source page, so get the source page objects */ srcpageobj = xref->page_objs[box->srcbox.pageno-1]; wmupdf_page_bbox(srcpageobj,v); srcx0=v[0]; srcy0=v[1]; /* printf("SRCX0=%g, SRCY0=%g\n",srcx0,srcy0); */ rotobj=pdf_dict_gets(srcpageobj,"Rotate"); srcpagerot = rotobj!=NULL ? pdf_to_real(rotobj) : 0.; /* printf("Page rotation = %g\n",srcpagerot); */ srcpagecontents=pdf_dict_gets(srcpageobj,"Contents"); /* if (pdf_is_array(srcpagecontents)) { int k; printf(" source page contents = array.\n"); for (k=0;k<pdf_array_len(srcpagecontents);k++) { pdf_obj *obj; obj=pdf_array_get(srcpagecontents,k); if (pdf_is_indirect(obj)) { printf(" contents[%d] = indirect (%d)\n",k,pdf_to_num(obj)); pdf_resolve_indirect(obj); } } } */ if (use_forms) { pdf_obj *xobjdict; int pageno; xobjdict=pdf_dict_gets(destpageresources,"XObject"); pageno=box->srcbox.pageno; pdf_dict_puts(xobjdict,xobject_name(pageno),xref->page_refs[pageno-1]); pdf_dict_puts(destpageresources,"XObject",xobjdict); } else { pdf_obj *srcpageresources; /* Merge source page resources into destination page resources */ srcpageresources=pdf_dict_gets(srcpageobj,"Resources"); /* printf("box->dstpage=%d, srcpage=%d (ind.#=%d)\n",box->dstpage,box->srcbox.pageno,pdf_to_num(xref->page_refs[box->srcbox.pageno-1])); */ wmupdf_dict_merge(ctx,"Resources",destpageresources,srcpageresources); } } /* ** Process this source box: ** ** Create a tranformation matrix and clipping path to only show the ** desired part of the source page at the appropriate place on the ** destination page. ** ** How the tranformation matrix works: ** - Translations shall be specified as [ 1 0 0 1 tx ty ], where tx and ty ** shall be the distances to translate the origin of the coordinate system ** in the horizontal and vertical dimensions, respectively. ** ** - Scaling shall be obtained by [ sx 0 0 sy 0 0 ]. This scales the coordinates ** so that 1 unit in the horizontal and vertical dimensions of the new coordinate ** system is the same size as sx and sy units, respectively, in the previous ** coordinate system. ** ** - Rotations shall be produced by [ cos q sin q -sin q cos q 0 0 ], which has the ** effect of rotating the coordinate system axes by an angle q counter-clockwise. ** ** - Skew shall be specified by [ 1 tan a tan b 1 0 0 ], which skews the x axis by ** an angle a and the y axis by an angle b. ** */ wpdfbox_determine_original_source_position(box); /* printf("Before unrotate.\n"); printf("box->srcrot=%g\n",box->srcrot_deg); printf("box->x0=%g, box->y0=%g\n",box->x0,box->y0); printf("box->w=%g, box->h=%g\n",box->w,box->h); printf("box->pw=%g, box->ph=%g\n",box->src_width_pts,box->src_height_pts); */ if (fabs(srcpagerot) > 1.0e-4) wpdfbox_unrotate(box,srcpagerot); /* printf("box->srcrot=%g\n",box->srcrot_deg); printf("box->x0=%g, box->y0=%g\n",box->x0,box->y0); printf("box->w=%g, box->h=%g\n",box->w,box->h); printf("box->pw=%g, box->ph=%g\n",box->src_width_pts,box->src_height_pts); */ matrix_unity(m,1.); /* printf("xfmatrix = [ %9.6f %9.6f %9.6f ]\n" " [ %9.6f %9.6f %9.6f ]\n" " [ %9.6f %9.6f %9.6f ]\n", m[0][0],m[0][1],m[0][2], m[1][0],m[1][1],m[1][2], m[2][0],m[2][1],m[2][2]); */ matrix_translate(m1,-box->x0-srcx0,-box->y0-srcy0); matrix_mul(m,m1); matrix_rotate(m1,-box->srcrot_deg+box->dstrot_deg); matrix_mul(m,m1); matrix_unity(m1,box->scale); matrix_mul(m,m1); matrix_translate(m1,box->x1,box->y1); matrix_mul(m,m1); matrix_zero_round(m); matrix_rotate(cpm,box->srcrot_deg); matrix_translate(m1,box->x0+srcx0,box->y0+srcy0); matrix_mul(cpm,m1); /* printf("Clip matrix:\n"); printf("xfmatrix = [ %9.6f %9.6f %9.6f ]\n" " [ %9.6f %9.6f %9.6f ]\n" " [ %9.6f %9.6f %9.6f ]\n", cpm[0][0],cpm[0][1],cpm[0][2], cpm[1][0],cpm[1][1],cpm[1][2], cpm[2][0],cpm[2][1],cpm[2][2]); */ set_clip_array(xclip,yclip,box->srcrot_deg,box->w,box->h); for (k=0;k<4;k++) matrix_xymul(cpm,&xclip[k],&yclip[k]); /* printf("Clip path:\n %7.2f %7.2f\n %7.2f,%7.2f\n %7.2f,%7.2f\n" " %7.2f %7.2f\n %7.2f,%7.2f\n", xclip[0],yclip[0],xclip[1],yclip[1],xclip[2],yclip[2], xclip[3],yclip[3],xclip[0],yclip[0]); */ strcpy(buf,"q"); for (k=0;k<=2;k++) { cat_pdf_double(buf,m[k][0]); cat_pdf_double(buf,m[k][1]); } strcat(buf," cm"); for (k=0;k<=4;k++) { cat_pdf_double(buf,xclip[k&3]); cat_pdf_double(buf,yclip[k&3]); strcat(buf,k==0 ? " m" : " l"); } strcat(buf," W n"); if (use_forms) { /* FORM METHOD */ sprintf(&buf[strlen(buf)]," /%s Do Q\n",xobject_name(box->srcbox.pageno)); if (strlen(bigbuf)+strlen(buf) > nbb) { int newsize; newsize=nbb*2; willus_mem_realloc_robust_warn((void **)&bigbuf,newsize,nbb,funcname,10); nbb=newsize; } strcat(bigbuf,buf); } else { /* NO-FORMS METHOD */ strcat(buf,"\n"); /* Create new objects in document for tx matrix and restore matrix */ s1indirect = pdf_new_indirect(ctx,new_stream_object(xref,ctx,buf),0,(void *)xref); if (qref==0) qref=new_stream_object(xref,ctx,"Q\n"); qindirect = pdf_new_indirect(ctx,qref,0,(void *)xref); /* Store this region into the destination page contents array */ pdf_array_push(destpagecontents,s1indirect); if (pdf_is_array(srcpagecontents)) { int k; for (k=0;k<pdf_array_len(srcpagecontents);k++) pdf_array_push(destpagecontents,pdf_array_get(srcpagecontents,k)); } else pdf_array_push(destpagecontents,srcpagecontents); pdf_array_push(destpagecontents,qindirect); pdf_drop_obj(s1indirect); pdf_drop_obj(qindirect); } } pdf_drop_obj(parent); /* For forms, convert all original source pages to XObject Forms */ if (use_forms) wmupdf_convert_pages_to_forms(xref,ctx,srcpageused); /* Update page count and kids array */ countobj = pdf_new_int(ctx, pdf_array_len(kids)); pdf_dict_puts(pages, "Count", countobj); pdf_drop_obj(countobj); pdf_dict_puts(pages, "Kids", kids); pdf_drop_obj(kids); /* Also preserve the (partial) Dests name tree */ if (olddests) wmupdf_preserve_old_dests(olddests,ctx,xref,pages); if (use_forms) { /* Free memory */ willus_mem_free((double **)&bigbuf,funcname); willus_mem_free((double **)&srcpageused,funcname); } return(0); }
static void retainpages(fz_context *ctx, globals *glo, int argc, char **argv) { pdf_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests; pdf_document *doc = glo->doc; int argidx = 0; pdf_obj *names_list = NULL; int pagecount; int i; /* Keep only pages/type and (reduced) dest entries to avoid * references to unretained pages */ oldroot = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); pages = pdf_dict_get(ctx, oldroot, PDF_NAME_Pages); olddests = pdf_load_name_tree(ctx, doc, PDF_NAME_Dests); root = pdf_new_dict(ctx, doc, 2); pdf_dict_put(ctx, root, PDF_NAME_Type, pdf_dict_get(ctx, oldroot, PDF_NAME_Type)); pdf_dict_put(ctx, root, PDF_NAME_Pages, pdf_dict_get(ctx, oldroot, PDF_NAME_Pages)); pdf_update_object(ctx, doc, pdf_to_num(ctx, oldroot), root); pdf_drop_obj(ctx, root); /* Create a new kids array with only the pages we want to keep */ parent = pdf_new_indirect(ctx, doc, pdf_to_num(ctx, pages), pdf_to_gen(ctx, pages)); kids = pdf_new_array(ctx, doc, 1); /* Retain pages specified */ while (argc - argidx) { int page, spage, epage; char *spec, *dash; char *pagelist = argv[argidx]; pagecount = pdf_count_pages(ctx, doc); 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; } spage = fz_clampi(spage, 1, pagecount); epage = fz_clampi(epage, 1, pagecount); if (spage < epage) for (page = spage; page <= epage; ++page) retainpage(ctx, doc, parent, kids, page); else for (page = spage; page >= epage; --page) retainpage(ctx, doc, parent, kids, page); spec = fz_strsep(&pagelist, ","); } argidx++; } pdf_drop_obj(ctx, parent); /* Update page count and kids array */ countobj = pdf_new_int(ctx, doc, pdf_array_len(ctx, kids)); pdf_dict_put(ctx, pages, PDF_NAME_Count, countobj); pdf_drop_obj(ctx, countobj); pdf_dict_put(ctx, pages, PDF_NAME_Kids, kids); pdf_drop_obj(ctx, kids); /* Also preserve the (partial) Dests name tree */ if (olddests) { pdf_obj *names = pdf_new_dict(ctx, doc, 1); pdf_obj *dests = pdf_new_dict(ctx, doc, 1); int len = pdf_dict_len(ctx, olddests); names_list = pdf_new_array(ctx, doc, 32); for (i = 0; i < len; i++) { pdf_obj *key = pdf_dict_get_key(ctx, olddests, i); pdf_obj *val = pdf_dict_get_val(ctx, olddests, i); pdf_obj *dest = pdf_dict_get(ctx, val, PDF_NAME_D); dest = pdf_array_get(ctx, dest ? dest : val, 0); if (pdf_array_contains(ctx, pdf_dict_get(ctx, pages, PDF_NAME_Kids), dest)) { pdf_obj *key_str = pdf_new_string(ctx, doc, pdf_to_name(ctx, key), strlen(pdf_to_name(ctx, key))); pdf_array_push(ctx, names_list, key_str); pdf_array_push(ctx, names_list, val); pdf_drop_obj(ctx, key_str); } } root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); pdf_dict_put(ctx, dests, PDF_NAME_Names, names_list); pdf_dict_put(ctx, names, PDF_NAME_Dests, dests); pdf_dict_put(ctx, root, PDF_NAME_Names, names); pdf_drop_obj(ctx, names); pdf_drop_obj(ctx, dests); pdf_drop_obj(ctx, names_list); pdf_drop_obj(ctx, olddests); } /* Force the next call to pdf_count_pages to recount */ glo->doc->page_count = 0; /* Edit each pages /Annot list to remove any links that point to * nowhere. */ pagecount = pdf_count_pages(ctx, doc); for (i = 0; i < pagecount; i++) { pdf_obj *pageref = pdf_lookup_page_obj(ctx, doc, i); pdf_obj *pageobj = pdf_resolve_indirect(ctx, pageref); pdf_obj *annots = pdf_dict_get(ctx, pageobj, PDF_NAME_Annots); int len = pdf_array_len(ctx, annots); int j; for (j = 0; j < len; j++) { pdf_obj *o = pdf_array_get(ctx, annots, j); pdf_obj *p; if (!pdf_name_eq(ctx, pdf_dict_get(ctx, o, PDF_NAME_Subtype), PDF_NAME_Link)) continue; p = pdf_dict_get(ctx, o, PDF_NAME_A); if (!pdf_name_eq(ctx, pdf_dict_get(ctx, p, PDF_NAME_S), PDF_NAME_GoTo)) continue; if (string_in_names_list(ctx, pdf_dict_get(ctx, p, PDF_NAME_D), names_list)) continue; /* FIXME: Should probably look at Next too */ /* Remove this annotation */ pdf_array_delete(ctx, annots, j); j--; } } }
void pdfapp_open(pdfapp_t *app, char *filename) { #if 0 fz_error error; fz_obj *obj; char *password = ""; #else fz_error error; fz_stream *file; char *password = ""; fz_obj *obj; fz_obj *info; int fd; fd = open(filename, O_BINARY | O_RDONLY, 0666); if (fd < 0) fprintf(stderr, "error, file %s does not exist\n", filename); #endif /* * Open PDF and load xref table */ app->filename = filename; #if 0 app->xref = pdf_newxref(); error = pdf_loadxref(app->xref, filename); if (error) { fz_catch(error, "trying to air"); error = pdf_repairxref(app->xref, filename); if (error) pdfapp_error(app, error); } error = pdf_decryptxref(app->xref); if (error) pdfapp_error(app, error); #else file = fz_open_fd(fd); error = pdf_open_xref_with_stream(&app->xref, file, NULL); if (error) pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename)); fz_close(file); #endif /* * 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 * TODO: move this into mupdf library */ #if 0 obj = fz_dictgets(app->xref->trailer, "Root"); app->xref->root = fz_resolveindirect(obj); if (!app->xref->root) pdfapp_error(app, fz_throw("syntaxerror: missing Root object")); fz_keepobj(app->xref->root); obj = fz_dictgets(app->xref->trailer, "Info"); app->xref->info = fz_resolveindirect(obj); if (!app->xref->info) pdfapp_warn(app, "Could not load PDF meta information."); if (app->xref->info) fz_keepobj(app->xref->info); /*app->outline = pdf_loadoutline(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; if (app->xref->info) { obj = fz_dictgets(app->xref->info, "Title"); if (obj) { app->doctitle = pdf_toutf8(obj); } } #else 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); } #endif /* * Start at first page */ #if 0 app->pagecount = pdf_getpagecount(app->xref); #else error = pdf_load_page_tree(app->xref); if (error) pdfapp_error(app, fz_rethrow(error, "cannot load page tree")); app->pagecount = pdf_count_pages(app->xref); #endif app->rotate = 0; }
static void decimatepages(fz_context *ctx, pdf_document *doc) { pdf_obj *oldroot, *root, *pages, *kids, *parent; int num_pages = pdf_count_pages(ctx, doc); int page, kidcount; oldroot = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root); pages = pdf_dict_get(ctx, oldroot, PDF_NAME_Pages); root = pdf_new_dict(ctx, doc, 2); pdf_dict_put(ctx, root, PDF_NAME_Type, pdf_dict_get(ctx, oldroot, PDF_NAME_Type)); pdf_dict_put(ctx, root, PDF_NAME_Pages, pdf_dict_get(ctx, oldroot, PDF_NAME_Pages)); pdf_update_object(ctx, doc, pdf_to_num(ctx, oldroot), root); pdf_drop_obj(ctx, root); /* Create a new kids array with our new pages in */ parent = pdf_new_indirect(ctx, doc, pdf_to_num(ctx, pages), pdf_to_gen(ctx, pages)); kids = pdf_new_array(ctx, doc, 1); kidcount = 0; for (page=0; page < num_pages; page++) { pdf_page *page_details = pdf_load_page(ctx, doc, page); int xf = x_factor, yf = y_factor; int x, y; float w = page_details->mediabox.x1 - page_details->mediabox.x0; float h = page_details->mediabox.y1 - page_details->mediabox.y0; if (xf == 0 && yf == 0) { /* Nothing specified, so split along the long edge */ if (w > h) xf = 2, yf = 1; else xf = 1, yf = 2; } else if (xf == 0) xf = 1; else if (yf == 0) yf = 1; for (y = yf-1; y >= 0; y--) { for (x = 0; x < xf; x++) { pdf_obj *newpageobj, *newpageref, *newmediabox; fz_rect mb; int num; newpageobj = pdf_copy_dict(ctx, pdf_lookup_page_obj(ctx, doc, page)); num = pdf_create_object(ctx, doc); pdf_update_object(ctx, doc, num, newpageobj); newpageref = pdf_new_indirect(ctx, doc, num, 0); newmediabox = pdf_new_array(ctx, doc, 4); mb.x0 = page_details->mediabox.x0 + (w/xf)*x; if (x == xf-1) mb.x1 = page_details->mediabox.x1; else mb.x1 = page_details->mediabox.x0 + (w/xf)*(x+1); mb.y0 = page_details->mediabox.y0 + (h/yf)*y; if (y == yf-1) mb.y1 = page_details->mediabox.y1; else mb.y1 = page_details->mediabox.y0 + (h/yf)*(y+1); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.x0)); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.y0)); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.x1)); pdf_array_push(ctx, newmediabox, pdf_new_real(ctx, doc, mb.y1)); pdf_dict_put(ctx, newpageobj, PDF_NAME_Parent, parent); pdf_dict_put(ctx, newpageobj, PDF_NAME_MediaBox, newmediabox); /* Store page object in new kids array */ pdf_array_push(ctx, kids, newpageref); kidcount++; } } } pdf_drop_obj(ctx, parent); /* Update page count and kids array */ pdf_dict_put(ctx, pages, PDF_NAME_Count, pdf_new_int(ctx, doc, kidcount)); pdf_dict_put(ctx, pages, PDF_NAME_Kids, kids); pdf_drop_obj(ctx, kids); }
static void decimatepages(pdf_document *xref) { pdf_obj *oldroot, *root, *pages, *kids, *parent; fz_context *ctx = xref->ctx; int num_pages = pdf_count_pages(xref); int page, kidcount; /* Keep only pages/type and (reduced) dest entries to avoid * references to unretained pages */ oldroot = pdf_dict_gets(pdf_trailer(xref), "Root"); pages = pdf_dict_gets(oldroot, "Pages"); root = pdf_new_dict(ctx, 2); pdf_dict_puts(root, "Type", pdf_dict_gets(oldroot, "Type")); pdf_dict_puts(root, "Pages", pdf_dict_gets(oldroot, "Pages")); pdf_update_object(xref, pdf_to_num(oldroot), root); pdf_drop_obj(root); /* Create a new kids array with only the pages we want to keep */ parent = pdf_new_indirect(ctx, pdf_to_num(pages), pdf_to_gen(pages), xref); kids = pdf_new_array(ctx, 1); kidcount = 0; for (page=0; page < num_pages; page++) { pdf_page *page_details = pdf_load_page(xref, page); int xf = x_factor, yf = y_factor; int x, y; float w = page_details->mediabox.x1 - page_details->mediabox.x0; float h = page_details->mediabox.y1 - page_details->mediabox.y0; if (xf == 0 && yf == 0) { /* Nothing specified, so split along the long edge */ if (w > h) xf = 2, yf = 1; else xf = 1, yf = 2; } else if (xf == 0) xf = 1; else if (yf == 0) yf = 1; for (y = yf-1; y >= 0; y--) { for (x = 0; x < xf; x++) { pdf_obj *newpageobj, *newpageref, *newmediabox; fz_rect mb; int num; newpageobj = pdf_copy_dict(ctx, xref->page_objs[page]); num = pdf_create_object(xref); pdf_update_object(xref, num, newpageobj); newpageref = pdf_new_indirect(ctx, num, 0, xref); newmediabox = pdf_new_array(ctx, 4); mb.x0 = page_details->mediabox.x0 + (w/xf)*x; if (x == xf-1) mb.x1 = page_details->mediabox.x1; else mb.x1 = page_details->mediabox.x0 + (w/xf)*(x+1); mb.y0 = page_details->mediabox.y0 + (h/yf)*y; if (y == yf-1) mb.y1 = page_details->mediabox.y1; else mb.y1 = page_details->mediabox.y0 + (h/yf)*(y+1); pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x0)); pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y0)); pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x1)); pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y1)); pdf_dict_puts(newpageobj, "Parent", parent); pdf_dict_puts(newpageobj, "MediaBox", newmediabox); /* Store page object in new kids array */ pdf_array_push(kids, newpageref); kidcount++; } } } pdf_drop_obj(parent); /* Update page count and kids array */ pdf_dict_puts(pages, "Count", pdf_new_int(ctx, kidcount)); pdf_dict_puts(pages, "Kids", kids); pdf_drop_obj(kids); }
int Document::GetNumPages () const { return pdf_count_pages (MuDoc_); }
static int _pdf_doc_load(struct _pdf_doc *self, mume_stream_t *stm) { fz_error error; fz_stream *fzstm; fz_rect *mbox; fz_obj *page_obj, *box_obj; int i, c; _pdf_doc_clear(self); fzstm = fz_new_stream(stm, _pdf_stream_read, _pdf_stream_close); mume_stream_reference(stm); fzstm->seek = _pdf_stream_seek; error = pdf_open_xref_with_stream(&self->xref, fzstm, NULL); fz_close(fzstm); if (error) { mume_error(("Read xref failed\n", error)); return 0; } assert(!pdf_needs_password(self->xref)); /* Load meta information. */ error = pdf_load_page_tree(self->xref); if (error) { mume_error(("Cannot load page tree\n")); return 0; } c = pdf_count_pages(self->xref); self->glyph_cache = fz_new_glyph_cache(); self->pages = calloc_abort(c, sizeof(pdf_page*)); self->disps = calloc_abort(c, sizeof(fz_display_list*)); self->media_boxes = malloc_abort(c * sizeof(fz_rect)); self->page_rotates = malloc_abort(c * sizeof(int)); /* Extract each pages' media box and rotation. */ for (i = 0; i < c; ++i) { mbox = self->media_boxes + i; page_obj = self->xref->page_objs[i]; if (!page_obj) { *mbox = fz_empty_rect; continue; } box_obj = fz_dict_gets(page_obj, "MediaBox"); *mbox = pdf_to_rect(box_obj); if (fz_is_empty_rect(*mbox)) { fz_warn("Cannot find page bounds, guessing page bounds."); mbox->x1 = 612; mbox->y1 = 792; } box_obj = fz_dict_gets(page_obj, "CropBox"); if (fz_is_array(box_obj)) *mbox = fz_intersect_rect(*mbox, pdf_to_rect(box_obj)); self->page_rotates[i] = fz_to_int( fz_dict_gets(page_obj, "Rotate")); if (self->page_rotates[i] % 90) self->page_rotates[i] = 0; } return 1; }
int PDFDocument::GetNumPages() { return pdf_count_pages(_fz_context, _pdf_document); }
int PDFDocument::GetPageCount() { return pdf_count_pages(_pdf_document); }
char * pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action, int pagenum) { pdf_obj *obj, *dest, *file_spec; if (!action) return NULL; obj = pdf_dict_get(ctx, action, PDF_NAME_S); if (pdf_name_eq(ctx, PDF_NAME_GoTo, obj)) { dest = pdf_dict_get(ctx, action, PDF_NAME_D); return pdf_parse_link_dest(ctx, doc, dest); } else if (pdf_name_eq(ctx, PDF_NAME_URI, obj)) { /* URI entries are ASCII strings */ const char *uri = pdf_to_str_buf(ctx, pdf_dict_get(ctx, action, PDF_NAME_URI)); if (!fz_is_external_link(ctx, uri)) { pdf_obj *uri_base_obj = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/URI/Base"); const char *uri_base = uri_base_obj ? pdf_to_str_buf(ctx, uri_base_obj) : "file://"; char *new_uri = fz_malloc(ctx, strlen(uri_base) + strlen(uri) + 1); strcpy(new_uri, uri_base); strcat(new_uri, uri); return new_uri; } return fz_strdup(ctx, uri); } else if (pdf_name_eq(ctx, PDF_NAME_Launch, obj)) { file_spec = pdf_dict_get(ctx, action, PDF_NAME_F); return pdf_parse_file_spec(ctx, doc, file_spec, NULL); } else if (pdf_name_eq(ctx, PDF_NAME_GoToR, obj)) { dest = pdf_dict_get(ctx, action, PDF_NAME_D); file_spec = pdf_dict_get(ctx, action, PDF_NAME_F); return pdf_parse_file_spec(ctx, doc, file_spec, dest); } else if (pdf_name_eq(ctx, PDF_NAME_Named, obj)) { dest = pdf_dict_get(ctx, action, PDF_NAME_N); if (pdf_name_eq(ctx, PDF_NAME_FirstPage, dest)) pagenum = 0; else if (pdf_name_eq(ctx, PDF_NAME_LastPage, dest)) pagenum = pdf_count_pages(ctx, doc) - 1; else if (pdf_name_eq(ctx, PDF_NAME_PrevPage, dest) && pagenum >= 0) { if (pagenum > 0) pagenum--; } else if (pdf_name_eq(ctx, PDF_NAME_NextPage, dest) && pagenum >= 0) { if (pagenum < pdf_count_pages(ctx, doc) - 1) pagenum++; } else return NULL; return fz_asprintf(ctx, "#%d", pagenum + 1); } return NULL; }
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 */ file = fz_open_fd(fd); error = pdf_open_xref_with_stream(&app->xref, file, NULL); if (error) 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 */ error = pdf_load_page_tree(app->xref); if (error) pdfapp_error(app, fz_rethrow(error, "cannot load page tree")); app->pagecount = pdf_count_pages(app->xref); }
int Pdf::numPages() const { return pdf_count_pages(xref); }