void
pdf_set_annot_flags(fz_context *ctx, pdf_annot *annot, int flags)
{
	pdf_document *doc = annot->page->doc;
	pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags));
	annot->changed = 1;
}
示例#2
0
void pdf_update_xobject_contents(pdf_document *doc, pdf_xobject *form, fz_buffer *buffer)
{
	pdf_dict_dels(form->contents, "Filter");
	pdf_dict_puts_drop(form->contents, "Length", pdf_new_int(doc, buffer->len));
	pdf_update_stream(doc, pdf_to_num(form->contents), buffer);
	form->iteration ++;
}
示例#3
0
pdf_obj *
pdf_parse_stm_obj(pdf_document *doc, fz_stream *file, pdf_lexbuf *buf)
{
	pdf_token tok;
	fz_context *ctx = file->ctx;

	tok = pdf_lex(file, buf);

	switch (tok)
	{
	case PDF_TOK_OPEN_ARRAY:
		return pdf_parse_array(doc, file, buf);
	case PDF_TOK_OPEN_DICT:
		return pdf_parse_dict(doc, file, buf);
	case PDF_TOK_NAME: return pdf_new_name(doc, buf->scratch); break;
	case PDF_TOK_REAL: return pdf_new_real(doc, buf->f); break;
	case PDF_TOK_STRING: return pdf_new_string(doc, buf->scratch, buf->len); break;
	case PDF_TOK_TRUE: return pdf_new_bool(doc, 1); break;
	case PDF_TOK_FALSE: return pdf_new_bool(doc, 0); break;
	case PDF_TOK_NULL: return pdf_new_null(doc); break;
	case PDF_TOK_INT: return pdf_new_int(doc, buf->i); break;
	default: fz_throw(ctx, FZ_ERROR_GENERIC, "unknown token in object stream");
	}
	return NULL; /* Stupid MSVC */
}
示例#4
0
static int strip_outlines(fz_context *ctx, pdf_document *doc, pdf_obj *outlines, int page_count, int *page_object_nums, pdf_obj *names_list)
{
	int nc;
	pdf_obj *first;
	pdf_obj *last;

	first = pdf_dict_get(ctx, outlines, PDF_NAME_First);
	if (first == NULL)
		nc = 0;
	else
		nc = strip_outline(ctx, doc, first, page_count, page_object_nums, names_list, &first, &last);

	if (nc == 0)
	{
		pdf_dict_del(ctx, outlines, PDF_NAME_First);
		pdf_dict_del(ctx, outlines, PDF_NAME_Last);
		pdf_dict_del(ctx, outlines, PDF_NAME_Count);
	}
	else
	{
		int old_count = pdf_to_int(ctx, pdf_dict_get(ctx, outlines, PDF_NAME_Count));
		pdf_dict_put(ctx, outlines, PDF_NAME_First, first);
		pdf_dict_put(ctx, outlines, PDF_NAME_Last, last);
		pdf_dict_put(ctx, outlines, PDF_NAME_Count, pdf_new_int(ctx, doc, old_count > 0 ? nc : -nc));
	}

	return nc;
}
示例#5
0
void pdf_reorder_portfolio_schema(fz_context *ctx, pdf_document *doc, int entry, int new_pos)
{
	pdf_portfolio **pp;
	pdf_portfolio *p;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "Bad pdf_portfolio_schema_info call");

	if (doc->portfolio == NULL)
		load_portfolio(ctx, doc);

	/* Take p out */
	pp = &doc->portfolio;
	while (*pp && entry > 0)
		pp = &(*pp)->next, entry--;
	p = *pp;
	if (p == NULL || entry)
		fz_throw(ctx, FZ_ERROR_GENERIC, "entry out of range in pdf_reorder_portfolio_schema");
	*pp = p->next;

	/* Put p back in */
	pp = &doc->portfolio;
	while (*pp && new_pos > 0)
		pp = &(*pp)->next, new_pos--;
	p->next = *pp;
	*pp = p;

	/* Rewrite the underlying orderings */
	for (p = doc->portfolio, entry = 0; p; p = p->next, entry++)
		pdf_dict_put_drop(ctx, p->val, PDF_NAME_O, pdf_new_int(ctx, doc, entry));
}
示例#6
0
文件: data.c 项目: amba/pdfout
pdf_obj *
pdfout_data_scalar_to_pdf_int (fz_context *ctx, pdf_document *doc,
			       pdfout_data *scalar)
{
  char *s = scalar_get_string (ctx, scalar);
  int n = pdfout_strtoint_null (ctx, s);
  return pdf_new_int (ctx, doc, n);
}
示例#7
0
pdf_page *
pdf_create_page(pdf_document *doc, fz_rect mediabox, int res, int rotate)
{
	pdf_page *page = NULL;
	pdf_obj *pageobj;
	float userunit = 1;
	fz_context *ctx = doc->ctx;
	fz_matrix ctm, tmp;
	fz_rect realbox;

	page = fz_malloc_struct(ctx, pdf_page);

	fz_try(ctx)
	{
		page->resources = NULL;
		page->contents = NULL;
		page->transparency = 0;
		page->links = NULL;
		page->annots = NULL;
		page->me = pageobj = pdf_new_dict(doc, 4);

		pdf_dict_puts_drop(pageobj, "Type", pdf_new_name(doc, "Page"));

		page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit;
		page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit;
		page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit;
		page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit;
		pdf_dict_puts_drop(pageobj, "MediaBox", pdf_new_rect(doc, &page->mediabox));

		/* Snap page->rotate to 0, 90, 180 or 270 */
		if (page->rotate < 0)
			page->rotate = 360 - ((-page->rotate) % 360);
		if (page->rotate >= 360)
			page->rotate = page->rotate % 360;
		page->rotate = 90*((page->rotate + 45)/90);
		if (page->rotate > 360)
			page->rotate = 0;
		pdf_dict_puts_drop(pageobj, "Rotate", pdf_new_int(doc, page->rotate));

		fz_pre_rotate(fz_scale(&ctm, 1, -1), -page->rotate);
		realbox = page->mediabox;
		fz_transform_rect(&realbox, &ctm);
		fz_pre_scale(fz_translate(&tmp, -realbox.x0, -realbox.y0), userunit, userunit);
		fz_concat(&ctm, &ctm, &tmp);
		page->ctm = ctm;
		/* Do not create a Contents, as an empty Contents dict is not
		 * valid. See Bug 694712 */
	}
	fz_catch(ctx)
	{
		pdf_drop_obj(page->me);
		fz_free(ctx, page);
		fz_rethrow_message(ctx, "Failed to create page");
	}

	return page;
}
示例#8
0
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);
	}
}
示例#9
0
文件: page-add.c 项目: s-k2/Juggler
ErrorCode juggler_add_pages_from_file(juggler_t *dest, juggler_t *src, int dest_index)
{
	pdf_obj *dest_pages = pdf_dict_getp(dest->ctx, 
		pdf_trailer(dest->ctx, dest->pdf), "Root/Pages");
	int dest_pages_index = pdf_array_len(dest->ctx, 
		pdf_dict_gets(dest->ctx, dest_pages, "Kids"));
		
	/* be aware that this function does not change the two variables if the page
	   index is greater than the number of pages */
	find_destination_pages(dest->ctx, 
		dest_pages, dest_index, &dest_pages, &dest_pages_index);

	pdf_obj *dest_kids = pdf_dict_gets(dest->ctx, dest_pages, "Kids");
	if(!pdf_is_indirect(dest->ctx, dest_pages) || 
		!pdf_is_dict(dest->ctx, dest_pages) || !pdf_is_array(dest->ctx, dest_kids))
	{
		return(ERROR_INVALID_RANGE);
	}
	
	pdf_obj *pages_root = pdf_dict_getp(src->ctx, pdf_trailer(src->ctx, src->pdf), "Root/Pages");
	if(!pdf_is_indirect(src->ctx, pages_root) || !pdf_is_dict(src->ctx, pages_root))
		return(ERROR_NO_PAGES);

	/* if we copy the root pages-node and it's referenced objects, we will copy 
	   all pages and all objects those pages need */
	pdf_obj *new_pages_ref = copy_object_single(dest->ctx, dest->pdf, src->ctx, src->pdf, pages_root);

	/* insert new pages-node */
	pdf_array_insert_drop(dest->ctx, dest_kids, new_pages_ref, dest_pages_index);

	/* update the parent */
	pdf_obj *new_pages_parent = pdf_new_indirect(dest->ctx, dest->pdf, 
		pdf_to_num(dest->ctx, dest_pages), pdf_to_gen(dest->ctx, dest_pages));
	pdf_dict_puts_drop(dest->ctx, new_pages_ref, "Parent", new_pages_parent);

	/* TODO: If dest_pages contains anything inheritable but not the new node
	         we need to insert empty items to prevent this inerhitance */

	/* update count */
	int new_count = pdf_to_int(dest->ctx, 
		pdf_dict_gets(dest->ctx, dest_pages, "Count")) + src->pagecount;
	pdf_dict_puts_drop(dest->ctx, dest_pages, "Count", 
		pdf_new_int(dest->ctx, dest->pdf, new_count));

	/* let MuPDF rebuild the page tree */
	pdf_finish_edit(dest->ctx, dest->pdf);
	dest->pdf->page_count = new_count;

	/* update juggler's state */
	juggler_page_tree_changed_due_to_insert(dest, dest_index, src->pagecount);

	return(NoError);
}
示例#10
0
文件: page-labels.c 项目: amba/pdfout
static pdf_obj *
hash_to_pdf_dict (fz_context *ctx, pdf_document *doc, pdfout_data *hash,
		  int *page)
{
  pdf_obj *dict_obj = pdf_new_dict (ctx, doc, 3);
  int len = pdfout_data_hash_len (ctx, hash);
  for (int j = 0; j < len; ++j)
    {
      char *key, *value;
      int value_len;
      pdfout_data_hash_get_key_value (ctx, hash, &key, &value, &value_len, j);

      if (streq (key, "page"))
	*page = pdfout_strtoint_null (ctx, value);
      else if (streq (key, "prefix"))
	{
	  pdf_obj *string = pdfout_utf8_to_str_obj (ctx, doc, value,
						    value_len);
	  pdf_dict_puts_drop (ctx, dict_obj, "P", string);
	}
      else if (streq (key, "first"))
	{
	  int first = pdfout_strtoint_null (ctx, value);
	  pdf_dict_puts_drop (ctx, dict_obj, "St",
			      pdf_new_int (ctx, doc, first));
	}
      else if (streq (key, "style"))
	{
	  const char *name;
	  if (streq (value, "arabic"))
	    name = "D";
	  else if (streq (value, "Roman"))
	    name = "R";
	  else if (streq (value, "roman"))
	    name = "r";
	  else if (streq (value, "Letters"))
	    name = "A";
	  else if (streq (value, "letters"))
	    name = "a";
	  else
	    abort ();
	  pdf_obj *name_obj = pdf_new_name (ctx, doc, name);
	  pdf_dict_puts_drop (ctx, dict_obj, "S", name_obj);
	}
     
    }

  return dict_obj;
}
示例#11
0
void
pdf_delete_page(pdf_document *doc, int at)
{
	pdf_obj *parent, *kids;
	int i;

	pdf_lookup_page_loc(doc, at, &parent, &i);
	kids = pdf_dict_gets(parent, "Kids");
	pdf_array_delete(kids, i);

	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");
	}
}
示例#12
0
pdf_obj *
pdf_parse_stm_obj(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
{
    int tok;
    fz_context *ctx = file->ctx;

    tok = pdf_lex(file, buf);
    /* RJW: "cannot parse token in object stream") */

    switch (tok)
    {
    case PDF_TOK_OPEN_ARRAY:
        return pdf_parse_array(xref, file, buf);
    /* RJW: "cannot parse object stream" */
    case PDF_TOK_OPEN_DICT:
        return pdf_parse_dict(xref, file, buf);
    /* RJW: "cannot parse object stream" */
    case PDF_TOK_NAME:
        return fz_new_name(ctx, buf->scratch);
        break;
    case PDF_TOK_REAL:
        return pdf_new_real(ctx, buf->f);
        break;
    case PDF_TOK_STRING:
        return pdf_new_string(ctx, buf->scratch, buf->len);
        break;
    case PDF_TOK_TRUE:
        return pdf_new_bool(ctx, 1);
        break;
    case PDF_TOK_FALSE:
        return pdf_new_bool(ctx, 0);
        break;
    case PDF_TOK_NULL:
        return pdf_new_null(ctx);
        break;
    case PDF_TOK_INT:
        return pdf_new_int(ctx, buf->i);
        break;
    default:
        fz_throw(ctx, "unknown token in object stream");
    }
    return NULL; /* Stupid MSVC */
}
示例#13
0
static int new_stream_object(pdf_document *xref,fz_context *ctx,char *buf)

    {
    int ref;
    pdf_obj *obj,*len;
    fz_buffer *fzbuf;

    ref = pdf_create_object(xref);
    obj = pdf_new_dict(ctx,1);
    len=pdf_new_int(ctx,strlen(buf));
    pdf_dict_puts(obj,"Length",len);
    pdf_drop_obj(len);
    pdf_update_object(xref,ref,obj);
    pdf_drop_obj(obj);
    fzbuf=fz_new_buffer(ctx,strlen(buf));
    fz_write_buffer(ctx,fzbuf,(unsigned char *)buf,strlen(buf));
    pdf_update_stream(xref,ref,fzbuf);
    fz_drop_buffer(ctx,fzbuf);
    return(ref);
    }
示例#14
0
void pdf_set_text_annot_position(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point pt)
{
	fz_matrix ctm;
	fz_rect rect;
	int flags;

	fz_invert_matrix(&ctm, &annot->page->ctm);
	rect.x0 = pt.x;
	rect.x1 = pt.x + TEXT_ANNOT_SIZE;
	rect.y0 = pt.y;
	rect.y1 = pt.y + TEXT_ANNOT_SIZE;
	fz_transform_rect(&rect, &ctm);

	pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect));

	flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F));
	flags |= (F_NoZoom|F_NoRotate);
	pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags));

	update_rect(ctx, annot);
}
示例#15
0
void pdf_set_text_annot_position(fz_context *ctx, pdf_annot *annot, fz_point pt)
{
	pdf_document *doc = annot->page->doc;
	fz_matrix page_ctm, inv_page_ctm;
	fz_rect rect;
	int flags;

	pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
	fz_invert_matrix(&inv_page_ctm, &page_ctm);

	rect.x0 = pt.x;
	rect.x1 = pt.x + TEXT_ANNOT_SIZE;
	rect.y0 = pt.y;
	rect.y1 = pt.y + TEXT_ANNOT_SIZE;
	fz_transform_rect(&rect, &inv_page_ctm);

	pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect));

	flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F));
	flags |= (PDF_ANNOT_IS_NO_ZOOM|PDF_ANNOT_IS_NO_ROTATE);
	pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags));
}
示例#16
0
文件: page-labels.c 项目: amba/pdfout
void
pdfout_page_labels_set (fz_context *ctx, pdf_document *doc,
			pdfout_data *labels)
{
  if (labels)
    check_page_labels (ctx, labels);
  
  pdf_obj *root = pdf_dict_get (ctx, pdf_trailer (ctx, doc), PDF_NAME_Root);
  
  if (root == NULL)
    pdfout_throw (ctx, "no document catalog, cannot set/unset page labels");
  
  if (labels == NULL)
    {
      /* Remove page labels.  */
      pdf_dict_dels (ctx, root, "PageLabels");
      return;
    }

  int num = pdfout_data_array_len (ctx, labels);
  pdf_obj *array_obj = pdf_new_array (ctx, doc, 2 * num);
  
  for (int i = 0; i < num; ++i)
    {
      pdfout_data *hash = pdfout_data_array_get (ctx, labels, i);
      int page;
      pdf_obj *dict_obj = hash_to_pdf_dict (ctx, doc, hash, &page);

      pdf_obj *page_obj = pdf_new_int (ctx, doc, page);
      pdf_array_push_drop (ctx, array_obj, page_obj);
      
      pdf_array_push_drop (ctx, array_obj, dict_obj);
    }
      
  pdf_obj *labels_obj = pdf_new_dict (ctx, doc, 1);
  pdf_dict_puts_drop (ctx, labels_obj, "Nums", array_obj);
  pdf_dict_puts_drop (ctx, root, "PageLabels", labels_obj);
  
}
示例#17
0
void pdf_update_xobject_contents(pdf_document *xref, pdf_xobject *form, fz_buffer *buffer)
{
	fz_context *ctx = xref->ctx;
	pdf_obj *len = NULL;

	fz_var(len);

	fz_try(ctx)
	{
		len = pdf_new_int(ctx, buffer->len);
		pdf_dict_dels(form->contents, "Filter");
		pdf_dict_puts(form->contents, "Length", len);
		pdf_update_stream(xref, pdf_to_num(form->contents), buffer);
	}
	fz_always(ctx)
	{
		pdf_drop_obj(len);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
示例#18
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);
}
示例#19
0
pdf_annot *
pdf_create_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_annot_type type)
{
	pdf_annot *annot = NULL;
	pdf_obj *annot_obj = pdf_new_dict(ctx, doc, 0);
	pdf_obj *ind_obj = NULL;

	fz_var(annot);
	fz_var(ind_obj);
	fz_try(ctx)
	{
		int ind_obj_num;
		fz_rect rect = {0.0, 0.0, 0.0, 0.0};
		const char *type_str = annot_type_str(type);
		pdf_obj *annot_arr = pdf_dict_get(ctx, page->me, PDF_NAME_Annots);
		if (annot_arr == NULL)
		{
			annot_arr = pdf_new_array(ctx, doc, 0);
			pdf_dict_put_drop(ctx, page->me, PDF_NAME_Annots, annot_arr);
		}

		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Type, PDF_NAME_Annot);

		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Subtype, pdf_new_name(ctx, doc, type_str));
		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect));

		/* Make printable as default */
		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_F, pdf_new_int(ctx, doc, F_Print));

		annot = fz_malloc_struct(ctx, pdf_annot);
		annot->page = page;
		annot->rect = rect;
		annot->pagerect = rect;
		annot->ap = NULL;
		annot->widget_type = PDF_WIDGET_TYPE_NOT_WIDGET;
		annot->annot_type = type;

		/*
			Both annotation object and annotation structure are now created.
			Insert the object in the hierarchy and the structure in the
			page's array.
		*/
		ind_obj_num = pdf_create_object(ctx, doc);
		pdf_update_object(ctx, doc, ind_obj_num, annot_obj);
		ind_obj = pdf_new_indirect(ctx, doc, ind_obj_num, 0);
		pdf_array_push(ctx, annot_arr, ind_obj);
		annot->obj = pdf_keep_obj(ctx, ind_obj);

		/*
			Linking must be done after any call that might throw because
			pdf_drop_annot below actually frees a list. Put the new annot
			at the end of the list, so that it will be drawn last.
		*/
		*page->annot_tailp = annot;
		page->annot_tailp = &annot->next;

		doc->dirty = 1;
	}
	fz_always(ctx)
	{
		pdf_drop_obj(ctx, annot_obj);
		pdf_drop_obj(ctx, ind_obj);
	}
	fz_catch(ctx)
	{
		pdf_drop_annot(ctx, annot);
		fz_rethrow(ctx);
	}

	return annot;
}
示例#20
0
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 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--;
		}
	}
}
示例#22
0
pdf_obj *
pdf_parse_dict(pdf_document *doc, fz_stream *file, pdf_lexbuf *buf)
{
	pdf_obj *dict;
	pdf_obj *key = NULL;
	pdf_obj *val = NULL;
	pdf_token tok;
	int a, b;
	fz_context *ctx = file->ctx;

	dict = pdf_new_dict(doc, 8);

	fz_var(key);
	fz_var(val);

	fz_try(ctx)
	{
		while (1)
		{
			tok = pdf_lex(file, buf);
	skip:
			if (tok == PDF_TOK_CLOSE_DICT)
				break;

			/* for BI .. ID .. EI in content streams */
			if (tok == PDF_TOK_KEYWORD && !strcmp(buf->scratch, "ID"))
				break;

			if (tok != PDF_TOK_NAME)
				fz_throw(ctx, FZ_ERROR_GENERIC, "invalid key in dict");

			key = pdf_new_name(doc, buf->scratch);

			tok = pdf_lex(file, buf);

			switch (tok)
			{
			case PDF_TOK_OPEN_ARRAY:
				val = pdf_parse_array(doc, file, buf);
				break;

			case PDF_TOK_OPEN_DICT:
				val = pdf_parse_dict(doc, file, buf);
				break;

			case PDF_TOK_NAME: val = pdf_new_name(doc, buf->scratch); break;
			case PDF_TOK_REAL: val = pdf_new_real(doc, buf->f); break;
			case PDF_TOK_STRING: val = pdf_new_string(doc, buf->scratch, buf->len); break;
			case PDF_TOK_TRUE: val = pdf_new_bool(doc, 1); break;
			case PDF_TOK_FALSE: val = pdf_new_bool(doc, 0); break;
			case PDF_TOK_NULL: val = pdf_new_null(doc); break;

			case PDF_TOK_INT:
				/* 64-bit to allow for numbers > INT_MAX and overflow */
				a = buf->i;
				tok = pdf_lex(file, buf);
				if (tok == PDF_TOK_CLOSE_DICT || tok == PDF_TOK_NAME ||
					(tok == PDF_TOK_KEYWORD && !strcmp(buf->scratch, "ID")))
				{
					val = pdf_new_int(doc, a);
					pdf_dict_put(dict, key, val);
					pdf_drop_obj(val);
					val = NULL;
					pdf_drop_obj(key);
					key = NULL;
					goto skip;
				}
				if (tok == PDF_TOK_INT)
				{
					b = buf->i;
					tok = pdf_lex(file, buf);
					if (tok == PDF_TOK_R)
					{
						val = pdf_new_indirect(doc, a, b);
						break;
					}
				}
				fz_throw(ctx, FZ_ERROR_GENERIC, "invalid indirect reference in dict");

			default:
				fz_throw(ctx, FZ_ERROR_GENERIC, "unknown token in dict");
			}

			pdf_dict_put(dict, key, val);
			pdf_drop_obj(val);
			val = NULL;
			pdf_drop_obj(key);
			key = NULL;
		}
	}
	fz_catch(ctx)
	{
		pdf_drop_obj(dict);
		pdf_drop_obj(key);
		pdf_drop_obj(val);
		fz_rethrow_message(ctx, "cannot parse dict");
	}
	return dict;
}
pdf_annot *
pdf_create_annot(fz_context *ctx, pdf_page *page, fz_annot_type type)
{
	pdf_annot *annot = NULL;
	pdf_document *doc = page->doc;
	pdf_obj *annot_obj = pdf_new_dict(ctx, doc, 0);
	pdf_obj *ind_obj = NULL;

	fz_var(annot);
	fz_var(ind_obj);
	fz_try(ctx)
	{
		int ind_obj_num;
		fz_rect rect = {0.0f, 0.0f, 0.0f, 0.0f};
		const char *type_str;
		pdf_obj *annot_arr;

		type_str = pdf_string_from_annot_type(ctx, type);
		if (type == PDF_ANNOT_UNKNOWN)
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot create unknown annotation");

		annot_arr = pdf_dict_get(ctx, page->obj, PDF_NAME_Annots);
		if (annot_arr == NULL)
		{
			annot_arr = pdf_new_array(ctx, doc, 0);
			pdf_dict_put_drop(ctx, page->obj, PDF_NAME_Annots, annot_arr);
		}

		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Type, PDF_NAME_Annot);

		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Subtype, pdf_new_name(ctx, doc, type_str));
		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect));

		/* Make printable as default */
		pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_F, pdf_new_int(ctx, doc, PDF_ANNOT_IS_PRINT));

		annot = pdf_new_annot(ctx, page);
		annot->ap = NULL;

		/*
			Both annotation object and annotation structure are now created.
			Insert the object in the hierarchy and the structure in the
			page's array.
		*/
		ind_obj_num = pdf_create_object(ctx, doc);
		pdf_update_object(ctx, doc, ind_obj_num, annot_obj);
		ind_obj = pdf_new_indirect(ctx, doc, ind_obj_num, 0);
		pdf_array_push(ctx, annot_arr, ind_obj);
		annot->obj = pdf_keep_obj(ctx, ind_obj);

		/*
			Linking must be done after any call that might throw because
			pdf_drop_annots below actually frees a list. Put the new annot
			at the end of the list, so that it will be drawn last.
		*/
		*page->annot_tailp = annot;
		page->annot_tailp = &annot->next;

		doc->dirty = 1;
	}
	fz_always(ctx)
	{
		pdf_drop_obj(ctx, annot_obj);
		pdf_drop_obj(ctx, ind_obj);
	}
	fz_catch(ctx)
	{
		pdf_drop_annots(ctx, annot);
		fz_rethrow(ctx);
	}

	return annot;
}
示例#24
0
pdf_obj *
pdf_parse_ind_obj(fz_context *ctx, pdf_document *doc,
	fz_stream *file, pdf_lexbuf *buf,
	int *onum, int *ogen, int *ostmofs, int *try_repair)
{
	pdf_obj *obj = NULL;
	int num = 0, gen = 0, stm_ofs;
	pdf_token tok;
	int a, b;

	fz_var(obj);

	tok = pdf_lex(ctx, file, buf);
	if (tok != PDF_TOK_INT)
	{
		if (try_repair)
			*try_repair = 1;
		fz_throw(ctx, FZ_ERROR_GENERIC, "expected object number");
	}
	num = buf->i;

	tok = pdf_lex(ctx, file, buf);
	if (tok != PDF_TOK_INT)
	{
		if (try_repair)
			*try_repair = 1;
		fz_throw(ctx, FZ_ERROR_GENERIC, "expected generation number (%d ? obj)", num);
	}
	gen = buf->i;

	tok = pdf_lex(ctx, file, buf);
	if (tok != PDF_TOK_OBJ)
	{
		if (try_repair)
			*try_repair = 1;
		fz_throw(ctx, FZ_ERROR_GENERIC, "expected 'obj' keyword (%d %d ?)", num, gen);
	}

	tok = pdf_lex(ctx, file, buf);

	switch (tok)
	{
	case PDF_TOK_OPEN_ARRAY:
		obj = pdf_parse_array(ctx, doc, file, buf);
		break;

	case PDF_TOK_OPEN_DICT:
		obj = pdf_parse_dict(ctx, doc, file, buf);
		break;

	case PDF_TOK_NAME: obj = pdf_new_name(ctx, doc, buf->scratch); break;
	case PDF_TOK_REAL: obj = pdf_new_real(ctx, doc, buf->f); break;
	case PDF_TOK_STRING: obj = pdf_new_string(ctx, doc, buf->scratch, buf->len); break;
	case PDF_TOK_TRUE: obj = pdf_new_bool(ctx, doc, 1); break;
	case PDF_TOK_FALSE: obj = pdf_new_bool(ctx, doc, 0); break;
	case PDF_TOK_NULL: obj = pdf_new_null(ctx, doc); break;

	case PDF_TOK_INT:
		a = buf->i;
		tok = pdf_lex(ctx, file, buf);

		if (tok == PDF_TOK_STREAM || tok == PDF_TOK_ENDOBJ)
		{
			obj = pdf_new_int(ctx, doc, a);
			goto skip;
		}
		if (tok == PDF_TOK_INT)
		{
			b = buf->i;
			tok = pdf_lex(ctx, file, buf);
			if (tok == PDF_TOK_R)
			{
				obj = pdf_new_indirect(ctx, doc, a, b);
				break;
			}
		}
		fz_throw(ctx, FZ_ERROR_GENERIC, "expected 'R' keyword (%d %d R)", num, gen);

	case PDF_TOK_ENDOBJ:
		obj = pdf_new_null(ctx, doc);
		goto skip;

	default:
		fz_throw(ctx, FZ_ERROR_GENERIC, "syntax error in object (%d %d R)", num, gen);
	}

	fz_try(ctx)
	{
		tok = pdf_lex(ctx, file, buf);
	}
	fz_catch(ctx)
	{
		pdf_drop_obj(ctx, obj);
		fz_rethrow_message(ctx, "cannot parse indirect object (%d %d R)", num, gen);
	}

skip:
	if (tok == PDF_TOK_STREAM)
	{
		int c = fz_read_byte(ctx, file);
		while (c == ' ')
			c = fz_read_byte(ctx, file);
		if (c == '\r')
		{
			c = fz_peek_byte(ctx, file);
			if (c != '\n')
				fz_warn(ctx, "line feed missing after stream begin marker (%d %d R)", num, gen);
			else
				fz_read_byte(ctx, file);
		}
		stm_ofs = fz_tell(ctx, file);
	}
	else if (tok == PDF_TOK_ENDOBJ)
	{
		stm_ofs = 0;
	}
	else
	{
		fz_warn(ctx, "expected 'endobj' or 'stream' keyword (%d %d R)", num, gen);
		stm_ofs = 0;
	}

	if (onum) *onum = num;
	if (ogen) *ogen = gen;
	if (ostmofs) *ostmofs = stm_ofs;
	return obj;
}
示例#25
0
pdf_obj *
pdf_parse_array(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
{
    pdf_obj *ary = NULL;
    pdf_obj *obj = NULL;
    int a = 0, b = 0, n = 0;
    int tok;
    fz_context *ctx = file->ctx;
    pdf_obj *op;

    fz_var(obj);

    ary = pdf_new_array(ctx, 4);

    fz_try(ctx)
    {
        while (1)
        {
            tok = pdf_lex(file, buf);

            if (tok != PDF_TOK_INT && tok != PDF_TOK_R)
            {
                if (n > 0)
                {
                    obj = pdf_new_int(ctx, a);
                    pdf_array_push(ary, obj);
                    pdf_drop_obj(obj);
                    obj = NULL;
                }
                if (n > 1)
                {
                    obj = pdf_new_int(ctx, b);
                    pdf_array_push(ary, obj);
                    pdf_drop_obj(obj);
                    obj = NULL;
                }
                n = 0;
            }

            if (tok == PDF_TOK_INT && n == 2)
            {
                obj = pdf_new_int(ctx, a);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                a = b;
                n --;
            }

            switch (tok)
            {
            case PDF_TOK_CLOSE_ARRAY:
                op = ary;
                goto end;

            case PDF_TOK_INT:
                if (n == 0)
                    a = buf->i;
                if (n == 1)
                    b = buf->i;
                n ++;
                break;

            case PDF_TOK_R:
                if (n != 2)
                    fz_throw(ctx, "cannot parse indirect reference in array");
                obj = pdf_new_indirect(ctx, a, b, xref);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                n = 0;
                break;

            case PDF_TOK_OPEN_ARRAY:
                obj = pdf_parse_array(xref, file, buf);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;

            case PDF_TOK_OPEN_DICT:
                obj = pdf_parse_dict(xref, file, buf);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;

            case PDF_TOK_NAME:
                obj = fz_new_name(ctx, buf->scratch);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;
            case PDF_TOK_REAL:
                obj = pdf_new_real(ctx, buf->f);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;
            case PDF_TOK_STRING:
                obj = pdf_new_string(ctx, buf->scratch, buf->len);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;
            case PDF_TOK_TRUE:
                obj = pdf_new_bool(ctx, 1);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;
            case PDF_TOK_FALSE:
                obj = pdf_new_bool(ctx, 0);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;
            case PDF_TOK_NULL:
                obj = pdf_new_null(ctx);
                pdf_array_push(ary, obj);
                pdf_drop_obj(obj);
                obj = NULL;
                break;

            default:
                fz_throw(ctx, "cannot parse token in array");
            }
        }
end:
        {}
    }
    fz_catch(ctx)
    {
        pdf_drop_obj(obj);
        pdf_drop_obj(ary);
        fz_throw(ctx, "cannot parse array");
    }
    return op;
}
示例#26
0
文件: pdfposter.c 项目: andyhan/mupdf
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);
}
示例#27
0
pdf_obj *
pdf_parse_dict(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
{
    pdf_obj *dict;
    pdf_obj *key = NULL;
    pdf_obj *val = NULL;
    int tok;
    int a, b;
    fz_context *ctx = file->ctx;

    dict = pdf_new_dict(ctx, 8);

    fz_var(key);
    fz_var(val);

    fz_try(ctx)
    {
        while (1)
        {
            tok = pdf_lex(file, buf);
skip:
            if (tok == PDF_TOK_CLOSE_DICT)
                break;

            /* for BI .. ID .. EI in content streams */
            if (tok == PDF_TOK_KEYWORD && !strcmp(buf->scratch, "ID"))
                break;

            if (tok != PDF_TOK_NAME)
                fz_throw(ctx, "invalid key in dict");

            key = fz_new_name(ctx, buf->scratch);

            tok = pdf_lex(file, buf);

            switch (tok)
            {
            case PDF_TOK_OPEN_ARRAY:
                /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1643 */
                fz_try(ctx)
                {
                    val = pdf_parse_array(xref, file, buf);
                }
                fz_catch(ctx)
                {
                    fz_warn(ctx, "ignoring broken array for '%s'", pdf_to_name(key));
                    pdf_drop_obj(key);
                    val = key = NULL;
                    do
                        tok = pdf_lex(file, buf);
                    while (tok != PDF_TOK_CLOSE_DICT && tok != PDF_TOK_CLOSE_ARRAY &&
                            tok != PDF_TOK_EOF && tok != PDF_TOK_OPEN_ARRAY && tok != PDF_TOK_OPEN_DICT);
                    if (tok == PDF_TOK_CLOSE_DICT)
                        goto skip;
                    if (tok == PDF_TOK_CLOSE_ARRAY)
                        continue;
                    fz_throw(ctx, "cannot make sense of broken array after all");
                }
                break;

            case PDF_TOK_OPEN_DICT:
                val = pdf_parse_dict(xref, file, buf);
                break;

            case PDF_TOK_NAME:
                val = fz_new_name(ctx, buf->scratch);
                break;
            case PDF_TOK_REAL:
                val = pdf_new_real(ctx, buf->f);
                break;
            case PDF_TOK_STRING:
                val = pdf_new_string(ctx, buf->scratch, buf->len);
                break;
            case PDF_TOK_TRUE:
                val = pdf_new_bool(ctx, 1);
                break;
            case PDF_TOK_FALSE:
                val = pdf_new_bool(ctx, 0);
                break;
            case PDF_TOK_NULL:
                val = pdf_new_null(ctx);
                break;

            case PDF_TOK_INT:
                /* 64-bit to allow for numbers > INT_MAX and overflow */
                a = buf->i;
                tok = pdf_lex(file, buf);
                if (tok == PDF_TOK_CLOSE_DICT || tok == PDF_TOK_NAME ||
                        (tok == PDF_TOK_KEYWORD && !strcmp(buf->scratch, "ID")))
                {
                    val = pdf_new_int(ctx, a);
                    fz_dict_put(dict, key, val);
                    pdf_drop_obj(val);
                    val = NULL;
                    pdf_drop_obj(key);
                    key = NULL;
                    goto skip;
                }
                if (tok == PDF_TOK_INT)
                {
                    b = buf->i;
                    tok = pdf_lex(file, buf);
                    if (tok == PDF_TOK_R)
                    {
                        val = pdf_new_indirect(ctx, a, b, xref);
                        break;
                    }
                }
                fz_throw(ctx, "invalid indirect reference in dict");

            default:
                fz_throw(ctx, "unknown token in dict");
            }

            fz_dict_put(dict, key, val);
            pdf_drop_obj(val);
            val = NULL;
            pdf_drop_obj(key);
            key = NULL;
        }
    }
    fz_catch(ctx)
    {
        pdf_drop_obj(dict);
        pdf_drop_obj(key);
        pdf_drop_obj(val);
        fz_throw(ctx, "cannot parse dict");
    }
    return dict;
}
示例#28
0
void pdf_add_portfolio_schema(fz_context *ctx, pdf_document *doc, int entry, const pdf_portfolio_schema *info)
{
	pdf_portfolio **pp;
	pdf_portfolio *p;
	pdf_obj *s;
	pdf_obj *sc;
	int num;
	char str_name[32];
	pdf_obj *num_name = NULL;

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "Bad pdf_add_portfolio_schema call");

	if (doc->portfolio == NULL)
		load_portfolio(ctx, doc);

	fz_var(num_name);

	pp = &doc->portfolio;
	while (*pp && entry > 0)
		pp = &(*pp)->next, entry--;

	fz_try(ctx)
	{
		/* Find a name for the new schema entry */
		num = 0;
		do
		{
			pdf_drop_obj(ctx, num_name);
			num_name = NULL;
			num++;
			sprintf(str_name, "%d", num);
			num_name = pdf_new_name(ctx, doc, str_name);
			p = doc->portfolio;
			for (p = doc->portfolio; p; p = p->next)
				if (pdf_name_eq(ctx, num_name, p->key))
					break;
		}
		while (p);

		sc = pdf_new_dict(ctx, doc, 4);
		pdf_dict_put_drop(ctx, sc, PDF_NAME_E, pdf_new_bool(ctx, doc, !!info->editable));
		pdf_dict_put_drop(ctx, sc, PDF_NAME_V, pdf_new_bool(ctx, doc, !!info->visible));
		pdf_dict_put_drop(ctx, sc, PDF_NAME_N, info->name);
		pdf_dict_put(ctx, sc, PDF_NAME_Subtype, PDF_NAME_S);

		/* Add to our linked list (in the correct sorted place) */
		p = fz_malloc_struct(ctx, pdf_portfolio);
		p->entry = *info;
		p->sort = 0; /* Will be rewritten in a mo */
		p->key = pdf_keep_obj(ctx, num_name);
		p->val = pdf_keep_obj(ctx, sc);
		p->next = *pp;
		*pp = p;

		/* Add the key to the schema */
		s = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root, PDF_NAME_Collection, PDF_NAME_Schema, NULL);
		pdf_dict_put(ctx, s, num_name, sc);

		/* Renumber the schema entries */
		for (num = 0, p = doc->portfolio; p; num++, p = p->next)
		{
			pdf_dict_put_drop(ctx, p->val, PDF_NAME_O, pdf_new_int(ctx, doc, num));
			p->sort = num;
		}
	}
	fz_always(ctx)
		pdf_drop_obj(ctx, num_name);
	fz_catch(ctx)
		fz_rethrow(ctx);
}
示例#29
0
pdf_obj *
pdf_parse_ind_obj(pdf_document *xref,
                  fz_stream *file, pdf_lexbuf *buf,
                  int *onum, int *ogen, int *ostmofs)
{
    pdf_obj *obj = NULL;
    int num = 0, gen = 0, stm_ofs;
    int tok;
    int a, b;
    fz_context *ctx = file->ctx;

    fz_var(obj);

    tok = pdf_lex(file, buf);
    /* RJW: cannot parse indirect object (%d %d R)", num, gen */
    if (tok != PDF_TOK_INT)
        fz_throw(ctx, "expected object number (%d %d R)", num, gen);
    num = buf->i;

    tok = pdf_lex(file, buf);
    /* RJW: "cannot parse indirect object (%d %d R)", num, gen */
    if (tok != PDF_TOK_INT)
        fz_throw(ctx, "expected generation number (%d %d R)", num, gen);
    gen = buf->i;

    tok = pdf_lex(file, buf);
    /* RJW: "cannot parse indirect object (%d %d R)", num, gen */
    if (tok != PDF_TOK_OBJ)
        fz_throw(ctx, "expected 'obj' keyword (%d %d R)", num, gen);

    tok = pdf_lex(file, buf);
    /* RJW: "cannot parse indirect object (%d %d R)", num, gen */

    switch (tok)
    {
    case PDF_TOK_OPEN_ARRAY:
        obj = pdf_parse_array(xref, file, buf);
        /* RJW: "cannot parse indirect object (%d %d R)", num, gen */
        break;

    case PDF_TOK_OPEN_DICT:
        obj = pdf_parse_dict(xref, file, buf);
        /* RJW: "cannot parse indirect object (%d %d R)", num, gen */
        break;

    case PDF_TOK_NAME:
        obj = fz_new_name(ctx, buf->scratch);
        break;
    case PDF_TOK_REAL:
        obj = pdf_new_real(ctx, buf->f);
        break;
    case PDF_TOK_STRING:
        obj = pdf_new_string(ctx, buf->scratch, buf->len);
        break;
    case PDF_TOK_TRUE:
        obj = pdf_new_bool(ctx, 1);
        break;
    case PDF_TOK_FALSE:
        obj = pdf_new_bool(ctx, 0);
        break;
    case PDF_TOK_NULL:
        obj = pdf_new_null(ctx);
        break;

    case PDF_TOK_INT:
        a = buf->i;
        tok = pdf_lex(file, buf);
        /* "cannot parse indirect object (%d %d R)", num, gen */
        if (tok == PDF_TOK_STREAM || tok == PDF_TOK_ENDOBJ)
        {
            obj = pdf_new_int(ctx, a);
            goto skip;
        }
        if (tok == PDF_TOK_INT)
        {
            b = buf->i;
            tok = pdf_lex(file, buf);
            /* RJW: "cannot parse indirect object (%d %d R)", num, gen); */
            if (tok == PDF_TOK_R)
            {
                obj = pdf_new_indirect(ctx, a, b, xref);
                break;
            }
        }
        fz_throw(ctx, "expected 'R' keyword (%d %d R)", num, gen);

    case PDF_TOK_ENDOBJ:
        obj = pdf_new_null(ctx);
        goto skip;

    default:
        fz_throw(ctx, "syntax error in object (%d %d R)", num, gen);
    }

    fz_try(ctx)
    {
        tok = pdf_lex(file, buf);
    }
    fz_catch(ctx)
    {
        pdf_drop_obj(obj);
        fz_throw(ctx, "cannot parse indirect object (%d %d R)", num, gen);
    }

skip:
    if (tok == PDF_TOK_STREAM)
    {
        int c = fz_read_byte(file);
        while (c == ' ')
            c = fz_read_byte(file);
        if (c == '\r')
        {
            c = fz_peek_byte(file);
            if (c != '\n')
                fz_warn(ctx, "line feed missing after stream begin marker (%d %d R)", num, gen);
            else
                fz_read_byte(file);
        }
        stm_ofs = fz_tell(file);
    }
    else if (tok == PDF_TOK_ENDOBJ)
    {
        stm_ofs = 0;
    }
    else
    {
        fz_warn(ctx, "expected 'endobj' or 'stream' keyword (%d %d R)", num, gen);
        stm_ofs = 0;
    }

    if (onum) *onum = num;
    if (ogen) *ogen = gen;
    if (ostmofs) *ostmofs = stm_ofs;
    return obj;
}
示例#30
0
int pdf_add_portfolio_entry(fz_context *ctx, pdf_document *doc,
				const char *name, int name_len,
				const char *desc, int desc_len,
				const char *filename, int filename_len,
				const char *unifile, int unifile_len, fz_buffer *buf)
{
	int entry, len;
	pdf_obj *ef, *f, *params, *s;
	pdf_obj *key;
	pdf_obj *val = NULL;

	fz_var(val);

	if (!doc)
		fz_throw(ctx, FZ_ERROR_GENERIC, "Bad pdf_add_portfolio_entry call");

	if (doc->portfolio == NULL)
		load_portfolio(ctx, doc);

	key = pdf_new_string(ctx, doc, name, name_len);
	fz_try(ctx)
	{
		val = pdf_new_dict(ctx, doc, 6);
		pdf_dict_put_drop(ctx, val, PDF_NAME_CI, pdf_new_dict(ctx, doc, 4));
		pdf_dict_put_drop(ctx, val, PDF_NAME_EF, (ef = pdf_new_dict(ctx, doc, 4)));
		pdf_dict_put_drop(ctx, val, PDF_NAME_F, pdf_new_string(ctx, doc, filename, filename_len));
		pdf_dict_put_drop(ctx, val, PDF_NAME_UF, pdf_new_string(ctx, doc, unifile, unifile_len));
		pdf_dict_put_drop(ctx, val, PDF_NAME_Desc, pdf_new_string(ctx, doc, desc, desc_len));
		pdf_dict_put_drop(ctx, val, PDF_NAME_Type, PDF_NAME_Filespec);
		pdf_dict_put_drop(ctx, ef, PDF_NAME_F, (f = pdf_add_stream(ctx, doc, buf, NULL, 0)));
		len = fz_buffer_storage(ctx, buf, NULL);
		pdf_dict_put_drop(ctx, f, PDF_NAME_DL, pdf_new_int(ctx, doc, len));
		pdf_dict_put_drop(ctx, f, PDF_NAME_Length, pdf_new_int(ctx, doc, len));
		pdf_dict_put_drop(ctx, f, PDF_NAME_Params, (params = pdf_new_dict(ctx, doc, 4)));
		pdf_dict_put_drop(ctx, params, PDF_NAME_Size, pdf_new_int(ctx, doc, len));

		s = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root, PDF_NAME_Collection, NULL);
		if (s == NULL)
		{
			s = pdf_new_dict(ctx, doc, 4);
			pdf_dict_putl_drop(ctx, pdf_trailer(ctx, doc), s, PDF_NAME_Root, PDF_NAME_Collection, NULL);
		}

		s = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root, PDF_NAME_Names, PDF_NAME_EmbeddedFiles, NULL);
		if (s == NULL)
		{
			s = pdf_new_dict(ctx, doc, 4);
			pdf_dict_putl_drop(ctx, pdf_trailer(ctx, doc), s, PDF_NAME_Root, PDF_NAME_Names, PDF_NAME_EmbeddedFiles, NULL);
		}
		entry = pdf_name_tree_insert(ctx, doc, s, key, val);
	}
	fz_always(ctx)
	{
		pdf_drop_obj(ctx, key);
		pdf_drop_obj(ctx, val);
	}
	fz_catch(ctx)
		fz_rethrow(ctx);

	return entry;
}