Example #1
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;
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #4
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 ++;
}
Example #5
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);
	}
}
Example #6
0
void pdf_set_text_annot_position(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_puts_drop(annot->obj, "Rect", pdf_new_rect(doc, &rect));

	flags = pdf_to_int(pdf_dict_gets(annot->obj, "F"));
	flags |= (F_NoZoom|F_NoRotate);
	pdf_dict_puts_drop(annot->obj, "F", pdf_new_int(doc, flags));

	update_rect(doc->ctx, annot);
}
Example #7
0
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);
  
}
Example #8
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");
	}
}
Example #9
0
static void insert_resource_name(pdf_csi *csi, pdf_filter_state *state, const char *key, const char *name)
{
	pdf_obj *xobj;
	pdf_obj *obj;

	if (!state->resources || !name || name[0] == 0)
		return;

	xobj = pdf_dict_gets(csi->rdb, key);
	obj = pdf_dict_gets(xobj, name);

	xobj = pdf_dict_gets(state->resources, key);
	if (xobj == NULL) {
		xobj = pdf_new_dict(csi->doc, 1);
		pdf_dict_puts_drop(state->resources, key, xobj);
	}
	pdf_dict_putp(xobj, name, obj);
}
Example #10
0
void
pdf_set_markup_annot_quadpoints(pdf_document *doc, pdf_annot *annot, fz_point *qp, int n)
{
	fz_matrix ctm;
	pdf_obj *arr = pdf_new_array(doc, n*2);
	int i;

	fz_invert_matrix(&ctm, &annot->page->ctm);

	pdf_dict_puts_drop(annot->obj, "QuadPoints", arr);

	for (i = 0; i < n; i++)
	{
		fz_point pt = qp[i];
		pdf_obj *r;

		fz_transform_point(&pt, &ctm);
		r = pdf_new_real(doc, pt.x);
		pdf_array_push_drop(arr, r);
		r = pdf_new_real(doc, pt.y);
		pdf_array_push_drop(arr, r);
	}
}
Example #11
0
static int copy_and_rename_resources(fz_context *dest_ctx, pdf_obj *dest, 
	fz_context *src_ctx, pdf_obj *src, struct put_info *info)
{
    static char *RESOURCE_TYPES[] = 
		{ "ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", 
		  "Font", "Properties" };
	static char *RESOURCE_PREFIXES[] =
		{ "E_", "C_", "P_", "S_", "X_", "F_", "T_" };
    static const size_t RESOURCE_TYPES_COUNT = 
		sizeof(RESOURCE_TYPES) / sizeof(RESOURCE_TYPES[0]);

    size_t i;
    for(i = 0; i < RESOURCE_TYPES_COUNT; i++) {
        pdf_obj *src_type = pdf_dict_gets(src_ctx, src, RESOURCE_TYPES[i]);
        pdf_obj *dest_type = pdf_dict_gets(dest_ctx, dest, RESOURCE_TYPES[i]);

		/* we only copy resource-dicts that exist in the source-page ;) */
		if(pdf_is_dict(src_ctx, src_type)) {printf("TODO: REMOVEME: Copying and renaming resources of type %s!!!\n", RESOURCE_TYPES[i]);
			/* if this kind of dict does not exists in the dest resources, 
			   we must create it */
			if(!pdf_is_dict(dest_ctx, dest_type)) {
				dest_type = pdf_new_dict(dest_ctx, info->dest_doc, 8);
				pdf_dict_puts_drop(dest_ctx, dest, RESOURCE_TYPES[i], dest_type);
			}

			if(copy_and_rename_resource(dest_ctx, dest_type, 
				src_ctx, src_type, RESOURCE_PREFIXES[i], info))
			{
				return(2);
			}
		}
	}

    // TODO: Merge Procedure-Sets (although they are obsolete)

	return(0);
}
Example #12
0
static void
write_variable_text(fz_context *ctx, pdf_annot *annot, fz_buffer *buf, pdf_obj **res,
	const char *text, const char *fontname, float size, float color[3], int q,
	float w, float h, float padding, float baseline, float lineheight,
	int multiline, int comb, int adjust_baseline)
{
	pdf_obj *res_font;
	fz_font *font;

	w -= padding * 2;
	h -= padding * 2;

	font = fz_new_base14_font(ctx, full_font_name(&fontname));
	fz_try(ctx)
	{
		if (size == 0)
		{
			if (multiline)
				size = 12;
			else
			{
				size = w / measure_simple_string(ctx, font, text);
				if (size > h)
					size = h;
			}
		}

		lineheight = size * lineheight;
		baseline = size * baseline;

		if (adjust_baseline)
		{
			/* Make sure baseline is inside rectangle */
			if (baseline + 0.2f * size > h)
				baseline = h - 0.2f * size;
		}

		/* /Resources << /Font << /Helv %d 0 R >> >> */
		*res = pdf_new_dict(ctx, annot->page->doc, 1);
		res_font = pdf_dict_put_dict(ctx, *res, PDF_NAME(Font), 1);
		pdf_dict_puts_drop(ctx, res_font, fontname, pdf_add_simple_font(ctx, annot->page->doc, font, 0));

		fz_append_string(ctx, buf, "BT\n");
		fz_append_printf(ctx, buf, "%g %g %g rg\n", color[0], color[1], color[2]);
		fz_append_printf(ctx, buf, "/%s %g Tf\n", fontname, size);
		if (multiline)
		{
			fz_append_printf(ctx, buf, "%g TL\n", lineheight);
			fz_append_printf(ctx, buf, "%g %g Td\n", padding, padding+h-baseline+lineheight);
			write_simple_string_with_quadding(ctx, buf, font, size, text, w, q);
		}
		else if (comb > 0)
		{
			float ty = (h - size) / 2;
			fz_append_printf(ctx, buf, "%g %g Td\n", padding, padding+h-baseline-ty);
			write_comb_string(ctx, buf, text, text + strlen(text), font, (w * 1000 / size) / comb);
		}
		else
		{
			float tx = 0, ty = (h - size) / 2;
			if (q > 0)
			{
				float tw = measure_simple_string(ctx, font, text) * size;
				if (q == 1)
					tx = (w - tw) / 2;
				else
					tx = (w - tw);
			}
			fz_append_printf(ctx, buf, "%g %g Td\n", padding+tx, padding+h-baseline-ty);
			write_simple_string(ctx, buf, text, text + strlen(text));
			fz_append_printf(ctx, buf, " Tj\n");
		}
		fz_append_string(ctx, buf, "ET\n");
	}
	fz_always(ctx)
		fz_drop_font(ctx, font);
	fz_catch(ctx)
		fz_rethrow(ctx);
}
Example #13
0
void pdf_set_annot_contents(pdf_document *doc, pdf_annot *annot, char *text)
{
	pdf_dict_puts_drop(annot->obj, "Contents", pdf_new_string(doc, text, strlen(text)));
}
Example #14
0
void
pdf_set_ink_annot_list(pdf_document *doc, pdf_annot *annot, fz_point *pts, int *counts, int ncount, float color[3], float thickness)
{
	fz_context *ctx = doc->ctx;
	fz_matrix ctm;
	pdf_obj *list = pdf_new_array(doc, ncount);
	pdf_obj *bs, *col;
	fz_rect rect;
	int i, k = 0;

	fz_invert_matrix(&ctm, &annot->page->ctm);

	pdf_dict_puts_drop(annot->obj, "InkList", list);

	for (i = 0; i < ncount; i++)
	{
		int j;
		pdf_obj *arc = pdf_new_array(doc, counts[i]);

		pdf_array_push_drop(list, arc);

		for (j = 0; j < counts[i]; j++)
		{
			fz_point pt = pts[k];

			fz_transform_point(&pt, &ctm);

			if (i == 0 && j == 0)
			{
				rect.x0 = rect.x1 = pt.x;
				rect.y0 = rect.y1 = pt.y;
			}
			else
			{
				fz_include_point_in_rect(&rect, &pt);
			}

			pdf_array_push_drop(arc, pdf_new_real(doc, pt.x));
			pdf_array_push_drop(arc, pdf_new_real(doc, pt.y));
			k++;
		}
	}

	/*
		Expand the rectangle by thickness all around. We cannot use
		fz_expand_rect because the rectangle might be empty in the
		single point case
	*/
	if (k > 0)
	{
		rect.x0 -= thickness;
		rect.y0 -= thickness;
		rect.x1 += thickness;
		rect.y1 += thickness;
	}

	pdf_dict_puts_drop(annot->obj, "Rect", pdf_new_rect(doc, &rect));
	update_rect(ctx, annot);

	bs = pdf_new_dict(doc, 1);
	pdf_dict_puts_drop(annot->obj, "BS", bs);
	pdf_dict_puts_drop(bs, "W", pdf_new_real(doc, thickness));

	col = pdf_new_array(doc, 3);
	pdf_dict_puts_drop(annot->obj, "C", col);
	for (i = 0; i < 3; i++)
		pdf_array_push_drop(col, pdf_new_real(doc, color[i]));
}
Example #15
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 */
}
void
pdf_set_free_text_details(fz_context *ctx, pdf_annot *annot, fz_point *pos, char *text, char *font_name, float font_size, float color[3])
{
	pdf_document *doc = annot->page->doc;
	char nbuf[32];
	pdf_obj *dr;
	pdf_obj *form_fonts;
	pdf_obj *font = NULL;
	pdf_obj *ref;
	pdf_font_desc *font_desc = NULL;
	fz_matrix page_ctm, inv_page_ctm;
	pdf_da_info da_info;
	fz_buffer *fzbuf = NULL;
	fz_point page_pos;

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

	dr = pdf_dict_get(ctx, annot->page->obj, PDF_NAME_Resources);
	if (!dr)
	{
		dr = pdf_new_dict(ctx, doc, 1);
		pdf_dict_put_drop(ctx, annot->page->obj, PDF_NAME_Resources, dr);
	}

	/* Ensure the resource dictionary includes a font dict */
	form_fonts = pdf_dict_get(ctx, dr, PDF_NAME_Font);
	if (!form_fonts)
	{
		form_fonts = pdf_new_dict(ctx, doc, 1);
		pdf_dict_put_drop(ctx, dr, PDF_NAME_Font, form_fonts);
		/* form_fonts is still valid if execution continues past the above call */
	}

	fz_var(fzbuf);
	fz_var(font);
	fz_try(ctx)
	{
		unsigned char *da_str;
		size_t da_len;
		fz_rect bounds;

		find_free_font_name(ctx, form_fonts, nbuf, sizeof(nbuf));

		font = pdf_new_dict(ctx, doc, 5);
		ref = pdf_add_object(ctx, doc, font);
		pdf_dict_puts_drop(ctx, form_fonts, nbuf, ref);

		pdf_dict_put_drop(ctx, font, PDF_NAME_Type, PDF_NAME_Font);
		pdf_dict_put_drop(ctx, font, PDF_NAME_Subtype, PDF_NAME_Type1);
		pdf_dict_put_drop(ctx, font, PDF_NAME_BaseFont, pdf_new_name(ctx, doc, font_name));
		pdf_dict_put_drop(ctx, font, PDF_NAME_Encoding, PDF_NAME_WinAnsiEncoding);

		memcpy(da_info.col, color, sizeof(float)*3);
		da_info.col_size = 3;
		da_info.font_name = nbuf;
		da_info.font_size = font_size;

		fzbuf = fz_new_buffer(ctx, 0);
		pdf_fzbuf_print_da(ctx, fzbuf, &da_info);

		da_len = fz_buffer_storage(ctx, fzbuf, &da_str);
		pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_DA, pdf_new_string(ctx, doc, (char *)da_str, da_len));

		/* FIXME: should convert to WinAnsiEncoding */
		pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Contents, pdf_new_string(ctx, doc, text, strlen(text)));

		font_desc = pdf_load_font(ctx, doc, NULL, font, 0);
		pdf_measure_text(ctx, font_desc, (unsigned char *)text, strlen(text), &bounds);

		page_pos = *pos;
		fz_transform_point(&page_pos, &inv_page_ctm);

		bounds.x0 *= font_size;
		bounds.x1 *= font_size;
		bounds.y0 *= font_size;
		bounds.y1 *= font_size;

		bounds.x0 += page_pos.x;
		bounds.x1 += page_pos.x;
		bounds.y0 += page_pos.y;
		bounds.y1 += page_pos.y;

		pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &bounds));
	}
	fz_always(ctx)
	{
		pdf_drop_obj(ctx, font);
		fz_drop_buffer(ctx, fzbuf);
		pdf_drop_font(ctx, font_desc);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Example #17
0
void pdf_set_free_text_details(pdf_document *doc, pdf_annot *annot, fz_point *pos, char *text, char *font_name, float font_size, float color[3])
{
	fz_context *ctx = doc->ctx;
	char nbuf[32];
	pdf_obj *dr;
	pdf_obj *form_fonts;
	pdf_obj *font = NULL;
	pdf_obj *ref;
	pdf_font_desc *font_desc = NULL;
	pdf_da_info da_info;
	fz_buffer *fzbuf = NULL;
	fz_matrix ctm;
	fz_point page_pos;

	fz_invert_matrix(&ctm, &annot->page->ctm);

	dr = pdf_dict_gets(annot->page->me, "Resources");
	if (!dr)
	{
		dr = pdf_new_dict(doc, 1);
		pdf_dict_putp_drop(annot->page->me, "Resources", dr);
	}

	/* Ensure the resource dictionary includes a font dict */
	form_fonts = pdf_dict_gets(dr, "Font");
	if (!form_fonts)
	{
		form_fonts = pdf_new_dict(doc, 1);
		pdf_dict_puts_drop(dr, "Font", form_fonts);
		/* form_fonts is still valid if execution continues past the above call */
	}

	fz_var(fzbuf);
	fz_var(font);
	fz_try(ctx)
	{
		unsigned char *da_str;
		int da_len;
		fz_rect bounds;

		find_free_font_name(form_fonts, nbuf, sizeof(nbuf));

		font = pdf_new_dict(doc, 5);
		ref = pdf_new_ref(doc, font);
		pdf_dict_puts_drop(form_fonts, nbuf, ref);

		pdf_dict_puts_drop(font, "Type", pdf_new_name(doc, "Font"));
		pdf_dict_puts_drop(font, "Subtype", pdf_new_name(doc, "Type1"));
		pdf_dict_puts_drop(font, "BaseFont", pdf_new_name(doc, font_name));
		pdf_dict_puts_drop(font, "Encoding", pdf_new_name(doc, "WinAnsiEncoding"));

		memcpy(da_info.col, color, sizeof(float)*3);
		da_info.col_size = 3;
		da_info.font_name = nbuf;
		da_info.font_size = font_size;

		fzbuf = fz_new_buffer(ctx, 0);
		pdf_fzbuf_print_da(ctx, fzbuf, &da_info);

		da_len = fz_buffer_storage(ctx, fzbuf, &da_str);
		pdf_dict_puts_drop(annot->obj, "DA", pdf_new_string(doc, (char *)da_str, da_len));

		/* FIXME: should convert to WinAnsiEncoding */
		pdf_dict_puts_drop(annot->obj, "Contents", pdf_new_string(doc, text, strlen(text)));

		font_desc = pdf_load_font(doc, NULL, font, 0);
		pdf_measure_text(ctx, font_desc, (unsigned char *)text, strlen(text), &bounds);

		page_pos = *pos;
		fz_transform_point(&page_pos, &ctm);

		bounds.x0 *= font_size;
		bounds.x1 *= font_size;
		bounds.y0 *= font_size;
		bounds.y1 *= font_size;

		bounds.x0 += page_pos.x;
		bounds.x1 += page_pos.x;
		bounds.y0 += page_pos.y;
		bounds.y1 += page_pos.y;

		pdf_dict_puts_drop(annot->obj, "Rect", pdf_new_rect(doc, &bounds));
		update_rect(ctx, annot);
	}
	fz_always(ctx)
	{
		pdf_drop_obj(font);
		fz_drop_buffer(ctx, fzbuf);
		pdf_drop_font(ctx, font_desc);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Example #18
0
pdf_annot *
pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type)
{
	fz_context *ctx = doc->ctx;
	pdf_annot *annot = NULL;
	pdf_obj *annot_obj = pdf_new_dict(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_gets(page->me, "Annots");
		if (annot_arr == NULL)
		{
			annot_arr = pdf_new_array(doc, 0);
			pdf_dict_puts_drop(page->me, "Annots", annot_arr);
		}

		pdf_dict_puts_drop(annot_obj, "Type", pdf_new_name(doc, "Annot"));

		pdf_dict_puts_drop(annot_obj, "Subtype", pdf_new_name(doc, type_str));
		pdf_dict_puts_drop(annot_obj, "Rect", pdf_new_rect(doc, &rect));

		/* Make printable as default */
		pdf_dict_puts_drop(annot_obj, "F", pdf_new_int(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(doc);
		pdf_update_object(doc, ind_obj_num, annot_obj);
		ind_obj = pdf_new_indirect(doc, ind_obj_num, 0);
		pdf_array_push(annot_arr, ind_obj);
		annot->obj = pdf_keep_obj(ind_obj);

		/*
			Linking must be done after any call that might throw because
			pdf_free_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(annot_obj);
		pdf_drop_obj(ind_obj);
	}
	fz_catch(ctx)
	{
		pdf_free_annot(ctx, annot);
		fz_rethrow(ctx);
	}

	return annot;
}
Example #19
0
/* dest points to the new pages content-streams-dict, src is a reference to 
   one source content-stream */
int copy_content_stream_of_page(fz_context *dest_ctx, pdf_obj *dest, 
	fz_context *src_ctx, pdf_obj *src, 
	struct put_info *info, struct pos_info *pos)
{
	if(!pdf_is_array(dest_ctx, dest) && !pdf_is_indirect(src_ctx, src))
		return(-1);

	/*
	  translation:  1     0    0    1     diff_x diff_y
	  scale:        scale 0    0    scale 0      0
	  rotation:     cos   sin  -sin cos   0      0
	  -------------------------------------------------
	  rotation 0:   1     0    0    1     0      0
	  rotation 90:  0     1    -1   0     0      0
	  rotation 180: -1    0    0    -1    0      0
	  rotation 270: 0     -1   1    0     0      0 
	*/

	fz_buffer *buffer = fz_new_buffer(dest_ctx, 1024);
	fz_output *output = fz_new_output_with_buffer(dest_ctx, buffer);

	fz_printf(dest_ctx, output, "q\n");

	/* set the outer clip region */
	fz_printf(dest_ctx, output, "%f %f %f %f re W n\n", 
		pos->outer_clip_x, pos->outer_clip_y, 
		pos->outer_clip_width, pos->outer_clip_height);

	/* position the page correctly */
	if(pos->rotate == 0) {
		fz_printf(dest_ctx, output, "1 0 0 1 %f %f cm\n", 
			pos->x + pos->content_translate_x, pos->y + pos->content_translate_y);
	} else if(pos->rotate == 90) {
		fz_printf(dest_ctx, output, "0 1 -1 0 %f %f cm\n", pos->x + pos->width, pos->y);
	} else if(pos->rotate == 180) {
		fz_printf(dest_ctx, output, "-1 0 0 -1 %f %f cm\n", 
			pos->width + pos->x - pos->content_translate_x, 
			pos->height + pos->y - pos->content_translate_y);
	} else if(pos->rotate == 270) {
		fz_printf(dest_ctx, output, "0 -1 1 0 %f %f cm\n", pos->x, pos->y + pos->height);
	}
	
	if(pos->bleed_clip_x != 0.0 || pos->bleed_clip_y != 0.0 || 
		pos->bleed_clip_width != 0.0 || pos->bleed_clip_height != 0.0)
	{
		fz_printf(dest_ctx, output, "%f %f %f %f re W n\n", 
			pos->bleed_clip_x, pos->bleed_clip_y, pos->bleed_clip_width, pos->bleed_clip_height);
	}

 	int src_num = pdf_to_num(src_ctx, src);
	int src_gen = pdf_to_gen(src_ctx, src);
	fz_stream *input = pdf_open_stream(src_ctx, info->src_doc, src_num, src_gen);

	rename_res_in_content_stream(src_ctx, input, dest_ctx, output, info->rename_dict);

	fz_printf(dest_ctx, output, "Q");

	fz_drop_output(dest_ctx, output);
	fz_drop_stream(dest_ctx, input);
	
	int new_num = pdf_create_object(dest_ctx, info->dest_doc);
	pdf_obj *new_ref = pdf_new_indirect(dest_ctx, info->dest_doc, new_num, 0);

	/* each stream has a dict containing at least its length... */
	pdf_obj *stream_info_dict = pdf_new_dict(dest_ctx, info->dest_doc, 1);
	pdf_dict_puts_drop(dest_ctx, stream_info_dict, "Length", pdf_new_int(dest_ctx, info->dest_doc, buffer->len));
	pdf_update_object(dest_ctx, info->dest_doc, new_num, stream_info_dict);
	pdf_drop_obj(dest_ctx, stream_info_dict);

	pdf_update_stream(dest_ctx, info->dest_doc, new_ref, buffer, 0);
	fz_drop_buffer(dest_ctx, buffer);

	pdf_array_push(dest_ctx, dest, new_ref);
	pdf_drop_obj(dest_ctx, new_ref);

	return(0);
}