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 #2
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;
}
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;
}
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;
}
Exemple #5
0
fz_error*
processErrorPage(
    soPdfFile* inFile,
    fz_obj *pageObj,
    int pageNo,
    fz_rect *bbRect,
    fz_error *error
    )
{
    // Wrap the error
    error = fz_rethrow(error, "Cannot process page %d", pageNo + 1);

    // If we are not supposed to proceed with error then it ends
    if (p_proceedWithErrors == false)
            return error;

    // Save the error in the list
    if (g_errorCount >= MAX_ERRORS_BEFORE_STOP)
        return soPdfErrorList(error);
                
    g_errorList[g_errorCount++] = error;


    // Get the box for the page
    fz_obj *obj = fz_dictgets(pageObj, "CropBox");
    if (!obj)
        obj = fz_dictgets(pageObj, "MediaBox");

    error = pdf_resolve(&obj, inFile->xref);
    if (error)
        return fz_rethrow(error, "Cannot proceed with error %d", pageNo + 1);

    if (!fz_isarray(obj))
        return fz_throw("Cannot find page bounds : %d", pageNo + 1);

    fz_rect bbox = pdf_torect(obj);
    fz_rect mediaBox;

	mediaBox.x0 = MIN(bbox.x0, bbox.x1);
	mediaBox.y0 = MIN(bbox.y0, bbox.y1);
	mediaBox.x1 = MAX(bbox.x0, bbox.x1);
	mediaBox.y1 = MAX(bbox.y0, bbox.y1);
    float mbHeight = mediaBox.y1 - mediaBox.y0;


    switch(p_mode)
    {
    case FitHeight:
    case FitWidth:
        bbRect[0] = mediaBox;
        break;

    case Fit2xHeight:
    case Fit2xWidth:
        {
            float overlap = (mbHeight * (float)(p_overlap / 100)) / 2;
            bbRect[0] = mediaBox;
            bbRect[0].y0 = bbRect[0].y0 + (float)(0.5 * mbHeight) - overlap;
            bbRect[1] = mediaBox;
            bbRect[1].y1 = bbRect[1].y1 - (float)(0.5 * mbHeight) + overlap;
        }
        break;

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

    return NULL;
}
Exemple #6
0
void pdfmoz_open(pdfmoz_t *moz, char *filename)
{
    SCROLLINFO si;
    fz_error error;
    fz_obj *obj;
    fz_irect bbox;
    int rot;
    int i;

    strcpy(moz->error, "");

    error = fz_newrenderer(&moz->rast, pdf_devicergb, 0, 1024 * 512);
    if (error)
	pdfmoz_error(moz, error);

    /*
     * Open PDF and load xref table
     */

    moz->filename = filename;

    moz->xref = pdf_newxref();
    error = pdf_loadxref(moz->xref, filename);
    if (error)
    {
	error = pdf_repairxref(moz->xref, filename);
	if (error)
	    pdfmoz_error(moz, error);
    }

    /*
     * Handle encrypted PDF files
     */

    error = pdf_decryptxref(moz->xref);
    if (error)
	pdfmoz_error(moz, error);

    if (pdf_needspassword(moz->xref))
    {
	pdfmoz_warn(moz, "PDF file is encrypted and needs a password.");
    }

    moz->pagecount = pdf_getpagecount(moz->xref);
    moz->pages = fz_malloc(sizeof(page_t) * moz->pagecount);

    for (i = 0; i < moz->pagecount; i++)
    {
	fz_obj *pageobj;
	pageobj = pdf_getpageobject(moz->xref, i);
	moz->pages[i].obj = fz_keepobj(pageobj);
	moz->pages[i].page = nil;
	moz->pages[i].image = nil;

	obj = fz_dictgets(moz->pages[i].obj, "CropBox");
	if (!obj)
	    obj = fz_dictgets(moz->pages[i].obj, "MediaBox");
	bbox = fz_roundrect(pdf_torect(obj));
	moz->pages[i].w = bbox.x1 - bbox.x0;
	moz->pages[i].h = bbox.y1 - bbox.y0;

	rot = fz_toint(fz_dictgets(moz->pages[i].obj, "Rotate"));
	if ((rot / 90) % 2)
	{
	    int t = moz->pages[i].w;
	    moz->pages[i].w = moz->pages[i].h;
	    moz->pages[i].h = t;
	}

	moz->pages[i].px = 1 + PAD;
    }

    /*
     * Load meta information
     * TODO: move this into mupdf library
     */

    obj = fz_dictgets(moz->xref->trailer, "Root");
    moz->xref->root = fz_resolveindirect(obj);
    if (!moz->xref->root)
	pdfmoz_error(moz, fz_throw("syntaxerror: missing Root object"));
    if (moz->xref->root)
	fz_keepobj(moz->xref->root);

    obj = fz_dictgets(moz->xref->trailer, "Info");
    moz->xref->info = fz_resolveindirect(obj);
    if (moz->xref->info)
	fz_keepobj(moz->xref->info);

    moz->doctitle = filename;
    if (strrchr(moz->doctitle, '\\'))
	moz->doctitle = strrchr(moz->doctitle, '\\') + 1;
    if (strrchr(moz->doctitle, '/'))
	moz->doctitle = strrchr(moz->doctitle, '/') + 1;
    if (moz->xref->info)
    {
	obj = fz_dictgets(moz->xref->info, "Title");
	if (obj)
	    moz->doctitle = pdf_toutf8(obj);
    }

    /*
     * Start at first page
     */

    si.cbSize = sizeof(si);
    si.fMask = SIF_POS | SIF_RANGE; // XXX | SIF_PAGE;
    si.nPos = 0;
    si.nMin = 0;
    si.nMax = 1;
    si.nPage = 1;
    SetScrollInfo(moz->hwnd, SB_VERT, &si, TRUE);

    moz->scrollpage = 0;
    moz->scrollyofs = 0;

    InvalidateRect(moz->hwnd, NULL, FALSE);
}
Exemple #7
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 #8
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 #9
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 #10
0
fz_error *
pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
	fz_error *error;
	pdf_xobject *form;
	fz_obj *obj;

	if ((*formp = pdf_finditem(xref->store, PDF_KXOBJECT, ref)))
	{
		pdf_keepxobject(*formp);
		return fz_okay;
	}

	form = fz_malloc(sizeof(pdf_xobject));
	if (!form)
		return fz_throw("outofmem: xobject struct");

	form->refs = 1;
	form->resources = nil;
	form->contents = nil;

	/* Store item immediately, to avoid infinite recursion if contained
	   objects refer again to this xobject */
	error = pdf_storeitem(xref->store, PDF_KXOBJECT, ref, form);
	if (error)
	{
		pdf_dropxobject(form);
		return fz_rethrow(error, "cannot store xobject resource");
	}

	pdf_logrsrc("load xobject %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), form);

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

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

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

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

	obj = fz_dictgets(dict, "I");
	form->isolated = fz_tobool(obj);
	obj = fz_dictgets(dict, "K");
	form->knockout = fz_tobool(obj);

	pdf_logrsrc("isolated %d\n", form->isolated);
	pdf_logrsrc("knockout %d\n", form->knockout);

	obj = fz_dictgets(dict, "Resources");
	if (obj)
	{
		error = pdf_resolve(&obj, xref);
		if (error)
		{
			fz_dropobj(obj);
			error = fz_rethrow(error, "cannot resolve xobject resources");
			goto cleanup;
		}
		error = pdf_loadresources(&form->resources, xref, obj);
		fz_dropobj(obj);
		if (error)
		{
			error = fz_rethrow(error, "cannot load xobject resources");
			goto cleanup;
		}
	}

	error = pdf_loadstream(&form->contents, xref, fz_tonum(ref), fz_togen(ref));
	if (error)
	{
		error = fz_rethrow(error, "cannot load xobject content stream");
		goto cleanup;
	}

	pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp);

	pdf_logrsrc("}\n");

	*formp = form;
	return fz_okay;
cleanup:
	pdf_removeitem(xref->store, PDF_KXOBJECT, ref);
	pdf_dropxobject(form);
	return error;
}
Exemple #11
0
fz_error
pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
	fz_error error;
	char buf[256];
	char *estrings[256];
	pdf_fontdesc *fontdesc;
	fz_obj *encoding;
	fz_obj *widths;
	fz_obj *resources;
	fz_obj *charprocs;
	fz_obj *obj;
	int first, last;
	int i, k, n;
	fz_rect bbox;
	fz_matrix matrix;

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

	fontdesc = pdf_newfontdesc();

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

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

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

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

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

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

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

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

	/*
	 * Encoding
	 */

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

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

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

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

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

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

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

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

	/*
	 * Widths
	 */

	pdf_setdefaulthmtx(fontdesc, 0);

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

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

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

	pdf_endhmtx(fontdesc);

	/*
	 * Resources
	 */

	resources = fz_dictgets(dict, "Resources");

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

	/*
	 * CharProcs
	 */

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

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

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

	pdf_logfont("}\n");

	*fontdescp = fontdesc;
	return fz_okay;

cleanup:
	fz_dropfont(fontdesc->font);
	fz_free(fontdesc);
	return fz_rethrow(error, "cannot load type3 font");
}
Exemple #12
0
fz_error *
pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
    fz_error *error;
    char buf[256];
    char *estrings[256];
    pdf_font *font;
    fz_obj *encoding;
    fz_obj *widths;
    fz_obj *resources;
    fz_obj *charprocs;
    fz_obj *obj;
    int first, last;
    int i, k, n;
    fz_rect bbox;

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

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

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

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

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

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

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

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

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

    /*
     * Encoding
     */

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

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

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

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

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

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

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

    fz_dropobj(encoding);

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

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

    /*
     * Widths
     */

    fz_setdefaulthmtx((fz_font*)font, 0);

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

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

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

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

    fz_dropobj(widths);

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

    /*
     * Resources
     */

    resources = nil;

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

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

        fz_dropobj(obj);

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

    /*
     * CharProcs
     */

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

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

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

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

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

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

    pdf_logfont("}\n");

    *fontp = font;
    return fz_okay;

cleanup2:
    if (resources)
        fz_dropobj(resources);
cleanup:
    fz_dropfont((fz_font*)font);
    return fz_rethrow(error, "cannot load type3 font");
}
Exemple #13
0
fz_error
pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	pdf_xobject *form;
	fz_obj *obj;

	if ((*formp = pdf_finditem(xref->store, PDF_KXOBJECT, dict)))
	{
		pdf_keepxobject(*formp);
		return fz_okay;
	}

	form = fz_malloc(sizeof(pdf_xobject));
	form->refs = 1;
	form->resources = nil;
	form->contents = nil;

	/* Store item immediately, to avoid possible recursion if objects refer back to this one */
	pdf_storeitem(xref->store, PDF_KXOBJECT, dict, form);

	pdf_logrsrc("load xobject (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), form);

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

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

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

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

	form->isolated = 0;
	form->knockout = 0;
	form->transparency = 0;

	obj = fz_dictgets(dict, "Group");
	if (obj)
	{
		fz_obj *attrs = obj;

		form->isolated = fz_tobool(fz_dictgets(attrs, "I"));
		form->knockout = fz_tobool(fz_dictgets(attrs, "K"));

		obj = fz_dictgets(attrs, "S");
		if (fz_isname(obj) && !strcmp(fz_toname(obj), "Transparency"))
			form->transparency = 1;
	}

	pdf_logrsrc("isolated %d\n", form->isolated);
	pdf_logrsrc("knockout %d\n", form->knockout);
	pdf_logrsrc("transparency %d\n", form->transparency);

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

	error = pdf_loadstream(&form->contents, xref, fz_tonum(dict), fz_togen(dict));
	if (error)
	{
		pdf_removeitem(xref->store, PDF_KXOBJECT, dict);
		pdf_dropxobject(form);
		return fz_rethrow(error, "cannot load xobject content stream (%d %d R)", fz_tonum(dict), fz_togen(dict));
	}

	pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp);
	pdf_logrsrc("}\n");

	*formp = form;
	return fz_okay;
}
Exemple #14
0
fz_error
pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	pdf_page *page;
	fz_obj *obj;
	fz_bbox bbox;

	pdf_logpage("load page {\n");

	// TODO: move this to a more appropriate place
	/* Ensure that we have a store for resource objects */
	if (!xref->store)
		xref->store = pdf_newstore();

	page = fz_malloc(sizeof(pdf_page));
	page->resources = nil;
	page->contents = nil;
	page->transparency = 0;
	page->list = nil;
	page->text = nil;
	page->links = nil;
	page->annots = nil;

	obj = fz_dictgets(dict, "MediaBox");
	bbox = fz_roundrect(pdf_torect(obj));
	if (fz_isemptyrect(pdf_torect(obj)))
	{
		fz_warn("cannot find page bounds, guessing page bounds.");
		bbox.x0 = 0;
		bbox.y0 = 0;
		bbox.x1 = 612;
		bbox.y1 = 792;
	}

	obj = fz_dictgets(dict, "CropBox");
	if (fz_isarray(obj))
	{
		fz_bbox cropbox = fz_roundrect(pdf_torect(obj));
		bbox = fz_intersectbbox(bbox, cropbox);
	}

	page->mediabox.x0 = MIN(bbox.x0, bbox.x1);
	page->mediabox.y0 = MIN(bbox.y0, bbox.y1);
	page->mediabox.x1 = MAX(bbox.x0, bbox.x1);
	page->mediabox.y1 = MAX(bbox.y0, bbox.y1);

	if (page->mediabox.x1 - page->mediabox.x0 < 1 || page->mediabox.y1 - page->mediabox.y0 < 1)
		return fz_throw("invalid page size");

	page->rotate = fz_toint(fz_dictgets(dict, "Rotate"));

	pdf_logpage("bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);
	pdf_logpage("rotate %d\n", page->rotate);

	obj = fz_dictgets(dict, "Annots");
	if (obj)
	{
		pdf_loadlinks(&page->links, xref, obj);
		pdf_loadannots(&page->annots, xref, obj);
	}

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

	obj = fz_dictgets(dict, "Contents");
	error = pdf_loadpagecontents(&page->contents, xref, obj);
	if (error)
	{
		pdf_freepage(page);
		return fz_rethrow(error, "cannot load page contents (%d %d R)", fz_tonum(obj), fz_togen(obj));
	}

	if (page->resources && pdf_resourcesuseblending(page->resources))
		page->transparency = 1;

	pdf_logpage("} %p\n", page);

	*pagep = page;
	return fz_okay;
}
fz_error
pdf_loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	pdf_link *link;
	fz_obj *dest;
	fz_obj *action;
	fz_obj *obj;
	fz_rect bbox;
	pdf_linkkind kind;

	pdf_logpage("load link {\n");

	link = nil;
	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));
		}
		else
		{
			pdf_logpage("unhandled link action, ignoring link\n");
			dest = nil;
		}
	}

	pdf_logpage("}\n");

	if (dest)
	{
		error = pdf_newlink(&link, kind, bbox, dest);
		if (error)
			return fz_rethrow(error, "cannot create link");
		*linkp = link;
	}

	return fz_okay;
}
fz_error *
pdf_loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict)
{
	fz_error *error;
	pdf_link *link;
	fz_obj *dest;
	fz_obj *action;
	fz_obj *obj;
	fz_rect bbox;
	pdf_linkkind kind;

	pdf_logpage("load link {\n");

	link = nil;
	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)
	{
		error = pdf_resolve(&obj, xref);
		if (error)
			return error;
		dest = resolvedest(xref, obj);
		pdf_logpage("dest %d %d R\n", fz_tonum(dest), fz_togen(dest));
		fz_dropobj(obj);
	}

	kind = PDF_LUNKNOWN;
	action = fz_dictgets(dict, "A");
	if (action)
	{
		error = pdf_resolve(&action, xref);
		if (error)
			return error;

		obj = fz_dictgets(action, "S");
		if (!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 (!strcmp(fz_toname(obj), "URI"))
		{
			kind = PDF_LURI;
			dest = fz_dictgets(action, "URI");
			pdf_logpage("action uri %s\n", fz_tostrbuf(dest));
		}
		else
			pdf_logpage("action ... ?\n");

		fz_dropobj(action);
	}

	pdf_logpage("}\n");

	if (dest)
	{
		error = pdf_newlink(&link, bbox, dest, kind);
		if (error)
			return error;
		*linkp = link;
	}

	return nil;
}