static fz_error
loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen)
{
	fz_error error;
	fz_stream *stream;
	int codeptr;

	pdf_logrsrc("load postscript function (%d %d R)\n", oid, gen);

	error = pdf_openstream(&stream, xref, oid, gen);
	if (error)
		return fz_rethrow(error, "cannot open calculator function stream");

	if (fz_readbyte(stream) != '{')
	{
		fz_dropstream(stream);
		return fz_throw("stream is not a calculator function");
	}

	func->u.p.code = nil;
	func->u.p.cap = 0;

	codeptr = 0;
	error = parsecode(func, stream, &codeptr);
	if (error)
	{
		fz_dropstream(stream);
		return fz_rethrow(error, "cannot parse calculator function");
	}

	fz_dropstream(stream);
	return fz_okay;
}
Beispiel #2
0
static fz_error
loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref)
{
	fz_error error;
	pdf_csi *csi;
	fz_stream *stm;

	error = pdf_newcsi(&csi, 1);
	if (error)
		return fz_rethrow(error, "cannot create interpreter");

	error = pdf_openstream(&stm, xref, fz_tonum(stmref), fz_togen(stmref));
	if (error)
	{
		pdf_dropcsi(csi);
		return fz_rethrow(error, "cannot open glyph content stream");
	}

	error = pdf_runcsi(csi, xref, rdb, stm);
	if (error)
	{
		fz_dropstream(stm);
		pdf_dropcsi(csi);
		return fz_rethrow(error, "cannot interpret glyph content stream (%d %d R)", fz_tonum(stmref), fz_togen(stmref));
	}

	*treep = csi->tree;
	csi->tree = nil;

	fz_dropstream(stm);
	pdf_dropcsi(csi);
	return fz_okay;
}
Beispiel #3
0
static void showstream(int num, int gen)
{
	fz_error error;
	fz_stream *stm;
	unsigned char buf[2048];
	int n;

	showcolumn = 0;

	if (showdecode)
		error = pdf_openstream(&stm, xref, num, gen);
	else
		error = pdf_openrawstream(&stm, xref, num, gen);
	if (error)
		die(error);

	while (1)
	{
		error = fz_read(&n, stm, buf, sizeof buf);
		if (error)
			die(error);
		if (n == 0)
			break;
		if (showbinary)
			fwrite(buf, 1, n, stdout);
		else
			showsafe(buf, n);
	}

	fz_dropstream(stm);
}
void
fz_dropstream(fz_stream *stm)
{
	stm->refs --;
	if (stm->refs == 0)
	{
		if (stm->error)
		{
			fz_catch(stm->error, "dropped unhandled ioerror");
			stm->error = fz_okay;
		}

		switch (stm->kind)
		{
		case FZ_SFILE:
			close(stm->file);
			break;
		case FZ_SFILTER:
			fz_dropfilter(stm->filter);
			fz_dropstream(stm->chain);
			break;
		case FZ_SBUFFER:
			break;
		}

		fz_dropbuffer(stm->buffer);
		fz_free(stm);
	}
}
Beispiel #5
0
/*
 * Load predefined CMap from system.
 */
fz_error
pdf_loadsystemcmap(pdf_cmap **cmapp, char *cmapname)
{
	fz_error error;
	fz_stream *stream;
	pdf_cmap *usecmap;
	pdf_cmap *cmap;
	unsigned char *data;
	unsigned int len;
	int i;

	pdf_logfont("loading system cmap %s\n", cmapname);

	error = pdf_getcmapbuffer(cmapname, &data, &len);
	if(error)
		return fz_rethrow(error, "no builtin cmap file: %s", cmapname);

	stream = fz_openrmemory(data, len);
	error = pdf_parsecmap(&cmap, stream);
	fz_dropstream(stream);
	if(error)
		return fz_rethrow(error, "cannot parse cmap data");

	if (cmap->usecmapname[0] && !cmap->usecmap)
	{
		pdf_logfont("charmap depends on other charmap (%s), loading it\n", cmap->usecmapname);
		error = pdf_loadsystemcmap(&usecmap, cmap->usecmapname);
		if (error)
			return fz_rethrow(error, "could not load usecmap: %s", cmap->usecmapname);
		pdf_setusecmap(cmap, usecmap);
	}

	*cmapp = cmap;
	return fz_okay;
}
static fz_error *
parseTTCs(char *path)
{
	fz_error *err = nil;
	int byteread;
	fz_stream *file = nil;
	FONT_COLLECTION fontcollectioin;
	ULONG i;

	err = fz_openrfile(&file, path);
	if(err)
		goto cleanup;

	SAFE_FZ_READ(file, &fontcollectioin, sizeof(FONT_COLLECTION));
	if(memcmp(fontcollectioin.Tag,"ttcf",sizeof(fontcollectioin.Tag)) == 0)
	{
		fontcollectioin.Version = SWAPLONG(fontcollectioin.Version);
		fontcollectioin.NumFonts = SWAPLONG(fontcollectioin.NumFonts);
		if( fontcollectioin.Version == TTC_VERSION1 ||
			fontcollectioin.Version == TTC_VERSION2 )
		{
			ULONG *offsettable = fz_malloc(sizeof(ULONG)*fontcollectioin.NumFonts);
			if(offsettable == nil)
			{
				err = fz_outofmem;
				goto cleanup;
			}

			SAFE_FZ_READ(file, offsettable, sizeof(ULONG)*fontcollectioin.NumFonts);
			for(i = 0; i < fontcollectioin.NumFonts; ++i)
			{
				offsettable[i] = SWAPLONG(offsettable[i]);
				parseTTF(file,offsettable[i],i,path);				
			}
			fz_free(offsettable);
		}
		else
		{
			err = fz_throw("fonterror : invalid version");
			goto cleanup;
		}
	}
	else
	{
		err = fz_throw("fonterror: wrong format");
		goto cleanup;
	}
	
		
cleanup:
	if(file)
		fz_dropstream(file);

	return err;
}
Beispiel #7
0
/*
 * Load uncompressed contents of a stream into buf.
 */
fz_error *
pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen)
{
	fz_error *error;
	fz_stream *stm;

	error = pdf_openstream(&stm, xref, oid, gen);
	if (error)
		return fz_rethrow(error, "cannot open stream (%d)", oid);

	error = fz_readall(bufp, stm, 0);
	fz_dropstream(stm);
	if (error)
		return fz_rethrow(error, "cannot load stream into buffer (%d)", oid);
	return fz_okay;
}
static fz_error *
parseTTFs(char *path)
{
	fz_error *err = nil;
	fz_stream *file = nil;

	err = fz_openrfile(&file, path);
	if(err)
		goto cleanup;

	err = parseTTF(file,0,0,path);
	if(err)
		goto cleanup;
		
cleanup:
	if(file)
		fz_dropstream(file);

	return err;
}
Beispiel #9
0
void
fz_dropstream(fz_stream *stm)
{
	stm->refs --;
	if (stm->refs == 0)
	{
		if (stm->error)
		{
			fflush(stdout);
			fz_printerror(stm->error);
			fz_droperror(stm->error);
			fflush(stderr);
			fz_warn("dropped unhandled ioerror");
		}

		if (stm->mode == FZ_SWRITE)
		{
			stm->buffer->eof = 1;
			fz_flush(stm);
		}

		switch (stm->kind)
		{
		case FZ_SFILE:
			close(stm->file);
			break;
		case FZ_SFILTER:
			fz_dropfilter(stm->filter);
			fz_dropstream(stm->chain);
			break;
		case FZ_SBUFFER:
			break;
		}

		fz_dropbuffer(stm->buffer);
		fz_free(stm);
	}
}
Beispiel #10
0
fz_error *
pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
		fz_obj *rdb, fz_obj *dict, fz_stream *file)
{
	fz_error *error;
	pdf_image *img;
	fz_filter *filter;
	fz_obj *f;
	fz_obj *cs;
	fz_obj *d;
	int ismask;
	int i;

	img = fz_malloc(sizeof(pdf_image));
	if (!img)
		return fz_outofmem;

	pdf_logimage("load inline image %p {\n", img);

	img->super.loadtile = pdf_loadtile;
	img->super.drop = pdf_dropimage;
	img->super.n = 0;
	img->super.a = 0;
	img->super.refs = 0;
	img->indexed = nil;
	img->usecolorkey = 0;
	img->mask = nil;

	img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W"));
	img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H"));
	img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC"));
	ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM"));
	d = fz_dictgetsa(dict, "Decode", "D");
	cs = fz_dictgetsa(dict, "ColorSpace", "CS");

	pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc);

	if (ismask)
	{
		pdf_logimage("is mask\n");
		img->super.cs = nil;
		img->super.n = 0;
		img->super.a = 1;
		img->bpc = 1;
	}

	if (cs)
	{
		img->super.cs = nil;

		if (fz_isname(cs))
		{
			fz_obj *csd = fz_dictgets(rdb, "ColorSpace");
			if (csd)
			{
				fz_obj *cso = fz_dictget(csd, cs);
				img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso);
				if (img->super.cs)
					fz_keepcolorspace(img->super.cs);
			}
		}

		if (!img->super.cs)
		{
			/* XXX danger! danger! does this resolve? */
			error = pdf_loadcolorspace(&img->super.cs, xref, cs);
			if (error)
				return error;
		}

		if (!strcmp(img->super.cs->name, "Indexed"))
		{
			pdf_logimage("indexed\n");
			img->indexed = (pdf_indexed*)img->super.cs;
			img->super.cs = img->indexed->base;
		}

		pdf_logimage("colorspace %s\n", img->super.cs->name);

		img->super.n = img->super.cs->n;
		img->super.a = 0;
	}

	if (fz_isarray(d))
	{
		pdf_logimage("decode array\n");
		if (img->indexed)
			for (i = 0; i < 2; i++)
				img->decode[i] = fz_toreal(fz_arrayget(d, i));
		else
			for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
				img->decode[i] = fz_toreal(fz_arrayget(d, i));
	}
	else
	{
		if (img->indexed)
			for (i = 0; i < 2; i++)
				img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0;
		else
			for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
				img->decode[i] = i & 1;
	}

	if (img->indexed)
		img->stride = (img->super.w * img->bpc + 7) / 8;
	else
		img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8;

	/* load image data */

	f = fz_dictgetsa(dict, "Filter", "F");
	if (f)
	{
		fz_stream *tempfile;

		error = pdf_buildinlinefilter(&filter, dict);
		if (error)
			return error;

		error = fz_openrfilter(&tempfile, filter, file);
		if (error)
			return error;

		i = fz_readall(&img->samples, tempfile);
		if (i < 0)
			return fz_ioerror(tempfile);

		fz_dropfilter(filter);
		fz_dropstream(tempfile);
	}
	else
	{
		error = fz_newbuffer(&img->samples, img->super.h * img->stride);
		if (error)
			return error;

		i = fz_read(file, img->samples->bp, img->super.h * img->stride);
		if (i < 0)
			return fz_ioerror(file);

		img->samples->wp += img->super.h * img->stride;
	}

	/* 0 means opaque and 1 means transparent, so we invert to get alpha */
	if (ismask)
	{
		unsigned char *p;
		for (p = img->samples->bp; p < img->samples->ep; p++)
			*p = ~*p;
	}

	pdf_logimage("}\n");

	*imgp = img;
	return nil;
}
/*
 * Load CMap stream in PDF file
 */
fz_error
pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref)
{
    fz_error error = fz_okay;
    fz_obj *stmobj;
    fz_stream *file = nil;
    pdf_cmap *cmap = nil;
    pdf_cmap *usecmap;
    fz_obj *wmode;
    fz_obj *obj;

    if ((*cmapp = pdf_finditem(xref->store, PDF_KCMAP, stmref)))
    {
	pdf_keepcmap(*cmapp);
	return fz_okay;
    }

    pdf_logfont("load embedded cmap (%d %d R) {\n", fz_tonum(stmref), fz_togen(stmref));

    stmobj = fz_resolveindirect(stmref);

    error = pdf_openstream(&file, xref, fz_tonum(stmref), fz_togen(stmref));
    if (error)
    {
	error = fz_rethrow(error, "cannot open cmap stream");
	goto cleanup;
    }

    error = pdf_parsecmap(&cmap, file);
    if (error)
    {
	error = fz_rethrow(error, "cannot parse cmap stream");
	goto cleanup;
    }

    fz_dropstream(file);

    wmode = fz_dictgets(stmobj, "WMode");
    if (fz_isint(wmode))
    {
	pdf_logfont("wmode %d\n", wmode);
	pdf_setwmode(cmap, fz_toint(wmode));
    }

    obj = fz_dictgets(stmobj, "UseCMap");
    if (fz_isname(obj))
    {
	pdf_logfont("usecmap /%s\n", fz_toname(obj));
	error = pdf_loadsystemcmap(&usecmap, fz_toname(obj));
	if (error)
	{
	    error = fz_rethrow(error, "cannot load system usecmap '%s'", fz_toname(obj));
	    goto cleanup;
	}
	pdf_setusecmap(cmap, usecmap);
	pdf_dropcmap(usecmap);
    }
    else if (fz_isindirect(obj))
    {
	pdf_logfont("usecmap (%d %d R)\n", fz_tonum(obj), fz_togen(obj));
	error = pdf_loadembeddedcmap(&usecmap, xref, obj);
	if (error)
	{
	    error = fz_rethrow(error, "cannot load embedded usecmap");
	    goto cleanup;
	}
	pdf_setusecmap(cmap, usecmap);
	pdf_dropcmap(usecmap);
    }

    pdf_logfont("}\n");

    error = pdf_storeitem(xref->store, PDF_KCMAP, stmref, cmap);
    if (error)
    {
	error = fz_rethrow(error, "cannot store cmap resource");
	goto cleanup;
    }

    *cmapp = cmap;
    return fz_okay;

cleanup:
    if (file)
	fz_dropstream(file);
    if (cmap)
	pdf_dropcmap(cmap);
    return error; /* already rethrown */
}
fz_error *
pdf_updatexref(pdf_xref *xref, char *path)
{
	fz_error *error;
	fz_stream *out;
	int oid;
	int i, n;
	int startxref;
	fz_obj *obj;

	pdf_logxref("updatexref '%s' %p\n", path, xref);

	error = fz_openafile(&out, path);
	if (error)
		return error;

	fz_print(out, "\n");

	for (oid = 0; oid < xref->len; oid++)
	{
		if (xref->table[oid].type == 'a')
		{
			xref->table[oid].ofs = fz_tell(out);
			error = writeobject(out, xref, xref->crypt, oid, xref->table[oid].gen);
			if (error)
				goto cleanup;
		}
	}

	/* always write out entry 0 in appended xref sections */
	xref->table[0].type = 'd';

	startxref = fz_tell(out);
	fz_print(out, "xref\n");

	oid = 0;
	while (oid < xref->len)
	{
		n = countmodified(xref, oid);

		pdf_logxref("  section %d +%d\n", oid, n);

		fz_print(out, "%d %d\n", oid, n);

		for (i = 0; i < n; i++)
		{
			if (xref->table[oid + i].type == 'd')
				xref->table[oid + i].type = 'f';
			if (xref->table[oid + i].type == 'a')
				xref->table[oid + i].type = 'n';

			fz_print(out, "%010d %05d %c \n",
				xref->table[oid + i].ofs,
				xref->table[oid + i].gen,
				xref->table[oid + i].type);
		}

		oid += n;
		while (oid < xref->len &&
				xref->table[oid].type != 'a' &&
				xref->table[oid].type != 'd')
			oid ++;
	}

	fz_print(out, "\n");

	fz_print(out, "trailer\n<<\n  /Size %d\n  /Prev %d", xref->len, xref->startxref);

	obj = fz_dictgets(xref->trailer, "Root");
	fz_print(out,"\n  /Root %d %d R", fz_tonum(obj), fz_togen(obj));

	obj = fz_dictgets(xref->trailer, "Info");
	if (obj)
		fz_print(out,"\n  /Info %d %d R", fz_tonum(obj), fz_togen(obj));

	obj = fz_dictgets(xref->trailer, "Encrypt");
	if (obj) {
		fz_print(out,"\n  /Encrypt ");
		fz_printobj(out, obj, TIGHT);
	}

	obj = fz_dictgets(xref->trailer, "ID");
	if (obj) {
		fz_print(out,"\n  /ID ");
		fz_printobj(out, obj, TIGHT);
	}

	fz_print(out, "\n>>\n\n");

	fz_print(out, "startxref\n");
	fz_print(out, "%d\n", startxref);
	fz_print(out, "%%%%EOF\n");

	xref->startxref = startxref;

	fz_dropstream(out);
	return nil;

cleanup:
	fz_dropstream(out);
	return error;
}
Beispiel #13
0
fz_error
pdf_loadxref(pdf_xref *xref, char *filename)
{
	fz_error error;
	fz_obj *size;
	int i;

	char buf[65536];	/* yeowch! */

	pdf_logxref("loadxref '%s' %p\n", filename, xref);

	error = fz_openrfile(&xref->file, filename);
	if (error)
	{
		return fz_rethrow(error, "cannot open file: '%s'", filename);
	}

	error = loadversion(xref);
	if (error)
	{
		error = fz_rethrow(error, "cannot read version marker");
		goto cleanup;
	}

	error = readstartxref(xref);
	if (error)
	{
		error = fz_rethrow(error, "cannot read startxref");
		goto cleanup;
	}

	error = readtrailer(xref, buf, sizeof buf);
	if (error)
	{
		error = fz_rethrow(error, "cannot read trailer");
		goto cleanup;
	}

	size = fz_dictgets(xref->trailer, "Size");
	if (!size)
	{
		error = fz_throw("trailer missing Size entry");
		goto cleanup;
	}

	pdf_logxref("  size %d at 0x%x\n", fz_toint(size), xref->startxref);

	assert(xref->table == nil);

	xref->len = fz_toint(size);
	xref->cap = xref->len + 1; /* for hack to allow broken pdf generators with off-by-one errors */
	xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry));
	for (i = 0; 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;
	}

	error = readxrefsections(xref, xref->startxref, buf, sizeof buf);
	if (error)
	{
		error = fz_rethrow(error, "cannot read xref");
		goto cleanup;
	}

	/* broken pdfs where first object is not free */
	if (xref->table[0].type != 'f')
	{
		fz_warn("first object in xref is not free");
		xref->table[0].type = 'f';
	}

	/* broken pdfs where freed objects have offset and gen set to 0
	but still exits */
	for (i = 0; i < xref->len; i++)
		if (xref->table[i].type == 'n' && xref->table[i].ofs == 0 &&
			xref->table[i].gen == 0 && xref->table[i].obj == nil)
	{
		fz_warn("object (%d %d R) has invalid offset, assumed missing", i, xref->table[i].gen);
		xref->table[i].type = 'f';
	}

	return fz_okay;

cleanup:
	fz_dropstream(xref->file);
	xref->file = nil;
	free(xref->table);
	xref->table = nil;
	return error;
}
Beispiel #14
0
int
main(int argc, char **argv)
{
	pdf_cmap *cmap;
	fz_error error;
	fz_stream *fi;
	FILE *fo;
	char name[256];
	char *realname;
	int i, k;

	if (argc < 3)
	{
		fprintf(stderr, "usage: cmapdump output.c lots of cmap files\n");
		return 1;
	}

	fo = fopen(argv[1], "wb");
	if (!fo)
	{
		fprintf(stderr, "cmapdump: could not open output file\n");
		return 1;
	}

	fprintf(fo, "#include \"fitz.h\"\n");
	fprintf(fo, "#include \"mupdf.h\"\n");
	fprintf(fo, "\n");

	for (i = 2; i < argc; i++)
	{
		realname = strrchr(argv[i], '/');
		if (!realname)
			realname = strrchr(argv[i], '\\');
		if (realname)
			realname ++;
		else
			realname = argv[i];

		if (strlen(realname) > (sizeof name - 1))
		{
			fprintf(stderr, "cmapdump: file name too long\n");
			return 1;
		}

		strcpy(name, realname);
		clean(name);

		error = fz_openrfile(&fi, argv[i]);
		if (error)
		{
			fz_catch(error, "cmapdump: could not open input file %s\n", argv[i]);
			return 1;
		}

		error = pdf_parsecmap(&cmap, fi);
		if (error)
		{
			fz_catch(error, "cmapdump: could not parse input cmap %s\n", argv[i]);
			return 1;
		}

		fprintf(fo, "/*\n * %s\n */\n\n", cmap->cmapname);

		fprintf(fo, "static const pdf_range pdf_cmap_%s_ranges[] =\n{\n", name);
		if (cmap->rlen == 0)
		{
			fprintf(fo, "    /* dummy entry for non-c99 compilers */\n");
			fprintf(fo, "    { 0x0, 0x0, PDF_CMAP_RANGE, 0 }\n");
		}
		for (k = 0; k < cmap->rlen; k++)
		{
			fprintf(fo, "    { 0x%04x, 0x%04x, %s %d },\n",
				cmap->ranges[k].low, cmap->ranges[k].high,
				flagtoname(cmap->ranges[k].flag),
				cmap->ranges[k].offset);
		}
		fprintf(fo, "};\n\n");

		if (cmap->tlen == 0)
		{
			fprintf(fo, "static const unsigned short pdf_cmap_%s_table[1] = { 0 };\n\n", name);
		}
		else
		{
			fprintf(fo, "static const unsigned short pdf_cmap_%s_table[%d] =\n{",
				name, cmap->tlen);
			for (k = 0; k < cmap->tlen; k++)
			{
				if (k % 8 == 0)
					fprintf(fo, "\n    ");
				fprintf(fo, "%d, ", cmap->table[k]);
			}
			fprintf(fo, "\n};\n\n");
		}

		fprintf(fo, "pdf_cmap pdf_cmap_%s =\n", name);
		fprintf(fo, "{\n");
		fprintf(fo, "    -1, ");
		fprintf(fo, "\"%s\", ", cmap->cmapname);
		fprintf(fo, "\"%s\", nil, ", cmap->usecmapname);
		fprintf(fo, "%d,\n", cmap->wmode);

		fprintf(fo, "    %d, /* codespace table */\n", cmap->ncspace);
		fprintf(fo, "    {\n");

		if (cmap->ncspace == 0)
		{
			fprintf(fo, "    /* dummy entry for non-c99 compilers */\n");
			fprintf(fo, "    { 0, 0x0, 0x0 },\n");
		}
		for (k = 0; k < cmap->ncspace; k++)
		{
			fprintf(fo, "\t{ %d, 0x%04x, 0x%04x },\n",
				cmap->cspace[k].n, cmap->cspace[k].low, cmap->cspace[k].high);
		}
		fprintf(fo, "    },\n");

		fprintf(fo, "    %d, %d, (pdf_range*) pdf_cmap_%s_ranges,\n",
			cmap->rlen, cmap->rlen, name);

		fprintf(fo, "    %d, %d, (unsigned short*) pdf_cmap_%s_table,\n",
			cmap->tlen, cmap->tlen, name);

		fprintf(fo, "};\n\n");

		fz_dropstream(fi);
	}

	return 0;
}
Beispiel #15
0
fz_error
pdf_loadobjstm(pdf_xref *xref, int oid, int gen, char *buf, int cap)
{
	fz_error error;
	fz_stream *stm;
	fz_obj *objstm;
	int *oidbuf;
	int *ofsbuf;

	fz_obj *obj;
	int first;
	int count;
	int i, n;
	pdf_token_e tok;

	pdf_logxref("loadobjstm (%d %d R)\n", oid, gen);

	error = pdf_loadobject(&objstm, xref, oid, gen);
	if (error)
		return fz_rethrow(error, "cannot load object stream object");

	count = fz_toint(fz_dictgets(objstm, "N"));
	first = fz_toint(fz_dictgets(objstm, "First"));

	pdf_logxref("  count %d\n", count);

	oidbuf = fz_malloc(count * sizeof(int));
	ofsbuf = fz_malloc(count * sizeof(int));

	error = pdf_openstream(&stm, xref, oid, gen);
	if (error)
	{
		error = fz_rethrow(error, "cannot open object stream");
		goto cleanupbuf;
	}

	for (i = 0; i < count; i++)
	{
		error = pdf_lex(&tok, stm, buf, cap, &n);
		if (error || tok != PDF_TINT)
		{
			error = fz_rethrow(error, "corrupt object stream");
			goto cleanupstm;
		}
		oidbuf[i] = atoi(buf);

		error = pdf_lex(&tok, stm, buf, cap, &n);
		if (error || tok != PDF_TINT)
		{
			error = fz_rethrow(error, "corrupt object stream");
			goto cleanupstm;
		}
		ofsbuf[i] = atoi(buf);
	}

	error = fz_seek(stm, first, 0);
	if (error)
	{
		error = fz_rethrow(error, "cannot seek in object stream");
		goto cleanupstm;
	}

	for (i = 0; i < count; i++)
	{
		/* FIXME: seek to first + ofsbuf[i] */

		error = pdf_parsestmobj(&obj, xref, stm, buf, cap);
		if (error)
		{
			error = fz_rethrow(error, "cannot parse object %d in stream", i);
			goto cleanupstm;
		}

		if (oidbuf[i] < 1 || oidbuf[i] >= xref->len)
		{
			fz_dropobj(obj);
			error = fz_throw("object id (%d 0 R) out of range (0..%d)", oidbuf[i], xref->len - 1);
			goto cleanupstm;
		}

		if (xref->table[oidbuf[i]].obj)
			fz_dropobj(xref->table[oidbuf[i]].obj);
		xref->table[oidbuf[i]].obj = obj;
	}

	fz_dropstream(stm);
	fz_free(ofsbuf);
	fz_free(oidbuf);
	fz_dropobj(objstm);
	return fz_okay;

cleanupstm:
	fz_dropstream(stm);
cleanupbuf:
	fz_free(ofsbuf);
	fz_free(oidbuf);
	fz_dropobj(objstm);
	return error; /* already rethrown */
}
Beispiel #16
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;
}
Beispiel #17
0
/*
 * Open a stream for reading uncompressed data. 
 * Put the opened file in xref->stream.
 * Using xref->file while a stream is open is a Bad idea.
 */
fz_error *
pdf_openstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen)
{
	pdf_xrefentry *x;
	fz_error *error;
	fz_stream *rawstm;
	fz_filter *filter;

	if (oid < 0 || oid >= xref->len)
		return fz_throw("object id out of range (%d)", oid);

	x = xref->table + oid;

	error = pdf_cacheobject(xref, oid, gen);
	if (error)
		return fz_rethrow(error, "cannot load stream object (%d)", oid);

	if (x->stmbuf)
	{
		error = pdf_buildfilter(&filter, xref, x->obj, oid, gen);
		if (error)
			return fz_rethrow(error, "cannot create filter");

		error = fz_openrbuffer(&rawstm, x->stmbuf);
		if (error)
		{
			fz_dropfilter(filter);
			return fz_rethrow(error, "cannot open stream from buffer");
		}

		error = fz_openrfilter(stmp, filter, rawstm);
		fz_dropfilter(filter);
		fz_dropstream(rawstm);
		if (error)
			return fz_rethrow(error, "cannot open filter stream");
		return fz_okay;
	}

	if (x->stmofs)
	{
		error = pdf_buildfilter(&filter, xref, x->obj, oid, gen);
		if (error)
			return fz_rethrow(error, "cannot create filter");

		error = fz_seek(xref->file, x->stmofs, 0);
		if (error)
		{
			fz_dropfilter(filter);
			return fz_rethrow(error, "cannot seek to stream");
		}

		error = fz_openrfilter(stmp, filter, xref->file);
		fz_dropfilter(filter);
		if (error)
			return fz_rethrow(error, "cannot open filter stream");

		return fz_okay;
	}

	return fz_throw("object is not a stream");
}
static fz_error *
writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen)
{
	fz_error *error;
	fz_stream *dststm;
	fz_stream *srcstm;
	unsigned char buf[4096];
	fz_filter *ef;
	int n;

	fz_print(out, "stream\n");

	if (encrypt)
	{
		error = pdf_cryptstream(&ef, encrypt, oid, gen);
		if (error)
			return error;

		error = fz_openrfilter(&dststm, ef, out);
		fz_dropfilter(ef);
		if (error)
			return error;
	}
	else
	{
		dststm = fz_keepstream(out);
	}

	error = pdf_openrawstream(&srcstm, xref, oid, gen);
	if (error)
		goto cleanupdst;

	while (1)
	{
		n = fz_read(srcstm, buf, sizeof buf);
		if (n == 0)
			break;
		if (n < 0)
		{
			error = fz_ioerror(srcstm);
			goto cleanupsrc;
		}

		n = fz_write(dststm, buf, n);
		if (n < 0)
		{
			error = fz_ioerror(dststm);
			goto cleanupsrc;
		}
	}

	fz_dropstream(srcstm);
	fz_dropstream(dststm);

	fz_print(out, "endstream\n");

	return nil;

cleanupsrc:
	fz_dropstream(srcstm);
cleanupdst:
	fz_dropstream(dststm);
	return error;
}
fz_error *
pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt)
{
	fz_error *error;
	fz_stream *out;
	int oid;
	int startxref;
	int *ofsbuf;
	fz_obj *obj;
	int eoid, egen;

	pdf_logxref("savexref '%s' %p\n", path, xref);

	/* need to add encryption object for acrobat < 6 */
	if (encrypt)
	{
		pdf_logxref("make encryption dict\n");

		error = pdf_allocobject(xref, &eoid, &egen);
		if (error)
			return error;

		pdf_cryptobj(encrypt, encrypt->encrypt, eoid, egen);

		error = pdf_updateobject(xref, eoid, egen, encrypt->encrypt);
		if (error)
			return error;
	}

	ofsbuf = fz_malloc(sizeof(int) * xref->len);
	if (!ofsbuf)
		return fz_outofmem;

	error = fz_openwfile(&out, path);
	if (error)
	{
		fz_free(ofsbuf);
		return error;
	}

	fz_print(out, "%%PDF-%1.1f\n", xref->version);
	fz_print(out, "%%\342\343\317\323\n\n");

	for (oid = 0; oid < xref->len; oid++)
	{
		pdf_xrefentry *x = xref->table + oid;
		if (x->type == 'n' || x->type == 'o' || x->type == 'a')
		{
			ofsbuf[oid] = fz_tell(out);
			error = writeobject(out, xref, encrypt, oid, x->type == 'o' ? 0 : x->gen);
			if (error)
				goto cleanup;
		}
		else
		{
			ofsbuf[oid] = x->ofs;
		}
	}

	startxref = fz_tell(out);
	fz_print(out, "xref\n");
	fz_print(out, "0 %d\n", xref->len);

	for (oid = 0; oid < xref->len; oid++)
	{
		int gen = xref->table[oid].gen;
		int type = xref->table[oid].type;
		if (type == 'o')
			gen = 0;
		if (type == 'a' || type == 'o')
			type = 'n';
		if (type == 'd')
			type = 'f';
		fz_print(out, "%010d %05d %c \n", ofsbuf[oid], gen, type);
	}

	fz_print(out, "\n");

	fz_print(out, "trailer\n<<\n  /Size %d", xref->len);
	obj = fz_dictgets(xref->trailer, "Root");
	fz_print(out, "\n  /Root %d %d R", fz_tonum(obj), fz_togen(obj));
	obj = fz_dictgets(xref->trailer, "Info");
	if (obj)
		fz_print(out, "\n  /Info %d %d R", fz_tonum(obj), fz_togen(obj));
	if (encrypt)
	{
		fz_print(out, "\n  /Encrypt %d %d R", eoid, egen);
		fz_print(out, "\n  /ID [");
		fz_printobj(out, encrypt->id, 1);
		fz_printobj(out, encrypt->id, 1);
		fz_print(out, "]");

		pdf_cryptobj(encrypt, encrypt->encrypt, eoid, egen);
	}
	fz_print(out, "\n>>\n\n");

	fz_print(out, "startxref\n");
	fz_print(out, "%d\n", startxref);
	fz_print(out, "%%%%EOF\n");

	xref->startxref = startxref;

	if(ofsbuf) fz_free(ofsbuf);
	fz_dropstream(out);
	return nil;

cleanup:
	if(ofsbuf) fz_free(ofsbuf);
	fz_dropstream(out);
	return error;
}
Beispiel #20
0
static fz_error
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 oid, 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, &oid, &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");
	}
	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 (oid < 0 || oid >= xref->len)
	{
		if (oid == xref->len && oid < 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)", oid, gen, xref->len - 1);
			xref->len ++;
		}
		else
		{
			fz_dropobj(trailer);
			return fz_throw("object id (%d %d R) out of range (0..%d)", oid, gen, xref->len - 1);
		}
	}

	xref->table[oid].type = 'n';
	xref->table[oid].gen = gen;
	xref->table[oid].obj = fz_keepobj(trailer);
	xref->table[oid].stmofs = stmofs;
	xref->table[oid].ofs = 0;

	obj = fz_dictgets(trailer, "W");
	if (!obj) {
		fz_dropobj(trailer);
		return fz_throw("xref stream missing W entry");
	}
	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_openstream(&stm, xref, oid, gen);
	if (error)
	{
		fz_dropobj(trailer);
		return fz_rethrow(error, "cannot open compressed xref stream");
	}

	if (!index)
	{
		error = readnewxrefsection(xref, stm, 0, size, w0, w1, w2);
		if (error)
		{
			fz_dropstream(stm);
			fz_dropobj(trailer);
			return fz_rethrow(error, "cannot read xref stream");
		}
	}
	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 = readnewxrefsection(xref, stm, i0, i1, w0, w1, w2);
			if (error)
			{
				fz_dropstream(stm);
				fz_dropobj(trailer);
				return fz_rethrow(error, "cannot read xref stream section");
			}
		}
	}

	fz_dropstream(stm);

	*trailerp = trailer;

	return fz_okay;
}
Beispiel #21
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;
}