Exemple #1
0
static fz_stream *
pdf_open_object_array(fz_context *ctx, pdf_document *doc, pdf_obj *list)
{
	fz_stream *stm;
	int i, n;

	n = pdf_array_len(ctx, list);
	stm = fz_open_concat(ctx, n, 1);

	fz_var(i); /* Workaround Mac compiler bug */
	for (i = 0; i < n; i++)
	{
		pdf_obj *obj = pdf_array_get(ctx, list, i);
		fz_try(ctx)
		{
			fz_concat_push(ctx, stm, pdf_open_stream(ctx, doc, pdf_to_num(ctx, obj), pdf_to_gen(ctx, obj)));
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "cannot load content stream part %d/%d", i + 1, n);
			continue;
		}
	}

	return stm;
}
Exemple #2
0
static boolean fill_input_buffer(j_decompress_ptr cinfo)
{
	struct jpeg_source_mgr *src = cinfo->src;
	fz_dctd *state = cinfo->client_data;
	fz_stream *curr_stm = state->curr_stm;
	fz_context *ctx = curr_stm->ctx;

	curr_stm->rp = curr_stm->wp;
	fz_try(ctx)
	{
		fz_fill_buffer(curr_stm);
	}
	fz_catch(ctx)
	{
		fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
		return 0;
	}
	src->next_input_byte = curr_stm->rp;
	src->bytes_in_buffer = curr_stm->wp - curr_stm->rp;

	if (src->bytes_in_buffer == 0)
	{
		static unsigned char eoi[2] = { 0xFF, JPEG_EOI };
		fz_warn(state->ctx, "premature end of file in jpeg");
		src->next_input_byte = eoi;
		src->bytes_in_buffer = 2;
	}

	return 1;
}
Exemple #3
0
void
xps_read_page_list(fz_context *ctx, xps_document *doc)
{
	xps_fixdoc *fixdoc;

	xps_read_and_process_metadata_part(ctx, doc, "/_rels/.rels", NULL);

	if (!doc->start_part)
		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find fixed document sequence start part");

	xps_read_and_process_metadata_part(ctx, doc, doc->start_part, NULL);

	for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next)
	{
		char relbuf[1024];
		fz_try(ctx)
		{
			xps_rels_for_part(ctx, doc, relbuf, fixdoc->name, sizeof relbuf);
			xps_read_and_process_metadata_part(ctx, doc, relbuf, fixdoc);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "cannot process FixedDocument rels part");
		}
		xps_read_and_process_metadata_part(ctx, doc, fixdoc->name, fixdoc);
	}
}
void
pdf_update_annot(pdf_document *doc, pdf_annot *annot)
{
	/* SumatraPDF: prevent regressions */
#if 0
	pdf_obj *obj, *ap, *as, *n;
	fz_context *ctx = doc->ctx;

	if (doc->update_appearance)
		doc->update_appearance(doc, annot);

	obj = annot->obj;

	ap = pdf_dict_gets(obj, "AP");
	as = pdf_dict_gets(obj, "AS");

	if (pdf_is_dict(ap))
	{
		pdf_hotspot *hp = &doc->hotspot;

		n = NULL;

		if (hp->num == pdf_to_num(obj)
			&& hp->gen == pdf_to_gen(obj)
			&& (hp->state & HOTSPOT_POINTER_DOWN))
		{
			n = pdf_dict_gets(ap, "D"); /* down state */
		}

		if (n == NULL)
			n = pdf_dict_gets(ap, "N"); /* normal state */

		/* lookup current state in sub-dictionary */
		if (!pdf_is_stream(doc, pdf_to_num(n), pdf_to_gen(n)))
			n = pdf_dict_get(n, as);

		pdf_drop_xobject(ctx, annot->ap);
		annot->ap = NULL;

		if (pdf_is_stream(doc, pdf_to_num(n), pdf_to_gen(n)))
		{
			fz_try(ctx)
			{
				annot->ap = pdf_load_xobject(doc, n);
				pdf_transform_annot(annot);
				annot->ap_iteration = annot->ap->iteration;
			}
			fz_catch(ctx)
			{
				fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
				fz_warn(ctx, "ignoring broken annotation");
			}
		}
	}
#endif
}
static void
pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont, int has_encoding)
{
	pdf_obj *obj1, *obj2, *obj3, *obj;
	char *fontname, *origname;
	FT_Face face;
	fz_context *ctx = doc->ctx;

	/* Prefer BaseFont; don't bother with FontName */
	origname = basefont;

	/* SumatraPDF: handle /BaseFont /Arial,Bold+000041 /FontName /Arial,Bold */
	if (strchr(basefont, '+') && pdf_is_name(pdf_dict_gets(dict, "FontName")))
		origname = pdf_to_name(pdf_dict_gets(dict, "FontName"));

	/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1616 */
	if (strlen(origname) > 7 && origname[6] == '+')
		origname += 7;

	/* Look through list of alternate names for built in fonts */
	fontname = clean_font_name(origname);

	fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags"));
	fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle"));
	fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent"));
	fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent"));
	fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight"));
	fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight"));
	fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth"));

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

	if (pdf_is_indirect(obj))
	{
		fz_try(ctx)
		{
			pdf_load_embedded_font(doc, fontdesc, fontname, obj);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font");
			if (origname != fontname && !iscidfont)
				pdf_load_builtin_font(ctx, fontdesc, fontname);
			else
				pdf_load_system_font(ctx, fontdesc, fontname, collection, has_encoding);
		}
	}
	else
	{
		if (origname != fontname && !iscidfont)
void
pdf_update_annot(fz_context *ctx, pdf_document *doc, pdf_annot *annot)
{
	pdf_obj *obj, *ap, *as, *n;

	if (doc->update_appearance)
		doc->update_appearance(ctx, doc, annot);

	obj = annot->obj;

	ap = pdf_dict_get(ctx, obj, PDF_NAME_AP);
	as = pdf_dict_get(ctx, obj, PDF_NAME_AS);

	if (pdf_is_dict(ctx, ap))
	{
		pdf_hotspot *hp = &doc->hotspot;

		n = NULL;

		if (hp->num == pdf_to_num(ctx, obj)
			&& hp->gen == pdf_to_gen(ctx, obj)
			&& (hp->state & HOTSPOT_POINTER_DOWN))
		{
			n = pdf_dict_get(ctx, ap, PDF_NAME_D); /* down state */
		}

		if (n == NULL)
			n = pdf_dict_get(ctx, ap, PDF_NAME_N); /* normal state */

		/* lookup current state in sub-dictionary */
		if (!pdf_is_stream(ctx, doc, pdf_to_num(ctx, n), pdf_to_gen(ctx, n)))
			n = pdf_dict_get(ctx, n, as);

		pdf_drop_xobject(ctx, annot->ap);
		annot->ap = NULL;

		if (pdf_is_stream(ctx, doc, pdf_to_num(ctx, n), pdf_to_gen(ctx, n)))
		{
			fz_try(ctx)
			{
				annot->ap = pdf_load_xobject(ctx, doc, n);
				pdf_transform_annot(ctx, annot);
				annot->ap_iteration = annot->ap->iteration;
			}
			fz_catch(ctx)
			{
				fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
				fz_warn(ctx, "ignoring broken annotation");
			}
		}
	}
}
Exemple #7
0
static void
pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont)
{
	pdf_obj *obj1, *obj2, *obj3, *obj;
	char *fontname, *origname;
	FT_Face face;
	fz_context *ctx = doc->ctx;

	/* Prefer BaseFont; don't bother with FontName */
	origname = basefont;

	/* Look through list of alternate names for built in fonts */
	fontname = clean_font_name(origname);

	fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags"));
	fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle"));
	fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent"));
	fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent"));
	fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight"));
	fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight"));
	fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth"));

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

	if (pdf_is_indirect(obj))
	{
		fz_try(ctx)
		{
			pdf_load_embedded_font(doc, fontdesc, fontname, obj);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font");
			if (origname != fontname && !iscidfont)
				pdf_load_builtin_font(ctx, fontdesc, fontname);
			else
				pdf_load_system_font(ctx, fontdesc, fontname, collection);
		}
	}
	else
	{
		if (origname != fontname && !iscidfont)
Exemple #8
0
void pdf_load_type3_glyphs(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, int nested_depth)
{
	int i;

	fz_try(ctx)
	{
		for (i = 0; i < 256; i++)
		{
			if (fontdesc->font->t3procs[i])
			{
				fz_prepare_t3_glyph(ctx, fontdesc->font, i, nested_depth);
				fontdesc->size += 0; // TODO: display list size calculation
			}
		}
	}
	fz_catch(ctx)
	{
		fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
		fz_warn(ctx, "Type3 glyph load failed: %s", fz_caught_message(ctx));
	}
}
Exemple #9
0
fz_link *
pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, int pagenum, const fz_matrix *page_ctm)
{
	fz_link *link, *head, *tail;
	pdf_obj *obj;
	int i, n;

	head = tail = NULL;
	link = NULL;

	n = pdf_array_len(ctx, annots);
	for (i = 0; i < n; i++)
	{
		/* FIXME: Move the try/catch out of the loop for performance? */
		fz_try(ctx)
		{
			obj = pdf_array_get(ctx, annots, i);
			link = pdf_load_link(ctx, doc, obj, pagenum, page_ctm);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			link = NULL;
		}

		if (link)
		{
			if (!head)
				head = tail = link;
			else
			{
				tail->next = link;
				tail = link;
			}
		}
	}

	return head;
}
Exemple #10
0
fz_font *
xps_lookup_font(fz_context *ctx, xps_document *doc, char *base_uri, char *font_uri, char *style_att)
{
    char partname[1024];
    char fakename[1024];
    char *subfont;
    int subfontid = 0;
    xps_part *part;
    fz_font *font;

    xps_resolve_url(ctx, doc, partname, base_uri, font_uri, sizeof partname);
    subfont = strrchr(partname, '#');
    if (subfont)
    {
        subfontid = atoi(subfont + 1);
        *subfont = 0;
    }

    /* Make a new part name for font with style simulation applied */
    fz_strlcpy(fakename, partname, sizeof fakename);
    if (style_att)
    {
        if (!strcmp(style_att, "BoldSimulation"))
            fz_strlcat(fakename, "#Bold", sizeof fakename);
        else if (!strcmp(style_att, "ItalicSimulation"))
            fz_strlcat(fakename, "#Italic", sizeof fakename);
        else if (!strcmp(style_att, "BoldItalicSimulation"))
            fz_strlcat(fakename, "#BoldItalic", sizeof fakename);
    }

    font = xps_lookup_font_imp(ctx, doc, fakename);
    if (!font)
    {
        fz_buffer *buf = NULL;
        fz_var(buf);

        fz_try(ctx)
        {
            part = xps_read_part(ctx, doc, partname);
        }
        fz_catch(ctx)
        {
            fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
            fz_warn(ctx, "cannot find font resource part '%s'", partname);
            return NULL;
        }

        /* deobfuscate if necessary */
        if (strstr(part->name, ".odttf"))
            xps_deobfuscate_font_resource(ctx, doc, part);
        if (strstr(part->name, ".ODTTF"))
            xps_deobfuscate_font_resource(ctx, doc, part);

        fz_try(ctx)
        {
            buf = fz_new_buffer_from_data(ctx, part->data, part->size);
            /* part->data is now owned by buf */
            part->data = NULL;
            font = fz_new_font_from_buffer(ctx, NULL, buf, subfontid, 1);
        }
        fz_always(ctx)
        {
            fz_drop_buffer(ctx, buf);
            xps_drop_part(ctx, doc, part);
        }
        fz_catch(ctx)
        {
            fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
            fz_warn(ctx, "cannot load font resource '%s'", partname);
            return NULL;
        }

        if (style_att)
        {
            font->ft_bold = !!strstr(style_att, "Bold");
            font->ft_italic = !!strstr(style_att, "Italic");
        }

        xps_select_best_font_encoding(ctx, doc, font);
        xps_insert_font(ctx, doc, fakename, font);
    }
Exemple #11
0
void
xps_parse_glyphs(fz_context *ctx, xps_document *doc, const fz_matrix *ctm,
		char *base_uri, xps_resource *dict, fz_xml *root)
{
	fz_device *dev = doc->dev;

	fz_xml *node;

	char *fill_uri;
	char *opacity_mask_uri;

	char *bidi_level_att;
	char *fill_att;
	char *font_size_att;
	char *font_uri_att;
	char *origin_x_att;
	char *origin_y_att;
	char *is_sideways_att;
	char *indices_att;
	char *unicode_att;
	char *style_att;
	char *transform_att;
	char *clip_att;
	char *opacity_att;
	char *opacity_mask_att;
	char *navigate_uri_att;

	fz_xml *transform_tag = NULL;
	fz_xml *clip_tag = NULL;
	fz_xml *fill_tag = NULL;
	fz_xml *opacity_mask_tag = NULL;

	char *fill_opacity_att = NULL;

	xps_part *part;
	fz_font *font;

	char partname[1024];
	char fakename[1024];
	char *subfont;

	float font_size = 10;
	int subfontid = 0;
	int is_sideways = 0;
	int bidi_level = 0;

	fz_text *text;
	fz_rect area;

	fz_matrix local_ctm = *ctm;

	/*
	 * Extract attributes and extended attributes.
	 */

	bidi_level_att = fz_xml_att(root, "BidiLevel");
	fill_att = fz_xml_att(root, "Fill");
	font_size_att = fz_xml_att(root, "FontRenderingEmSize");
	font_uri_att = fz_xml_att(root, "FontUri");
	origin_x_att = fz_xml_att(root, "OriginX");
	origin_y_att = fz_xml_att(root, "OriginY");
	is_sideways_att = fz_xml_att(root, "IsSideways");
	indices_att = fz_xml_att(root, "Indices");
	unicode_att = fz_xml_att(root, "UnicodeString");
	style_att = fz_xml_att(root, "StyleSimulations");
	transform_att = fz_xml_att(root, "RenderTransform");
	clip_att = fz_xml_att(root, "Clip");
	opacity_att = fz_xml_att(root, "Opacity");
	opacity_mask_att = fz_xml_att(root, "OpacityMask");
	navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri");

	for (node = fz_xml_down(root); node; node = fz_xml_next(node))
	{
		if (fz_xml_is_tag(node, "Glyphs.RenderTransform"))
			transform_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Glyphs.OpacityMask"))
			opacity_mask_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Glyphs.Clip"))
			clip_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Glyphs.Fill"))
			fill_tag = fz_xml_down(node);
	}

	fill_uri = base_uri;
	opacity_mask_uri = base_uri;

	xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);
	xps_resolve_resource_reference(ctx, doc, dict, &clip_att, &clip_tag, NULL);
	xps_resolve_resource_reference(ctx, doc, dict, &fill_att, &fill_tag, &fill_uri);
	xps_resolve_resource_reference(ctx, doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);

	/*
	 * Check that we have all the necessary information.
	 */

	if (!font_size_att || !font_uri_att || !origin_x_att || !origin_y_att) {
		fz_warn(ctx, "missing attributes in glyphs element");
		return;
	}

	if (!indices_att && !unicode_att)
		return; /* nothing to draw */

	if (is_sideways_att)
		is_sideways = !strcmp(is_sideways_att, "true");

	if (bidi_level_att)
		bidi_level = atoi(bidi_level_att);

	/*
	 * Find and load the font resource
	 */

	xps_resolve_url(ctx, doc, partname, base_uri, font_uri_att, sizeof partname);
	subfont = strrchr(partname, '#');
	if (subfont)
	{
		subfontid = atoi(subfont + 1);
		*subfont = 0;
	}

	/* Make a new part name for font with style simulation applied */
	fz_strlcpy(fakename, partname, sizeof fakename);
	if (style_att)
	{
		if (!strcmp(style_att, "BoldSimulation"))
			fz_strlcat(fakename, "#Bold", sizeof fakename);
		else if (!strcmp(style_att, "ItalicSimulation"))
			fz_strlcat(fakename, "#Italic", sizeof fakename);
		else if (!strcmp(style_att, "BoldItalicSimulation"))
			fz_strlcat(fakename, "#BoldItalic", sizeof fakename);
	}

	font = xps_lookup_font(ctx, doc, fakename);
	if (!font)
	{
		fz_buffer *buf = NULL;
		fz_var(buf);

		fz_try(ctx)
		{
			part = xps_read_part(ctx, doc, partname);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "cannot find font resource part '%s'", partname);
			return;
		}

		/* deobfuscate if necessary */
		if (strstr(part->name, ".odttf"))
			xps_deobfuscate_font_resource(ctx, doc, part);
		if (strstr(part->name, ".ODTTF"))
			xps_deobfuscate_font_resource(ctx, doc, part);

		fz_try(ctx)
		{
			buf = fz_new_buffer_from_data(ctx, part->data, part->size);
			/* part->data is now owned by buf */
			part->data = NULL;
			font = fz_new_font_from_buffer(ctx, NULL, buf, subfontid, 1);
		}
		fz_always(ctx)
		{
			fz_drop_buffer(ctx, buf);
			xps_drop_part(ctx, doc, part);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "cannot load font resource '%s'", partname);
			return;
		}

		if (style_att)
		{
			font->ft_bold = !!strstr(style_att, "Bold");
			font->ft_italic = !!strstr(style_att, "Italic");
		}

		xps_select_best_font_encoding(ctx, doc, font);
		xps_insert_font(ctx, doc, fakename, font);
	}
Exemple #12
0
static pdf_font_desc *
pdf_load_simple_font_by_name(pdf_document *doc, pdf_obj *dict, char *basefont)
{
	pdf_obj *descriptor;
	pdf_obj *encoding;
	pdf_obj *widths;
	unsigned short *etable = NULL;
	pdf_font_desc *fontdesc = NULL;
	char *subtype;
	FT_Face face;
	FT_CharMap cmap;
	int symbolic;
	int kind;

	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;
	int has_lock = 0;
	fz_context *ctx = doc->ctx;

	fz_var(fontdesc);
	fz_var(etable);
	fz_var(has_lock);

	/* Load font file */
	fz_try(ctx)
	{
		fontdesc = pdf_new_font_desc(ctx);

		descriptor = pdf_dict_gets(dict, "FontDescriptor");
		if (descriptor)
			pdf_load_font_descriptor(fontdesc, doc, descriptor, NULL, basefont, 0);
		else
			pdf_load_builtin_font(ctx, fontdesc, basefont);

		/* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */
		if (descriptor && pdf_is_string(pdf_dict_gets(descriptor, "FontName")) &&
			!pdf_dict_gets(dict, "ToUnicode") &&
			!strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") &&
			pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4)
		{
			char *cp936fonts[] = {
				"\xCB\xCE\xCC\xE5", "SimSun,Regular",
				"\xBA\xDA\xCC\xE5", "SimHei,Regular",
				"\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular",
				"\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular",
				"\xC1\xA5\xCA\xE9", "SimLi,Regular",
				NULL
			};
			for (i = 0; cp936fonts[i]; i += 2)
				if (!strcmp(basefont, cp936fonts[i]))
					break;
			if (cp936fonts[i])
			{
				fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings");
				pdf_drop_font(ctx, fontdesc);
				fontdesc = NULL;
				fontdesc = pdf_new_font_desc(ctx);
				pdf_load_font_descriptor(fontdesc, doc, descriptor, "Adobe-GB1", cp936fonts[i+1], 0);
				fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H");
				fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
				fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");

				face = fontdesc->font->ft_face;
				/* kind = ft_kind(face); */
				goto skip_encoding;
			}
		}

		face = fontdesc->font->ft_face;
		kind = ft_kind(face);

		/* Encoding */

		symbolic = fontdesc->flags & 4;

		if (face->num_charmaps > 0)
			cmap = face->charmaps[0];
		else
			cmap = NULL;

		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 (symbolic && test->platform_id == 3 && test->encoding_id == 0)
					cmap = test;
			}
		}

		if (cmap)
		{
			fterr = FT_Set_Charmap(face, cmap);
			if (fterr)
				fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr));
		}
		else
			fz_warn(ctx, "freetype could not find any cmaps");

		etable = fz_malloc_array(ctx, 256, sizeof(unsigned short));
		fontdesc->size += 256 * sizeof(unsigned short);
		for (i = 0; i < 256; i++)
		{
			estrings[i] = NULL;
			etable[i] = 0;
		}

		encoding = pdf_dict_gets(dict, "Encoding");
		if (encoding)
		{
			if (pdf_is_name(encoding))
				pdf_load_encoding(estrings, pdf_to_name(encoding));

			if (pdf_is_dict(encoding))
			{
				pdf_obj *base, *diff, *item;

				base = pdf_dict_gets(encoding, "BaseEncoding");
				if (pdf_is_name(base))
					pdf_load_encoding(estrings, pdf_to_name(base));
				else if (!fontdesc->is_embedded && !symbolic)
					pdf_load_encoding(estrings, "StandardEncoding");

				diff = pdf_dict_gets(encoding, "Differences");
				if (pdf_is_array(diff))
				{
					n = pdf_array_len(diff);
					k = 0;
					for (i = 0; i < n; i++)
					{
						item = pdf_array_get(diff, i);
						if (pdf_is_int(item))
							k = pdf_to_int(item);
						if (pdf_is_name(item) && k >= 0 && k < nelem(estrings))
							estrings[k++] = pdf_to_name(item);
					}
				}
			}
		}

		/* start with the builtin encoding */
		for (i = 0; i < 256; i++)
			etable[i] = ft_char_index(face, i);

		fz_lock(ctx, FZ_LOCK_FREETYPE);
		has_lock = 1;

		/* built-in and substitute fonts may be a different type than what the document expects */
		subtype = pdf_to_name(pdf_dict_gets(dict, "Subtype"));
		if (!strcmp(subtype, "Type1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "MMType1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "TrueType"))
			kind = TRUETYPE;
		else if (!strcmp(subtype, "CIDFontType0"))
			kind = TYPE1;
		else if (!strcmp(subtype, "CIDFontType2"))
			kind = TRUETYPE;

		/* encode by glyph name where we can */
		if (kind == TYPE1)
		{
			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_lookup_agl(estrings[i]);
						const char **dupnames = pdf_lookup_agl_duplicates(aglcode);
						while (*dupnames)
						{
							etable[i] = FT_Get_Name_Index(face, (char*)*dupnames);
							if (etable[i])
								break;
							dupnames++;
						}
						if (etable[i] == 0)
						{
							char buf[10];
							sprintf(buf, "uni%04X", aglcode);
							etable[i] = FT_Get_Name_Index(face, buf);
						}
					}
				}
			}
		}

		/* encode by glyph name where we can */
		if (kind == TRUETYPE)
		{
			/* Unicode cmap */
			if (!symbolic && face->charmap && face->charmap->platform_id == 3)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						int aglcode = pdf_lookup_agl(estrings[i]);
						if (!aglcode)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, aglcode);
					}
				}
			}

			/* MacRoman cmap */
			else if (!symbolic && face->charmap && face->charmap->platform_id == 1)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						k = lookup_mre_code(estrings[i]);
						if (k <= 0)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, k);
					}
				}
			}

			/* Symbolic cmap */
			else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						etable[i] = FT_Get_Name_Index(face, estrings[i]);
						if (etable[i] == 0)
							etable[i] = ft_char_index(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(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr));
					if (ebuffer[i][0])
						estrings[i] = ebuffer[i];
				}
				else
				{
					estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */
				}
			}
		}

		/* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */
		if (kind == TYPE1 && symbolic)
		{
			for (i = 0; i < 256; i++)
				if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i]))
					estrings[i] = (char*) pdf_standard[i];
		}

		fz_unlock(ctx, FZ_LOCK_FREETYPE);
		has_lock = 0;

		fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
		fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
		fontdesc->cid_to_gid_len = 256;
		fontdesc->cid_to_gid = etable;

		fz_try(ctx)
		{
			pdf_load_to_unicode(doc, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			fz_warn(ctx, "cannot load ToUnicode CMap");
		}

	skip_encoding:

		/* Widths */

		pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width);

		widths = pdf_dict_gets(dict, "Widths");
		if (widths)
		{
			int first, last;

			first = pdf_to_int(pdf_dict_gets(dict, "FirstChar"));
			last = pdf_to_int(pdf_dict_gets(dict, "LastChar"));

			if (first < 0 || last > 255 || first > last)
				first = last = 0;

			for (i = 0; i < last - first + 1; i++)
			{
				int wid = pdf_to_int(pdf_array_get(widths, i));
				pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid);
			}
		}
		else
		{
			fz_lock(ctx, FZ_LOCK_FREETYPE);
			has_lock = 1;
			fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
			if (fterr)
				fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr));
			for (i = 0; i < 256; i++)
			{
				pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i));
			}
			fz_unlock(ctx, FZ_LOCK_FREETYPE);
			has_lock = 0;
		}

		pdf_end_hmtx(ctx, fontdesc);
	}
	fz_catch(ctx)
	{
		if (has_lock)
			fz_unlock(ctx, FZ_LOCK_FREETYPE);
		if (fontdesc && etable != fontdesc->cid_to_gid)
			fz_free(ctx, etable);
		pdf_drop_font(ctx, fontdesc);
		fz_rethrow_message(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}
	return fontdesc;
}
Exemple #13
0
int
pdf_repair_obj(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf, fz_off_t *stmofsp, int *stmlenp, pdf_obj **encrypt, pdf_obj **id, pdf_obj **page, fz_off_t *tmpofs, pdf_obj **root)
{
	fz_stream *file = doc->file;
	pdf_token tok;
	int stm_len;

	*stmofsp = 0;
	if (stmlenp)
		*stmlenp = -1;

	stm_len = 0;

	/* On entry to this function, we know that we've just seen
	 * '<int> <int> obj'. We expect the next thing we see to be a
	 * pdf object. Regardless of the type of thing we meet next
	 * we only need to fully parse it if it is a dictionary. */
	tok = pdf_lex(ctx, file, buf);

	if (tok == PDF_TOK_OPEN_DICT)
	{
		pdf_obj *dict, *obj;

		fz_try(ctx)
		{
			dict = pdf_parse_dict(ctx, doc, file, buf);
		}
		fz_catch(ctx)
		{
			fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
			/* Don't let a broken object at EOF overwrite a good one */
			if (file->eof)
				fz_rethrow(ctx);
			/* Silently swallow the error */
			dict = pdf_new_dict(ctx, NULL, 2);
		}

		/* We must be careful not to try to resolve any indirections
		 * here. We have just read dict, so we know it to be a non
		 * indirected dictionary. Before we look at any values that
		 * we get back from looking up in it, we need to check they
		 * aren't indirected. */

		if (encrypt || id || root)
		{
			obj = pdf_dict_get(ctx, dict, PDF_NAME_Type);
			if (!pdf_is_indirect(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME_XRef))
			{
				if (encrypt)
				{
					obj = pdf_dict_get(ctx, dict, PDF_NAME_Encrypt);
					if (obj)
					{
						pdf_drop_obj(ctx, *encrypt);
						*encrypt = pdf_keep_obj(ctx, obj);
					}
				}

				if (id)
				{
					obj = pdf_dict_get(ctx, dict, PDF_NAME_ID);
					if (obj)
					{
						pdf_drop_obj(ctx, *id);
						*id = pdf_keep_obj(ctx, obj);
					}
				}

				if (root)
					*root = pdf_keep_obj(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Root));
			}
		}

		obj = pdf_dict_get(ctx, dict, PDF_NAME_Length);
		if (!pdf_is_indirect(ctx, obj) && pdf_is_int(ctx, obj))
			stm_len = pdf_to_int(ctx, obj);

		if (doc->file_reading_linearly && page)
		{
			obj = pdf_dict_get(ctx, dict, PDF_NAME_Type);
			if (!pdf_is_indirect(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME_Page))
			{
				pdf_drop_obj(ctx, *page);
				*page = pdf_keep_obj(ctx, dict);
			}
		}

		pdf_drop_obj(ctx, dict);
	}
Exemple #14
0
static fz_xml *
xps_load_fixed_page(fz_context *ctx, xps_document *doc, xps_fixpage *page)
{
	xps_part *part;
	fz_xml *root;
	char *width_att;
	char *height_att;

	part = xps_read_part(ctx, doc, page->name);
	fz_try(ctx)
	{
		root = fz_parse_xml(ctx, part->data, part->size, 0);
	}
	fz_always(ctx)
	{
		xps_drop_part(ctx, doc, part);
	}
	fz_catch(ctx)
	{
		fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
		root = NULL;
	}
	if (!root)
		fz_throw(ctx, FZ_ERROR_GENERIC, "FixedPage missing root element");

	if (fz_xml_is_tag(root, "AlternateContent"))
	{
		fz_xml *node = xps_lookup_alternate_content(ctx, doc, root);
		if (!node)
		{
			fz_drop_xml(ctx, root);
			fz_throw(ctx, FZ_ERROR_GENERIC, "FixedPage missing alternate root element");
		}
		fz_detach_xml(node);
		fz_drop_xml(ctx, root);
		root = node;
	}

	if (!fz_xml_is_tag(root, "FixedPage"))
	{
		fz_drop_xml(ctx, root);
		fz_throw(ctx, FZ_ERROR_GENERIC, "expected FixedPage element");
	}

	width_att = fz_xml_att(root, "Width");
	if (!width_att)
	{
		fz_drop_xml(ctx, root);
		fz_throw(ctx, FZ_ERROR_GENERIC, "FixedPage missing required attribute: Width");
	}

	height_att = fz_xml_att(root, "Height");
	if (!height_att)
	{
		fz_drop_xml(ctx, root);
		fz_throw(ctx, FZ_ERROR_GENERIC, "FixedPage missing required attribute: Height");
	}

	page->width = atoi(width_att);
	page->height = atoi(height_att);

	return root;
}
Exemple #15
0
fz_pixmap *
fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int in_line, int indexed, int l2factor, int native_l2factor)
{
	fz_pixmap *tile = NULL;
	int stride, len, i;
	unsigned char *samples = NULL;
	int f = 1<<native_l2factor;
	int w = (image->w + f-1) >> native_l2factor;
	int h = (image->h + f-1) >> native_l2factor;

	fz_var(tile);
	fz_var(samples);

	fz_try(ctx)
	{
		tile = fz_new_pixmap(ctx, image->colorspace, w, h);
		tile->interpolate = image->interpolate;

		stride = (w * image->n * image->bpc + 7) / 8;

		samples = fz_malloc_array(ctx, h, stride);

		len = fz_read(stm, samples, h * stride);
		if (len < 0)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read image data");
		}

		/* Make sure we read the EOF marker (for inline images only) */
		if (in_line)
		{
			unsigned char tbuf[512];
			fz_try(ctx)
			{
				int tlen = fz_read(stm, tbuf, sizeof tbuf);
				if (tlen > 0)
					fz_warn(ctx, "ignoring garbage at end of image");
			}
			fz_catch(ctx)
			{
				fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
				fz_warn(ctx, "ignoring error at end of image");
			}
		}

		/* Pad truncated images */
		if (len < stride * h)
		{
			fz_warn(ctx, "padding truncated image");
			memset(samples + len, 0, stride * h - len);
		}

		/* Invert 1-bit image masks */
		if (image->imagemask)
		{
			/* 0=opaque and 1=transparent so we need to invert */
			unsigned char *p = samples;
			len = h * stride;
			for (i = 0; i < len; i++)
				p[i] = ~p[i];
		}

		fz_unpack_tile(tile, samples, image->n, image->bpc, stride, indexed);

		fz_free(ctx, samples);
		samples = NULL;

		if (image->usecolorkey)
			fz_mask_color_key(tile, image->n, image->colorkey);

		if (indexed)
		{
			fz_pixmap *conv;
			fz_decode_indexed_tile(tile, image->decode, (1 << image->bpc) - 1);
			conv = fz_expand_indexed_pixmap(ctx, tile);
			fz_drop_pixmap(ctx, tile);
			tile = conv;
		}
		else
		{
			fz_decode_tile(tile, image->decode);
		}
	}
	fz_always(ctx)
	{
		fz_close(stm);
	}
	fz_catch(ctx)
	{
		if (tile)
			fz_drop_pixmap(ctx, tile);
		fz_free(ctx, samples);

		fz_rethrow(ctx);
	}

	/* Now apply any extra subsampling required */
	if (l2factor - native_l2factor > 0)
	{
		if (l2factor - native_l2factor > 8)
			l2factor = native_l2factor + 8;
		fz_subsample_pixmap(ctx, tile, l2factor - native_l2factor);
	}

	return tile;
}