Beispiel #1
0
static pdf_annot *
pdf_create_highlight_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 512);
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	fz_obj *quad_points = fz_dict_gets(ctx, obj, "QuadPoints");
	fz_obj *resources = pdf_dict_from_string(xref, ANNOT_HIGHLIGHT_AP_RESOURCES);
	fz_rect a, b;
	float rgb[3];
	float skew;
	int i;

	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		skew = 0.15 * fabs(a.y0 - b.y0);
		b.x0 -= skew; b.x1 += skew;
		rect = fz_union_rect(rect, fz_union_rect(a, b));
	}
	pdf_get_annot_color(ctx, obj, rgb);

	fz_buffer_printf(ctx, content, "q /GS gs %.4f %.4f %.4f rg 1 0 0 1 -%.4f -%.4f cm ",
		rgb[0], rgb[1], rgb[2], rect.x0, rect.y0);
	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		skew = 0.15 * fabs(a.y0 - b.y0);
		fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l %.4f %.4f l %.4f %.4f l h ",
			a.x0, a.y0, b.x1 + skew, b.y1, a.x1, a.y1, b.x0 - skew, b.y0);
	}
	fz_buffer_printf(ctx, content, "f Q");

	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, resources, 1);
}
Beispiel #2
0
static void
pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
{
	fz_obj *obj;
	float d0, d1;
	int e0, e1;
	float x0, y0, r0, x1, y1, r1;
	struct vertex p1, p2;
	fz_context *ctx = xref->ctx;

	obj = fz_dict_gets(ctx, dict, "Coords");
	x0 = fz_to_real(ctx, fz_array_get(ctx, obj, 0));
	y0 = fz_to_real(ctx, fz_array_get(ctx, obj, 1));
	r0 = fz_to_real(ctx, fz_array_get(ctx, obj, 2));
	x1 = fz_to_real(ctx, fz_array_get(ctx, obj, 3));
	y1 = fz_to_real(ctx, fz_array_get(ctx, obj, 4));
	r1 = fz_to_real(ctx, fz_array_get(ctx, obj, 5));

	d0 = 0;
	d1 = 1;
	obj = fz_dict_gets(ctx, dict, "Domain");
	if (fz_array_len(ctx, obj) == 2)
	{
		d0 = fz_to_real(ctx, fz_array_get(ctx, obj, 0));
		d1 = fz_to_real(ctx, fz_array_get(ctx, obj, 1));
	}

	e0 = e1 = 0;
	obj = fz_dict_gets(ctx, dict, "Extend");
	if (fz_array_len(ctx, obj) == 2)
	{
		e0 = fz_to_bool(ctx, fz_array_get(ctx, obj, 0));
		e1 = fz_to_bool(ctx, fz_array_get(ctx, obj, 1));
	}

	pdf_sample_shade_function(ctx, shade, funcs, func, d0, d1);

	shade->type = FZ_RADIAL;

	shade->extend[0] = e0;
	shade->extend[1] = e1;

	p1.x = x0;
	p1.y = y0;
	p1.c[0] = r0;
	pdf_add_vertex(ctx, shade, &p1);

	p2.x = x1;
	p2.y = y1;
	p2.c[0] = r1;
	pdf_add_vertex(ctx, shade, &p2);
}
Beispiel #3
0
static void
pdf_load_mesh_params(pdf_xref *xref, fz_obj *dict, struct mesh_params *p)
{
	fz_obj *obj;
	int i, n;
	fz_context *ctx = xref->ctx;

	p->x0 = p->y0 = 0;
	p->x1 = p->y1 = 1;
	for (i = 0; i < FZ_MAX_COLORS; i++)
	{
		p->c0[i] = 0;
		p->c1[i] = 1;
	}

	p->vprow = fz_to_int(ctx, fz_dict_gets(ctx, dict, "VerticesPerRow"));
	p->bpflag = fz_to_int(ctx, fz_dict_gets(ctx, dict, "BitsPerFlag"));
	p->bpcoord = fz_to_int(ctx, fz_dict_gets(ctx, dict, "BitsPerCoordinate"));
	p->bpcomp = fz_to_int(ctx, fz_dict_gets(ctx, dict, "BitsPerComponent"));

	obj = fz_dict_gets(ctx, dict, "Decode");
	if (fz_array_len(ctx, obj) >= 6)
	{
		n = (fz_array_len(ctx, obj) - 4) / 2;
		p->x0 = fz_to_real(ctx, fz_array_get(ctx, obj, 0));
		p->x1 = fz_to_real(ctx, fz_array_get(ctx, obj, 1));
		p->y0 = fz_to_real(ctx, fz_array_get(ctx, obj, 2));
		p->y1 = fz_to_real(ctx, fz_array_get(ctx, obj, 3));

		for (i = 0; i < n; i++)
		{
			p->c0[i] = fz_to_real(ctx, fz_array_get(ctx, obj, 4 + i * 2));
			p->c1[i] = fz_to_real(ctx, fz_array_get(ctx, obj, 5 + i * 2));
		}
	}

	if (p->vprow < 2)
		p->vprow = 2;

	if (p->bpflag != 2 && p->bpflag != 4 && p->bpflag != 8)
		p->bpflag = 8;

	if (p->bpcoord != 1 && p->bpcoord != 2 && p->bpcoord != 4 &&
		p->bpcoord != 8 && p->bpcoord != 12 && p->bpcoord != 16 &&
		p->bpcoord != 24 && p->bpcoord != 32)
		p->bpcoord = 8;

	if (p->bpcomp != 1 && p->bpcomp != 2 && p->bpcomp != 4 &&
		p->bpcomp != 8 && p->bpcomp != 12 && p->bpcomp != 16)
		p->bpcomp = 8;
}
static void
pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
{
	fz_obj *obj;
	float d0, d1;
	int e0, e1;
	float x0, y0, x1, y1;
	struct vertex p1, p2;

	obj = fz_dict_gets(dict, "Coords");
	x0 = fz_to_real(fz_array_get(obj, 0));
	y0 = fz_to_real(fz_array_get(obj, 1));
	x1 = fz_to_real(fz_array_get(obj, 2));
	y1 = fz_to_real(fz_array_get(obj, 3));

	d0 = 0;
	d1 = 1;
	obj = fz_dict_gets(dict, "Domain");
	if (fz_array_len(obj) == 2)
	{
		d0 = fz_to_real(fz_array_get(obj, 0));
		d1 = fz_to_real(fz_array_get(obj, 1));
	}

	e0 = e1 = 0;
	obj = fz_dict_gets(dict, "Extend");
	if (fz_array_len(obj) == 2)
	{
		e0 = fz_to_bool(fz_array_get(obj, 0));
		e1 = fz_to_bool(fz_array_get(obj, 1));
	}

	pdf_sample_shade_function(shade, funcs, func, d0, d1);

	shade->type = FZ_LINEAR;

	shade->extend[0] = e0;
	shade->extend[1] = e1;

	p1.x = x0;
	p1.y = y0;
	p1.c[0] = 0;
	pdf_add_vertex(shade, &p1);

	p2.x = x1;
	p2.y = y1;
	p2.c[0] = 0;
	pdf_add_vertex(shade, &p2);
}
Beispiel #5
0
static fz_error
pdf_read_ocg(pdf_xref *xref)
{
	fz_obj *obj, *ocg;
	int len, i;
	pdf_ocg_descriptor *desc;

	obj = fz_dict_gets(fz_dict_gets(xref->trailer, "Root"), "OCProperties");
	if (obj == NULL)
		return fz_okay;
	ocg = fz_dict_gets(obj, "OCGs");
	if (ocg == NULL || !fz_is_array(ocg))
		/* Not ever supposed to happen, but live with it. */
		return fz_okay;
	len = fz_array_len(ocg);
	desc = fz_malloc(sizeof(*desc));
	desc->len = len;
	desc->ocgs = fz_calloc(len, sizeof(*desc->ocgs));
	desc->intent = NULL;

	for (i=0; i < len; i++)
	{
		fz_obj *o = fz_array_get(ocg, i);
		desc->ocgs[i].num = fz_to_num(o);
		desc->ocgs[i].gen = fz_to_gen(o);
		desc->ocgs[i].state = 0;
	}
	xref->ocg = desc;

	return pdf_ocg_set_config(xref, 0);
}
Beispiel #6
0
/* SumatraPDF: partial support for link borders */
static pdf_annot *
pdf_create_link_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_obj *border, *dashes;
	fz_buffer *content;
	fz_rect rect;
	float rgb[3];
	int i;

	border = fz_dict_gets(xref->ctx, obj, "Border");
	if (fz_to_real(xref->ctx, fz_array_get(xref->ctx, border, 2)) <= 0)
		return NULL;

	pdf_get_annot_color(xref->ctx, obj, rgb);
	dashes = fz_array_get(xref->ctx, border, 3);
	rect = pdf_to_rect(xref->ctx, fz_dict_gets(xref->ctx, obj, "Rect"));

	obj = pdf_clone_for_view_only(xref, obj);

	// TODO: draw rounded rectangles if the first two /Border values are non-zero
	content = fz_new_buffer(xref->ctx, 128);
	fz_buffer_printf(xref->ctx, content, "q %.4f w [", fz_to_real(xref->ctx, fz_array_get(xref->ctx, border, 2)));
	for (i = 0; i < fz_array_len(xref->ctx, dashes); i++)
		fz_buffer_printf(xref->ctx, content, "%.4f ", fz_to_real(xref->ctx, fz_array_get(xref->ctx, dashes, i)));
	fz_buffer_printf(xref->ctx, content, "] 0 d %.4f %.4f %.4f RG 0 0 %.4f %.4f re S Q",
		rgb[0], rgb[1], rgb[2], rect.x1 - rect.x0, rect.y1 - rect.y0);

	return pdf_create_annot(xref->ctx, rect, obj, content, NULL, 0);
}
Beispiel #7
0
void
pdf_load_links(pdf_link **linkp, pdf_xref *xref, fz_obj *annots)
{
	pdf_link *link, *head, *tail;
	fz_obj *obj;
	int i;
	fz_context *ctx = xref->ctx;

	head = tail = NULL;
	link = NULL;

	for (i = 0; i < fz_array_len(ctx, annots); i++)
	{
		obj = fz_array_get(ctx, annots, i);
		link = pdf_load_link(xref, obj);
		if (link)
		{
			if (!head)
				head = tail = link;
			else
			{
				tail->next = link;
				tail = link;
			}
		}
	}

	*linkp = head;
}
/*
 * Load uncompressed contents of a stream into buf.
 */
fz_error
pdf_load_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *dict, *obj;
	int i, len;

	error = pdf_open_stream(&stm, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot open stream (%d %d R)", num, gen);

	error = pdf_load_object(&dict, xref, num, gen);
	if (error)
		return fz_rethrow(error, "cannot load stream dictionary (%d %d R)", num, gen);

	len = fz_to_int(fz_dict_gets(dict, "Length"));
	obj = fz_dict_gets(dict, "Filter");
	len = pdf_guess_filter_length(len, fz_to_name(obj));
	for (i = 0; i < fz_array_len(obj); i++)
		len = pdf_guess_filter_length(len, fz_to_name(fz_array_get(obj, i)));

	fz_drop_obj(dict);

	error = fz_read_all(bufp, stm, len);
	if (error)
	{
		fz_close(stm);
		return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen);
	}

	fz_close(stm);
	return fz_okay;
}
Beispiel #9
0
fz_obj *
fz_copy_array(fz_context *ctx, fz_obj *obj)
{
	fz_obj *arr;
	int i;
	int n;

	RESOLVE(obj);
	if (!obj || obj->kind != FZ_ARRAY)
		fz_warn(ctx, "assert: not an array (%s)", fz_objkindstr(obj));

	arr = fz_new_array(ctx, fz_array_len(obj));
	n = fz_array_len(obj);
	for (i = 0; i < n; i++)
		fz_array_push(arr, fz_array_get(obj, i));

	return arr;
}
Beispiel #10
0
int
fz_array_contains(fz_obj *arr, fz_obj *obj)
{
	int i;

	for (i = 0; i < fz_array_len(arr); i++)
		if (!fz_objcmp(fz_array_get(arr, i), obj))
			return 1;

	return 0;
}
Beispiel #11
0
static fz_colorspace *
load_separation(pdf_document *xref, fz_obj *array)
{
	fz_colorspace *cs;
	struct separation *sep = NULL;
	fz_context *ctx = xref->ctx;
	fz_obj *nameobj = fz_array_get(array, 1);
	fz_obj *baseobj = fz_array_get(array, 2);
	fz_obj *tintobj = fz_array_get(array, 3);
	fz_colorspace *base;
	pdf_function *tint = NULL;
	int n;

	fz_var(tint);
	fz_var(sep);

	if (fz_is_array(nameobj))
		n = fz_array_len(nameobj);
	else
		n = 1;

	if (n > FZ_MAX_COLORS)
		fz_throw(ctx, "too many components in colorspace");

	base = pdf_load_colorspace(xref, baseobj);
	/* RJW: "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj) */

	fz_try(ctx)
	{
		tint = pdf_load_function(xref, tintobj);
		/* RJW: fz_drop_colorspace(ctx, base);
		 * "cannot load tint function (%d %d R)", fz_to_num(tintobj), fz_to_gen(tintobj) */

		sep = fz_malloc_struct(ctx, struct separation);
		sep->base = base;
		sep->tint = tint;

		cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", n);
		cs->to_rgb = separation_to_rgb;
		cs->free_data = free_separation;
		cs->data = sep;
		cs->size += sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(tint);
	}
	fz_catch(ctx)
	{
		fz_drop_colorspace(ctx, base);
		pdf_drop_function(ctx, tint);
		fz_free(ctx, sep);
		fz_rethrow(ctx);
	}

	return cs;
}
int
pdf_is_jpx_image(fz_obj *dict)
{
	fz_obj *filter;
	int i;

	filter = fz_dict_gets(dict, "Filter");
	if (!strcmp(fz_to_name(filter), "JPXDecode"))
		return 1;
	for (i = 0; i < fz_array_len(filter); i++)
		if (!strcmp(fz_to_name(fz_array_get(filter, i)), "JPXDecode"))
			return 1;
	return 0;
}
Beispiel #13
0
static void sweepobj(fz_obj *obj)
{
	int i;

	if (fz_is_indirect(obj))
		sweepref(obj);

	else if (fz_is_dict(ctx, obj))
		for (i = 0; i < fz_dict_len(ctx, obj); i++)
			sweepobj(fz_dict_get_val(ctx, obj, i));

	else if (fz_is_array(ctx, obj))
		for (i = 0; i < fz_array_len(ctx, obj); i++)
			sweepobj(fz_array_get(ctx, obj, i));
}
Beispiel #14
0
static pdf_annot *
pdf_create_markup_annot(pdf_xref *xref, fz_obj *obj, char *type)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 512);
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	fz_obj *quad_points = fz_dict_gets(ctx, obj, "QuadPoints");
	fz_rect a, b;
	float rgb[3];
	int i;

	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		b.y0 -= 0.25; a.y1 += 0.25;
		rect = fz_union_rect(rect, fz_union_rect(a, b));
	}
	pdf_get_annot_color(ctx, obj, rgb);

	fz_buffer_printf(ctx, content, "q %.4f %.4f %.4f RG 1 0 0 1 -%.4f -%.4f cm 0.5 w ",
		rgb[0], rgb[1], rgb[2], rect.x0, rect.y0);
	if (!strcmp(type, "Squiggly"))
		fz_buffer_printf(ctx, content, "[1 1] d ");
	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		if (!strcmp(type, "StrikeOut"))
			fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l ",
				(a.x0 + b.x0) / 2, (a.y0 + b.y0) / 2, (a.x1 + b.x1) / 2, (a.y1 + b.y1) / 2);
		else
			fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l ", b.x0, b.y0, a.x1, a.y1);
	}
	fz_buffer_printf(ctx, content, "S Q");

	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, NULL, 0);
}
/*
 * Build a chain of filters given filter names and param dicts.
 * If head is given, start filter chain with it.
 * Assume ownership of head.
 */
static fz_stream *
build_filter_chain(fz_stream *chain, pdf_xref *xref, fz_obj *fs, fz_obj *ps, int num, int gen)
{
	fz_obj *f;
	fz_obj *p;
	int i;

	for (i = 0; i < fz_array_len(fs); i++)
	{
		f = fz_array_get(fs, i);
		p = fz_array_get(ps, i);
		chain = build_filter(chain, xref, f, p, num, gen);
	}

	return chain;
}
/*
 * Construct a filter to decode a stream, constraining
 * to stream length and decrypting.
 */
static fz_stream *
pdf_open_filter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, int gen)
{
	fz_obj *filters;
	fz_obj *params;

	filters = fz_dict_getsa(stmobj, "Filter", "F");
	params = fz_dict_getsa(stmobj, "DecodeParms", "DP");

	chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen);

	if (fz_is_name(filters))
		return build_filter(chain, xref, filters, params, num, gen);
	if (fz_array_len(filters) > 0)
		return build_filter_chain(chain, xref, filters, params, num, gen);

	return chain;
}
static fz_error
load_separation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	fz_colorspace *cs;
	struct separation *sep;
	fz_obj *nameobj = fz_array_get(array, 1);
	fz_obj *baseobj = fz_array_get(array, 2);
	fz_obj *tintobj = fz_array_get(array, 3);
	fz_colorspace *base;
	pdf_function *tint;
	int n;

	if (fz_is_array(nameobj))
		n = fz_array_len(nameobj);
	else
		n = 1;

	if (n > FZ_MAX_COLORS)
		return fz_throw("too many components in colorspace");

	error = pdf_load_colorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj));

	error = pdf_load_function(&tint, xref, tintobj);
	if (error)
	{
		fz_drop_colorspace(base);
		return fz_rethrow(error, "cannot load tint function (%d %d R)", fz_to_num(tintobj), fz_to_gen(tintobj));
	}

	sep = fz_malloc(sizeof(struct separation));
	sep->base = base;
	sep->tint = tint;

	cs = fz_new_colorspace(n == 1 ? "Separation" : "DeviceN", n);
	cs->to_rgb = separation_to_rgb;
	cs->free_data = free_separation;
	cs->data = sep;

	*csp = cs;
	return fz_okay;
}
Beispiel #18
0
static void renumberobj(fz_obj *obj)
{
	int i;
	fz_context *ctx = xref->ctx;

	if (fz_is_dict(obj))
	{
		int n = fz_dict_len(obj);
		for (i = 0; i < n; i++)
		{
			fz_obj *key = fz_dict_get_key(obj, i);
			fz_obj *val = fz_dict_get_val(obj, i);
			if (fz_is_indirect(val))
			{
				val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref);
				fz_dict_put(obj, key, val);
				fz_drop_obj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}

	else if (fz_is_array(obj))
	{
		int n = fz_array_len(obj);
		for (i = 0; i < n; i++)
		{
			fz_obj *val = fz_array_get(obj, i);
			if (fz_is_indirect(val))
			{
				val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref);
				fz_array_put(obj, i, val);
				fz_drop_obj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}
}
/*
 * Construct a filter to decode a stream, without
 * constraining to stream length, and without decryption.
 */
fz_stream *
pdf_open_inline_stream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int length)
{
	fz_obj *filters;
	fz_obj *params;

	filters = fz_dict_getsa(stmobj, "Filter", "F");
	params = fz_dict_getsa(stmobj, "DecodeParms", "DP");

	/* don't close chain when we close this filter */
	fz_keep_stream(chain);

	if (fz_is_name(filters))
		return build_filter(chain, xref, filters, params, 0, 0);
	if (fz_array_len(filters) > 0)
		return build_filter_chain(chain, xref, filters, params, 0, 0);

	return fz_open_null(chain, length);
}
Beispiel #20
0
static void sweepobj(fz_obj *obj)
{
	int i;

	if (fz_is_indirect(obj))
		sweepref(obj);

	else if (fz_is_dict(obj))
	{
		int n = fz_dict_len(obj);
		for (i = 0; i < n; i++)
			sweepobj(fz_dict_get_val(obj, i));
	}

	else if (fz_is_array(obj))
	{
		int n = fz_array_len(obj);
		for (i = 0; i < n; i++)
			sweepobj(fz_array_get(obj, i));
	}
}
/*
 * Scan stream dictionary for an explicit /Crypt filter
 */
static int
pdf_stream_has_crypt(fz_obj *stm)
{
	fz_obj *filters;
	fz_obj *obj;
	int i;

	filters = fz_dict_getsa(stm, "Filter", "F");
	if (filters)
	{
		if (!strcmp(fz_to_name(filters), "Crypt"))
			return 1;
		if (fz_is_array(filters))
		{
			for (i = 0; i < fz_array_len(filters); i++)
			{
				obj = fz_array_get(filters, i);
				if (!strcmp(fz_to_name(obj), "Crypt"))
					return 1;
			}
		}
	}
	return 0;
}
Beispiel #22
0
fz_error
pdf_ocg_set_config(pdf_xref *xref, int config)
{
	int i, j, len, len2;
	pdf_ocg_descriptor *desc = xref->ocg;
	fz_obj *obj, *cobj;
	char *name;

	obj = fz_dict_gets(fz_dict_gets(xref->trailer, "Root"), "OCProperties");
	if (obj == NULL)
	{
		if (config == 0)
			return fz_okay;
		else
			return fz_throw("Unknown OCG config (None known!)");
	}
	if (config == 0)
	{
		cobj = fz_dict_gets(obj, "D");
		if (cobj == NULL)
			return fz_throw("No default OCG config");
	}
	else
	{
		cobj = fz_array_get(fz_dict_gets(obj, "Configs"), config);
		if (cobj == NULL)
			return fz_throw("Illegal OCG config");
	}

	if (desc->intent != NULL)
		fz_drop_obj(desc->intent);
	desc->intent = fz_dict_gets(cobj, "Intent");
	if (desc->intent != NULL)
		fz_keep_obj(desc->intent);

	len = desc->len;
	name = fz_to_name(fz_dict_gets(cobj, "BaseState"));
	if (strcmp(name, "Unchanged") == 0)
	{
		/* Do nothing */
	}
	else if (strcmp(name, "OFF") == 0)
	{
		for (i = 0; i < len; i++)
		{
			desc->ocgs[i].state = 0;
		}
	}
	else /* Default to ON */
	{
		for (i = 0; i < len; i++)
		{
			desc->ocgs[i].state = 1;
		}
	}

	obj = fz_dict_gets(cobj, "ON");
	len2 = fz_array_len(obj);
	for (i = 0; i < len2; i++)
	{
		fz_obj *o = fz_array_get(obj, i);
		int n = fz_to_num(o);
		int g = fz_to_gen(o);
		for (j=0; j < len; j++)
		{
			if (desc->ocgs[j].num == n && desc->ocgs[j].gen == g)
			{
				desc->ocgs[j].state = 1;
				break;
			}
		}
	}

	obj = fz_dict_gets(cobj, "OFF");
	len2 = fz_array_len(obj);
	for (i = 0; i < len2; i++)
	{
		fz_obj *o = fz_array_get(obj, i);
		int n = fz_to_num(o);
		int g = fz_to_gen(o);
		for (j=0; j < len; j++)
		{
			if (desc->ocgs[j].num == n && desc->ocgs[j].gen == g)
			{
				desc->ocgs[j].state = 0;
				break;
			}
		}
	}

	/* FIXME: Should make 'num configs' available in the descriptor. */
	/* FIXME: Should copy out 'Intent' here into the descriptor, and remove
	 * csi->intent in favour of that. */
	/* FIXME: Should copy 'AS' into the descriptor, and visibility
	 * decisions should respect it. */
	/* FIXME: Make 'Order' available via the descriptor (when we have an
	 * app that needs it) */
	/* FIXME: Make 'ListMode' available via the descriptor (when we have
	 * an app that needs it) */
	/* FIXME: Make 'RBGroups' available via the descriptor (when we have
	 * an app that needs it) */
	/* FIXME: Make 'Locked' available via the descriptor (when we have
	 * an app that needs it) */
	return fz_okay;
}
Beispiel #23
0
void
pdf_load_annots(pdf_annot **annotp, pdf_xref *xref, fz_obj *annots)
{
	pdf_annot *annot, *head, *tail;
	fz_obj *obj, *ap, *as, *n, *rect;
	pdf_xobject *form;
	fz_error error;
	int i;
	fz_context *ctx = xref->ctx;

	head = tail = NULL;
	annot = NULL;

	for (i = 0; i < fz_array_len(ctx, annots); i++)
	{
		obj = fz_array_get(ctx, annots, i);

		/* cf. http://bugs.ghostscript.com/show_bug.cgi?id=692078 */
		if ((annot = pdf_update_tx_widget_annot(xref, obj)))
		{
			if (!head)
				head = tail = annot;
			else
			{
				tail->next = annot;
				tail = annot;
			}
			continue;
		}

		rect = fz_dict_gets(ctx, obj, "Rect");
		ap = fz_dict_gets(ctx, obj, "AP");
		as = fz_dict_gets(ctx, obj, "AS");
		if (fz_is_dict(ctx, ap))
		{
			n = fz_dict_gets(ctx, ap, "N"); /* normal state */

			/* lookup current state in sub-dictionary */
			if (!pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n)))
				n = fz_dict_get(ctx, n, as);

			if (pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n)))
			{
				error = pdf_load_xobject(&form, xref, n);
				if (error)
				{
					fz_error_handle(ctx, error, "ignoring broken annotation");
					continue;
				}

				annot = fz_malloc(ctx, sizeof(pdf_annot));
				annot->obj = fz_keep_obj(obj);
				annot->rect = pdf_to_rect(ctx, rect);
				annot->ap = form;
				annot->next = NULL;

				pdf_transform_annot(annot);

				if (annot)
				{
					if (!head)
						head = tail = annot;
					else
					{
						tail->next = annot;
						tail = annot;
					}
				}
			}
		}
		/* SumatraPDF: synthesize appearance streams for a few more annotations */
		else if ((annot = pdf_create_annot_with_appearance(xref, obj)))
		{
			if (!head)
				head = tail = annot;
			else
			{
				tail->next = annot;
				tail = annot;
			}
		}
	}

	*annotp = head;
}
Beispiel #24
0
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);
	}
}
Beispiel #25
0
static fz_error
pdf_read_new_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *trailer;
	fz_obj *index;
	fz_obj *obj;
	int num, gen, stm_ofs;
	int size, w0, w1, w2;
	int t;

	error = pdf_parse_ind_obj(&trailer, xref, xref->file, buf, cap, &num, &gen, &stm_ofs);
	if (error)
		return fz_rethrow(error, "cannot parse compressed xref stream object");

	obj = fz_dict_gets(trailer, "Size");
	if (!obj)
	{
		fz_drop_obj(trailer);
		return fz_throw("xref stream missing Size entry (%d %d R)", num, gen);
	}
	size = fz_to_int(obj);

	if (size > xref->len)
	{
		pdf_resize_xref(xref, size);
	}

	if (num < 0 || num >= xref->len)
	{
		fz_drop_obj(trailer);
		return fz_throw("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1);
	}

	obj = fz_dict_gets(trailer, "W");
	if (!obj) {
		fz_drop_obj(trailer);
		return fz_throw("xref stream missing W entry (%d %d R)", num, gen);
	}
	w0 = fz_to_int(fz_array_get(obj, 0));
	w1 = fz_to_int(fz_array_get(obj, 1));
	w2 = fz_to_int(fz_array_get(obj, 2));

	index = fz_dict_gets(trailer, "Index");

	error = pdf_open_stream_at(&stm, xref, num, gen, trailer, stm_ofs);
	if (error)
	{
		fz_drop_obj(trailer);
		return fz_rethrow(error, "cannot open compressed xref stream (%d %d R)", num, gen);
	}

	if (!index)
	{
		error = pdf_read_new_xref_section(xref, stm, 0, size, w0, w1, w2);
		if (error)
		{
			fz_close(stm);
			fz_drop_obj(trailer);
			return fz_rethrow(error, "cannot read xref stream (%d %d R)", num, gen);
		}
	}
	else
	{
		for (t = 0; t < fz_array_len(index); t += 2)
		{
			int i0 = fz_to_int(fz_array_get(index, t + 0));
			int i1 = fz_to_int(fz_array_get(index, t + 1));
			error = pdf_read_new_xref_section(xref, stm, i0, i1, w0, w1, w2);
			if (error)
			{
				fz_close(stm);
				fz_drop_obj(trailer);
				return fz_rethrow(error, "cannot read xref stream section (%d %d R)", num, gen);
			}
		}
	}

	fz_close(stm);

	*trailerp = trailer;

	return fz_okay;
}
static void
pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_function *func)
{
	fz_obj *obj;
	float x0, y0, x1, y1;
	fz_matrix matrix;
	struct vertex v[4];
	int xx, yy;
	float x, y;
	float xn, yn;
	int i;

	x0 = y0 = 0;
	x1 = y1 = 1;
	obj = fz_dict_gets(dict, "Domain");
	if (fz_array_len(obj) == 4)
	{
		x0 = fz_to_real(fz_array_get(obj, 0));
		x1 = fz_to_real(fz_array_get(obj, 1));
		y0 = fz_to_real(fz_array_get(obj, 2));
		y1 = fz_to_real(fz_array_get(obj, 3));
	}

	matrix = fz_identity;
	obj = fz_dict_gets(dict, "Matrix");
	if (fz_array_len(obj) == 6)
		matrix = pdf_to_matrix(obj);

	for (yy = 0; yy < FUNSEGS; yy++)
	{
		y = y0 + (y1 - y0) * yy / FUNSEGS;
		yn = y0 + (y1 - y0) * (yy + 1) / FUNSEGS;

		for (xx = 0; xx < FUNSEGS; xx++)
		{
			x = x0 + (x1 - x0) * xx / FUNSEGS;
			xn = x0 + (x1 - x0) * (xx + 1) / FUNSEGS;

			v[0].x = x; v[0].y = y;
			v[1].x = xn; v[1].y = y;
			v[2].x = xn; v[2].y = yn;
			v[3].x = x; v[3].y = yn;

			for (i = 0; i < 4; i++)
			{
				fz_point pt;
				float fv[2];

				fv[0] = v[i].x;
				fv[1] = v[i].y;
				pdf_eval_function(func, fv, 2, v[i].c, shade->colorspace->n);

				pt.x = v[i].x;
				pt.y = v[i].y;
				pt = fz_transform_point(matrix, pt);
				v[i].x = pt.x;
				v[i].y = pt.y;
			}

			pdf_add_quad(shade, &v[0], &v[1], &v[2], &v[3]);
		}
	}
}
static fz_error
pdf_load_shading_dict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix transform)
{
	fz_error error;
	fz_shade *shade;
	pdf_function *func[FZ_MAX_COLORS] = { NULL };
	fz_stream *stream = NULL;
	fz_obj *obj;
	int funcs;
	int type;
	int i;

	shade = fz_malloc(sizeof(fz_shade));
	shade->refs = 1;
	shade->type = FZ_MESH;
	shade->use_background = 0;
	shade->use_function = 0;
	shade->matrix = transform;
	shade->bbox = fz_infinite_rect;
	shade->extend[0] = 0;
	shade->extend[1] = 0;

	shade->mesh_len = 0;
	shade->mesh_cap = 0;
	shade->mesh = NULL;

	shade->colorspace = NULL;

	funcs = 0;

	obj = fz_dict_gets(dict, "ShadingType");
	type = fz_to_int(obj);

	obj = fz_dict_gets(dict, "ColorSpace");
	if (!obj)
	{
		fz_drop_shade(shade);
		return fz_throw("shading colorspace is missing");
	}
	error = pdf_load_colorspace(&shade->colorspace, xref, obj);
	if (error)
	{
		fz_drop_shade(shade);
		return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
	}

	obj = fz_dict_gets(dict, "Background");
	if (obj)
	{
		shade->use_background = 1;
		for (i = 0; i < shade->colorspace->n; i++)
			shade->background[i] = fz_to_real(fz_array_get(obj, i));
	}

	obj = fz_dict_gets(dict, "BBox");
	if (fz_is_array(obj))
	{
		shade->bbox = pdf_to_rect(obj);
	}

	obj = fz_dict_gets(dict, "Function");
	if (fz_is_dict(obj))
	{
		funcs = 1;

		error = pdf_load_function(&func[0], xref, obj);
		if (error)
		{
			error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
			goto cleanup;
		}
	}
	else if (fz_is_array(obj))
	{
		funcs = fz_array_len(obj);
		if (funcs != 1 && funcs != shade->colorspace->n)
		{
			error = fz_throw("incorrect number of shading functions");
			goto cleanup;
		}

		for (i = 0; i < funcs; i++)
		{
			error = pdf_load_function(&func[i], xref, fz_array_get(obj, i));
			if (error)
			{
				error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
				goto cleanup;
			}
		}
	}

	if (type >= 4 && type <= 7)
	{
		error = pdf_open_stream(&stream, xref, fz_to_num(dict), fz_to_gen(dict));
		if (error)
		{
			error = fz_rethrow(error, "cannot open shading stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
			goto cleanup;
		}
	}

	switch (type)
	{
	case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break;
	case 2: pdf_load_axial_shading(shade, xref, dict, funcs, func); break;
	case 3: pdf_load_radial_shading(shade, xref, dict, funcs, func); break;
	case 4: pdf_load_type4_shade(shade, xref, dict, funcs, func, stream); break;
	case 5: pdf_load_type5_shade(shade, xref, dict, funcs, func, stream); break;
	case 6: pdf_load_type6_shade(shade, xref, dict, funcs, func, stream); break;
	case 7: pdf_load_type7_shade(shade, xref, dict, funcs, func, stream); break;
	default:
		error = fz_throw("unknown shading type: %d", type);
		goto cleanup;
	}

	if (stream)
		fz_close(stream);
	for (i = 0; i < funcs; i++)
		if (func[i])
			pdf_drop_function(func[i]);

	*shadep = shade;
	return fz_okay;

cleanup:
	if (stream)
		fz_close(stream);
	for (i = 0; i < funcs; i++)
		if (func[i])
			pdf_drop_function(func[i]);
	fz_drop_shade(shade);

	return fz_rethrow(error, "cannot load shading type %d (%d %d R)", type, fz_to_num(dict), fz_to_gen(dict));
}