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 void runrange(const char *range) { int start, end, i; while ((range = fz_parse_page_range(ctx, range, &start, &end, count))) { if (start < end) for (i = start; i <= end; ++i) runpage(i); else for (i = start; i >= end; --i) runpage(i); } }
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; }
static void retainpages(fz_context *ctx, globals *glo, int argc, char **argv) { pdf_obj *oldroot, *root, *pages, *kids, *countobj, *olddests; pdf_document *doc = glo->doc; int argidx = 0; pdf_obj *names_list = NULL; pdf_obj *outlines; pdf_obj *ocproperties; 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); ocproperties = pdf_dict_get(ctx, oldroot, PDF_NAME_OCProperties); 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)); if (outlines) pdf_dict_put(ctx, root, PDF_NAME_Outlines, outlines); if (ocproperties) pdf_dict_put(ctx, root, PDF_NAME_OCProperties, ocproperties); pdf_update_object(ctx, doc, pdf_to_num(ctx, oldroot), root); /* Create a new kids array with only the pages we want to keep */ kids = pdf_new_array(ctx, doc, 1); /* Retain pages specified */ while (argc - argidx) { int page, spage, epage; const char *pagelist = argv[argidx]; pagecount = pdf_count_pages(ctx, doc); while ((pagelist = fz_parse_page_range(ctx, pagelist, &spage, &epage, pagecount))) { if (spage < epage) for (page = spage; page <= epage; ++page) retainpage(ctx, doc, pages, kids, page); else for (page = spage; page >= epage; --page) retainpage(ctx, doc, pages, kids, page); } argidx++; } /* 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_drop(ctx, names_list, key_str); pdf_array_push(ctx, names_list, val); } } 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 *annots = pdf_dict_get(ctx, pageref, 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); }