Exemple #1
0
static fz_error
pdf_loadpagecontents(fz_buffer **bufp, pdf_xref *xref, fz_obj *obj)
{
	fz_error error;

	if (fz_isarray(obj))
	{
		error = pdf_loadpagecontentsarray(bufp, xref, obj);
		if (error)
			return fz_rethrow(error, "cannot load content stream array (%d 0 R)", fz_tonum(obj));
	}
	else if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj)))
	{
		error = pdf_loadstream(bufp, xref, fz_tonum(obj), fz_togen(obj));
		if (error)
			return fz_rethrow(error, "cannot load content stream (%d 0 R)", fz_tonum(obj));
	}
	else
	{
		fz_warn("page contents missing, leaving page blank");
		*bufp = fz_newbuffer(0);
	}

	return fz_okay;
}
Exemple #2
0
static void sweepref(fz_obj *obj)
{
	int num = fz_tonum(obj);
	int gen = fz_togen(obj);

	if (num < 0 || num >= xref->len)
		return;
	if (uselist[num])
		return;

	uselist[num] = 1;

	/* Bake in /Length in stream objects */
	if (pdf_isstream(xref, num, gen))
	{
		fz_obj *len = fz_dictgets(obj, "Length");
		if (fz_isindirect(len))
		{
			uselist[fz_tonum(len)] = 0;
			len = fz_resolveindirect(len);
			fz_dictputs(obj, "Length", len);
		}
	}

	sweepobj(fz_resolveindirect(obj));
}
Exemple #3
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;
}
Exemple #4
0
void
pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val)
{
	pdf_item *item;

	item = fz_malloc(sizeof(pdf_item));
	item->kind = kind;
	item->key = fz_keepobj(key);
	item->val = val;
	item->age = 0;
	item->next = nil;

	if (fz_isindirect(key))
	{
		struct refkey refkey;

		pdf_logrsrc("store item %s (%d %d R) ptr=%p\n", kindstr(kind), fz_tonum(key), fz_togen(key), val);

		refkey.kind = kind;
		refkey.oid = fz_tonum(key);
		refkey.gen = fz_togen(key);

		fz_hashinsert(store->hash, &refkey, item);
	}
	else
	{
		pdf_logrsrc("store item %s: ... = %p\n", kindstr(kind), val);

		item->next = store->root;
		store->root = item;
	}

	keepitem(kind, val);
}
fz_error
pdf_loadembeddedfont(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *stmref)
{
	fz_error error;
	fz_buffer *buf;

	pdf_logfont("load embedded font\n");

	error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref));
	if (error)
		return fz_rethrow(error, "cannot load font stream (%d %d R)", fz_tonum(stmref), fz_togen(stmref));

	error = fz_newfontfrombuffer(&fontdesc->font, buf->data, buf->len, 0);
	if (error)
	{
		fz_dropbuffer(buf);
		return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_tonum(stmref), fz_togen(stmref));
	}

	fontdesc->buffer = buf->data; /* save the buffer so we can free it later */
	fz_free(buf); /* only free the fz_buffer struct, not the contained data */

	fontdesc->isembedded = 1;

	return fz_okay;
}
Exemple #6
0
static fz_error
gatherpsobjs(int page, fz_obj *pageobj, fz_obj *dict)
{
	int i;

	for (i = 0; i < fz_dictlen(dict); i++)
	{
		fz_obj *ref;
		fz_obj *xobjdict;
		fz_obj *type;
		fz_obj *subtype;
		int k;

		xobjdict = ref = fz_dictgetval(dict, i);
		if (!fz_isdict(xobjdict))
			return fz_throw("not a xobject dict (%d %d R)", fz_tonum(ref), fz_togen(ref));

		type = fz_dictgets(xobjdict, "Subtype");
		if (!fz_isname(type))
			return fz_throw("not a xobject type (%d %d R)", fz_tonum(ref), fz_togen(ref));
		if (strcmp(fz_toname(type), "Form"))
			continue;

		subtype = fz_dictgets(xobjdict, "Subtype2");
		if (subtype && !fz_isname(subtype))
			return fz_throw("not a xobject subtype (%d %d R)", fz_tonum(ref), fz_togen(ref));
		if (strcmp(fz_toname(type), "PS") &&
			(strcmp(fz_toname(type), "Form") || strcmp(fz_toname(subtype), "PS")))
			continue;

		for (k = 0; k < psobjs; k++)
			if (fz_tonum(psobj[k]->ref) == fz_tonum(ref) &&
				fz_togen(psobj[k]->ref) == fz_togen(ref))
				break;

		if (k < psobjs)
			continue;

		psobjs++;

		psobj = fz_realloc(psobj, psobjs * sizeof (struct info *));
		if (!psobj)
			return fz_throw("out of memory");

		psobj[psobjs - 1] = fz_malloc(sizeof (struct info));
		if (!psobj[psobjs - 1])
			return fz_throw("out of memory");

		psobj[psobjs - 1]->page = page;
		psobj[psobjs - 1]->pageobj = pageobj;
		psobj[psobjs - 1]->ref = ref;
	}

	return fz_okay;
}
int
pdf_findpageobject(pdf_xref *xref, fz_obj *page)
{
	int num = fz_tonum(page);
	int gen = fz_togen(page);
	int i;
	for (i = 0; i < xref->pagelen; i++)
		if (num == fz_tonum(xref->pagerefs[i]) && gen == fz_togen(xref->pagerefs[i]))
			return i + 1;
	return 0;
}
Exemple #8
0
int
epdf_index_item_page_get(const Epdf_Document *doc, const Epdf_Index_Item *item)
{
   fz_obj *dest;
   int p;
   int n;
   int g;

   if (!item || !item->link)
     return -1;

   if (PDF_LGOTO != item->link->kind)
     return -1;

   dest = item->link->dest;
   p = 0;
   if (fz_isint(dest))
     {
        p = fz_toint(dest);
        return p;
     }
   if (fz_isdict(dest))
     {
        /* The destination is linked from a Go-To action's D array */
       fz_obj *D;

       D = fz_dictgets(dest, "D");
       if (D && fz_isarray(D))
         dest = fz_arrayget(D, 0);
     }

   n = fz_tonum(dest);
   g = fz_togen(dest);

   for (p = 1; p <= epdf_document_page_count_get(doc); p++)
     {
        fz_obj *page;
        int np;
        int gp;

        page = pdf_getpageobject(doc->xref, p);
        if (!page)
          continue;

        np = fz_tonum(page);
        gp = fz_togen(page);
        if (n == np && g == gp)
          return p-1;
    }

   return 0;
}
fz_error *
pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val)
{
	fz_error *error;

	switch (kind)
	{
	case PDF_KCOLORSPACE: fz_keepcolorspace(val); break;
	case PDF_KFUNCTION: pdf_keepfunction(val); break;
	case PDF_KXOBJECT: pdf_keepxobject(val); break;
	case PDF_KIMAGE: fz_keepimage(val); break;
	case PDF_KPATTERN: pdf_keeppattern(val); break;
	case PDF_KSHADE: fz_keepshade(val); break;
	case PDF_KCMAP: pdf_keepcmap(val); break;
	case PDF_KFONT: fz_keepfont(val); break;
	}

	if (fz_isindirect(key))
	{
		struct refkey item;

		pdf_logrsrc("store item %d: %d %d R = %p\n", kind, fz_tonum(key), fz_togen(key), val);

		item.kind = kind;
		item.oid = fz_tonum(key);
		item.gen = fz_togen(key);

		error = fz_hashinsert(store->hash, &item, val);
		if (error)
			return error;
	}

	else
	{
		pdf_item *item;

		item = fz_malloc(sizeof(pdf_item));
		if (!item)
			return fz_outofmem;

		pdf_logrsrc("store item %d: ... = %p\n", kind, val);

		item->kind = kind;
		item->key = fz_keepobj(key);
		item->val = val;

		item->next = store->root;
		store->root = item;
	}

	return nil;
}
Exemple #10
0
static fz_error
gathershadings(int page, fz_obj *pageobj, fz_obj *dict)
{
	int i;

	for (i = 0; i < fz_dictlen(dict); i++)
	{
		fz_obj *ref;
		fz_obj *shade;
		fz_obj *type;
		int k;

		shade = ref = fz_dictgetval(dict, i);
		if (!fz_isdict(shade))
			return fz_throw("not a shading dict (%d %d R)", fz_tonum(ref), fz_togen(ref));

		type = fz_dictgets(shade, "ShadingType");
		if (!fz_isint(type) || fz_toint(type) < 1 || fz_toint(type) > 7)
		{
			fz_warn("not a shading type (%d %d R)", fz_tonum(ref), fz_togen(ref));
			type = nil;
		}

		for (k = 0; k < shadings; k++)
			if (fz_tonum(shading[k]->ref) == fz_tonum(ref) &&
				fz_togen(shading[k]->ref) == fz_togen(ref))
				break;

		if (k < shadings)
			continue;

		shadings++;

		shading = fz_realloc(shading, shadings * sizeof (struct info *));
		if (!shading)
			return fz_throw("out of memory");

		shading[shadings - 1] = fz_malloc(sizeof (struct info));
		if (!shading[shadings - 1])
			return fz_throw("out of memory");

		shading[shadings - 1]->page = page;
		shading[shadings - 1]->pageobj = pageobj;
		shading[shadings - 1]->ref = ref;
		shading[shadings - 1]->u.shading.type = type;
	}

	return fz_okay;
}
Exemple #11
0
fz_error *
pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref)
{
	fz_error *error;
	int fterr;
	FT_Face face;
	fz_buffer *buf;

	error = initfontlibs();
	if (error)
		return fz_rethrow(error, "cannot init font libraries");

	pdf_logfont("load embedded font\n");

	error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref));
	if (error)
		return fz_rethrow(error, "cannot load font stream");

	fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face);
	if (fterr)
	{
		fz_dropbuffer(buf);
		return fz_throw("freetype: cannot load embedded font: %s", ft_errstr(fterr));
	}

	font->ftface = face;
	font->fontdata = buf;

	return fz_okay;
}
Exemple #12
0
static void evictitem(pdf_item *item)
{
	pdf_logrsrc("evicting item %s (%d %d R) at age %d\n", kindstr(item->kind), fz_tonum(item->key), fz_togen(item->key), item->age);
	fz_dropobj(item->key);
	dropitem(item->kind, item->val);
	fz_free(item);
}
Exemple #13
0
void *
pdf_finditem(pdf_store *store, pdf_itemkind kind, fz_obj *key)
{
	pdf_item *item;
	struct refkey refkey;

	if (key == nil)
		return nil;

	if (fz_isindirect(key))
	{
		refkey.kind = kind;
		refkey.oid = fz_tonum(key);
		refkey.gen = fz_togen(key);

		item = fz_hashfind(store->hash, &refkey);
		if (item)
		{
			item->age = 0;
			return item->val;
		}
	}

	else
	{
		for (item = store->root; item; item = item->next)
			if (item->kind == kind && !fz_objcmp(item->key, key))
		{
			item->age = 0;
			return item->val;
		}
	}

	return nil;
}
fz_error *
pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref)
{
	fz_error *error;
	int fterr;
	FT_Face face;
	fz_buffer *buf;

	error = initfontlibs();
	if (error)
		return error;

	pdf_logfont("load embedded font\n");

	error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref));
	if (error)
		return error;

	fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face);

	if (fterr) {
		fz_free(buf);
		return fz_throw("freetype could not load embedded font: %s", pdf_fterrorstring(fterr));
	}

	font->ftface = face;
	font->fontdata = buf;

	return nil;
}
Exemple #15
0
static fz_error
loadtype0(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	fz_obj *dfonts;
	fz_obj *dfont;
	fz_obj *subtype;
	fz_obj *encoding;
	fz_obj *tounicode;

	dfonts = fz_dictgets(dict, "DescendantFonts");
	if (!dfonts)
		return fz_throw("cid font is missing descendant fonts");

	dfont = fz_arrayget(dfonts, 0);

	subtype = fz_dictgets(dfont, "Subtype");
	encoding = fz_dictgets(dict, "Encoding");
	tounicode = fz_dictgets(dict, "ToUnicode");

	if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType0"))
		error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode);
	else if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType2"))
		error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode);
	else
		error = fz_throw("syntaxerror: unknown cid font type");
	if (error)
		return fz_rethrow(error, "cannot load descendant font (%d %d R)", fz_tonum(dfont), fz_togen(dfont));

	return fz_okay;
}
Exemple #16
0
void
pdf_removeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key)
{
	pdf_item *item, *prev;
	struct refkey refkey;

	if (key == nil)
		return;

	if (fz_isindirect(key))
	{
		refkey.kind = kind;
		refkey.oid = fz_tonum(key);
		refkey.gen = fz_togen(key);

		item = fz_hashfind(store->hash, &refkey);
		if (!item)
			return;
		fz_hashremove(store->hash, &refkey);

		pdf_logrsrc("remove item %s (%d %d R) ptr=%p\n", kindstr(kind), fz_tonum(key), fz_togen(key), item->val);

		dropitem(kind, item->val);
		fz_dropobj(item->key);
		fz_free(item);
	}

	else
	{
		prev = nil;
		for (item = store->root; item; item = item->next)
		{
			if (item->kind == kind && !fz_objcmp(item->key, key))
			{
				if (!prev)
					store->root = item->next;
				else
					prev->next = item->next;
				dropitem(kind, item->val);
				fz_dropobj(item->key);
				fz_free(item);
				break;
			}
			prev = item;
		}
	}
}
Exemple #17
0
fz_error
pdf_loadfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
	fz_error error;
	char *subtype;
	fz_obj *dfonts;
	fz_obj *charprocs;

	if ((*fontdescp = pdf_finditem(xref->store, pdf_dropfont, dict)))
	{
		pdf_keepfont(*fontdescp);
		return fz_okay;
	}

	subtype = fz_toname(fz_dictgets(dict, "Subtype"));
	dfonts = fz_dictgets(dict, "DescendantFonts");
	charprocs = fz_dictgets(dict, "CharProcs");

	if (subtype && !strcmp(subtype, "Type0"))
		error = loadtype0(fontdescp, xref, dict);
	else if (subtype && !strcmp(subtype, "Type1"))
		error = loadsimplefont(fontdescp, xref, dict);
	else if (subtype && !strcmp(subtype, "MMType1"))
		error = loadsimplefont(fontdescp, xref, dict);
	else if (subtype && !strcmp(subtype, "TrueType"))
		error = loadsimplefont(fontdescp, xref, dict);
	else if (subtype && !strcmp(subtype, "Type3"))
		error = pdf_loadtype3font(fontdescp, xref, rdb, dict);
	else if (charprocs)
	{
		fz_warn("unknown font format, guessing type3.");
		error = pdf_loadtype3font(fontdescp, xref, rdb, dict);
	}
	else if (dfonts)
	{
		fz_warn("unknown font format, guessing type0.");
		error = loadtype0(fontdescp, xref, dict);
	}
	else
	{
		fz_warn("unknown font format, guessing type1 or truetype.");
		error = loadsimplefont(fontdescp, xref, dict);
	}
	if (error)
		return fz_rethrow(error, "cannot load font (%d %d R)", fz_tonum(dict), fz_togen(dict));

	/* Save the widths to stretch non-CJK substitute fonts */
	if ((*fontdescp)->font->ftsubstitute && !(*fontdescp)->tottfcmap)
		pdf_makewidthtable(*fontdescp);

	/* SumatraPDF: this font renders wrong without hinting */
	if (strstr((*fontdescp)->font->name, "MingLiU"))
		(*fontdescp)->font->fthint = 1;

	pdf_storeitem(xref->store, pdf_keepfont, pdf_dropfont, dict, *fontdescp);

	return fz_okay;
}
Exemple #18
0
static void
printglobalinfo(void)
{
	printf("\nPDF-%d.%d\n", xref->version / 10, xref->version % 10);

	if (info->u.info.obj)
	{
		printf("Info object (%d %d R):\n", fz_tonum(info->ref), fz_togen(info->ref));
		fz_debugobj(fz_resolveindirect(info->u.info.obj));
	}

	if (cryptinfo->u.crypt.obj)
	{
		printf("\nEncryption object (%d %d R):\n", fz_tonum(cryptinfo->ref), fz_togen(cryptinfo->ref));
		fz_debugobj(cryptinfo->u.crypt.obj);
	}

	printf("\nPages: %d\n\n", pagecount);
}
Exemple #19
0
static void renumberobjs(void)
{
	pdf_xrefentry *oldxref;
	int newlen;
	int num;

	/* Apply renumber map to indirect references in all objects in xref */
	renumberobj(xref->trailer);
	for (num = 0; num < xref->len; num++)
	{
		fz_obj *obj = xref->table[num].obj;

		if (fz_isindirect(obj))
		{
			obj = fz_newindirect(renumbermap[fz_tonum(obj)], 0, xref);
			pdf_updateobject(xref, num, 0, obj);
			fz_dropobj(obj);
		}
		else
		{
			renumberobj(obj);
		}
	}

	/* Create new table for the reordered, compacted xref */
	oldxref = xref->table;
	xref->table = fz_calloc(xref->len, sizeof(pdf_xrefentry));
	xref->table[0] = oldxref[0];

	/* Move used objects into the new compacted xref */
	newlen = 0;
	for (num = 1; num < xref->len; num++)
	{
		if (uselist[num])
		{
			if (newlen < renumbermap[num])
				newlen = renumbermap[num];
			xref->table[renumbermap[num]] = oldxref[num];
		}
		else
		{
			if (oldxref[num].obj)
				fz_dropobj(oldxref[num].obj);
		}
	}

	fz_free(oldxref);

	/* Update the used objects count in compacted xref */
	xref->len = newlen + 1;

	/* Update list of used objects to fit with compacted xref */
	for (num = 1; num < xref->len; num++)
		uselist[num] = 1;
}
Exemple #20
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);
			}
		}
	}
}
void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj)
{
	int oid = fz_tonum(obj);
	int i;

	for (i = 0; i < pdf_getpagecount(app->pages); i++)
	{
		if (fz_tonum(app->pages->pref[i]) == oid)
		{
			if (app->histlen + 1 == 256)
			{
				memmove(app->hist, app->hist + 1, sizeof(int) * 255);
				app->histlen --;
			}
			app->hist[app->histlen++] = app->pageno;
			app->pageno = i + 1;
			pdfapp_showpage(app, 1, 1);
			return;
		}
	}
}
Exemple #22
0
fz_error
pdf_loadimage(fz_pixmap **pixp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;

	if ((*pixp = pdf_finditem(xref->store, fz_droppixmap, dict)))
	{
		fz_keeppixmap(*pixp);
		return fz_okay;
	}

	pdf_logimage("load image (%d 0 R) {\n", fz_tonum(dict));

	error = pdf_loadimageimp(pixp, xref, nil, dict, nil, 0);
	if (error)
		return fz_rethrow(error, "cannot load image (%d 0 R)", fz_tonum(dict));

	pdf_storeitem(xref->store, fz_keeppixmap, fz_droppixmap, dict, *pixp);

	pdf_logimage("}\n");

	return fz_okay;
}
Exemple #23
0
static fz_error
gatherdimensions(int page, fz_obj *pageobj)
{
	fz_obj *ref;
	fz_rect bbox;
	fz_obj *obj;
	int j;

	obj = ref = fz_dictgets(pageobj, "MediaBox");
	if (!fz_isarray(obj))
		return fz_throw("cannot find page bounds (%d %d R)", fz_tonum(ref), fz_togen(ref));

	bbox = pdf_torect(obj);

	for (j = 0; j < dims; j++)
		if (!memcmp(dim[j]->u.dim.bbox, &bbox, sizeof (fz_rect)))
			break;

	if (j < dims)
		return fz_okay;

	dims++;

	dim = fz_realloc(dim, dims * sizeof (struct info *));
	if (!dim)
		return fz_throw("out of memory");

	dim[dims - 1] = fz_malloc(sizeof (struct info));
	if (!dim[dims - 1])
		return fz_throw("out of memory");

	dim[dims - 1]->u.dim.bbox = fz_malloc(sizeof (fz_rect));
	if (!dim[dims - 1]->u.dim.bbox)
		return fz_throw("out of memory");

	dim[dims - 1]->page = page;
	dim[dims - 1]->pageobj = pageobj;
	dim[dims - 1]->ref = nil;
	memcpy(dim[dims - 1]->u.dim.bbox, &bbox, sizeof (fz_rect));

	return fz_okay;
}
Exemple #24
0
void
editcopy(int pagenum)
{
	fz_error *error;
	fz_obj *obj;
	fz_obj *ref;
	fz_obj *num;

	printf("copy %s page %d\n", srcname, pagenum);

	ref = srcpages->pref[pagenum - 1];
	obj = pdf_getpageobject(srcpages, pagenum - 1);

	fz_dictdels(obj, "Parent");
	/*
	fz_dictdels(obj, "B");
	fz_dictdels(obj, "PieceInfo");
	fz_dictdels(obj, "Metadata");
	fz_dictdels(obj, "Annots");
	fz_dictdels(obj, "Tabs");
	*/

	pdf_updateobject(src, fz_tonum(ref), fz_togen(ref), obj);

	error = fz_arraypush(editobjects, ref);
	if (error)
		die(error);

	error = fz_newint(&num, editmode);
	if (error)
		die(error);

	error = fz_arraypush(editmodelist, num);
	if (error)
		die(error);

	fz_dropobj(num);
}
Exemple #25
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;
}
Exemple #26
0
fz_error
pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	pdf_pattern *pat;
	fz_obj *obj;

	if ((*patp = pdf_finditem(xref->store, pdf_droppattern, dict)))
	{
		pdf_keeppattern(*patp);
		return fz_okay;
	}

	pdf_logrsrc("load pattern (%d %d R) {\n", fz_tonum(dict), fz_togen(dict));

	pat = fz_malloc(sizeof(pdf_pattern));
	pat->refs = 1;
	pat->resources = nil;
	pat->contents = nil;

	/* Store pattern now, to avoid possible recursion if objects refer back to this one */
	pdf_storeitem(xref->store, pdf_keeppattern, pdf_droppattern, dict, pat);

	pat->ismask = fz_toint(fz_dictgets(dict, "PaintType")) == 2;
	pat->xstep = fz_toreal(fz_dictgets(dict, "XStep"));
	pat->ystep = fz_toreal(fz_dictgets(dict, "YStep"));

	pdf_logrsrc("mask %d\n", pat->ismask);
	pdf_logrsrc("xstep %g\n", pat->xstep);
	pdf_logrsrc("ystep %g\n", pat->ystep);

	obj = fz_dictgets(dict, "BBox");
	pat->bbox = pdf_torect(obj);

	pdf_logrsrc("bbox [%g %g %g %g]\n",
		pat->bbox.x0, pat->bbox.y0,
		pat->bbox.x1, pat->bbox.y1);

	obj = fz_dictgets(dict, "Matrix");
	if (obj)
		pat->matrix = pdf_tomatrix(obj);
	else
		pat->matrix = fz_identity;

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

	pat->resources = fz_dictgets(dict, "Resources");
	if (pat->resources)
		fz_keepobj(pat->resources);

	error = pdf_loadstream(&pat->contents, xref, fz_tonum(dict), fz_togen(dict));
	if (error)
	{
		pdf_removeitem(xref->store, pdf_droppattern, dict);
		pdf_droppattern(pat);
		return fz_rethrow(error, "cannot load pattern stream (%d %d R)", fz_tonum(dict), fz_togen(dict));
	}

	pdf_logrsrc("}\n");

	*patp = pat;
	return fz_okay;
}
Exemple #27
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);
}
static fz_error *
loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_matrix matrix)
{
	fz_error *error;
	fz_shade *shade;
	fz_obj *obj;
	int type;
	int i;

	pdf_logshade("load shade dict %d %d {\n", fz_tonum(ref), fz_togen(ref));

	shade = fz_malloc(sizeof(fz_shade));
	if (!shade)
		return fz_outofmem;

	shade->refs = 1;
	shade->usebackground = 0;
	shade->usefunction = 0;
	shade->matrix = matrix;
	shade->bbox = fz_infiniterect;

	shade->meshlen = 0;
	shade->meshcap = 0;
	shade->mesh = nil;

	obj = fz_dictgets(dict, "ShadingType");
	type = fz_toint(obj);
	pdf_logshade("type %d\n", type);

	/* TODO: flatten indexed... */
	obj = fz_dictgets(dict, "ColorSpace");
	if (obj)
	{
		shade->cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj);
		if (shade->cs)
			fz_keepcolorspace(shade->cs);
		else
		{
			error = pdf_resolve(&obj, xref);
			if (error)
				return error;
			error = pdf_loadcolorspace(&shade->cs, xref, obj);
			if (error)
				return error;
			fz_dropobj(obj);
		}
	}
	pdf_logshade("colorspace %s\n", shade->cs->name);

	obj = fz_dictgets(dict, "Background");
	if (obj)
	{
		pdf_logshade("background\n");
		shade->usebackground = 1;
		for (i = 0; i < shade->cs->n; i++)
			shade->background[i] = fz_toreal(fz_arrayget(obj, i));
	}

	obj = fz_dictgets(dict, "BBox");
	if (fz_isarray(obj))
	{
		shade->bbox = pdf_torect(obj);
		pdf_logshade("bbox [%g %g %g %g]\n",
			shade->bbox.x0, shade->bbox.y0,
			shade->bbox.x1, shade->bbox.y1);
	}

	switch(type)
	{
	case 1:
		error = pdf_loadtype1shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 2:
		error = pdf_loadtype2shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 3:
		error = pdf_loadtype3shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 4:
		error = pdf_loadtype4shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 5:
		error = pdf_loadtype5shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 6:
		error = pdf_loadtype6shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 7:
		error = pdf_loadtype7shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	default:
		fz_warn("syntaxerror: unknown shading type: %d", type);
		break;
	};

	pdf_logshade("}\n");

	*shadep = shade;
	return nil;

cleanup:
	fz_dropshade(shade);
	return error;
}
fz_error *
pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
	fz_error *error;
	fz_matrix mat;
	fz_obj *obj;
	fz_obj *shd;

	if ((*shadep = pdf_finditem(xref->store, PDF_KSHADE, ref)))
		return nil;

	/*
	 * Type 2 pattern dictionary
	 */
	if (fz_dictgets(dict, "PatternType"))
	{
		pdf_logshade("load shade pattern %d %d {\n", fz_tonum(ref), fz_togen(ref));

		obj = fz_dictgets(dict, "Matrix");
		if (obj)
		{
			mat = pdf_tomatrix(obj);
			pdf_logshade("matrix [%g %g %g %g %g %g]\n",
				mat.a, mat.b, mat.c, mat.d, mat.e, mat.f);
		}
		else
		{
			mat = fz_identity();
		}

		obj = fz_dictgets(dict, "ExtGState");
		if (obj)
		{
			pdf_logshade("extgstate ...\n");
		}

		obj = fz_dictgets(dict, "Shading");
		if (!obj)
			return fz_throw("syntaxerror: missing shading dictionary");

		shd = obj;
		error = pdf_resolve(&shd, xref);
		if (error)
			return error;
		error = loadshadedict(shadep, xref, shd, obj, mat);
		fz_dropobj(shd);
		if (error)
			return error;

		pdf_logshade("}\n");
	}

	/*
	 * Naked shading dictionary
	 */
	else
	{
		error = loadshadedict(shadep, xref, dict, ref, fz_identity());
		if (error)
			return error;
	}

	error = pdf_storeitem(xref->store, PDF_KSHADE, ref, *shadep);
	if (error)
	{
		fz_dropshade(*shadep);
		return error;
	}

	return nil;
}
Exemple #30
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;
}