Exemple #1
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 #2
0
static void showobject(int num, int gen)
{
	fz_error error;
	fz_obj *obj;

	if (!xref)
		die(fz_throw("no file specified"));

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

	if (pdf_isstream(xref, num, gen))
	{
		printf("%d %d obj\n", num, gen);
		fz_debugobj(obj);
		printf("stream\n");
		showstream(num, gen);
		printf("endstream\n");
		printf("endobj\n\n");
	}
	else
	{
		printf("%d %d obj\n", num, gen);
		fz_debugobj(obj);
		printf("endobj\n\n");
	}

	fz_dropobj(obj);
}
static fz_error *
writeobject(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen)
{
	pdf_xrefentry *x = xref->table + oid;
	fz_error *error;

	error = pdf_cacheobject(xref, oid, gen);
	if (error)
		return error;

	if (encrypt)
		pdf_cryptobj(encrypt, x->obj, oid, gen);

	fz_print(out, "%d %d obj\n", oid, gen);
	fz_printobj(out, x->obj, TIGHT);
	fz_print(out, "\n");

	if (encrypt)
		pdf_cryptobj(encrypt, x->obj, oid, gen);

	if (pdf_isstream(xref, oid, gen))
	{
		error = writestream(out, xref, encrypt, oid, gen);
		if (error)
			return error;
	}

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

	return nil;
}
Exemple #4
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 #5
0
static void removeduplicateobjs(void)
{
	int num, other;

	for (num = 1; num < xref->len; num++)
	{
		/* Only compare an object to objects preceeding it */
		for (other = 1; other < num; other++)
		{
			fz_obj *a, *b;

			if (num == other || !uselist[num] || !uselist[other])
				continue;

			/*
			 * Comparing stream objects data contents would take too long.
			 *
			 * pdf_isstream calls pdf_cacheobject and ensures
			 * that the xref table has the objects loaded.
			 */
			if (pdf_isstream(xref, num, 0) || pdf_isstream(xref, other, 0))
				continue;

			a = xref->table[num].obj;
			b = xref->table[other].obj;

			a = fz_resolveindirect(a);
			b = fz_resolveindirect(b);

			if (fz_objcmp(a, b))
				continue;

			/* Keep the lowest numbered object */
			renumbermap[num] = MIN(num, other);
			renumbermap[other] = MIN(num, other);
			uselist[MAX(num, other)] = 0;

			/* One duplicate was found, do not look for another */
			break;
		}
	}
}
void showobject(int num, int gen)
{
    fz_error *error;
    fz_obj *obj;

    if (!src)
        die(fz_throw("no file specified"));

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

    /* print the stream raw if we're binary */
    if (pdf_isstream(src, num, gen) && showbinary)
    {
        showstream(num, gen);
    }

    else
    {
        printf("%d %d obj\n", num, gen);
        fz_debugobj(obj);
        printf("\n");

        if (pdf_isstream(src, num, gen))
        {
            printf("stream\n");
            showstream(num, gen);
            printf("endstream\n");
        }

        printf("endobj\n\n");
    }

    fz_dropobj(obj);
}
Exemple #7
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);
}
Exemple #8
0
void
cleanexpand(void)
{
	fz_error *error;
	fz_obj *stmobj;
	fz_buffer *buf;
	fz_obj *stmlen;
	int i, gen;

	for (i = 0; i < src->len; i++)
	{
		if (src->table[i].type == 'n')
		{
			gen = src->table[i].gen;

			if (pdf_isstream(src, i, gen))
			{
				error = pdf_loadobject(&stmobj, src, i, gen);
				if (error) die(error);

				error = pdf_loadstream(&buf, src, i, gen);
				if (error) die(error);

				fz_dictdels(stmobj, "Filter");
				fz_dictdels(stmobj, "DecodeParms");

				error = fz_newint(&stmlen, buf->wp - buf->rp);
				if (error) die(error);
				error = fz_dictputs(stmobj, "Length", stmlen);
				if (error) die(error);
				fz_dropobj(stmlen);

				pdf_updateobject(src, i, gen, stmobj);
				pdf_updatestream(src, i, gen, buf);

				fz_dropobj(stmobj);
			}
		}
	}
}
Exemple #9
0
fz_error
pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref,
                  char **strings, char *collection, fz_obj *cmapstm)
{
    fz_error error = fz_okay;
    pdf_cmap *cmap;
    int cid;
    int ucsbuf[8];
    int ucslen;
    int i;

    if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm)))
    {
        pdf_logfont("tounicode embedded cmap\n");

        error = pdf_loadembeddedcmap(&cmap, xref, cmapstm);
        if (error)
            return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm));

        font->tounicode = pdf_newcmap();

        for (i = 0; i < (strings ? 256 : 65536); i++)
        {
            cid = pdf_lookupcmap(font->encoding, i);
            if (cid >= 0)
            {
                ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf);
                if (ucslen == 1)
                    pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]);
                if (ucslen > 1)
                    pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen);
            }
        }

        pdf_sortcmap(font->tounicode);

        pdf_dropcmap(cmap);
    }

    else if (collection)
    {
        pdf_logfont("tounicode cid collection (%s)\n", collection);

        error = fz_okay;

        if (!strcmp(collection, "Adobe-CNS1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2");
        else if (!strcmp(collection, "Adobe-GB1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2");
        else if (!strcmp(collection, "Adobe-Japan1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2");
        else if (!strcmp(collection, "Adobe-Japan2"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */
        else if (!strcmp(collection, "Adobe-Korea1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2");

        if (error)
            return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection);
    }

    if (strings)
    {
        pdf_logfont("tounicode strings\n");

        /* TODO one-to-many mappings */

        font->ncidtoucs = 256;
        font->cidtoucs = fz_calloc(256, sizeof(unsigned short));

        for (i = 0; i < 256; i++)
        {
            if (strings[i])
                font->cidtoucs[i] = pdf_lookupagl(strings[i]);
            else
                font->cidtoucs[i] = '?';
        }
    }

    if (!font->tounicode && !font->cidtoucs)
    {
        pdf_logfont("tounicode could not be loaded\n");
        /* TODO: synthesize a ToUnicode if it's a freetype font with
        * cmap and/or post tables or if it has glyph names. */
    }

    return fz_okay;
}
fz_error
pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
	fz_error error;
	char buf[256];
	char *estrings[256];
	pdf_fontdesc *fontdesc;
	fz_obj *encoding;
	fz_obj *widths;
	fz_obj *charprocs;
	fz_obj *obj;
	int first, last;
	int i, k, n;
	fz_rect bbox;
	fz_matrix matrix;

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

	fontdesc = pdf_newfontdesc();

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

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

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

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

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

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

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

	/* Encoding */

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

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

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

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

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

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

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

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

	/* Widths */

	pdf_setdefaulthmtx(fontdesc, 0);

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

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

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

	pdf_endhmtx(fontdesc);

	/* Resources -- inherit page resources if the font doesn't have its own */

	fontdesc->font->t3resources = fz_dictgets(dict, "Resources");
	if (!fontdesc->font->t3resources)
		fontdesc->font->t3resources = rdb;
	if (fontdesc->font->t3resources)
		fz_keepobj(fontdesc->font->t3resources);
	if (!fontdesc->font->t3resources)
		fz_warn("no resource dictionary for type 3 font!");

	fontdesc->font->t3xref = xref;
	fontdesc->font->t3run = pdf_runcontents;

	/* CharProcs */

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

	for (i = 0; i < 256; i++)
	{
		if (estrings[i])
		{
			obj = fz_dictgets(charprocs, estrings[i]);
			if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj)))
			{
				error = pdf_loadstream(&fontdesc->font->t3procs[i], xref, fz_tonum(obj), fz_togen(obj));
				if (error)
					goto cleanup;
			}
		}
	}

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	fz_dropfont(fontdesc->font);
	fz_free(fontdesc);
	return fz_rethrow(error, "cannot load type3 font (%d %d R)", fz_tonum(dict), fz_togen(dict));
}