Exemple #1
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 #2
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;
}
Exemple #3
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;
}
Exemple #4
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;
}
Exemple #5
0
fz_error *
pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
	fz_error *error;
	char *subtype;

	if ((*fontp = pdf_finditem(xref->store, PDF_KFONT, ref)))
	{
		fz_keepfont((fz_font*)*fontp);
		return fz_okay;
	}

	subtype = fz_toname(fz_dictgets(dict, "Subtype"));
	if (!strcmp(subtype, "Type0"))
		error = loadtype0(fontp, xref, dict, ref);
	else if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1"))
		error = loadsimplefont(fontp, xref, dict, ref);
	else if (!strcmp(subtype, "TrueType"))
		error = loadsimplefont(fontp, xref, dict, ref);
	else if (!strcmp(subtype, "Type3"))
		error = pdf_loadtype3font(fontp, xref, dict, ref);
	else
		return fz_throw("cannot recognize font format %s", subtype);

	if (error)
		return fz_rethrow(error, "cannot load font");

	error = pdf_storeitem(xref->store, PDF_KFONT, ref, *fontp);
	if (error)
		return fz_rethrow(error, "cannot store font resource");

	return fz_okay;
}
fz_error
pdf_loadfontdescriptor(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection)
{
	fz_error error;
	fz_obj *obj1, *obj2, *obj3, *obj;
	fz_rect bbox;
	char *fontname;

	pdf_logfont("load fontdescriptor {\n");

	fontname = fz_toname(fz_dictgets(dict, "FontName"));

	pdf_logfont("fontname '%s'\n", fontname);

	fontdesc->flags = fz_toint(fz_dictgets(dict, "Flags"));
	fontdesc->italicangle = fz_toreal(fz_dictgets(dict, "ItalicAngle"));
	fontdesc->ascent = fz_toreal(fz_dictgets(dict, "Ascent"));
	fontdesc->descent = fz_toreal(fz_dictgets(dict, "Descent"));
	fontdesc->capheight = fz_toreal(fz_dictgets(dict, "CapHeight"));
	fontdesc->xheight = fz_toreal(fz_dictgets(dict, "XHeight"));
	fontdesc->missingwidth = fz_toreal(fz_dictgets(dict, "MissingWidth"));

	bbox = pdf_torect(fz_dictgets(dict, "FontBBox"));
	pdf_logfont("bbox [%g %g %g %g]\n",
			bbox.x0, bbox.y0,
			bbox.x1, bbox.y1);

	pdf_logfont("flags %d\n", fontdesc->flags);

	obj1 = fz_dictgets(dict, "FontFile");
	obj2 = fz_dictgets(dict, "FontFile2");
	obj3 = fz_dictgets(dict, "FontFile3");
	obj = obj1 ? obj1 : obj2 ? obj2 : obj3;

	if (getenv("NOFONT"))
		obj = nil;

	if (fz_isindirect(obj))
	{
                error = pdf_loadembeddedfont(fontdesc, xref, obj);
                if (error)
                {
			fz_catch(error, "ignored error when loading embedded font, attempting to load system font");
                        error = pdf_loadsystemfont(fontdesc, fontname, collection);
                        if (error)
				return fz_rethrow(error, "cannot load font descriptor");
                }
	}
	else
	{
		error = pdf_loadsystemfont(fontdesc, fontname, collection);
		if (error)
			return fz_rethrow(error, "cannot load font descriptor");
	}

	pdf_logfont("}\n");

	return fz_okay;

}
Exemple #7
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;
}
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;
}
Exemple #9
0
static void writeobject(int num, int gen)
{
	fz_error error;
	fz_obj *obj;
	fz_obj *type;

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

	/* skip ObjStm and XRef objects */
	if (fz_isdict(obj))
	{
		type = fz_dictgets(obj, "Type");
		if (fz_isname(type) && !strcmp(fz_toname(type), "ObjStm"))
		{
			uselist[num] = 0;
			fz_dropobj(obj);
			return;
		}
		if (fz_isname(type) && !strcmp(fz_toname(type), "XRef"))
		{
			uselist[num] = 0;
			fz_dropobj(obj);
			return;
		}
	}

	if (!pdf_isstream(xref, num, gen))
	{
		fprintf(out, "%d %d obj\n", num, gen);
		fz_fprintobj(out, obj, !doexpand);
		fprintf(out, "endobj\n\n");
	}
	else
	{
		if (doexpand && !pdf_isjpximage(obj))
			expandstream(obj, num, gen);
		else
			copystream(obj, num, gen);
	}

	fz_dropobj(obj);
}
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;
}
Exemple #11
0
static fz_error *
loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
	fz_error *error;
	fz_obj *dfonts;
	fz_obj *dfont;
	fz_obj *subtype;
	fz_obj *encoding;
	fz_obj *tounicode;

	dfonts = fz_dictgets(dict, "DescendantFonts");
	error = pdf_resolve(&dfonts, xref);
	if (error)
		return fz_rethrow(error, "cannot find DescendantFonts");

	dfont = fz_arrayget(dfonts, 0);
	error = pdf_resolve(&dfont, xref);
	if (error)
	{
		fz_dropobj(dfonts);
		return fz_rethrow(error, "cannot find descendant font");
	}

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

	if (!strcmp(fz_toname(subtype), "CIDFontType0"))
		error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode);
	else if (!strcmp(fz_toname(subtype), "CIDFontType2"))
		error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode);
	else
		error = fz_throw("syntaxerror: unknown cid font type");

	fz_dropobj(dfont);
	fz_dropobj(dfonts);

	if (error)
		return fz_rethrow(error, "cannot load descendant font");

	return fz_okay;
}
Exemple #12
0
static int
pdf_extgstateusesblending(fz_obj *dict)
{
	fz_obj *obj;

	obj = fz_dictgets(dict, "BM");
	if (fz_isname(obj) && strcmp(fz_toname(obj), "Normal"))
		return 1;

	return 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_KFONT, 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");

	error = pdf_storeitem(xref->store, PDF_KFONT, dict, *fontdescp);
	if (error)
	    return fz_rethrow(error, "cannot store font resource");

	return fz_okay;
}
Exemple #14
0
fz_error
pdf_repairobjstms(pdf_xref *xref)
{
	fz_obj *dict;
	int i;

	for (i = 0; i < xref->len; i++)
	{
		if (xref->table[i].stmofs)
		{
			pdf_loadobject(&dict, xref, i, 0);
			if (!strcmp(fz_toname(fz_dictgets(dict, "Type")), "ObjStm"))
				pdf_repairobjstm(xref, i, 0);
			fz_dropobj(dict);
		}
	}

	return fz_okay;
}
Exemple #15
0
fz_error
pdf_loadfontdescriptor(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont)
{
	fz_error error;
	fz_obj *obj1, *obj2, *obj3, *obj;
	fz_rect bbox;
	char *fontname;
	char *origname;

	pdf_logfont("load fontdescriptor {\n");

	/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1014 */
	if (!strchr(basefont, ',') || strchr(basefont, '+'))
		origname = fz_toname(fz_dictgets(dict, "FontName"));
	else
		origname = basefont;
	fontname = cleanfontname(origname);

	pdf_logfont("fontname %s -> %s\n", origname, fontname);

	fontdesc->flags = fz_toint(fz_dictgets(dict, "Flags"));
	fontdesc->italicangle = fz_toreal(fz_dictgets(dict, "ItalicAngle"));
	fontdesc->ascent = fz_toreal(fz_dictgets(dict, "Ascent"));
	fontdesc->descent = fz_toreal(fz_dictgets(dict, "Descent"));
	fontdesc->capheight = fz_toreal(fz_dictgets(dict, "CapHeight"));
	fontdesc->xheight = fz_toreal(fz_dictgets(dict, "XHeight"));
	fontdesc->missingwidth = fz_toreal(fz_dictgets(dict, "MissingWidth"));

	bbox = pdf_torect(fz_dictgets(dict, "FontBBox"));
	pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	pdf_logfont("flags %d\n", fontdesc->flags);

	obj1 = fz_dictgets(dict, "FontFile");
	obj2 = fz_dictgets(dict, "FontFile2");
	obj3 = fz_dictgets(dict, "FontFile3");
	obj = obj1 ? obj1 : obj2 ? obj2 : obj3;

	if (getenv("NOFONT"))
		obj = nil;

	if (fz_isindirect(obj))
	{
		error = pdf_loadembeddedfont(fontdesc, xref, obj);
		if (error)
		{
			fz_catch(error, "ignored error when loading embedded font, attempting to load system font");
			if (origname != fontname)
				error = pdf_loadbuiltinfont(fontdesc, fontname);
			else
				error = pdf_loadsystemfont(fontdesc, fontname, collection);
			if (error)
				return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_tonum(dict), fz_togen(dict));
		}
	}
	else
	{
		if (origname != fontname && 0 /* SumatraPDF: prefer system fonts to the built-in ones */)
			error = pdf_loadbuiltinfont(fontdesc, fontname);
		else
			error = pdf_loadsystemfont(fontdesc, fontname, collection);
		if (error)
			return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_tonum(dict), fz_togen(dict));
	}

	fz_strlcpy(fontdesc->font->name, fontname, sizeof fontdesc->font->name);

	pdf_logfont("}\n");

	return fz_okay;

}
Exemple #16
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));
}
Exemple #17
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));
}
Exemple #18
0
static fz_error
pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
{
	if (fz_isname(obj))
	{
		if (!strcmp(fz_toname(obj), "DeviceGray"))
			*csp = pdf_devicegray;
		else if (!strcmp(fz_toname(obj), "DeviceRGB"))
			*csp = pdf_devicergb;
		else if (!strcmp(fz_toname(obj), "DeviceCMYK"))
			*csp = pdf_devicecmyk;
		else if (!strcmp(fz_toname(obj), "G"))
			*csp = pdf_devicegray;
		else if (!strcmp(fz_toname(obj), "RGB"))
			*csp = pdf_devicergb;
		else if (!strcmp(fz_toname(obj), "CMYK"))
			*csp = pdf_devicecmyk;
		else if (!strcmp(fz_toname(obj), "Pattern"))
			*csp = pdf_devicepattern;
		else
			return fz_throw("unknown colorspace: %s", fz_toname(obj));
		return fz_okay;
	}

	else if (fz_isarray(obj))
	{
		fz_obj *name = fz_arrayget(obj, 0);

		if (fz_isname(name))
		{
			if (!strcmp(fz_toname(name), "CalCMYK"))
				*csp = pdf_devicecmyk;

#ifdef USECAL
			else if (!strcmp(fz_toname(name), "CalGray"))
				*csp = loadcalgray(xref, fz_arrayget(obj, 1));
			else if (!strcmp(fz_toname(name), "CalRGB"))
				*csp = loadcalrgb(xref, fz_arrayget(obj, 1));
			else if (!strcmp(fz_toname(name), "Lab"))
				*csp = loadlab(xref, fz_arrayget(obj, 1));
#else
			else if (!strcmp(fz_toname(name), "CalGray"))
				*csp = pdf_devicegray;
			else if (!strcmp(fz_toname(name), "CalRGB"))
				*csp = pdf_devicergb;
			else if (!strcmp(fz_toname(name), "Lab"))
				*csp = pdf_devicelab;
#endif

			else if (!strcmp(fz_toname(name), "ICCBased"))
				return loadiccbased(csp, xref, fz_arrayget(obj, 1));

			else if (!strcmp(fz_toname(name), "Indexed"))
				return loadindexed(csp, xref, obj);

			else if (!strcmp(fz_toname(name), "I"))
				return loadindexed(csp, xref, obj);

			else if (!strcmp(fz_toname(name), "Separation"))
				return loadseparation(csp, xref, obj);

			else if (!strcmp(fz_toname(name), "DeviceN"))
				return loadseparation(csp, xref, obj);

			/* load base colorspace instead */
			else if (!strcmp(fz_toname(name), "Pattern"))
			{
				fz_error error;

				obj = fz_arrayget(obj, 1);
				if (!obj)
				{
					*csp = pdf_devicepattern;
					return fz_okay;
				}

				error = pdf_loadcolorspace(csp, xref, obj);
				if (error)
					return fz_rethrow(error, "cannot load pattern");
			}

			else if (!strcmp(fz_toname(name), "DeviceGray"))
				*csp = pdf_devicegray;
			else if (!strcmp(fz_toname(name), "DeviceRGB"))
				*csp = pdf_devicergb;
			else if (!strcmp(fz_toname(name), "DeviceCMYK"))
				*csp = pdf_devicecmyk;
			else if (!strcmp(fz_toname(name), "G"))
				*csp = pdf_devicegray;
			else if (!strcmp(fz_toname(name), "RGB"))
				*csp = pdf_devicergb;
			else if (!strcmp(fz_toname(name), "CMYK"))
				*csp = pdf_devicecmyk;

			else
				return fz_throw("syntaxerror: unknown colorspace %s", fz_toname(name));

			return fz_okay;
		}
	}

	return fz_throw("syntaxerror: could not parse color space");
}
Exemple #19
0
fz_error *
pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection)
{
	fz_error *error;
	fz_obj *obj1, *obj2, *obj3, *obj;
	fz_rect bbox;
	char *fontname;

	error = pdf_resolve(&desc, xref);
	if (error)
		return fz_rethrow(error, "cannot find font descriptor");

	pdf_logfont("load fontdescriptor {\n");

	obj = fz_dictgets(desc, "FontName");
	if (error)
		return fz_rethrow(error, "cannot resolve FontName");
	fontname = fz_toname(obj);

	pdf_logfont("fontname %s\n", fontname);

	font->flags = fz_toint(fz_dictgets(desc, "Flags"));
	font->italicangle = fz_toreal(fz_dictgets(desc, "ItalicAngle"));
	font->ascent = fz_toreal(fz_dictgets(desc, "Ascent"));
	font->descent = fz_toreal(fz_dictgets(desc, "Descent"));
	font->capheight = fz_toreal(fz_dictgets(desc, "CapHeight"));
	font->xheight = fz_toreal(fz_dictgets(desc, "XHeight"));
	font->missingwidth = fz_toreal(fz_dictgets(desc, "MissingWidth"));

	bbox = pdf_torect(fz_dictgets(desc, "FontBBox"));
	pdf_logfont("bbox [%g %g %g %g]\n",
			bbox.x0, bbox.y0,
			bbox.x1, bbox.y1);

	pdf_logfont("flags %d\n", font->flags);

	obj1 = fz_dictgets(desc, "FontFile");
	obj2 = fz_dictgets(desc, "FontFile2");
	obj3 = fz_dictgets(desc, "FontFile3");
	obj = obj1 ? obj1 : obj2 ? obj2 : obj3;

	if (getenv("NOFONT"))
		obj = nil;

	if (fz_isindirect(obj))
	{
		error = pdf_loadembeddedfont(font, xref, obj);
		if (error)
			goto cleanup;
	}
	else
	{
		error = pdf_loadsystemfont(font, fontname, collection);
		if (error)
			goto cleanup;
	}

	fz_dropobj(desc);

	pdf_logfont("}\n");

	return fz_okay;

cleanup:
	fz_dropobj(desc);
	return fz_rethrow(error, "cannot load font descriptor");
}
Exemple #20
0
static fz_error
gatherimages(int page, fz_obj *pageobj, fz_obj *dict)
{
	int i;

	for (i = 0; i < fz_dictlen(dict); i++)
	{
		fz_obj *ref;
		fz_obj *imagedict;
		fz_obj *type;
		fz_obj *width;
		fz_obj *height;
		fz_obj *bpc = nil;
		fz_obj *filter = nil;
		fz_obj *mask;
		fz_obj *cs = nil;
		fz_obj *altcs;
		int k;

		imagedict = ref = fz_dictgetval(dict, i);
		if (!fz_isdict(imagedict))
			return fz_throw("not an image dict (%d %d R)", fz_tonum(ref), fz_togen(ref));

		type = fz_dictgets(imagedict, "Subtype");
		if (!fz_isname(type))
			return fz_throw("not an image subtype (%d %d R)", fz_tonum(ref), fz_togen(ref));
		if (strcmp(fz_toname(type), "Image"))
			continue;

		filter = fz_dictgets(imagedict, "Filter");
		if (filter && !fz_isname(filter) && !fz_isarray(filter))
			return fz_throw("not an image filter (%d %d R)", fz_tonum(ref), fz_togen(ref));

		mask = fz_dictgets(imagedict, "ImageMask");

		altcs = nil;
		cs = fz_dictgets(imagedict, "ColorSpace");
		if (fz_isarray(cs))
		{
			fz_obj *cses = cs;

			cs = fz_arrayget(cses, 0);
			if (fz_isname(cs) && (!strcmp(fz_toname(cs), "DeviceN") || !strcmp(fz_toname(cs), "Separation")))
			{
				altcs = fz_arrayget(cses, 2);
				if (fz_isarray(altcs))
					altcs = fz_arrayget(altcs, 0);
			}
		}

		if (fz_isbool(mask) && fz_tobool(mask))
		{
			if (cs)
				fz_warn("image mask (%d %d R) may not have colorspace", fz_tonum(ref), fz_togen(ref));
		}
		if (cs && !fz_isname(cs))
			return fz_throw("not an image colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref));
		if (altcs && !fz_isname(altcs))
			return fz_throw("not an image alternate colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref));

		width = fz_dictgets(imagedict, "Width");
		if (!fz_isint(width))
			return fz_throw("not an image width (%d %d R)", fz_tonum(ref), fz_togen(ref));

		height = fz_dictgets(imagedict, "Height");
		if (!fz_isint(height))
			return fz_throw("not an image height (%d %d R)", fz_tonum(ref), fz_togen(ref));

		bpc = fz_dictgets(imagedict, "BitsPerComponent");
		if (!fz_tobool(mask) && !fz_isint(bpc))
			return fz_throw("not an image bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref));
		if (fz_tobool(mask) && fz_isint(bpc) && fz_toint(bpc) != 1)
			return fz_throw("not an image mask bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref));

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

		if (k < images)
			continue;

		images++;

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

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

		image[images - 1]->page = page;
		image[images - 1]->pageobj = pageobj;
		image[images - 1]->ref = ref;
		image[images - 1]->u.image.width = width;
		image[images - 1]->u.image.height = height;
		image[images - 1]->u.image.bpc = bpc;
		image[images - 1]->u.image.filter = filter;
		image[images - 1]->u.image.cs = cs;
		image[images - 1]->u.image.altcs = altcs;
	}

	return fz_okay;
}
Exemple #21
0
pdf_link *
pdf_loadlink(pdf_xref *xref, fz_obj *dict)
{
	fz_obj *dest;
	fz_obj *action;
	fz_obj *obj;
	fz_rect bbox;
	pdf_linkkind kind;

	pdf_logpage("load link {\n");

	dest = nil;

	obj = fz_dictgets(dict, "Rect");
	if (obj)
	{
		bbox = pdf_torect(obj);
		pdf_logpage("rect [%g %g %g %g]\n",
			bbox.x0, bbox.y0,
			bbox.x1, bbox.y1);
	}
	else
		bbox = fz_emptyrect;

	obj = fz_dictgets(dict, "Dest");
	if (obj)
	{
		kind = PDF_LGOTO;
		dest = resolvedest(xref, obj);
		pdf_logpage("dest (%d %d R)\n", fz_tonum(dest), fz_togen(dest));
	}

	action = fz_dictgets(dict, "A");
	if (action)
	{
		obj = fz_dictgets(action, "S");
		if (fz_isname(obj) && !strcmp(fz_toname(obj), "GoTo"))
		{
			kind = PDF_LGOTO;
			dest = resolvedest(xref, fz_dictgets(action, "D"));
			pdf_logpage("action goto (%d %d R)\n", fz_tonum(dest), fz_togen(dest));
		}
		else if (fz_isname(obj) && !strcmp(fz_toname(obj), "URI"))
		{
			kind = PDF_LURI;
			dest = fz_dictgets(action, "URI");
			pdf_logpage("action uri %s\n", fz_tostrbuf(dest));
		}
		/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=726 */
		else if (fz_isname(obj) && !strcmp(fz_toname(obj), "Launch"))
		{
			kind = PDF_LLAUNCH;
			dest = fz_dictgets(action, "F");
			pdf_logpage("action launch (%d %d R)\n", fz_tonum(dest), fz_togen(dest));
		}
		else
		{
			pdf_logpage("unhandled link action, ignoring link\n");
			dest = nil;
		}
	}

	pdf_logpage("}\n");

	if (dest)
	{
		return pdf_newlink(kind, bbox, dest);
	}

	return nil;
}
Exemple #22
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;
}
/*
 * 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 */
}
static int isfontdesc(fz_obj *obj)
{
    fz_obj *type = fz_dictgets(obj, "Type");
    return fz_isname(type) && !strcmp(fz_toname(type), "FontDescriptor");
}
static void savefont(fz_obj *dict, int num, int gen)
{
    fz_error error;
    char name[1024];
    char *subtype;
    fz_buffer *buf;
    fz_obj *stream = nil;
    fz_obj *obj;
    char *ext = "";
    FILE *f;
    unsigned char *p;
    char *fontname = "font";

    obj = fz_dictgets(dict, "FontName");
    if (obj)
        fontname = fz_toname(obj);

    obj = fz_dictgets(dict, "FontFile");
    if (obj)
    {
        stream = obj;
        ext = "pfa";
    }

    obj = fz_dictgets(dict, "FontFile2");
    if (obj)
    {
        stream = obj;
        ext = "ttf";
    }

    obj = fz_dictgets(dict, "FontFile3");
    if (obj)
    {
        stream = obj;

        obj = fz_dictgets(obj, "Subtype");
        if (obj && !fz_isname(obj))
            die(fz_throw("Invalid font descriptor subtype"));

        subtype = fz_toname(obj);
        if (!strcmp(subtype, "Type1C"))
            ext = "cff";
        else if (!strcmp(subtype, "CIDFontType0C"))
            ext = "cid";
        else
            die(fz_throw("Unhandled font type '%s'", subtype));
    }

    if (!stream)
    {
        fz_warn("Unhandled font type");
        return;
    }

    error = fz_newbuffer(&buf, 0);
    if (error)
        die(error);

    error = pdf_loadstream(&buf, xref, fz_tonum(stream), fz_togen(stream));
    if (error)
        die(error);

    sprintf(name, "%s-%04d.%s", fontname, num, ext);

    f = fopen(name, "wb");
    if (f == NULL)
        die(fz_throw("Error creating image file"));

    for (p = buf->rp; p < buf->wp; p ++)
        fprintf(f, "%c", *p);

    if (fclose(f) < 0)
        die(fz_throw("Error closing image file"));

    fz_dropbuffer(buf);
}
Exemple #26
0
static fz_error
gatherforms(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;
		fz_obj *group;
		fz_obj *reference;
		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(subtype), "PS"))
			continue;

		group = fz_dictgets(xobjdict, "Group");
		if (group && !fz_isdict(group))
			return fz_throw("not a form xobject group dict (%d %d R)", fz_tonum(ref), fz_togen(ref));

		reference = fz_dictgets(xobjdict, "Ref");
		if (reference && !fz_isdict(reference))
			return fz_throw("not a form xobject reference dict (%d %d R)", fz_tonum(ref), fz_togen(ref));

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

		if (k < forms)
			continue;

		forms++;

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

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

		form[forms - 1]->page = page;
		form[forms - 1]->pageobj = pageobj;
		form[forms - 1]->ref = ref;
		form[forms - 1]->u.form.group = group;
		form[forms - 1]->u.form.reference = reference;
	}

	return fz_okay;
}
Exemple #27
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;
	}
}
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");
}
Exemple #29
0
/*
 * Create a filter given a name and param dictionary.
 */
static fz_error *
buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p)
{
	fz_filter *decompress;
	fz_filter *predict;
	fz_error *error;
	char *s;

	s = fz_toname(f);

	if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx"))
		error = fz_newahxd(fp, p);

	else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85"))
		error = fz_newa85d(fp, p);

	else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF"))
		error = fz_newfaxd(fp, p);

	else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT"))
		error = fz_newdctd(fp, p);

	else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL"))
		error = fz_newrld(fp, p);

	else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl"))
	{
		if (fz_isdict(p))
		{
			fz_obj *obj = fz_dictgets(p, "Predictor");
			if (obj)
			{
				error = fz_newflated(&decompress, p);
				if (error)
					return fz_rethrow(error, "cannot create deflate filter");

				error = fz_newpredictd(&predict, p);
				if (error)
				{
					fz_dropfilter(decompress);
					return fz_rethrow(error, "cannot create predictor filter");
				}

				error = fz_newpipeline(fp, decompress, predict);
				fz_dropfilter(decompress);
				fz_dropfilter(predict);
				if (error)
					return fz_rethrow(error, "cannot create pipeline filter");
				return fz_okay;
			}
		}
		error = fz_newflated(fp, p);
	}

	else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW"))
	{
		if (fz_isdict(p))
		{
			fz_obj *obj = fz_dictgets(p, "Predictor");
			if (obj)
			{
				error = fz_newlzwd(&decompress, p);
				if (error)
					return fz_rethrow(error, "cannot create lzwd filter");

				error = fz_newpredictd(&predict, p);
				if (error)
				{
					fz_dropfilter(decompress);
					return fz_rethrow(error, "cannot create predictor filter");
				}

				error = fz_newpipeline(fp, decompress, predict);
				fz_dropfilter(decompress);
				fz_dropfilter(predict);
				if (error)
					return fz_rethrow(error, "cannot create pipeline filter");
				return fz_okay;
			}
		}
		error = fz_newlzwd(fp, p);
	}

#ifdef HAVE_JBIG2DEC
	else if (!strcmp(s, "JBIG2Decode"))
	{
		/* TODO: extract and feed JBIG2Global */
		error = fz_newjbig2d(fp, p);
	}
#endif

#ifdef HAVE_JASPER
	else if (!strcmp(s, "JPXDecode"))
		error = fz_newjpxd(fp, p);
#endif

	else
	{
		return fz_throw("unknown filter name (%s)", s);
	}

	if (error)
		return fz_rethrow(error, "cannot create filter");
	return fz_okay;
}
static int isimage(fz_obj *obj)
{
    fz_obj *type = fz_dictgets(obj, "Subtype");
    return fz_isname(type) && !strcmp(fz_toname(type), "Image");
}