Ejemplo n.º 1
0
void
pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots)
{
	pdf_comment *comment;
	pdf_link *link;
	fz_obj *subtype;
	fz_obj *obj;
	int i;

	comment = nil;
	link = nil;

	pdf_logpage("load annotations {\n");

	for (i = 0; i < fz_arraylen(annots); i++)
	{
		obj = fz_arrayget(annots, i);

		subtype = fz_dictgets(obj, "Subtype");
		if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link"))
		{
			pdf_link *temp = pdf_loadlink(xref, obj);
			if (temp)
			{
				temp->next = link;
				link = temp;
			}
		}
	}

	pdf_logpage("}\n");

	*cp = comment;
	*lp = link;
}
Ejemplo n.º 2
0
fz_error *
pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots)
{
	fz_error *error;
	pdf_comment *comment;
	pdf_link *link;
	fz_obj *subtype;
	fz_obj *obj;
	int i;

	comment = nil;
	link = nil;

	pdf_logpage("load annotations {\n");

	for (i = 0; i < fz_arraylen(annots); i++)
	{
		obj = fz_arrayget(annots, i);
		error = pdf_resolve(&obj, xref);
		if (error)
			goto cleanup;

		subtype = fz_dictgets(obj, "Subtype");
		if (!strcmp(fz_toname(subtype), "Link"))
		{
			pdf_link *temp = nil;

			error = pdf_loadlink(&temp, xref, obj);
			fz_dropobj(obj);
			if (error)
				goto cleanup;

			if (temp)
			{
				temp->next = link;
				link = temp;
			}
		}
		else
		{
			error = loadcomment(&comment, xref, obj);
			fz_dropobj(obj);
			if (error)
				goto cleanup;
		}
	}

	pdf_logpage("}\n");

	*cp = comment;
	*lp = link;
	return nil;

cleanup:
	pdf_droplink(link);
	return error;
}
fz_error
pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots)
{
	fz_error error;
	pdf_comment *comment;
	pdf_link *link;
	fz_obj *subtype;
	fz_obj *obj;
	int i;

	comment = nil;
	link = nil;

	pdf_logpage("load annotations {\n");

	for (i = 0; i < fz_arraylen(annots); i++)
	{
		obj = fz_arrayget(annots, i);

		subtype = fz_dictgets(obj, "Subtype");
		if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link"))
		{
			pdf_link *temp = nil;

			error = pdf_loadlink(&temp, xref, obj);
			if (error)
			{
				if (link)
					pdf_droplink(link);
				return fz_rethrow(error, "cannot load annotation link");
			}

			if (temp)
			{
				temp->next = link;
				link = temp;
			}
		}
		else
		{
			error = loadcomment(&comment, xref, obj);
			if (error)
			{
				if (link)
					pdf_droplink(link);
				return fz_rethrow(error, "cannot load annotation comment");
			}
		}
	}

	pdf_logpage("}\n");

	*cp = comment;
	*lp = link;
	return fz_okay;
}
Ejemplo n.º 4
0
static fz_error *
loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error *error;
	struct separation *cs;
	fz_obj *nameobj = fz_arrayget(array, 1);
	fz_obj *baseobj = fz_arrayget(array, 2);
	fz_obj *tintobj = fz_arrayget(array, 3);
	fz_colorspace *base;
	pdf_function *tint;
	int n;

	pdf_logrsrc("load Separation {\n");

	if (fz_isarray(nameobj))
		n = fz_arraylen(nameobj);
	else
		n = 1;

	pdf_logrsrc("n = %d\n", n);

	error = pdf_resolve(&baseobj, xref);
	if (error)
		return error;
	error = pdf_loadcolorspace(&base, xref, baseobj);
	fz_dropobj(baseobj);
	if (error)
		return error;

	error = pdf_loadfunction(&tint, xref, tintobj);
	if (error)
	{
		fz_dropcolorspace(base);
		return error;
	}

	cs = fz_malloc(sizeof(struct separation));
	if (!cs)
	{
		pdf_dropfunction(tint);
		fz_dropcolorspace(base);
		return fz_outofmem;
	}

	initcs((fz_colorspace*)cs,
		n == 1 ? "Separation" : "DeviceN", n,
		separationtoxyz, nil, dropseparation);

	cs->base = base;
	cs->tint = tint;

	pdf_logrsrc("}\n");

	*csp = (fz_colorspace*)cs;
	return nil;
}
Ejemplo n.º 5
0
static fz_error
loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	struct separation *cs;
	fz_obj *nameobj = fz_arrayget(array, 1);
	fz_obj *baseobj = fz_arrayget(array, 2);
	fz_obj *tintobj = fz_arrayget(array, 3);
	fz_colorspace *base;
	pdf_function *tint;
	int n;

	pdf_logrsrc("load Separation {\n");

	if (fz_isarray(nameobj))
		n = fz_arraylen(nameobj);
	else
		n = 1;

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

	pdf_logrsrc("n = %d\n", n);

	error = pdf_loadcolorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace");

	error = pdf_loadfunction(&tint, xref, tintobj);
	if (error)
	{
		fz_dropcolorspace(base);
		return fz_rethrow(error, "cannot load tint function");
	}

	cs = fz_malloc(sizeof(struct separation));

	initcs((fz_colorspace*)cs,
		n == 1 ? "Separation" : "DeviceN", n,
		separationtoxyz, nil, freeseparation);

	cs->base = fz_keepcolorspace(base);
	cs->tint = pdf_keepfunction(tint);

	fz_dropcolorspace(base);
	pdf_dropfunction(tint);

	pdf_logrsrc("}\n");

	*csp = (fz_colorspace*)cs;
	return fz_okay;
}
Ejemplo n.º 6
0
fz_error *
pdf_showtext(pdf_csi *csi, fz_obj *text)
{
	pdf_gstate *gstate = csi->gstate + csi->gtop;
	pdf_font *font = gstate->font;
	fz_error *error;
	unsigned char *buf;
	unsigned char *end;
	int i, len;
	int cpt, cid;

	if (fz_isarray(text))
	{
		for (i = 0; i < fz_arraylen(text); i++)
		{
			fz_obj *item = fz_arrayget(text, i);
			if (fz_isstring(item))
			{
				error = pdf_showtext(csi, item);
				if (error)
					return fz_rethrow(error, "cannot draw text item");
			}
			else
			{
				showspace(csi, - fz_toreal(item) * gstate->size / 1000.0);
			}
		}
		return fz_okay;
	}

	buf = (unsigned char *)fz_tostrbuf(text);
	len = fz_tostrlen(text);
	end = buf + len;

	while (buf < end)
	{
		buf = pdf_decodecmap(font->encoding, buf, &cpt);
		cid = pdf_lookupcmap(font->encoding, cpt);
		if (cid == -1)
			cid = 0;

		error = showglyph(csi, cid);
		if (error)
			return fz_rethrow(error, "cannot draw glyph");

		if (cpt == 32)
			showspace(csi, gstate->wordspace);
	}

	return fz_okay;
}
Ejemplo n.º 7
0
int
pdf_isjpximage(fz_obj *dict)
{
	fz_obj *filter;
	int i;

	filter = fz_dictgets(dict, "Filter");
	if (!strcmp(fz_toname(filter), "JPXDecode"))
		return 1;
	for (i = 0; i < fz_arraylen(filter); i++)
		if (!strcmp(fz_toname(fz_arrayget(filter, i)), "JPXDecode"))
			return 1;
	return 0;
}
Ejemplo n.º 8
0
static fz_error
pdf_loadpagecontentsarray(fz_buffer **bigbufp, pdf_xref *xref, fz_obj *list)
{
	fz_error error;
	fz_buffer *big;
	fz_buffer *one;
	int i;

	pdf_logpage("multiple content streams: %d\n", fz_arraylen(list));

	/* TODO: openstream, read, close into big buffer at once */

	big = fz_newbuffer(32 * 1024);

	for (i = 0; i < fz_arraylen(list); i++)
	{
		fz_obj *stm = fz_arrayget(list, i);
		error = pdf_loadstream(&one, xref, fz_tonum(stm), fz_togen(stm));
		if (error)
		{
			fz_dropbuffer(big);
			return fz_rethrow(error, "cannot load content stream part %d/%d (%d %d R)", i + 1, fz_arraylen(list), fz_tonum(stm), fz_togen(stm));
		}

		if (big->len + one->len + 1 > big->cap)
			fz_resizebuffer(big, big->len + one->len + 1);
		memcpy(big->data + big->len, one->data, one->len);
		big->data[big->len + one->len] = ' ';
		big->len += one->len + 1;

		fz_dropbuffer(one);
	}

	*bigbufp = big;
	return fz_okay;
}
Ejemplo n.º 9
0
static void sweepobj(fz_obj *obj)
{
	int i;

	if (fz_isindirect(obj))
		sweepref(obj);

	else if (fz_isdict(obj))
		for (i = 0; i < fz_dictlen(obj); i++)
			sweepobj(fz_dictgetval(obj, i));

	else if (fz_isarray(obj))
		for (i = 0; i < fz_arraylen(obj); i++)
			sweepobj(fz_arrayget(obj, i));
}
void
pdf_showtext(pdf_csi *csi, fz_obj *text)
{
	pdf_gstate *gstate = csi->gstate + csi->gtop;
	pdf_fontdesc *fontdesc = gstate->font;
	unsigned char *buf;
	unsigned char *end;
	int i, len;
	int cpt, cid;

	if (!fontdesc)
	{
		fz_warn("cannot draw text since font and size not set");
		return;
	}

	if (fz_isarray(text))
	{
		for (i = 0; i < fz_arraylen(text); i++)
		{
			fz_obj *item = fz_arrayget(text, i);
			if (fz_isstring(item))
				pdf_showtext(csi, item);
			else
				pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f);
		}
	}

	if (fz_isstring(text))
	{
		buf = (unsigned char *)fz_tostrbuf(text);
		len = fz_tostrlen(text);
		end = buf + len;

		while (buf < end)
		{
			buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt);
			cid = pdf_lookupcmap(fontdesc->encoding, cpt);
			if (cid == -1)
				cid = 0;

			pdf_showglyph(csi, cid);

			if (cpt == 32)
				pdf_showspace(csi, gstate->wordspace);
		}
	}
}
Ejemplo n.º 11
0
void
editflushobjects(void)
{
	fz_error *error;
	fz_obj *results;
	int i;

	error = pdf_transplant(editxref, src, &results, editobjects);
	if (error)
		die(error);

	for (i = 0; i < fz_arraylen(results); i++)
	{
		error = fz_arraypush(editpagelist, fz_arrayget(results, i));
		if (error)
			die(error);
	}

	fz_dropobj(results);
}
Ejemplo n.º 12
0
static void renumberobj(fz_obj *obj)
{
	int i;

	if (fz_isdict(obj))
	{
		for (i = 0; i < fz_dictlen(obj); i++)
		{
			fz_obj *key = fz_dictgetkey(obj, i);
			fz_obj *val = fz_dictgetval(obj, i);
			if (fz_isindirect(val))
			{
				val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref);
				fz_dictput(obj, key, val);
				fz_dropobj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}

	else if (fz_isarray(obj))
	{
		for (i = 0; i < fz_arraylen(obj); i++)
		{
			fz_obj *val = fz_arrayget(obj, i);
			if (fz_isindirect(val))
			{
				val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref);
				fz_arrayput(obj, i, val);
				fz_dropobj(val);
			}
			else
			{
				renumberobj(val);
			}
		}
	}
}
Ejemplo n.º 13
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_error *
buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps)
{
	fz_error *error;
	fz_filter *newhead;
	fz_filter *tail;
	fz_obj *f;
	fz_obj *p;
	int i;

	for (i = 0; i < fz_arraylen(fs); i++)
	{
		f = fz_arrayget(fs, i);
		if (fz_isarray(ps))
			p = fz_arrayget(ps, i);
		else
			p = nil;

		error = buildonefilter(&tail, f, p);
		if (error)
			return fz_rethrow(error, "cannot create filter");

		if (head)
		{
			error = fz_newpipeline(&newhead, head, tail);
			fz_dropfilter(head);
			fz_dropfilter(tail);
			if (error)
			{
				fz_dropfilter(newhead);
				return fz_rethrow(error, "cannot create pipeline filter");
			}
			head = newhead;
		}
		else
			head = tail;
	}

	*filterp = head;
	return fz_okay;
}
Ejemplo n.º 14
0
static void
loadcolorkey(int *colorkey, int bpc, int indexed, fz_obj *obj)
{
	int scale = 1;
	int i;

	pdf_logimage("keyed mask\n");

	if (!indexed)
	{
		switch (bpc)
		{
		case 1: scale = 255; break;
		case 2: scale = 85; break;
		case 4: scale = 17; break;
		case 8: scale = 1; break;
		}
	}

	for (i = 0; i < fz_arraylen(obj); i++)
		colorkey[i] = fz_toint(fz_arrayget(obj, i)) * scale;
}
Ejemplo n.º 15
0
void
pdf_showtext(pdf_csi *csi, fz_obj *text)
{
	pdf_gstate *gstate = csi->gstate + csi->gtop;
	int i;

	if (fz_isarray(text))
	{
		for (i = 0; i < fz_arraylen(text); i++)
		{
			fz_obj *item = fz_arrayget(text, i);
			if (fz_isstring(item))
				pdf_showstring(csi, (unsigned char *)fz_tostrbuf(item), fz_tostrlen(item));
			else
				pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f);
		}
	}
	else if (fz_isstring(text))
	{
		pdf_showstring(csi, (unsigned char *)fz_tostrbuf(text), fz_tostrlen(text));
	}
}
Ejemplo n.º 16
0
fz_error
pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
	fz_error error;
	char buf[256];
	char *estrings[256];
	pdf_fontdesc *fontdesc;
	fz_obj *encoding;
	fz_obj *widths;
	fz_obj *resources;
	fz_obj *charprocs;
	fz_obj *obj;
	int first, last;
	int i, k, n;
	fz_rect bbox;
	fz_matrix matrix;

	obj = fz_dictgets(dict, "Name");
	if (fz_isname(obj))
		strlcpy(buf, fz_toname(obj), sizeof buf);
	else
		sprintf(buf, "Unnamed-T3");

	fontdesc = pdf_newfontdesc();

	pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc);
	pdf_logfont("name %s\n", buf);

	obj = fz_dictgets(dict, "FontMatrix");
	matrix = pdf_tomatrix(obj);

	pdf_logfont("matrix [%g %g %g %g %g %g]\n",
		matrix.a, matrix.b,
		matrix.c, matrix.d,
		matrix.e, matrix.f);

	obj = fz_dictgets(dict, "FontBBox");
	bbox = pdf_torect(obj);

	pdf_logfont("bbox [%g %g %g %g]\n",
		bbox.x0, bbox.y0,
		bbox.x1, bbox.y1);

	bbox = fz_transformaabb(matrix, bbox);
	bbox.x0 = fz_floor(bbox.x0 * 1000);
	bbox.y0 = fz_floor(bbox.y0 * 1000);
	bbox.x1 = fz_ceil(bbox.x1 * 1000);
	bbox.y1 = fz_ceil(bbox.y1 * 1000);

	fontdesc->font = fz_newtype3font(buf, matrix);

	fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	/*
	 * Encoding
	 */

	for (i = 0; i < 256; i++)
		estrings[i] = nil;

	encoding = fz_dictgets(dict, "Encoding");
	if (!encoding)
	{
		error = fz_throw("syntaxerror: Type3 font missing Encoding");
		goto cleanup;
	}

	if (fz_isname(encoding))
		pdf_loadencoding(estrings, fz_toname(encoding));

	if (fz_isdict(encoding))
	{
		fz_obj *base, *diff, *item;

		base = fz_dictgets(encoding, "BaseEncoding");
		if (fz_isname(base))
			pdf_loadencoding(estrings, fz_toname(base));

		diff = fz_dictgets(encoding, "Differences");
		if (fz_isarray(diff))
		{
			n = fz_arraylen(diff);
			k = 0;
			for (i = 0; i < n; i++)
			{
				item = fz_arrayget(diff, i);
				if (fz_isint(item))
					k = fz_toint(item);
				if (fz_isname(item))
					estrings[k++] = fz_toname(item);
				if (k < 0) k = 0;
				if (k > 255) k = 255;
			}
		}
	}

	fontdesc->encoding = pdf_newidentitycmap(0, 1);

	error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode"));
	if (error)
		goto cleanup;

	/*
	 * Widths
	 */

	pdf_setdefaulthmtx(fontdesc, 0);

	first = fz_toint(fz_dictgets(dict, "FirstChar"));
	last = fz_toint(fz_dictgets(dict, "LastChar"));

	widths = fz_dictgets(dict, "Widths");
	if (!widths)
	{
		error = fz_throw("syntaxerror: Type3 font missing Widths");
		goto cleanup;
	}

	for (i = first; i <= last; i++)
	{
		float w = fz_toreal(fz_arrayget(widths, i - first));
		w = fontdesc->font->t3matrix.a * w * 1000.0;
		fontdesc->font->t3widths[i] = w * 0.001;
		pdf_addhmtx(fontdesc, i, i, w);
	}

	pdf_endhmtx(fontdesc);

	/*
	 * Resources
	 */

	resources = fz_dictgets(dict, "Resources");

	/* Inherit page's resource dict if type3 font does not have one */
	if (!resources && rdb)
		resources = rdb;
	else if (!resources && !rdb)
		fz_warn("no resource dictionary for type 3 font!");

	/*
	 * CharProcs
	 */

	charprocs = fz_dictgets(dict, "CharProcs");
	if (!charprocs)
	{
		error = fz_throw("syntaxerror: Type3 font missing CharProcs");
		goto cleanup;
	}

	for (i = 0; i < 256; i++)
	{
		if (estrings[i])
		{
			obj = fz_dictgets(charprocs, estrings[i]);
			if (obj)
			{
				pdf_logfont("load charproc %s {\n", estrings[i]);
				error = loadcharproc(&fontdesc->font->t3procs[i], xref, resources, obj);
				if (error)
					goto cleanup;

				pdf_logfont("}\n");
			}
		}
	}

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	fz_dropfont(fontdesc->font);
	fz_free(fontdesc);
	return fz_rethrow(error, "cannot load type3 font");
}
Ejemplo n.º 17
0
fz_error *
pdf_loadtype5shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
{
	fz_error *error;
	fz_stream *stream;
	fz_obj *obj;

	int bpcoord;
	int bpcomp;
	int vpr, vpc;
	int ncomp;

	float x0, x1, y0, y1;

	float c0[FZ_MAXCOLORS];
	float c1[FZ_MAXCOLORS];

	int i, n, j;
	int p, q;
	unsigned int t;

	float *x, *y, *c[FZ_MAXCOLORS];

	error = nil;

	ncomp = shade->cs->n;
	bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
	bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
	vpr = fz_toint(fz_dictgets(shading, "VerticesPerRow"));
	if (vpr < 2) {
		error = fz_throw("VerticesPerRow must be greater than or equal to 2");
		goto cleanup;
	}

	obj = fz_dictgets(shading, "Decode");
	if (fz_isarray(obj))
	{
		pdf_logshade("decode array\n");
		x0 = fz_toreal(fz_arrayget(obj, 0));
		x1 = fz_toreal(fz_arrayget(obj, 1));
		y0 = fz_toreal(fz_arrayget(obj, 2));
		y1 = fz_toreal(fz_arrayget(obj, 3));
		for (i=0; i < fz_arraylen(obj) / 2; ++i) {
			c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
			c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
		}
	}
	else {
		error = fz_throw("syntaxerror: No Decode key in Type 4 Shade");
		goto cleanup;
	}

	obj = fz_dictgets(shading, "Function");
	if (obj) {
		ncomp = 1;
		pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
		shade->usefunction = 1;
	} 
	else
		shade->usefunction = 0;

	n = 2 + shade->cs->n;
	j = 0;

#define BIGNUM 1024

	x = fz_malloc(sizeof(float) * vpr * BIGNUM);
	y = fz_malloc(sizeof(float) * vpr * BIGNUM);
	for (i = 0; i < ncomp; ++i) {
		c[i] = fz_malloc(sizeof(float) * vpr * BIGNUM);
	}
	q = 0;

	error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref));
	if (error) goto cleanup;

	while (fz_peekbyte(stream) != EOF)
	{
		for (p = 0; p < vpr; ++p) {
			int idx;
			idx = q * vpr + p;

			t = getdata(stream, bpcoord);
			x[idx] = x0 + (t * (x1 - x0) / ((float)pow(2, bpcoord) - 1));
			t = getdata(stream, bpcoord);
			y[idx] = y0 + (t * (y1 - y0) / ((float)pow(2, bpcoord) - 1));

			for (i=0; i < ncomp; ++i) {
				t = getdata(stream, bpcomp);
				c[i][idx] = c0[i] + (t * (c1[i] - c0[i]) / (float)(pow(2, bpcomp) - 1));
			}
		}
		q++;
	}

	fz_dropstream(stream);

#define ADD_VERTEX(idx) \
			{\
				int z;\
				shade->mesh[j++] = x[idx];\
				shade->mesh[j++] = y[idx];\
				for (z = 0; z < shade->cs->n; ++z) {\
					shade->mesh[j++] = c[z][idx];\
				}\
			}\

	vpc = q;

	shade->meshcap = 0;
	shade->mesh = fz_malloc(sizeof(float) * 1024);
	if (!shade) {
		error = fz_outofmem;
		goto cleanup;
	}

	j = 0;
	for (p = 0; p < vpr-1; ++p) {
		for (q = 0; q < vpc-1; ++q) {
			ADD_VERTEX(q * vpr + p);
			ADD_VERTEX(q * vpr + p + 1);
			ADD_VERTEX((q + 1) * vpr + p + 1);
			
			ADD_VERTEX(q * vpr + p);
			ADD_VERTEX((q + 1) * vpr + p + 1);
			ADD_VERTEX((q + 1) * vpr + p);
		}
	}

	shade->meshlen = j / n / 3;

	fz_free(x);
	fz_free(y);
	for (i = 0; i < ncomp; ++i) {
		fz_free(c[i]);
	}


cleanup:

	return nil;
}
Ejemplo n.º 18
0
static void retainpages(int argc, char **argv)
{
	fz_error error;
	fz_obj *oldroot, *root, *pages, *kids, *countobj, *parent;

	/* Load the old page tree */
	error = pdf_loadpagetree(xref);
	if (error)
		die(fz_rethrow(error, "cannot load page tree"));

	/* Keep only pages/type entry to avoid references to unretained pages */
	oldroot = fz_dictgets(xref->trailer, "Root");
	pages = fz_dictgets(oldroot, "Pages");

	root = fz_newdict(2);
	fz_dictputs(root, "Type", fz_dictgets(oldroot, "Type"));
	fz_dictputs(root, "Pages", fz_dictgets(oldroot, "Pages"));

	pdf_updateobject(xref, fz_tonum(oldroot), fz_togen(oldroot), root);

	fz_dropobj(root);

	/* Create a new kids array with only the pages we want to keep */
	parent = fz_newindirect(fz_tonum(pages), fz_togen(pages), xref);
	kids = fz_newarray(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_getpagecount(xref);
			else
				spage = epage = atoi(spec);

			if (dash)
			{
				if (strlen(dash) > 1)
					epage = atoi(dash + 1);
				else
					epage = pdf_getpagecount(xref);
			}

			if (spage > epage)
				page = spage, spage = epage, epage = page;

			if (spage < 1)
				spage = 1;
			if (epage > pdf_getpagecount(xref))
				epage = pdf_getpagecount(xref);

			for (page = spage; page <= epage; page++)
			{
				fz_obj *pageobj = pdf_getpageobject(xref, page);
				fz_obj *pageref = pdf_getpageref(xref, page);

				fz_dictputs(pageobj, "Parent", parent);

				/* Store page object in new kids array */
				fz_arraypush(kids, pageref);
			}

			spec = fz_strsep(&pagelist, ",");
		}

		fz_optind++;
	}

	fz_dropobj(parent);

	/* Update page count and kids array */
	countobj = fz_newint(fz_arraylen(kids));
	fz_dictputs(pages, "Count", countobj);
	fz_dropobj(countobj);
	fz_dictputs(pages, "Kids", kids);
	fz_dropobj(kids);
}
Ejemplo n.º 19
0
fz_error *
pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
    fz_error *error;
    char buf[256];
    char *estrings[256];
    pdf_font *font;
    fz_obj *encoding;
    fz_obj *widths;
    fz_obj *resources;
    fz_obj *charprocs;
    fz_obj *obj;
    int first, last;
    int i, k, n;
    fz_rect bbox;

    obj = fz_dictgets(dict, "Name");
    if (obj)
        strlcpy(buf, fz_toname(obj), sizeof buf);
    else
        sprintf(buf, "Unnamed-T3");

    font = pdf_newfont(buf);
    if (!font)
        return fz_throw("outofmem: font struct");

    pdf_logfont("load type3 font %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), font);
    pdf_logfont("name %s\n", buf);

    font->super.render = t3render;
    font->super.drop = (void(*)(fz_font*)) t3dropfont;

    obj = fz_dictgets(dict, "FontMatrix");
    font->matrix = pdf_tomatrix(obj);

    pdf_logfont("matrix [%g %g %g %g %g %g]\n",
                font->matrix.a, font->matrix.b,
                font->matrix.c, font->matrix.d,
                font->matrix.e, font->matrix.f);

    obj = fz_dictgets(dict, "FontBBox");
    bbox = pdf_torect(obj);

    pdf_logfont("bbox [%g %g %g %g]\n",
                bbox.x0, bbox.y0,
                bbox.x1, bbox.y1);

    bbox = fz_transformaabb(font->matrix, bbox);
    bbox.x0 = fz_floor(bbox.x0 * 1000);
    bbox.y0 = fz_floor(bbox.y0 * 1000);
    bbox.x1 = fz_ceil(bbox.x1 * 1000);
    bbox.y1 = fz_ceil(bbox.y1 * 1000);
    fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

    /*
     * Encoding
     */

    for (i = 0; i < 256; i++)
        estrings[i] = nil;

    encoding = fz_dictgets(dict, "Encoding");
    if (!encoding) {
        error = fz_throw("syntaxerror: Type3 font missing Encoding");
        goto cleanup;
    }

    error = pdf_resolve(&encoding, xref);
    if (error)
        goto cleanup;

    if (fz_isname(obj))
        pdf_loadencoding(estrings, fz_toname(encoding));

    if (fz_isdict(encoding))
    {
        fz_obj *base, *diff, *item;

        base = fz_dictgets(encoding, "BaseEncoding");
        if (fz_isname(base))
            pdf_loadencoding(estrings, fz_toname(base));

        diff = fz_dictgets(encoding, "Differences");
        if (fz_isarray(diff))
        {
            n = fz_arraylen(diff);
            k = 0;
            for (i = 0; i < n; i++)
            {
                item = fz_arrayget(diff, i);
                if (fz_isint(item))
                    k = fz_toint(item);
                if (fz_isname(item))
                    estrings[k++] = fz_toname(item);
                if (k < 0) k = 0;
                if (k > 255) k = 255;
            }
        }
    }

    fz_dropobj(encoding);

    error = pdf_newidentitycmap(&font->encoding, 0, 1);
    if (error)
        goto cleanup;

    error = pdf_loadtounicode(font, xref,
                              estrings, nil, fz_dictgets(dict, "ToUnicode"));
    if (error)
        goto cleanup;

    /*
     * Widths
     */

    fz_setdefaulthmtx((fz_font*)font, 0);

    first = fz_toint(fz_dictgets(dict, "FirstChar"));
    last = fz_toint(fz_dictgets(dict, "LastChar"));

    widths = fz_dictgets(dict, "Widths");
    if (!widths) {
        error = fz_throw("syntaxerror: Type3 font missing Widths");
        goto cleanup;
    }

    error = pdf_resolve(&widths, xref);
    if (error)
        goto cleanup;

    for (i = first; i <= last; i++)
    {
        float w = fz_toreal(fz_arrayget(widths, i - first));
        w = font->matrix.a * w * 1000.0;
        error = fz_addhmtx((fz_font*)font, i, i, w);
        if (error) {
            fz_dropobj(widths);
            goto cleanup;
        }
    }

    fz_dropobj(widths);

    error = fz_endhmtx((fz_font*)font);
    if (error)
        goto cleanup;

    /*
     * Resources
     */

    resources = nil;

    obj = fz_dictgets(dict, "Resources");
    if (obj)
    {
        error = pdf_resolve(&obj, xref);
        if (error)
            goto cleanup;

        error = pdf_loadresources(&resources, xref, obj);

        fz_dropobj(obj);

        if (error)
            goto cleanup;
    }
    else
        pdf_logfont("no resource dict!\n");

    /*
     * CharProcs
     */

    charprocs = fz_dictgets(dict, "CharProcs");
    if (!charprocs)
    {
        error = fz_throw("syntaxerror: Type3 font missing CharProcs");
        goto cleanup2;
    }

    error = pdf_resolve(&charprocs, xref);
    if (error)
        goto cleanup2;

    for (i = 0; i < 256; i++)
    {
        if (estrings[i])
        {
            obj = fz_dictgets(charprocs, estrings[i]);
            if (obj)
            {
                pdf_logfont("load charproc %s {\n", estrings[i]);
                error = loadcharproc(&font->charprocs[i], xref, resources, obj);
                if (error)
                    goto cleanup2;

                error = fz_optimizetree(font->charprocs[i]);
                if (error)
                    goto cleanup2;

                pdf_logfont("}\n");
            }
        }
    }

    fz_dropobj(charprocs);
    if (resources)
        fz_dropobj(resources);

    pdf_logfont("}\n");

    *fontp = font;
    return fz_okay;

cleanup2:
    if (resources)
        fz_dropobj(resources);
cleanup:
    fz_dropfont((fz_font*)font);
    return fz_rethrow(error, "cannot load type3 font");
}
Ejemplo n.º 20
0
int
copyPdfFile(
    soPdfFile* inFile,
    soPdfFile* outFile
    )
{
    fz_error    *error;
    int         pageTreeNum, pageTreeGen;

    assert(inFile != NULL);
    assert(outFile != NULL);

    //
    // Process every page in the source file
    //
    {
        printf("\nProcessing input page : ");
        for (int pageNo = 0; pageNo < pdf_getpagecount(inFile->pageTree); pageNo++)
        {
            displayPageNumber(pageNo + 1, !pageNo);

            // Get the page object from the source
            fz_obj  *pageRef = inFile->pageTree->pref[pageNo];
            fz_obj  *pageObj = pdf_getpageobject(inFile->pageTree, pageNo);

            //
            // Process the page. Each page can be split into up-to 3 pages
            //
            fz_rect    bbRect[3];
            error = processPage(inFile, pageNo, bbRect, 3);
            if (error)
                return soPdfError(error);


            for (int ctr = 0; ctr < 3; ctr++)
            {
                // Check if this was a blank page
                if (fz_isemptyrect(bbRect[ctr]))
                    break;

                //
                // copy the source page dictionary entry. The way this is done is basically
                // by making a copy of the page dict object in the source file, and adding
                // the copy in the source file. Then the copied page dict object is 
                // referenced and added to the destination file.
                //
                // This convoluted procedure is done because the copy is done by pdf_transplant
                // function that accepts a source and destination. Whatever is referenced by
                // destination object is deep copied
                //
                

                // allocate an object id and generation id in source file
                //
                // There is a bug in mupdf where the object allocation returns
                // 0 oid and 0 gid when the input pdf file has iref stream
                // so to work around the issue, we wrap the pdf_allocojbect
                // in a for loop 10 times to get the number
                //
                int sNum, sGen, tries;

                for (tries = 0; tries < 10; tries++)
                {
                    error = pdf_allocobject(inFile->xref, &sNum, &sGen);
                    if (error)
                        return soPdfError(error);

                    // If sNum is non zero then the allocation was successful
                    if (sNum != 0)
                        break;  
                    pdf_updateobject(inFile->xref, sNum, sGen, pageObj);
                }

                // If we didn't succeed even after 10 tries then this file 
                // is not going to work.
                if (tries >= 10)
                    return soPdfError(fz_throw("cannot allocate object because of mupdf bug"));

                // make a deep copy of the original page dict
                fz_obj  *pageObj2;
                error = fz_deepcopydict(&pageObj2, pageObj);
                if (error)
                    return soPdfError(error);

                // update the source file with the duplicate page object
                pdf_updateobject(inFile->xref, sNum, sGen, pageObj2);

                fz_dropobj(pageObj2);

                // create an indirect reference to the page object
                fz_obj  *pageRef2;
                error = fz_newindirect(&pageRef2, sNum, sGen);
                if (error)
                    return soPdfError(error);

                // delete the parent dictionary entry
                // Do we need to delete any other dictionary entry 
                // like annot, tabs, metadata, etc
                fz_dictdels(pageObj2, "Parent");

                // Set the media box
                setPageMediaBox(inFile->xref, pageObj2, bbRect[ctr]);

                // Set the rotation based on input
                switch(p_mode)
                {
                    // no rotation if fit height
                case FitHeight:
                case Fit2xHeight:
                    break;

                    // rotate -90 deg if fit width
                case Fit2xWidth:
                case FitWidth:
                    setPageRotate(pageObj2, p_reverseLandscape ? 90 : -90);
                    break;

                case SmartFitHeight:
                case SmartFitWidth:
                default:
                    return soPdfError(fz_throw("Mode(%d) not yet implemented.", p_mode));
                    break;
                }


                // push the indirect reference to the destination list for copy by pdf_transplant
                error = fz_arraypush(outFile->editobjs, pageRef2);
                if (error)
                    return soPdfError(error);
            }
        }
    }

    // flush the objects into destination from source
    {
        fz_obj      *results;
        int         outPages;

        printf("\nCopying output page : ");
        error = pdf_transplant(outFile->xref, inFile->xref, &results, outFile->editobjs);
        if (error)
            return soPdfError(error);

        outPages = fz_arraylen(results);
        for (int ctr = 0; ctr < outPages; ctr++)
        {
            displayPageNumber(ctr + 1, !ctr);
            error = fz_arraypush(outFile->pagelist, fz_arrayget(results, 
                p_reverseLandscape ? outPages - 1 - ctr : ctr));
            if (error)
                return soPdfError(error);
        }

        fz_dropobj(results);
    }

    // flush page tree

    // Create page tree and add back-links
    {
        fz_obj  *pageTreeObj;
        fz_obj  *pageTreeRef;

        // allocate a new object in out file for pageTree object
        error = pdf_allocobject(outFile->xref, &pageTreeNum, &pageTreeGen);
        if (error)
            return soPdfError(error);

        // Create a page tree object
        error = fz_packobj(&pageTreeObj, "<</Type/Pages/Count %i/Kids %o>>",
            fz_arraylen(outFile->pagelist), outFile->pagelist);
        if (error)
            return soPdfError(error);

        // Update the xref entry with the pageTree object
        pdf_updateobject(outFile->xref, pageTreeNum, pageTreeGen, pageTreeObj);

        fz_dropobj(pageTreeObj);

        // Create a reference to the pageTree object
        error = fz_newindirect(&pageTreeRef, pageTreeNum, pageTreeGen);
        if (error)
            return soPdfError(error);

        //
        // For every page in the output file, update the parent entry
        //
        for (int ctr = 0; ctr < fz_arraylen(outFile->pagelist); ctr++)
        {
            fz_obj  *pageObj;

            int num = fz_tonum(fz_arrayget(outFile->pagelist, ctr));
            int gen = fz_togen(fz_arrayget(outFile->pagelist, ctr));

            // Get the page object from xreft
            error = pdf_loadobject(&pageObj, outFile->xref, num, gen);
            if (error)
                return soPdfError(error);

            // Update the parent entry in the page dictionary
            error = fz_dictputs(pageObj, "Parent", pageTreeRef);
            if (error)
                return soPdfError(error);

            // Update the entry with the updated page object
            pdf_updateobject(outFile->xref, num, gen, pageObj);

            fz_dropobj(pageObj);
        }
    }

    // Create catalog and root entries
    {
        fz_obj  *catObj, *infoObj;
        int     rootNum, rootGen;
        int     infoNum, infoGen;

        //
        // Copy the info catalog to the destination

        // alloc an object id and gen id in destination file
        error = pdf_allocobject(outFile->xref, &infoNum, &infoGen);
        if (error)
            return soPdfError(error);

        // make a deep copy of the original page dict
        error = fz_deepcopydict(&infoObj, inFile->xref->info);
        if (error)
            return soPdfError(error);

        // update the dest file with object
        pdf_updateobject(outFile->xref, infoNum, infoGen, infoObj);
        outFile->xref->info = infoObj;

        fz_dropobj(infoObj);

        //
        // root/catalog object creation
        error = pdf_allocobject(outFile->xref, &rootNum, &rootGen);
        if (error)
            return soPdfError(error);

        error = fz_packobj(&catObj, "<</Type/Catalog /Pages %r>>", pageTreeNum, pageTreeGen);
        if (error)
            return soPdfError(error);

        pdf_updateobject(outFile->xref, rootNum, rootGen, catObj);

        fz_dropobj(catObj);

        // Create trailer
        error = fz_packobj(&outFile->xref->trailer, "<</Root %r /Info %r>>", 
            rootNum, rootGen, infoNum, infoGen);
        if (error)
            return soPdfError(error);

    }

    // Update the info in the target file and save the xref
    printf("\nSaving.\n");
    error = setPageInfo(inFile, outFile);
    if (error)
        return soPdfError(error);

    error = pdf_savexref(outFile->xref, outFile->fileName, NULL);
    if (error)
        return soPdfError(error);

    if (g_errorCount != 0)
    {
        printf("\nFollowing issues encounted were ignored.\n\n");
        for (int ctr = g_errorCount - 1; ctr >= 0; ctr--)
            soPdfError(g_errorList[ctr]);
    }
    printf("\nSaved.\n");

    return 0;
}
Ejemplo n.º 21
0
static fz_error
loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *tounicode)
{
	fz_error error;
	fz_obj *widths;
	fz_obj *descriptor;
	pdf_fontdesc *fontdesc;
	FT_Face face;
	fz_bbox bbox;
	int kind;
	char collection[256];
	char *basefont;
	int i, k, fterr;
	fz_obj *obj;
	int dw;

	/* Get font name and CID collection */

	basefont = fz_toname(fz_dictgets(dict, "BaseFont"));

	{
		fz_obj *cidinfo;
		char tmpstr[64];
		int tmplen;

		cidinfo = fz_dictgets(dict, "CIDSystemInfo");
		if (!cidinfo)
			return fz_throw("cid font is missing info");

		obj = fz_dictgets(cidinfo, "Registry");
		tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj));
		memcpy(tmpstr, fz_tostrbuf(obj), tmplen);
		tmpstr[tmplen] = '\0';
		fz_strlcpy(collection, tmpstr, sizeof collection);

		fz_strlcat(collection, "-", sizeof collection);

		obj = fz_dictgets(cidinfo, "Ordering");
		tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj));
		memcpy(tmpstr, fz_tostrbuf(obj), tmplen);
		tmpstr[tmplen] = '\0';
		fz_strlcat(collection, tmpstr, sizeof collection);
	}

	/* Load font file */

	fontdesc = pdf_newfontdesc();

	pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc);
	pdf_logfont("basefont %s\n", basefont);
	pdf_logfont("collection %s\n", collection);

	descriptor = fz_dictgets(dict, "FontDescriptor");
	if (descriptor)
		error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, collection, basefont);
	else
		error = fz_throw("syntaxerror: missing font descriptor");
	if (error)
		goto cleanup;

	face = fontdesc->font->ftface;
	kind = ftkind(face);

	bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM;
	bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM;
	bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM;
	bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM;

	pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	if (bbox.x0 == bbox.x1)
		fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000);
	else
		fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	/* Encoding */

	error = fz_okay;
	if (fz_isname(encoding))
	{
		pdf_logfont("encoding /%s\n", fz_toname(encoding));
		if (!strcmp(fz_toname(encoding), "Identity-H"))
			fontdesc->encoding = pdf_newidentitycmap(0, 2);
		else if (!strcmp(fz_toname(encoding), "Identity-V"))
			fontdesc->encoding = pdf_newidentitycmap(1, 2);
		else
			error = pdf_loadsystemcmap(&fontdesc->encoding, fz_toname(encoding));
	}
	else if (fz_isindirect(encoding))
	{
		pdf_logfont("encoding %d %d R\n", fz_tonum(encoding), fz_togen(encoding));
		error = pdf_loadembeddedcmap(&fontdesc->encoding, xref, encoding);
	}
	else
	{
		error = fz_throw("syntaxerror: font missing encoding");
	}
	if (error)
		goto cleanup;

	pdf_setfontwmode(fontdesc, pdf_getwmode(fontdesc->encoding));
	pdf_logfont("wmode %d\n", pdf_getwmode(fontdesc->encoding));

	if (kind == TRUETYPE)
	{
		fz_obj *cidtogidmap;

		cidtogidmap = fz_dictgets(dict, "CIDToGIDMap");
		if (fz_isindirect(cidtogidmap))
		{
			fz_buffer *buf;

			pdf_logfont("cidtogidmap stream\n");

			error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap));
			if (error)
				goto cleanup;

			fontdesc->ncidtogid = (buf->len) / 2;
			fontdesc->cidtogid = fz_malloc(fontdesc->ncidtogid * sizeof(unsigned short));
			for (i = 0; i < fontdesc->ncidtogid; i++)
				fontdesc->cidtogid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1];

			fz_dropbuffer(buf);
		}

		/* if truetype font is external, cidtogidmap should not be identity */
		/* so we map from cid to unicode and then map that through the (3 1) */
		/* unicode cmap to get a glyph id */
		else if (fontdesc->font->ftsubstitute)
		{
			pdf_logfont("emulate ttf cidfont\n");

			fterr = FT_Select_Charmap(face, ft_encoding_unicode);
			if (fterr)
			{
				error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_errorstring(fterr));
				goto cleanup;
			}

			if (!strcmp(collection, "Adobe-CNS1"))
				error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-CNS1-UCS2");
			else if (!strcmp(collection, "Adobe-GB1"))
				error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-GB1-UCS2");
			else if (!strcmp(collection, "Adobe-Japan1"))
				error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan1-UCS2");
			else if (!strcmp(collection, "Adobe-Japan2"))
				error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan2-UCS2");
			else if (!strcmp(collection, "Adobe-Korea1"))
				error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Korea1-UCS2");
			else
				error = fz_okay;

			if (error)
			{
				error = fz_rethrow(error, "cannot load system cmap %s", collection);
				goto cleanup;
			}
		}
	}

	error = pdf_loadtounicode(fontdesc, xref, nil, collection, tounicode);
	if (error)
		goto cleanup;

	/* Horizontal */

	dw = 1000;
	obj = fz_dictgets(dict, "DW");
	if (obj)
		dw = fz_toint(obj);
	pdf_setdefaulthmtx(fontdesc, dw);

	widths = fz_dictgets(dict, "W");
	if (widths)
	{
		int c0, c1, w;

		for (i = 0; i < fz_arraylen(widths); )
		{
			c0 = fz_toint(fz_arrayget(widths, i));
			obj = fz_arrayget(widths, i + 1);
			if (fz_isarray(obj))
			{
				for (k = 0; k < fz_arraylen(obj); k++)
				{
					w = fz_toint(fz_arrayget(obj, k));
					pdf_addhmtx(fontdesc, c0 + k, c0 + k, w);
				}
				i += 2;
			}
			else
			{
				c1 = fz_toint(obj);
				w = fz_toint(fz_arrayget(widths, i + 2));
				pdf_addhmtx(fontdesc, c0, c1, w);
				i += 3;
			}
		}
	}

	pdf_endhmtx(fontdesc);

	/* Vertical */

	if (pdf_getwmode(fontdesc->encoding) == 1)
	{
		int dw2y = 880;
		int dw2w = -1000;

		obj = fz_dictgets(dict, "DW2");
		if (obj)
		{
			dw2y = fz_toint(fz_arrayget(obj, 0));
			dw2w = fz_toint(fz_arrayget(obj, 1));
		}

		pdf_setdefaultvmtx(fontdesc, dw2y, dw2w);

		widths = fz_dictgets(dict, "W2");
		if (widths)
		{
			int c0, c1, w, x, y;

			for (i = 0; i < fz_arraylen(widths); )
			{
				c0 = fz_toint(fz_arrayget(widths, i));
				obj = fz_arrayget(widths, i + 1);
				if (fz_isarray(obj))
				{
					for (k = 0; k < fz_arraylen(obj); k += 3)
					{
						w = fz_toint(fz_arrayget(obj, k + 0));
						x = fz_toint(fz_arrayget(obj, k + 1));
						y = fz_toint(fz_arrayget(obj, k + 2));
						pdf_addvmtx(fontdesc, c0 + k, c0 + k, x, y, w);
					}
					i += 2;
				}
				else
				{
					c1 = fz_toint(obj);
					w = fz_toint(fz_arrayget(widths, i + 2));
					x = fz_toint(fz_arrayget(widths, i + 3));
					y = fz_toint(fz_arrayget(widths, i + 4));
					pdf_addvmtx(fontdesc, c0, c1, x, y, w);
					i += 5;
				}
			}
		}

		pdf_endvmtx(fontdesc);
	}

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	pdf_dropfont(fontdesc);
	return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_tonum(dict), fz_togen(dict));
}
Ejemplo n.º 22
0
static fz_error
loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	fz_obj *descriptor;
	fz_obj *encoding;
	fz_obj *widths;
	unsigned short *etable = nil;
	pdf_fontdesc *fontdesc;
	fz_bbox bbox;
	FT_Face face;
	FT_CharMap cmap;
	int kind;
	int symbolic;

	char *basefont;
	char *fontname;
	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;

	basefont = fz_toname(fz_dictgets(dict, "BaseFont"));
	fontname = cleanfontname(basefont);

	/* Load font file */

	fontdesc = pdf_newfontdesc();

	pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc);
	pdf_logfont("basefont %s -> %s\n", basefont, fontname);

	descriptor = fz_dictgets(dict, "FontDescriptor");
	if (descriptor)
		error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil, basefont);
	else
		error = pdf_loadbuiltinfont(fontdesc, fontname);
	if (error)
		goto cleanup;

	face = fontdesc->font->ftface;
	kind = ftkind(face);

	pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name);

	bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM;
	bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM;
	bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM;
	bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM;

	pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	if (bbox.x0 == bbox.x1)
		fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000);
	else
		fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	/* Encoding */

	symbolic = fontdesc->flags & 4;

	if (face->num_charmaps > 0)
		cmap = face->charmaps[0];
	else
		cmap = nil;

	for (i = 0; i < face->num_charmaps; i++)
	{
		FT_CharMap test = face->charmaps[i];

		if (kind == TYPE1)
		{
			if (test->platform_id == 7)
				cmap = test;
		}

		if (kind == TRUETYPE)
		{
			if (test->platform_id == 1 && test->encoding_id == 0)
				cmap = test;
			if (test->platform_id == 3 && test->encoding_id == 1)
				cmap = test;
		}
	}

	if (cmap)
	{
		fterr = FT_Set_Charmap(face, cmap);
		if (fterr)
			fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr));
	}
	else
		fz_warn("freetype could not find any cmaps");

	etable = fz_malloc(sizeof(unsigned short) * 256);
	for (i = 0; i < 256; i++)
	{
		estrings[i] = nil;
		etable[i] = 0;
	}

	encoding = fz_dictgets(dict, "Encoding");
	if (encoding)
	{
		if (fz_isname(encoding))
			pdf_loadencoding(estrings, fz_toname(encoding));

		if (fz_isdict(encoding))
		{
			fz_obj *base, *diff, *item;

			base = fz_dictgets(encoding, "BaseEncoding");
			if (fz_isname(base))
				pdf_loadencoding(estrings, fz_toname(base));
			else if (!fontdesc->isembedded && !symbolic)
				pdf_loadencoding(estrings, "StandardEncoding");
			/* cf. http://bugs.ghostscript.com/show_bug.cgi?id=690615 and http://code.google.com/p/sumatrapdf/issues/detail?id=687 */
			/* try to extract an encoding from the font or synthesize a likely one */
			/* note: FT_Get_Name_Index fails for symbolic CFF fonts, so let them be encoded by index */
			else if (!fontdesc->encoding && !ftloadt1encoding(face, estrings) && !(symbolic && !strcmp(FT_Get_X11_Font_Format(face), "CFF")))
				pdf_loadencoding(estrings, "StandardEncoding");

			diff = fz_dictgets(encoding, "Differences");
			if (fz_isarray(diff))
			{
				n = fz_arraylen(diff);
				k = 0;
				for (i = 0; i < n; i++)
				{
					item = fz_arrayget(diff, i);
					if (fz_isint(item))
						k = fz_toint(item);
					if (fz_isname(item))
						estrings[k++] = fz_toname(item);
					if (k < 0) k = 0;
					if (k > 255) k = 255;
				}
			}
		}
	}

	/* start with the builtin encoding */
	for (i = 0; i < 256; i++)
		etable[i] = ftcharindex(face, i);

	/* encode by glyph name where we can */
	if (kind == TYPE1)
	{
		pdf_logfont("encode type1/cff by strings\n");
		for (i = 0; i < 256; i++)
		{
			if (estrings[i])
			{
				etable[i] = FT_Get_Name_Index(face, estrings[i]);
				if (etable[i] == 0)
				{
					int aglcode = pdf_lookupagl(estrings[i]);
					char **aglnames = pdf_lookupaglnames(aglcode);
					while (*aglnames)
					{
						etable[i] = FT_Get_Name_Index(face, *aglnames);
						if (etable[i])
							break;
						aglnames++;
					}
				}
			}
		}
	}

	/* encode by glyph name where we can */
	if (kind == TRUETYPE)
	{
		/* Unicode cmap */
		if (!symbolic && face->charmap && face->charmap->platform_id == 3)
		{
			pdf_logfont("encode truetype via unicode\n");
			for (i = 0; i < 256; i++)
			{
				if (estrings[i])
				{
					int aglcode = pdf_lookupagl(estrings[i]);
					if (!aglcode)
						etable[i] = FT_Get_Name_Index(face, estrings[i]);
					else
						etable[i] = ftcharindex(face, aglcode);
				}
			}
		}

		/* MacRoman cmap */
		else if (!symbolic && face->charmap && face->charmap->platform_id == 1)
		{
			pdf_logfont("encode truetype via macroman\n");
			for (i = 0; i < 256; i++)
			{
				if (estrings[i])
				{
					k = mrecode(estrings[i]);
					if (k <= 0)
						etable[i] = FT_Get_Name_Index(face, estrings[i]);
					else
						etable[i] = ftcharindex(face, k);
				}
			}
		}

		/* Symbolic cmap */
		else
		{
			pdf_logfont("encode truetype symbolic\n");
			for (i = 0; i < 256; i++)
			{
				if (estrings[i])
				{
					etable[i] = FT_Get_Name_Index(face, estrings[i]);
					if (etable[i] == 0)
						etable[i] = ftcharindex(face, i);
				}
			}
		}
	}

	/* try to reverse the glyph names from the builtin encoding */
	for (i = 0; i < 256; i++)
	{
		if (etable[i] && !estrings[i])
		{
			if (FT_HAS_GLYPH_NAMES(face))
			{
				fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
				if (fterr)
					fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr));
				if (ebuffer[i][0])
					estrings[i] = ebuffer[i];
			}
			else
			{
				estrings[i] = (char*) pdf_winansi[i]; /* discard const */
			}
		}
	}

	/* Prevent encoding Differences from being overwritten by reloading them */
	/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=115 */
	if (fz_isdict(encoding))
	{
		fz_obj *diff, *item;

		diff = fz_dictgets(encoding, "Differences");
		if (fz_isarray(diff))
		{
			n = fz_arraylen(diff);
			k = 0;
			for (i = 0; i < n; i++)
			{
				item = fz_arrayget(diff, i);
				if (fz_isint(item))
					k = fz_toint(item);
				if (fz_isname(item))
					estrings[k++] = fz_toname(item);
				if (k < 0) k = 0;
				if (k > 255) k = 255;
			}
		}
	}

	fontdesc->encoding = pdf_newidentitycmap(0, 1);
	fontdesc->ncidtogid = 256;
	fontdesc->cidtogid = etable;

	error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode"));
	if (error)
		goto cleanup;

	/* Widths */

	pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth);

	widths = fz_dictgets(dict, "Widths");
	if (widths)
	{
		int first, last;

		first = fz_toint(fz_dictgets(dict, "FirstChar"));
		last = fz_toint(fz_dictgets(dict, "LastChar"));

		if (first < 0 || last > 255 || first > last)
			first = last = 0;

		for (i = 0; i < last - first + 1; i++)
		{
			int wid = fz_toint(fz_arrayget(widths, i));
			pdf_addhmtx(fontdesc, i + first, i + first, wid);
		}
	}
	else
	{
		fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
		if (fterr)
			fz_warn("freetype set character size: %s", ft_errorstring(fterr));
		for (i = 0; i < 256; i++)
		{
			pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i));
		}
	}

	pdf_endhmtx(fontdesc);

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	if (etable != fontdesc->cidtogid)
		fz_free(etable);
	pdf_dropfont(fontdesc);
	return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_tonum(dict), fz_togen(dict));
}
Ejemplo n.º 23
0
fz_error *
pdf_loadtype7shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
{
	fz_error *error;
	fz_stream *stream;
	fz_obj *obj;

	int bpcoord;
	int bpcomp;
	int bpflag;
	int ncomp;

	float x0, x1, y0, y1;

	float c0[FZ_MAXCOLORS];
	float c1[FZ_MAXCOLORS];

	int i, n, j;
	unsigned int t;

	int flag;
	fz_point p[16];
	pdf_tensorpatch patch;

	error = nil;

	ncomp = shade->cs->n;
	bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
	bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
	bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag"));

	obj = fz_dictgets(shading, "Decode");
	if (fz_isarray(obj))
	{
		pdf_logshade("decode array\n");
		x0 = fz_toreal(fz_arrayget(obj, 0));
		x1 = fz_toreal(fz_arrayget(obj, 1));
		y0 = fz_toreal(fz_arrayget(obj, 2));
		y1 = fz_toreal(fz_arrayget(obj, 3));
		for (i=0; i < fz_arraylen(obj) / 2; ++i) {
			c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
			c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
		}
	}
	else {
		error = fz_throw("syntaxerror: No Decode key in Type 6 Shade");
		goto cleanup;
	}

	obj = fz_dictgets(shading, "Function");
	if (obj) {
		ncomp = 1;
		pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
		shade->usefunction = 1;
	} 
	else
		shade->usefunction = 0;

	shade->meshcap = 0;
	shade->mesh = nil;
	error = growshademesh(shade, 1024);
	if (error) goto cleanup;

	n = 2 + shade->cs->n;
	j = 0;

	error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref));
	if (error) goto cleanup;

	while (fz_peekbyte(stream) != EOF)
	{
		flag = getdata(stream, bpflag);

		for (i = 0; i < 16; ++i) {
			t = getdata(stream, bpcoord);
			p[i].x = x0 + (t * (x1 - x0) / (pow(2, bpcoord) - 1.));
			t = getdata(stream, bpcoord);
			p[i].y = y0 + (t * (y1 - y0) / (pow(2, bpcoord) - 1.));
		}

		for (i = 0; i < 4; ++i) {
			int k;
			for (k=0; k < ncomp; ++k) {
				t = getdata(stream, bpcomp);
				patch.color[i][k] = 
					c0[k] + (t * (c1[k] - c0[k]) / (pow(2, bpcomp) - 1.0f));
			}
		}

		patch.pole[0][0] = p[0];
		patch.pole[0][1] = p[1];
		patch.pole[0][2] = p[2];
		patch.pole[0][3] = p[3];
		patch.pole[1][3] = p[4];
		patch.pole[2][3] = p[5];
		patch.pole[3][3] = p[6];
		patch.pole[3][2] = p[7];
		patch.pole[3][1] = p[8];
		patch.pole[3][0] = p[9];
		patch.pole[2][0] = p[10];
		patch.pole[1][0] = p[11];
		patch.pole[1][1] = p[12];
		patch.pole[1][2] = p[13];
		patch.pole[2][2] = p[14];
		patch.pole[2][1] = p[15];

		j = drawpatch(patch, shade, j, ncomp, 0);
	}

	fz_dropstream(stream);

	shade->meshlen = j / n / 3;

cleanup:

	return nil;
}
Ejemplo n.º 24
0
static fz_error
pdf_readnewxref(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, stmofs;
    int size, w0, w1, w2;
    int t;
    int i;

    pdf_logxref("load new xref format\n");

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

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

    if (size >= xref->cap)
    {
        xref->cap = size + 1; /* for hack to allow broken pdf generators with off-by-one errors */
        xref->table = fz_realloc(xref->table, xref->cap * sizeof(pdf_xrefentry));
    }

    if (size > xref->len)
    {
        for (i = xref->len; i < xref->cap; i++)
        {
            xref->table[i].ofs = 0;
            xref->table[i].gen = 0;
            xref->table[i].stmofs = 0;
            xref->table[i].obj = nil;
            xref->table[i].type = 0;
        }
        xref->len = size;
    }

    if (num < 0 || num >= xref->len)
    {
        if (num == xref->len && num < xref->cap)
        {
            /* allow broken pdf files that have off-by-one errors in the xref */
            fz_warn("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1);
            xref->len ++;
        }
        else
        {
            fz_dropobj(trailer);
            return fz_throw("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1);
        }
    }

    pdf_logxref("\tnum=%d gen=%d size=%d\n", num, gen, size);

    obj = fz_dictgets(trailer, "W");
    if (!obj) {
        fz_dropobj(trailer);
        return fz_throw("xref stream missing W entry (%d %d R)", num, gen);
    }
    w0 = fz_toint(fz_arrayget(obj, 0));
    w1 = fz_toint(fz_arrayget(obj, 1));
    w2 = fz_toint(fz_arrayget(obj, 2));

    index = fz_dictgets(trailer, "Index");

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

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

    fz_close(stm);

    *trailerp = trailer;

    return fz_okay;
}
Ejemplo n.º 25
0
static fz_error *
loadnametreenode(fz_obj *tree, pdf_xref *xref, fz_obj *node)
{
	fz_error *error;
	fz_obj *names;
	fz_obj *kids;
	fz_obj *key;
	fz_obj *val;
	int i, len;

	error = pdf_resolve(&node, xref);
	if (error)
		return error;

	names = fz_dictgets(node, "Names");
	if (names)
	{
		error = pdf_resolve(&names, xref);
		if (error)
			goto cleanup;

		len = fz_arraylen(names) / 2;

		for (i = 0; i < len; ++i)
		{
			key = fz_arrayget(names, i * 2 + 0);
			val = fz_arrayget(names, i * 2 + 1);
			error = fz_dictput(tree, key, val);
			if (error)
			{
				fz_dropobj(names);
				goto cleanup;
			}
		}

		fz_dropobj(names);
	}

	kids = fz_dictgets(node, "Kids");
	if (kids)
	{
		error = pdf_resolve(&kids, xref);
		if (error)
			goto cleanup;

		len = fz_arraylen(kids);
		for (i = 0; i < len; ++i)
		{
			error = loadnametreenode(tree, xref, fz_arrayget(kids, i));
			if (error)
			{
				fz_dropobj(kids);
				goto cleanup;
			}
		}

		fz_dropobj(kids);
	}

	fz_dropobj(node);
	return nil;

cleanup:
	fz_dropobj(node);
	return error;
}
Ejemplo n.º 26
0
void
pdf_loadpagetreenode(pdf_xref *xref, fz_obj *node, struct info info)
{
	fz_obj *dict, *kids, *count;
	fz_obj *obj, *tmp;
	int i, n;

	/* prevent infinite recursion */
	if (fz_dictgets(node, ".seen"))
		return;

	kids = fz_dictgets(node, "Kids");
	count = fz_dictgets(node, "Count");

	if (fz_isarray(kids) && fz_isint(count))
	{
		obj = fz_dictgets(node, "Resources");
		if (obj)
			info.resources = obj;
		obj = fz_dictgets(node, "MediaBox");
		if (obj)
			info.mediabox = obj;
		obj = fz_dictgets(node, "CropBox");
		if (obj)
			info.cropbox = obj;
		obj = fz_dictgets(node, "Rotate");
		if (obj)
			info.rotate = obj;

		tmp = fz_newnull();
		fz_dictputs(node, ".seen", tmp);
		fz_dropobj(tmp);

		n = fz_arraylen(kids);
		for (i = 0; i < n; i++)
		{
			obj = fz_arrayget(kids, i);
			pdf_loadpagetreenode(xref, obj, info);
		}

		fz_dictdels(node, ".seen");
	}
	else
	{
		dict = fz_resolveindirect(node);

		if (info.resources && !fz_dictgets(dict, "Resources"))
			fz_dictputs(dict, "Resources", info.resources);
		if (info.mediabox && !fz_dictgets(dict, "MediaBox"))
			fz_dictputs(dict, "MediaBox", info.mediabox);
		if (info.cropbox && !fz_dictgets(dict, "CropBox"))
			fz_dictputs(dict, "CropBox", info.cropbox);
		if (info.rotate && !fz_dictgets(dict, "Rotate"))
			fz_dictputs(dict, "Rotate", info.rotate);

		if (xref->pagelen == xref->pagecap)
		{
			fz_warn("found more pages than expected");
			xref->pagecap ++;
			xref->pagerefs = fz_realloc(xref->pagerefs, sizeof(fz_obj*) * xref->pagecap);
			xref->pageobjs = fz_realloc(xref->pageobjs, sizeof(fz_obj*) * xref->pagecap);
		}

		xref->pagerefs[xref->pagelen] = fz_keepobj(node);
		xref->pageobjs[xref->pagelen] = fz_keepobj(dict);
		xref->pagelen ++;
	}
}
Ejemplo n.º 27
0
static fz_error *
loadpagetree(pdf_xref *xref, pdf_pagetree *pages,
		struct stuff inherit, fz_obj *obj, fz_obj *ref, int *pagenum)
{
	fz_error *error;
	fz_obj *type;
	fz_obj *kids;
	fz_obj *kref, *kobj;
	fz_obj *inh;
	int i;

	type = fz_dictgets(obj, "Type");

	if (strcmp(fz_toname(type), "Page") == 0)
	{
		pdf_logpage("page %d, %d %d\n", *pagenum, ref->u.r.oid, ref->u.r.gid);
		(*pagenum)++;

		if (inherit.resources && !fz_dictgets(obj, "Resources"))
		{
			pdf_logpage("inherit resources (%d)\n", pages->cursor);
			error = fz_dictputs(obj, "Resources", inherit.resources);
			if (error) return fz_rethrow(error, "cannot inherit page tree resources");
		}

		if (inherit.mediabox && !fz_dictgets(obj, "MediaBox"))
		{
			pdf_logpage("inherit mediabox (%d)\n", pages->cursor);
			error = fz_dictputs(obj, "MediaBox", inherit.mediabox);
			if (error) return fz_rethrow(error, "cannot inherit page tree mediabox");
		}

		if (inherit.cropbox && !fz_dictgets(obj, "CropBox"))
		{
			pdf_logpage("inherit cropbox (%d)\n", pages->cursor);
			error = fz_dictputs(obj, "CropBox", inherit.cropbox);
			if (error) return fz_rethrow(error, "cannot inherit page tree cropbox");
		}

		if (inherit.rotate && !fz_dictgets(obj, "Rotate"))
		{
			pdf_logpage("inherit rotate (%d)\n", pages->cursor);
			error = fz_dictputs(obj, "Rotate", inherit.rotate);
			if (error) return fz_rethrow(error, "cannot inherit page tree rotate");
		}

		pages->pref[pages->cursor] = fz_keepobj(ref);
		pages->pobj[pages->cursor] = fz_keepobj(obj);
		pages->cursor ++;
	}

	else if (strcmp(fz_toname(type), "Pages") == 0)
	{
		inh = fz_dictgets(obj, "Resources");
		if (inh) inherit.resources = inh;

		inh = fz_dictgets(obj, "MediaBox");
		if (inh) inherit.mediabox = inh;

		inh = fz_dictgets(obj, "CropBox");
		if (inh) inherit.cropbox = inh;

		inh = fz_dictgets(obj, "Rotate");
		if (inh) inherit.rotate = inh;

		kids = fz_dictgets(obj, "Kids");
		error = pdf_resolve(&kids, xref);
		if (error)
			return fz_rethrow(error, "cannot resolve /Kids");

		pdf_logpage("subtree %d pages, %d %d {\n",
				fz_arraylen(kids), ref->u.r.oid, ref->u.r.gid);

		for (i = 0; i < fz_arraylen(kids); i++)
		{
			kref = fz_arrayget(kids, i);

			error = pdf_loadindirect(&kobj, xref, kref);
			if (error) { fz_dropobj(kids); return fz_rethrow(error, "cannot load kid"); }

			if (kobj == obj)
			{
				/* prevent infinite recursion possible in maliciously crafted PDFs */
				fz_dropobj(kids);
				return fz_throw("corrupted pdf file");
			}

			error = loadpagetree(xref, pages, inherit, kobj, kref, pagenum);
			fz_dropobj(kobj);
			if (error) { fz_dropobj(kids); return fz_rethrow(error, "cannot load subtree"); }
		}

		fz_dropobj(kids);

		pdf_logpage("}\n");
	}

	else
		return fz_throw("pagetree node has unexpected type %s", fz_toname(type));

	return fz_okay;
}
static fz_error
loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	fz_obj *descriptor = nil;
	fz_obj *encoding = nil;
	fz_obj *widths = nil;
	unsigned short *etable = nil;
	pdf_fontdesc *fontdesc;
	fz_irect bbox;
	FT_Face face;
	FT_CharMap cmap;
	int kind;
	int symbolic;

	char *basefont;
	char *fontname;
	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;

	basefont = fz_toname(fz_dictgets(dict, "BaseFont"));
	fontname = cleanfontname(basefont);

	/*
	 * Load font file
	 */

	fontdesc = pdf_newfontdesc();
	if (!fontdesc)
		return fz_rethrow(-1, "out of memory");

	pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc);
	pdf_logfont("basefont0 %s\n", basefont);
	pdf_logfont("basefont1 %s\n", fontname);

	descriptor = fz_dictgets(dict, "FontDescriptor");
	if (descriptor && basefont == fontname)
		error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil);
	else
		error = pdf_loadbuiltinfont(fontdesc, fontname);
	if (error)
		goto cleanup;

	face = fontdesc->font->ftface;
	kind = ftkind(face);

	pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name);

	bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM;
	bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM;
	bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM;
	bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM;

	pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	if (bbox.x0 == bbox.x1)
		fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000);
	else
		fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	/*
	 * Encoding
	 */

	symbolic = fontdesc->flags & 4;

	if (face->num_charmaps > 0)
		cmap = face->charmaps[0];
	else
		cmap = nil;

	for (i = 0; i < face->num_charmaps; i++)
	{
		FT_CharMap test = face->charmaps[i];

		if (kind == TYPE1)
		{
			if (test->platform_id == 7)
				cmap = test;
		}

		if (kind == TRUETYPE)
		{
			if (test->platform_id == 1 && test->encoding_id == 0)
				cmap = test;
			if (test->platform_id == 3 && test->encoding_id == 1)
				cmap = test;
		}
	}

	if (cmap)
	{
		fterr = FT_Set_Charmap(face, cmap);
		if (fterr)
			fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr));
	}
	else
		fz_warn("freetype could not find any cmaps");

	etable = fz_malloc(sizeof(unsigned short) * 256);
	if (!etable)
		goto cleanup;

	for (i = 0; i < 256; i++)
	{
		estrings[i] = nil;
		etable[i] = 0;
	}

	encoding = fz_dictgets(dict, "Encoding");
	if (encoding && !(kind == TRUETYPE && symbolic))
	{
		if (fz_isname(encoding))
			pdf_loadencoding(estrings, fz_toname(encoding));

		if (fz_isdict(encoding))
		{
			fz_obj *base, *diff, *item;

			base = fz_dictgets(encoding, "BaseEncoding");
			if (fz_isname(base))
				pdf_loadencoding(estrings, fz_toname(base));
			else if (!fontdesc->isembedded)
				pdf_loadencoding(estrings, "StandardEncoding");

			diff = fz_dictgets(encoding, "Differences");
			if (fz_isarray(diff))
			{
				n = fz_arraylen(diff);
				k = 0;
				for (i = 0; i < n; i++)
				{
					item = fz_arrayget(diff, i);
					if (fz_isint(item))
						k = fz_toint(item);
					if (fz_isname(item))
						estrings[k++] = fz_toname(item);
					if (k < 0) k = 0;
					if (k > 255) k = 255;
				}
			}
		}

		if (kind == TYPE1)
		{
			pdf_logfont("encode type1/cff by strings\n");
			for (i = 0; i < 256; i++)
				if (estrings[i])
					etable[i] = FT_Get_Name_Index(face, estrings[i]);
				else
					etable[i] = ftcharindex(face, i);
		}

		if (kind == TRUETYPE)
		{
			/* Unicode cmap */
			if (face->charmap && face->charmap->platform_id == 3)
			{
				pdf_logfont("encode truetype via unicode\n");
				for (i = 0; i < 256; i++)
					if (estrings[i])
					{
						int aglbuf[256];
						int aglnum;
						aglnum = pdf_lookupagl(estrings[i], aglbuf, nelem(aglbuf));
						if (aglnum != 1)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ftcharindex(face, aglbuf[0]);
					}
					else
						etable[i] = ftcharindex(face, i);
			}

			/* MacRoman cmap */
			else if (face->charmap && face->charmap->platform_id == 1)
			{
				pdf_logfont("encode truetype via macroman\n");
				for (i = 0; i < 256; i++)
					if (estrings[i])
					{
						k = mrecode(estrings[i]);
						if (k <= 0)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ftcharindex(face, k);
					}
					else
						etable[i] = ftcharindex(face, i);
			}

			/* Symbolic cmap */
			else
			{
				pdf_logfont("encode truetype symbolic\n");
				for (i = 0; i < 256; i++)
				{
					etable[i] = ftcharindex(face, i);
					fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
					if (fterr)
					{
						error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr));
						goto cleanup;
					}
					if (ebuffer[i][0])
						estrings[i] = ebuffer[i];
				}
			}
		}
	}

	else
	{
		pdf_logfont("encode builtin\n");
		for (i = 0; i < 256; i++)
		{
			etable[i] = ftcharindex(face, i);
			if (etable[i] == 0)
				continue;

			if (FT_HAS_GLYPH_NAMES(face))
			{
				fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
				if (fterr)
				{
					error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr));
					goto cleanup;
				}
				if (ebuffer[i][0])
					estrings[i] = ebuffer[i];
			}
		}
	}

	error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1);
	if (error)
		goto cleanup;

	fontdesc->ncidtogid = 256;
	fontdesc->cidtogid = etable;

	error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode"));
	if (error)
		goto cleanup;

	/*
	 * Widths
	 */

	pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth);

	widths = fz_dictgets(dict, "Widths");
	if (widths)
	{
		int first, last;

		first = fz_toint(fz_dictgets(dict, "FirstChar"));
		last = fz_toint(fz_dictgets(dict, "LastChar"));

		if (first < 0 || last > 255 || first > last)
			first = last = 0;

		for (i = 0; i < last - first + 1; i++)
		{
			int wid = fz_toint(fz_arrayget(widths, i));
			error = pdf_addhmtx(fontdesc, i + first, i + first, wid);
			if (error)
				goto cleanup;
		}
	}
	else
	{
		fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
		if (fterr)
			fz_warn("freetype set character size: %s", ft_errorstring(fterr));
		for (i = 0; i < 256; i++)
		{
			error = pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i));
			if (error)
				goto cleanup;
		}
	}

	error = pdf_endhmtx(fontdesc);
	if (error)
		goto cleanup;

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	fz_free(etable);
	fz_dropfont(fontdesc->font);
	fz_free(fontdesc);
	return fz_rethrow(error, "cannot load simple font");
}
Ejemplo n.º 29
0
void
editflushcatalog(void)
{
	fz_error *error;
	int rootnum, rootgen;
	int listnum, listgen;
	fz_obj *listref;
	fz_obj *obj;
	int i;

	/* Create page tree and add back-links */

	error = pdf_allocobject(editxref, &listnum, &listgen);
	if (error)
		die(error);

	error = fz_packobj(&obj, "<</Type/Pages/Count %i/Kids %o>>",
			fz_arraylen(editpagelist),
			editpagelist);
	if (error)
		die(error);

	pdf_updateobject(editxref, listnum, listgen, obj);

	fz_dropobj(obj);

	error = fz_newindirect(&listref, listnum, listgen);
	if (error)
		die(error);

	for (i = 0; i < fz_arraylen(editpagelist); i++)
	{
		int num = fz_tonum(fz_arrayget(editpagelist, i));
		int gen = fz_togen(fz_arrayget(editpagelist, i));

		error = pdf_loadobject(&obj, editxref, num, gen);
		if (error)
			die(error);

		error = fz_dictputs(obj, "Parent", listref);
		if (error)
			die(error);

		pdf_updateobject(editxref, num, gen, obj);

		fz_dropobj(obj);
	}

	/* Create catalog */

	error = pdf_allocobject(editxref, &rootnum, &rootgen);
	if (error)
		die(error);

	error = fz_packobj(&obj, "<</Type/Catalog/Pages %r>>", listnum, listgen);
	if (error)
		die(error);

	pdf_updateobject(editxref, rootnum, rootgen, obj);

	fz_dropobj(obj);

	/* Create trailer */

	error = fz_packobj(&editxref->trailer, "<</Root %r>>", rootnum, rootgen);
	if (error)
		die(error);
}
Ejemplo n.º 30
0
static void
printinfo(char *filename, int show, int page)
{
	int i;
	int j;

#define PAGE_FMT "\t% 6d (% 6d %1d R): "

	if (show & DIMENSIONS && dims > 0)
	{
		printf("MediaBox: ");
		printf("\n");
		for (i = 0; i < dims; i++)
		{
			printf(PAGE_FMT "[ %g %g %g %g ]\n",
				dim[i]->page,
				fz_tonum(dim[i]->pageobj), fz_togen(dim[i]->pageobj),
				dim[i]->u.dim.bbox->x0,
				dim[i]->u.dim.bbox->y0,
				dim[i]->u.dim.bbox->x1,
				dim[i]->u.dim.bbox->y1);
		}
		printf("\n");

		for (i = 0; i < dims; i++)
		{
			fz_free(dim[i]->u.dim.bbox);
			fz_free(dim[i]);
		}
		fz_free(dim);
		dim = nil;
		dims = 0;
	}

	if (show & FONTS && fonts > 0)
	{
		printf("Fonts (%d):\n", fonts);
		for (i = 0; i < fonts; i++)
		{
			printf(PAGE_FMT "%s '%s' (%d %d R)\n",
				font[i]->page,
				fz_tonum(font[i]->pageobj), fz_togen(font[i]->pageobj),
				fz_toname(font[i]->u.font.subtype),
				fz_toname(font[i]->u.font.name),
				fz_tonum(font[i]->ref), fz_togen(font[i]->ref));
		}
		printf("\n");

		for (i = 0; i < fonts; i++)
			fz_free(font[i]);
		fz_free(font);
		font = nil;
		fonts = 0;
	}

	if (show & IMAGES && images > 0)
	{
		printf("Images (%d):\n", images);
		for (i = 0; i < images; i++)
		{
			printf(PAGE_FMT "[ ",
				image[i]->page,
				fz_tonum(image[i]->pageobj), fz_togen(image[i]->pageobj));

			if (fz_isarray(image[i]->u.image.filter))
				for (j = 0; j < fz_arraylen(image[i]->u.image.filter); j++)
			{
				printf("%s%s",
					fz_toname(fz_arrayget(image[i]->u.image.filter, j)),
					j == fz_arraylen(image[i]->u.image.filter) - 1 ? "" : " ");
			}
			else if (image[i]->u.image.filter)
				printf("%s", fz_toname(image[i]->u.image.filter));
			else
				printf("Raw");

			printf(" ] %dx%d %dbpc %s%s%s (%d %d R)\n",
				fz_toint(image[i]->u.image.width),
				fz_toint(image[i]->u.image.height),
				image[i]->u.image.bpc ? fz_toint(image[i]->u.image.bpc) : 1,
				image[i]->u.image.cs ? fz_toname(image[i]->u.image.cs) : "ImageMask",
				image[i]->u.image.altcs ? " " : "",
				image[i]->u.image.altcs ? fz_toname(image[i]->u.image.altcs) : "",
				fz_tonum(image[i]->ref), fz_togen(image[i]->ref));
		}
		printf("\n");

		for (i = 0; i < images; i++)
			fz_free(image[i]);
		fz_free(image);
		image = nil;
		images = 0;
	}

	if (show & SHADINGS && shadings > 0)
	{
		printf("Shading patterns (%d):\n", shadings);
		for (i = 0; i < shadings; i++)
		{
			char *shadingtype[] =
			{
				"",
				"Function",
				"Axial",
				"Radial",
				"Free-form triangle mesh",
				"Lattice-form triangle mesh",
				"Coons patch mesh",
				"Tensor-product patch mesh",
			};

			printf(PAGE_FMT "%s (%d %d R)\n",
				shading[i]->page,
				fz_tonum(shading[i]->pageobj), fz_togen(shading[i]->pageobj),
				shadingtype[fz_toint(shading[i]->u.shading.type)],
				fz_tonum(shading[i]->ref), fz_togen(shading[i]->ref));
		}
		printf("\n");

		for (i = 0; i < shadings; i++)
			fz_free(shading[i]);
		fz_free(shading);
		shading = nil;
		shadings = 0;
	}

	if (show & PATTERNS && patterns > 0)
	{
		printf("Patterns (%d):\n", patterns);
		for (i = 0; i < patterns; i++)
		{
			char *patterntype[] =
			{
				"",
				"Tiling",
				"Shading",
			};
			char *painttype[] =
			{
				"",
				"Colored",
				"Uncolored",
			};
			char *tilingtype[] =
			{
				"",
				"Constant spacing",
				"No distortion",
				"Constant space/fast tiling",
			};

			printf(PAGE_FMT "%s %s %s (%d %d R)\n",
				pattern[i]->page,
				fz_tonum(pattern[i]->pageobj), fz_togen(pattern[i]->pageobj),
				patterntype[fz_toint(pattern[i]->u.pattern.pattern)],
				painttype[fz_toint(pattern[i]->u.pattern.paint)],
				tilingtype[fz_toint(pattern[i]->u.pattern.tiling)],
				fz_tonum(pattern[i]->ref), fz_togen(pattern[i]->ref));
		}
		printf("\n");

		for (i = 0; i < patterns; i++)
			fz_free(pattern[i]);
		fz_free(pattern);
		pattern = nil;
		patterns = 0;
	}

	if (show & XOBJS && forms > 0)
	{
		printf("Form xobjects (%d):\n", forms);
		for (i = 0; i < forms; i++)
		{
			printf(PAGE_FMT "%s%s (%d %d R)\n",
				form[i]->page,
				fz_tonum(form[i]->pageobj), fz_togen(form[i]->pageobj),
				form[i]->u.form.group ? "Group" : "",
				form[i]->u.form.reference ? "Reference" : "",
				fz_tonum(form[i]->ref), fz_togen(form[i]->ref));
		}
		printf("\n");

		for (i = 0; i < forms; i++)
			fz_free(form[i]);
		fz_free(form);
		form = nil;
		forms = 0;
	}

	if (show & XOBJS && psobjs > 0)
	{
		printf("Postscript xobjects (%d):\n", psobjs);
		for (i = 0; i < psobjs; i++)
		{
			printf(PAGE_FMT "(%d %d R)\n",
				psobj[i]->page,
				fz_tonum(psobj[i]->pageobj), fz_togen(psobj[i]->pageobj),
				fz_tonum(psobj[i]->ref), fz_togen(psobj[i]->ref));
		}
		printf("\n");

		for (i = 0; i < psobjs; i++)
			fz_free(psobj[i]);
		fz_free(psobj);
		psobj = nil;
		psobjs = 0;
	}
}