static pdf_font_desc *
pdf_load_type0_font(pdf_document *xref, pdf_obj *dict)
{
	pdf_obj *dfonts;
	pdf_obj *dfont;
	pdf_obj *subtype;
	pdf_obj *encoding;
	pdf_obj *to_unicode;

	dfonts = pdf_dict_gets(dict, "DescendantFonts");
	if (!dfonts)
		fz_throw(xref->ctx, "cid font is missing descendant fonts");

	dfont = pdf_array_get(dfonts, 0);

	subtype = pdf_dict_gets(dfont, "Subtype");
	encoding = pdf_dict_gets(dict, "Encoding");
	to_unicode = pdf_dict_gets(dict, "ToUnicode");

	if (pdf_is_name(subtype) && !strcmp(pdf_to_name(subtype), "CIDFontType0"))
		return load_cid_font(xref, dfont, encoding, to_unicode);
	else if (pdf_is_name(subtype) && !strcmp(pdf_to_name(subtype), "CIDFontType2"))
		return load_cid_font(xref, dfont, encoding, to_unicode);
	else
		fz_throw(xref->ctx, "syntaxerror: unknown cid font type");

	return NULL; /* Stupid MSVC */
}
Esempio n. 2
0
static pdf_obj *
resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, int depth)
{
	if (depth > 10) /* Arbitrary to avoid infinite recursion */
		return NULL;

	if (pdf_is_name(ctx, dest) || pdf_is_string(ctx, dest))
	{
		dest = pdf_lookup_dest(ctx, doc, dest);
		dest = resolve_dest_rec(ctx, doc, dest, depth+1);
		return dest;
	}

	else if (pdf_is_array(ctx, dest))
	{
		return dest;
	}

	else if (pdf_is_dict(ctx, dest))
	{
		dest = pdf_dict_get(ctx, dest, PDF_NAME_D);
		return resolve_dest_rec(ctx, doc, dest, depth+1);
	}

	else if (pdf_is_indirect(ctx, dest))
		return dest;

	return NULL;
}
Esempio n. 3
0
static void
pdf_load_name_tree_imp(pdf_obj *dict, pdf_document *xref, pdf_obj *node)
{
	fz_context *ctx = xref->ctx;
	pdf_obj *kids = pdf_dict_gets(node, "Kids");
	pdf_obj *names = pdf_dict_gets(node, "Names");
	int i;

	if (kids && !pdf_dict_mark(node))
	{
		for (i = 0; i < pdf_array_len(kids); i++)
			pdf_load_name_tree_imp(dict, xref, pdf_array_get(kids, i));
		pdf_dict_unmark(node);
	}

	if (names)
	{
		for (i = 0; i + 1 < pdf_array_len(names); i += 2)
		{
			pdf_obj *key = pdf_array_get(names, i);
			pdf_obj *val = pdf_array_get(names, i + 1);
			if (pdf_is_string(key))
			{
				key = pdf_to_utf8_name(ctx, key);
				pdf_dict_put(dict, key, val);
				pdf_drop_obj(key);
			}
			else if (pdf_is_name(key))
			{
				pdf_dict_put(dict, key, val);
			}
		}
	}
}
Esempio n. 4
0
static pdf_obj *
resolve_dest_rec(pdf_document *xref, pdf_obj *dest, int depth)
{
	if (depth > 10) /* Arbitrary to avoid infinite recursion */
		return NULL;

	if (pdf_is_name(dest) || pdf_is_string(dest))
	{
		dest = pdf_lookup_dest(xref, dest);
		return resolve_dest_rec(xref, dest, depth+1);
	}

	else if (pdf_is_array(dest))
	{
		return dest;
	}

	else if (pdf_is_dict(dest))
	{
		dest = pdf_dict_gets(dest, "D");
		return resolve_dest_rec(xref, dest, depth+1);
	}

	else if (pdf_is_indirect(dest))
		return dest;

	return NULL;
}
Esempio n. 5
0
pdf_obj *
pdf_lookup_dest(pdf_document *xref, pdf_obj *needle)
{
	fz_context *ctx = xref->ctx;

	pdf_obj *root = pdf_dict_gets(xref->trailer, "Root");
	pdf_obj *dests = pdf_dict_gets(root, "Dests");
	pdf_obj *names = pdf_dict_gets(root, "Names");
	pdf_obj *dest = NULL;

	/* PDF 1.1 has destinations in a dictionary */
	if (dests)
	{
		if (pdf_is_name(needle))
			return pdf_dict_get(dests, needle);
		else
			return pdf_dict_gets(dests, pdf_to_str_buf(needle));
	}

	/* PDF 1.2 has destinations in a name tree */
	if (names && !dest)
	{
		pdf_obj *tree = pdf_dict_gets(names, "Dests");
		return pdf_lookup_name_imp(ctx, tree, needle);
	}

	return NULL;
}
Esempio n. 6
0
/*
 * Create a filter given a name and param dictionary.
 */
static fz_stream *
build_filter(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *f, pdf_obj *p, int num, int gen, fz_compression_params *params)
{
	fz_compression_params local_params;

	if (params == NULL)
		params = &local_params;

	build_compression_params(ctx, f, p, params);

	/* If we were using params we were passed in, and we successfully
	 * recognised the image type, we can use the existing filter and
	 * shortstop here. */
	if (params != &local_params && params->type != FZ_IMAGE_RAW)
		return chain;

	if (params->type != FZ_IMAGE_RAW)
		return fz_open_image_decomp_stream(ctx, chain, params, NULL);

	if (pdf_name_eq(ctx, f, PDF_NAME_ASCIIHexDecode) || pdf_name_eq(ctx, f, PDF_NAME_AHx))
		return fz_open_ahxd(ctx, chain);

	else if (pdf_name_eq(ctx, f, PDF_NAME_ASCII85Decode) || pdf_name_eq(ctx, f, PDF_NAME_A85))
		return fz_open_a85d(ctx, chain);

	else if (pdf_name_eq(ctx, f, PDF_NAME_JBIG2Decode))
	{
		fz_jbig2_globals *globals = NULL;
		pdf_obj *obj = pdf_dict_get(ctx, p, PDF_NAME_JBIG2Globals);
		if (pdf_is_indirect(ctx, obj))
			globals = pdf_load_jbig2_globals(ctx, doc, obj);
		/* fz_open_jbig2d takes possession of globals */
		return fz_open_jbig2d(ctx, chain, globals);
	}

	else if (pdf_name_eq(ctx, f, PDF_NAME_JPXDecode))
		return chain; /* JPX decoding is special cased in the image loading code */

	else if (pdf_name_eq(ctx, f, PDF_NAME_Crypt))
	{
		pdf_obj *name;

		if (!doc->crypt)
		{
			fz_warn(ctx, "crypt filter in unencrypted document");
			return chain;
		}

		name = pdf_dict_get(ctx, p, PDF_NAME_Name);
		if (pdf_is_name(ctx, name))
			return pdf_open_crypt_with_filter(ctx, chain, doc->crypt, name, num, gen);

		return chain;
	}

	fz_warn(ctx, "unknown filter name (%s)", pdf_to_name(ctx, f));
	return chain;
}
Esempio n. 7
0
static void
parse_dict (fz_context *ctx, pdf_obj *dict, pdfout_data *hash)
{
  /* Check Style key. */
  
  pdf_obj *style = pdf_dict_get (ctx, dict, PDF_NAME_S);
  if (style)
    {
      const char *value;
      if (pdf_is_name (ctx, style) == false)
	pdfout_throw (ctx, "style key 'S' not a name object");
      /* pdf_to_name returns the empty string, not NULL, on all errors,
	 so the strcmps are allowed.  */
      if (pdf_name_eq (ctx, style, PDF_NAME_D))
	value = "arabic";
      else if (pdf_name_eq (ctx, style, PDF_NAME_R))
	value = "Roman";
      else if (pdf_name_eq (ctx, style, PDF_NAME_A))
	value = "Letters";
      else
	{
	  /* FIXME once PDF_NAMES for "r" and "a" available.  */
	  const char *string = pdf_to_name (ctx, style);
	  if (streq(string, "r"))
	    value = "roman";
	  else if (streq (string, "a"))
	    value = "letters";
	  else
	    pdfout_throw (ctx, "unknown numbering style '%s'", string);
	}

      int len = strlen (value);
      pdfout_data_hash_push_key_value (ctx, hash, "style", value, len);
    }
  
  pdf_obj *first = pdf_dict_gets (ctx, dict, "St");
  if (first)
    {
      int value  = pdf_to_int (ctx, first);
      if (value < 1)
	pdfout_throw (ctx, "value %d of 'St' is < 1 or not an int", value);

      push_int_key (ctx, hash, "first", value);
    }
      
  pdf_obj *prefix = pdf_dict_get (ctx, dict, PDF_NAME_P);
  if (prefix)
    {
      if (pdf_is_string (ctx, prefix) == false)
	pdfout_throw (ctx, "value of 'P' not a string");

      int utf8_len;
      char *utf8 = pdfout_str_obj_to_utf8 (ctx, prefix, &utf8_len);
      pdfout_data_hash_push_key_value (ctx, hash, "prefix", utf8, utf8_len);
      free (utf8);
    }
}  
Esempio n. 8
0
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)
Esempio n. 9
0
char *
pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_obj *dest)
{
	pdf_obj *filename = NULL;
	const char *path;
	char *uri;
	char frag[256];

	if (pdf_is_string(ctx, file_spec))
		filename = file_spec;

	if (pdf_is_dict(ctx, file_spec)) {
#ifdef _WIN32
		filename = pdf_dict_get(ctx, file_spec, PDF_NAME(DOS));
#else
		filename = pdf_dict_get(ctx, file_spec, PDF_NAME(Unix));
#endif
		if (!filename)
			filename = pdf_dict_geta(ctx, file_spec, PDF_NAME(UF), PDF_NAME(F));
	}

	if (!pdf_is_string(ctx, filename))
	{
		fz_warn(ctx, "cannot parse file specification");
		return NULL;
	}

	if (pdf_is_array(ctx, dest))
		fz_snprintf(frag, sizeof frag, "#page=%d", pdf_array_get_int(ctx, dest, 0) + 1);
	else if (pdf_is_name(ctx, dest))
		fz_snprintf(frag, sizeof frag, "#%s", pdf_to_name(ctx, dest));
	else if (pdf_is_string(ctx, dest))
		fz_snprintf(frag, sizeof frag, "#%s", pdf_to_str_buf(ctx, dest));
	else
		frag[0] = 0;

	path = pdf_to_text_string(ctx, filename);
	uri = NULL;
#ifdef _WIN32
	if (!pdf_name_eq(ctx, pdf_dict_get(ctx, file_spec, PDF_NAME(FS)), PDF_NAME(URL)))
	{
		/* Fix up the drive letter (change "/C/Documents/Foo" to "C:/Documents/Foo") */
		if (path[0] == '/' && (('A' <= path[1] && path[1] <= 'Z') || ('a' <= path[1] && path[1] <= 'z')) && path[2] == '/')
			uri = fz_asprintf(ctx, "file://%c:%s%s", path[1], path+2, frag);
	}
#endif
	if (!uri)
		uri = fz_asprintf(ctx, "file://%s%s", path, frag);

	return uri;
}
Esempio n. 10
0
static int
pdf_extgstate_uses_blending(pdf_document *doc, pdf_obj *dict)
{
	pdf_obj *obj = pdf_dict_gets(dict, "BM");
	/* SumatraPDF: properly support /BM arrays */
	if (pdf_is_array(obj))
	{
		int k;
		for (k = 0; k < pdf_array_len(obj); k++)
		{
			char *bm = pdf_to_name(pdf_array_get(obj, k));
			if (!strcmp(bm, "Normal") || fz_lookup_blendmode(bm) > 0)
				break;
		}
		obj = pdf_array_get(obj, k);
	}
	if (pdf_is_name(obj) && strcmp(pdf_to_name(obj), "Normal"))
		return 1;
	/* SumatraPDF: support transfer functions */
	obj = pdf_dict_getsa(dict, "TR", "TR2");
	if (obj && !pdf_is_name(obj))
		return 1;
	return 0;
}
Esempio n. 11
0
/* Check if an entry has a cached stream and return whether it is directly
 * reusable. A buffer is directly reusable only if the stream is
 * uncompressed, or if it is compressed purely a compression method we can
 * return details of in fz_compression_params.
 *
 * If the stream is reusable return 1, and set params as required, otherwise
 * return 0. */
static int
can_reuse_buffer(fz_context *ctx, pdf_xref_entry *entry, fz_compression_params *params)
{
	pdf_obj *f;
	pdf_obj *p;

	if (!entry || !entry->obj || !entry->stm_buf)
		return 0;

	if (params)
		params->type = FZ_IMAGE_RAW;

	f = pdf_dict_geta(ctx, entry->obj, PDF_NAME_Filter, PDF_NAME_F);
	/* If there are no filters, it's uncompressed, and we can use it */
	if (!f)
		return 1;

	p = pdf_dict_geta(ctx, entry->obj, PDF_NAME_DecodeParms, PDF_NAME_DP);
	if (pdf_is_array(ctx, f))
	{
		int len = pdf_array_len(ctx, f);

		/* Empty array of filters. It's uncompressed. We can cope. */
		if (len == 0)
			return 1;
		/* 1 filter is the most we can hope to cope with - if more,*/
		if (len != 1)
			return 0;
		p = pdf_array_get(ctx, p, 0);
	}
	if (pdf_is_null(ctx, f))
		return 1; /* Null filter is uncompressed */
	if (!pdf_is_name(ctx, f))
		return 0;

	/* There are filters, so unless we have the option of shortstopping,
	 * we can't use the existing buffer. */
	if (!params)
		return 0;

	build_compression_params(ctx, f, p, params);

	return (params->type == FZ_IMAGE_RAW) ? 0 : 1;

}
Esempio n. 12
0
File: data.c Progetto: amba/pdfout
pdfout_data *
pdfout_data_scalar_from_pdf (fz_context *ctx, pdf_obj *obj)
{
  const char *s;
  if (pdf_is_null (ctx, obj))
    return pdfout_data_scalar_new (ctx, "null", strlen ("null"));
  else if (pdf_is_bool (ctx, obj))
    {
      if (pdf_to_bool (ctx, obj))
	s = "true";
      else
	s = "false";
      return pdfout_data_scalar_new (ctx, s, strlen (s));
    }
  else if (pdf_is_name (ctx, obj))
    {
      s = pdf_to_name (ctx, obj);
      return pdfout_data_scalar_new (ctx, s, strlen (s));
    }
  else if (pdf_is_string (ctx, obj))
    {
      int len;
      char *str = pdfout_str_obj_to_utf8 (ctx, obj, &len);
      pdfout_data *result =  pdfout_data_scalar_new (ctx, str, len);
      free (str);
      return result;
    }
  else if (pdf_is_int (ctx, obj))
    {
      int n = pdf_to_int (ctx, obj);
      char buf[200];
      int len = pdfout_snprintf (ctx, buf, "%d", n);
      return pdfout_data_scalar_new (ctx, buf, len);
    }
  else if (pdf_is_real (ctx, obj))
    {
      float f = pdf_to_real (ctx, obj);
      char buf[200];
      int len = pdfout_snprintf (ctx, buf, "%g", f);
      return pdfout_data_scalar_new (ctx, buf, len);
    }
  else
    abort();
  
}
Esempio n. 13
0
/*
 * Construct a filter to decode a stream, constraining
 * to stream length and decrypting.
 */
static fz_stream *
pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, int offset, pdf_image_params *imparams)
{
	pdf_obj *filters;
	pdf_obj *params;

	filters = pdf_dict_getsa(stmobj, "Filter", "F");
	params = pdf_dict_getsa(stmobj, "DecodeParms", "DP");

	chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen, offset);

	if (pdf_is_name(filters))
		chain = build_filter(chain, xref, filters, params, num, gen, imparams);
	else if (pdf_array_len(filters) > 0)
		chain = build_filter_chain(chain, xref, filters, params, num, gen, imparams);

	return chain;
}
Esempio n. 14
0
/*
 * Construct a filter to decode a stream, without
 * constraining to stream length, and without decryption.
 */
fz_stream *
pdf_open_inline_stream(pdf_document *xref, pdf_obj *stmobj, int length, fz_stream *chain, pdf_image_params *imparams)
{
    pdf_obj *filters;
    pdf_obj *params;

    filters = pdf_dict_getsa(stmobj, "Filter", "F");
    params = pdf_dict_getsa(stmobj, "DecodeParms", "DP");

    /* don't close chain when we close this filter */
    fz_keep_stream(chain);

    if (pdf_is_name(filters))
        return build_filter(chain, xref, filters, params, 0, 0, imparams);
    if (pdf_array_len(filters) > 0)
        return build_filter_chain(chain, xref, filters, params, 0, 0, imparams);

    return fz_open_null(chain, length);
}
Esempio n. 15
0
/*
 * Construct a filter to decode a stream, without
 * constraining to stream length, and without decryption.
 */
fz_stream *
pdf_open_inline_stream(fz_context *ctx, pdf_document *doc, pdf_obj *stmobj, int length, fz_stream *chain, fz_compression_params *imparams)
{
	pdf_obj *filters;
	pdf_obj *params;

	filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F);
	params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP);

	/* don't close chain when we close this filter */
	fz_keep_stream(ctx, chain);

	if (pdf_is_name(ctx, filters))
		return build_filter(ctx, chain, doc, filters, params, 0, 0, imparams);
	if (pdf_array_len(ctx, filters) > 0)
		return build_filter_chain(ctx, chain, doc, filters, params, 0, 0, imparams);

	if (imparams)
		imparams->type = FZ_IMAGE_RAW;
	return fz_open_null(ctx, chain, length, fz_tell(ctx, chain));
}
Esempio n. 16
0
/*
 * Construct a filter to decode a stream, constraining
 * to stream length and decrypting.
 */
static fz_stream *
pdf_open_filter(fz_context *ctx, pdf_document *doc, fz_stream *chain, pdf_obj *stmobj, int num, fz_off_t offset, fz_compression_params *imparams)
{
	pdf_obj *filters;
	pdf_obj *params;
	int orig_num, orig_gen;

	filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F);
	params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP);

	chain = pdf_open_raw_filter(ctx, chain, doc, stmobj, num, &orig_num, &orig_gen, offset);

	fz_var(chain);

	fz_try(ctx)
	{
		if (pdf_is_name(ctx, filters))
		{
			fz_stream *chain2 = chain;
			chain = NULL;
			chain = build_filter(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams);
		}
		else if (pdf_array_len(ctx, filters) > 0)
		{
			fz_stream *chain2 = chain;
			chain = NULL;
			chain = build_filter_chain(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams);
		}
	}
	fz_catch(ctx)
	{
		fz_drop_stream(ctx, chain);
		fz_rethrow(ctx);
	}

	return chain;
}
Esempio n. 17
0
pdf_font_desc *
pdf_load_type3_font(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict)
{
	char buf[256];
	char *estrings[256];
	pdf_font_desc *fontdesc = NULL;
	pdf_obj *encoding;
	pdf_obj *widths;
	pdf_obj *charprocs;
	pdf_obj *obj;
	int first, last;
	int i, k, n;
	fz_rect bbox;
	fz_matrix matrix;
	fz_font *font;

	fz_var(fontdesc);

	/* Make a new type3 font entry in the document */
	if (doc->num_type3_fonts == doc->max_type3_fonts)
	{
		int new_max = doc->max_type3_fonts * 2;

		if (new_max == 0)
			new_max = 4;
		doc->type3_fonts = fz_resize_array(ctx, doc->type3_fonts, new_max, sizeof(*doc->type3_fonts));
		doc->max_type3_fonts = new_max;
	}

	fz_try(ctx)
	{
		obj = pdf_dict_get(ctx, dict, PDF_NAME_Name);
		if (pdf_is_name(ctx, obj))
			fz_strlcpy(buf, pdf_to_name(ctx, obj), sizeof buf);
		else
			fz_strlcpy(buf, "Unnamed-T3", sizeof buf);

		fontdesc = pdf_new_font_desc(ctx);

		obj = pdf_dict_get(ctx, dict, PDF_NAME_FontMatrix);
		pdf_to_matrix(ctx, obj, &matrix);

		obj = pdf_dict_get(ctx, dict, PDF_NAME_FontBBox);
		fz_transform_rect(pdf_to_rect(ctx, obj, &bbox), &matrix);

		font = fz_new_type3_font(ctx, buf, &matrix);
		fontdesc->font = font;
		fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float));

		fz_set_font_bbox(ctx, font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);

		/* Encoding */

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

		encoding = pdf_dict_get(ctx, dict, PDF_NAME_Encoding);
		if (!encoding)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing Encoding");
		}

		if (pdf_is_name(ctx, encoding))
			pdf_load_encoding(estrings, pdf_to_name(ctx, encoding));

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

			base = pdf_dict_get(ctx, encoding, PDF_NAME_BaseEncoding);
			if (pdf_is_name(ctx, base))
				pdf_load_encoding(estrings, pdf_to_name(ctx, base));

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

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

		pdf_load_to_unicode(ctx, doc, fontdesc, estrings, NULL, pdf_dict_get(ctx, dict, PDF_NAME_ToUnicode));

		/* Widths */

		pdf_set_default_hmtx(ctx, fontdesc, 0);

		first = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_FirstChar));
		last = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_LastChar));

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

		widths = pdf_dict_get(ctx, dict, PDF_NAME_Widths);
		if (!widths)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing Widths");
		}

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

		pdf_end_hmtx(ctx, fontdesc);

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

		font->t3freeres = pdf_t3_free_resources;
		font->t3resources = pdf_dict_get(ctx, dict, PDF_NAME_Resources);
		if (!font->t3resources)
			font->t3resources = rdb;
		if (font->t3resources)
			pdf_keep_obj(ctx, font->t3resources);
		if (!font->t3resources)
			fz_warn(ctx, "no resource dictionary for type 3 font!");

		font->t3doc = doc;
		font->t3run = pdf_run_glyph_func;

		/* CharProcs */

		charprocs = pdf_dict_get(ctx, dict, PDF_NAME_CharProcs);
		if (!charprocs)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing CharProcs");
		}

		for (i = 0; i < 256; i++)
		{
			if (estrings[i])
			{
				obj = pdf_dict_gets(ctx, charprocs, estrings[i]);
				if (pdf_is_stream(ctx, obj))
				{
					font->t3procs[i] = pdf_load_stream(ctx, obj);
					fz_trim_buffer(ctx, font->t3procs[i]);
					fontdesc->size += fz_buffer_storage(ctx, font->t3procs[i], NULL);
					fontdesc->size += 0; // TODO: display list size calculation
				}
			}
		}
	}
	fz_catch(ctx)
	{
		pdf_drop_font(ctx, fontdesc);
		fz_rethrow(ctx);
	}

	doc->type3_fonts[doc->num_type3_fonts++] = fz_keep_font(ctx, font);

	return fontdesc;
}
Esempio n. 18
0
/*
 * Load CMap stream in PDF file
 */
pdf_cmap *
pdf_load_embedded_cmap(pdf_document *doc, pdf_obj *stmobj)
{
	fz_stream *file = NULL;
	pdf_cmap *cmap = NULL;
	pdf_cmap *usecmap;
	pdf_obj *wmode;
	pdf_obj *obj = NULL;
	fz_context *ctx = doc->ctx;
	int phase = 0;

	fz_var(phase);
	fz_var(obj);
	fz_var(file);
	fz_var(cmap);

	if (pdf_obj_marked(stmobj))
		fz_throw(ctx, FZ_ERROR_GENERIC, "Recursion in embedded cmap");

	if ((cmap = pdf_find_item(ctx, pdf_free_cmap_imp, stmobj)) != NULL)
	{
		return cmap;
	}

	fz_try(ctx)
	{
		file = pdf_open_stream(doc, pdf_to_num(stmobj), pdf_to_gen(stmobj));
		phase = 1;
		cmap = pdf_load_cmap(ctx, file);
		phase = 2;
		fz_close(file);
		file = NULL;

		wmode = pdf_dict_gets(stmobj, "WMode");
		if (pdf_is_int(wmode))
			pdf_set_cmap_wmode(ctx, cmap, pdf_to_int(wmode));
		obj = pdf_dict_gets(stmobj, "UseCMap");
		if (pdf_is_name(obj))
		{
			usecmap = pdf_load_system_cmap(ctx, pdf_to_name(obj));
			pdf_set_usecmap(ctx, cmap, usecmap);
			pdf_drop_cmap(ctx, usecmap);
		}
		else if (pdf_is_indirect(obj))
		{
			phase = 3;
			pdf_mark_obj(obj);
			usecmap = pdf_load_embedded_cmap(doc, obj);
			pdf_unmark_obj(obj);
			phase = 4;
			pdf_set_usecmap(ctx, cmap, usecmap);
			pdf_drop_cmap(ctx, usecmap);
		}

		pdf_store_item(ctx, stmobj, cmap, pdf_cmap_size(ctx, cmap));
	}
	fz_catch(ctx)
	{
		if (file)
			fz_close(file);
		if (cmap)
			pdf_drop_cmap(ctx, cmap);
		if (phase < 1)
			fz_rethrow_message(ctx, "cannot open cmap stream (%d %d R)", pdf_to_num(stmobj), pdf_to_gen(stmobj));
		else if (phase < 2)
			fz_rethrow_message(ctx, "cannot parse cmap stream (%d %d R)", pdf_to_num(stmobj), pdf_to_gen(stmobj));
		else if (phase < 3)
			fz_rethrow_message(ctx, "cannot load system usecmap '%s'", pdf_to_name(obj));
		else
		{
			if (phase == 3)
				pdf_unmark_obj(obj);
			fz_rethrow_message(ctx, "cannot load embedded usecmap (%d %d R)", pdf_to_num(obj), pdf_to_gen(obj));
		}
	}

	return cmap;
}
Esempio n. 19
0
static void
pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_obj *dict)
{
	pdf_obj *obj;

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LW);
	if (pdf_is_number(ctx, obj) && proc->op_w)
		proc->op_w(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LC);
	if (pdf_is_int(ctx, obj) && proc->op_J)
		proc->op_J(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LJ);
	if (pdf_is_int(ctx, obj) && proc->op_j)
		proc->op_j(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_ML);
	if (pdf_is_number(ctx, obj) && proc->op_M)
		proc->op_M(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_D);
	if (pdf_is_array(ctx, obj) && proc->op_d)
	{
		pdf_obj *dash_array = pdf_array_get(ctx, obj, 0);
		pdf_obj *dash_phase = pdf_array_get(ctx, obj, 1);
		proc->op_d(ctx, proc, dash_array, pdf_to_real(ctx, dash_phase));
	}

	obj = pdf_dict_get(ctx, dict, PDF_NAME_RI);
	if (pdf_is_name(ctx, obj) && proc->op_ri)
		proc->op_ri(ctx, proc, pdf_to_name(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FL);
	if (pdf_is_number(ctx, obj) && proc->op_i)
		proc->op_i(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_Font);
	if (pdf_is_array(ctx, obj) && proc->op_Tf)
	{
		pdf_obj *font_ref = pdf_array_get(ctx, obj, 0);
		pdf_obj *font_size = pdf_array_get(ctx, obj, 1);
		pdf_font_desc *font = load_font_or_hail_mary(ctx, csi->doc, csi->rdb, font_ref, 0, csi->cookie);
		fz_try(ctx)
			proc->op_Tf(ctx, proc, "ExtGState", font, pdf_to_real(ctx, font_size));
		fz_always(ctx)
			pdf_drop_font(ctx, font);
		fz_catch(ctx)
			fz_rethrow(ctx);
	}

	/* transfer functions */

	obj = pdf_dict_get(ctx, dict, PDF_NAME_TR2);
	if (pdf_is_name(ctx, obj))
		if (!pdf_name_eq(ctx, obj, PDF_NAME_Identity) && !pdf_name_eq(ctx, obj, PDF_NAME_Default))
			fz_warn(ctx, "ignoring transfer function");
	if (!obj) /* TR is ignored in the presence of TR2 */
	{
		pdf_obj *tr = pdf_dict_get(ctx, dict, PDF_NAME_TR);
		if (pdf_is_name(ctx, tr))
			if (!pdf_name_eq(ctx, tr, PDF_NAME_Identity))
				fz_warn(ctx, "ignoring transfer function");
	}

	/* transparency state */

	obj = pdf_dict_get(ctx, dict, PDF_NAME_CA);
	if (pdf_is_number(ctx, obj) && proc->op_gs_CA)
		proc->op_gs_CA(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_ca);
	if (pdf_is_number(ctx, obj) && proc->op_gs_ca)
		proc->op_gs_ca(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_BM);
	if (pdf_is_array(ctx, obj))
		obj = pdf_array_get(ctx, obj, 0);
	if (pdf_is_name(ctx, obj) && proc->op_gs_BM)
		proc->op_gs_BM(ctx, proc, pdf_to_name(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_SMask);
	if (proc->op_gs_SMask)
	{
		if (pdf_is_dict(ctx, obj))
		{
			pdf_xobject *xobj;
			pdf_obj *group, *s, *bc, *tr;
			float softmask_bc[FZ_MAX_COLORS];
			fz_colorspace *colorspace;
			int colorspace_n = 1;
			int k, luminosity;

			fz_var(xobj);

			group = pdf_dict_get(ctx, obj, PDF_NAME_G);
			if (!group)
				fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load softmask xobject (%d 0 R)", pdf_to_num(ctx, obj));
			xobj = pdf_load_xobject(ctx, csi->doc, group);

			fz_try(ctx)
			{
				colorspace = pdf_xobject_colorspace(ctx, xobj);
				if (colorspace)
				{
					colorspace_n = fz_colorspace_n(ctx, colorspace);
					fz_drop_colorspace(ctx, colorspace);
				}

				/* Default background color is black. */
				for (k = 0; k < colorspace_n; k++)
					softmask_bc[k] = 0;
				/* Which in CMYK means not all zeros! This should really be
				 * a test for subtractive color spaces, but this will have
				 * to do for now. */
				if (colorspace == fz_device_cmyk(ctx))
					softmask_bc[3] = 1.0;

				bc = pdf_dict_get(ctx, obj, PDF_NAME_BC);
				if (pdf_is_array(ctx, bc))
				{
					for (k = 0; k < colorspace_n; k++)
						softmask_bc[k] = pdf_to_real(ctx, pdf_array_get(ctx, bc, k));
				}

				s = pdf_dict_get(ctx, obj, PDF_NAME_S);
				if (pdf_name_eq(ctx, s, PDF_NAME_Luminosity))
					luminosity = 1;
				else
					luminosity = 0;

				tr = pdf_dict_get(ctx, obj, PDF_NAME_TR);
				if (tr && !pdf_name_eq(ctx, tr, PDF_NAME_Identity))
					fz_warn(ctx, "ignoring transfer function");

				proc->op_gs_SMask(ctx, proc, xobj, csi->rdb, softmask_bc, luminosity);
			}
			fz_always(ctx)
			{
				pdf_drop_xobject(ctx, xobj);
			}
			fz_catch(ctx)
			{
				fz_rethrow(ctx);
			}
		}
		else if (pdf_is_name(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME_None))
		{
			proc->op_gs_SMask(ctx, proc, NULL, NULL, NULL, 0);
		}
	}
Esempio n. 20
0
static pdf_font_desc *
load_cid_font(pdf_document *xref, pdf_obj *dict, pdf_obj *encoding, pdf_obj *to_unicode)
{
	pdf_obj *widths;
	pdf_obj *descriptor;
	pdf_font_desc *fontdesc = NULL;
	FT_Face face;
	int kind;
	char collection[256];
	char *basefont;
	int i, k, fterr;
	pdf_obj *obj;
	int dw;
	fz_context *ctx = xref->ctx;

	fz_var(fontdesc);

	fz_try(ctx)
	{
		/* Get font name and CID collection */

		basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont"));

		{
			pdf_obj *cidinfo;
			char tmpstr[64];
			int tmplen;

			cidinfo = pdf_dict_gets(dict, "CIDSystemInfo");
			if (!cidinfo)
				fz_throw(ctx, "cid font is missing info");

			obj = pdf_dict_gets(cidinfo, "Registry");
			tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(obj));
			memcpy(tmpstr, pdf_to_str_buf(obj), tmplen);
			tmpstr[tmplen] = '\0';
			fz_strlcpy(collection, tmpstr, sizeof collection);

			fz_strlcat(collection, "-", sizeof collection);

			obj = pdf_dict_gets(cidinfo, "Ordering");
			tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(obj));
			memcpy(tmpstr, pdf_to_str_buf(obj), tmplen);
			tmpstr[tmplen] = '\0';
			fz_strlcat(collection, tmpstr, sizeof collection);
		}

		/* Load font file */

		fontdesc = pdf_new_font_desc(ctx);

		descriptor = pdf_dict_gets(dict, "FontDescriptor");
		if (!descriptor)
			fz_throw(ctx, "syntaxerror: missing font descriptor");
		pdf_load_font_descriptor(fontdesc, xref, descriptor, collection, basefont);

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

		/* Encoding */

		if (pdf_is_name(encoding))
		{
			if (!strcmp(pdf_to_name(encoding), "Identity-H"))
				fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 2);
			else if (!strcmp(pdf_to_name(encoding), "Identity-V"))
				fontdesc->encoding = pdf_new_identity_cmap(ctx, 1, 2);
			else
				fontdesc->encoding = pdf_load_system_cmap(ctx, pdf_to_name(encoding));
		}
		else if (pdf_is_indirect(encoding))
		{
			fontdesc->encoding = pdf_load_embedded_cmap(xref, encoding);
		}
		else
		{
			fz_throw(ctx, "syntaxerror: font missing encoding");
		}
		fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);

		pdf_set_font_wmode(ctx, fontdesc, pdf_cmap_wmode(ctx, fontdesc->encoding));

		if (kind == TRUETYPE)
		{
			pdf_obj *cidtogidmap;

			cidtogidmap = pdf_dict_gets(dict, "CIDToGIDMap");
			if (pdf_is_indirect(cidtogidmap))
			{
				fz_buffer *buf;

				buf = pdf_load_stream(xref, pdf_to_num(cidtogidmap), pdf_to_gen(cidtogidmap));

				fontdesc->cid_to_gid_len = (buf->len) / 2;
				fontdesc->cid_to_gid = fz_malloc_array(ctx, fontdesc->cid_to_gid_len, sizeof(unsigned short));
				fontdesc->size += fontdesc->cid_to_gid_len * sizeof(unsigned short);
				for (i = 0; i < fontdesc->cid_to_gid_len; i++)
					fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1];

				fz_drop_buffer(ctx, 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->ft_substitute)
			{
				fterr = FT_Select_Charmap(face, ft_encoding_unicode);
				if (fterr)
				{
					fz_throw(ctx, "fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr));
				}

				if (!strcmp(collection, "Adobe-CNS1"))
					fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2");
				else if (!strcmp(collection, "Adobe-GB1"))
					fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
				else if (!strcmp(collection, "Adobe-Japan1"))
					fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2");
				else if (!strcmp(collection, "Adobe-Japan2"))
					fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan2-UCS2");
				else if (!strcmp(collection, "Adobe-Korea1"))
					fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2");
			}
		}

		pdf_load_to_unicode(xref, fontdesc, NULL, collection, to_unicode);

		/* Horizontal */

		dw = 1000;
		obj = pdf_dict_gets(dict, "DW");
		if (obj)
			dw = pdf_to_int(obj);
		pdf_set_default_hmtx(ctx, fontdesc, dw);

		widths = pdf_dict_gets(dict, "W");
		if (widths)
		{
			int c0, c1, w, n, m;

			n = pdf_array_len(widths);
			for (i = 0; i < n; )
			{
				c0 = pdf_to_int(pdf_array_get(widths, i));
				obj = pdf_array_get(widths, i + 1);
				if (pdf_is_array(obj))
				{
					m = pdf_array_len(obj);
					for (k = 0; k < m; k++)
					{
						w = pdf_to_int(pdf_array_get(obj, k));
						pdf_add_hmtx(ctx, fontdesc, c0 + k, c0 + k, w);
					}
					i += 2;
				}
				else
				{
					c1 = pdf_to_int(obj);
					w = pdf_to_int(pdf_array_get(widths, i + 2));
					pdf_add_hmtx(ctx, fontdesc, c0, c1, w);
					i += 3;
				}
			}
		}

		pdf_end_hmtx(ctx, fontdesc);

		/* Vertical */

		if (pdf_cmap_wmode(ctx, fontdesc->encoding) == 1)
		{
			int dw2y = 880;
			int dw2w = -1000;

			obj = pdf_dict_gets(dict, "DW2");
			if (obj)
			{
				dw2y = pdf_to_int(pdf_array_get(obj, 0));
				dw2w = pdf_to_int(pdf_array_get(obj, 1));
			}

			pdf_set_default_vmtx(ctx, fontdesc, dw2y, dw2w);

			widths = pdf_dict_gets(dict, "W2");
			if (widths)
			{
				int c0, c1, w, x, y, n;

				n = pdf_array_len(widths);
				for (i = 0; i < n; )
				{
					c0 = pdf_to_int(pdf_array_get(widths, i));
					obj = pdf_array_get(widths, i + 1);
					if (pdf_is_array(obj))
					{
						int m = pdf_array_len(obj);
						for (k = 0; k * 3 < m; k ++)
						{
							w = pdf_to_int(pdf_array_get(obj, k * 3 + 0));
							x = pdf_to_int(pdf_array_get(obj, k * 3 + 1));
							y = pdf_to_int(pdf_array_get(obj, k * 3 + 2));
							pdf_add_vmtx(ctx, fontdesc, c0 + k, c0 + k, x, y, w);
						}
						i += 2;
					}
					else
					{
						c1 = pdf_to_int(obj);
						w = pdf_to_int(pdf_array_get(widths, i + 2));
						x = pdf_to_int(pdf_array_get(widths, i + 3));
						y = pdf_to_int(pdf_array_get(widths, i + 4));
						pdf_add_vmtx(ctx, fontdesc, c0, c1, x, y, w);
						i += 5;
					}
				}
			}

			pdf_end_vmtx(ctx, fontdesc);
		}
	}
	fz_catch(ctx)
	{
		pdf_drop_font(ctx, fontdesc);
		fz_throw(ctx, "cannot load cid font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}

	return fontdesc;
}
Esempio n. 21
0
static pdf_image *
pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_stream *stm = NULL;
	pdf_image *image = NULL;
	pdf_obj *obj, *res;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_image *mask = NULL; /* explicit mask/soft mask image */
	int usecolorkey;

	int i;
	fz_context *ctx = xref->ctx;

	fz_var(stm);
	fz_var(mask);

	image = fz_malloc_struct(ctx, pdf_image);

	fz_try(ctx)
	{
		/* special case for JPEG2000 images */
		if (pdf_is_jpx_image(ctx, dict))
		{
			pdf_load_jpx(xref, dict, image, forcemask);

			if (forcemask)
			{
				fz_pixmap *mask_pixmap;
				if (image->n != 2)
					fz_throw(ctx, "soft mask must be grayscale");
				mask_pixmap = fz_alpha_from_gray(ctx, image->tile, 1);
				fz_drop_pixmap(ctx, image->tile);
				image->tile = mask_pixmap;
			}
			break; /* Out of fz_try */
		}

		w = pdf_to_int(pdf_dict_getsa(dict, "Width", "W"));
		h = pdf_to_int(pdf_dict_getsa(dict, "Height", "H"));
		bpc = pdf_to_int(pdf_dict_getsa(dict, "BitsPerComponent", "BPC"));
		if (bpc == 0)
			bpc = 8;
		imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM"));
		interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I"));

		indexed = 0;
		usecolorkey = 0;
		mask = NULL;

		if (imagemask)
			bpc = 1;

		if (w <= 0)
			fz_throw(ctx, "image width is zero (or less)");
		if (h <= 0)
			fz_throw(ctx, "image height is zero (or less)");
		if (bpc <= 0)
			fz_throw(ctx, "image depth is zero (or less)");
		if (bpc > 16)
			fz_throw(ctx, "image depth is too large: %d", bpc);
		if (w > (1 << 16))
			fz_throw(ctx, "image is too wide");
		if (h > (1 << 16))
			fz_throw(ctx, "image is too high");

		obj = pdf_dict_getsa(dict, "ColorSpace", "CS");
		if (obj && !imagemask && !forcemask)
		{
			/* colorspace resource lookup is only done for inline images */
			if (pdf_is_name(obj))
			{
				res = pdf_dict_get(pdf_dict_gets(rdb, "ColorSpace"), obj);
				if (res)
					obj = res;
			}

			image->base.colorspace = pdf_load_colorspace(xref, obj);

			if (!strcmp(image->base.colorspace->name, "Indexed"))
				indexed = 1;

			n = image->base.colorspace->n;
		}
		else
		{
			n = 1;
		}

		obj = pdf_dict_getsa(dict, "Decode", "D");
		if (obj)
		{
			for (i = 0; i < n * 2; i++)
				image->decode[i] = pdf_to_real(pdf_array_get(obj, i));
		}
		else
		{
			float maxval = indexed ? (1 << bpc) - 1 : 1;
			for (i = 0; i < n * 2; i++)
				image->decode[i] = i & 1 ? maxval : 0;
		}

		obj = pdf_dict_getsa(dict, "SMask", "Mask");
		if (pdf_is_dict(obj))
		{
			/* Not allowed for inline images or soft masks */
			if (cstm)
				fz_warn(ctx, "Ignoring invalid inline image soft mask");
			else if (forcemask)
				fz_warn(ctx, "Ignoring recursive image soft mask");
			else
				mask = (fz_image *)pdf_load_image_imp(xref, rdb, obj, NULL, 1);
		}
		else if (pdf_is_array(obj))
		{
			usecolorkey = 1;
			for (i = 0; i < n * 2; i++)
			{
				if (!pdf_is_int(pdf_array_get(obj, i)))
				{
					fz_warn(ctx, "invalid value in color key mask");
					usecolorkey = 0;
				}
				image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
			}
		}

		/* Now, do we load a ref, or do we load the actual thing? */
		FZ_INIT_STORABLE(&image->base, 1, pdf_free_image);
		image->base.get_pixmap = pdf_image_get_pixmap;
		image->base.w = w;
		image->base.h = h;
		image->base.bpc = bpc;
		image->n = n;
		image->interpolate = interpolate;
		image->imagemask = imagemask;
		image->usecolorkey = usecolorkey;
		image->base.mask = mask;
		if (!cstm)
		{
			/* Just load the compressed image data now and we can
			 * decode it on demand. */
			int num = pdf_to_num(dict);
			int gen = pdf_to_gen(dict);
			image->buffer = pdf_load_compressed_stream(xref, num, gen);
			break; /* Out of fz_try */
		}

		/* We need to decompress the image now */
		if (cstm)
		{
			int stride = (w * image->n * image->base.bpc + 7) / 8;
			stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL);
		}
		else
		{
			stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
		}

		image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0, 0);
	}
	fz_catch(ctx)
	{
		pdf_free_image(ctx, (fz_storable *) image);
		fz_rethrow(ctx);
	}
	return image;
}
Esempio n. 22
0
char *
pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest)
{
	pdf_obj *obj;
	char buf[256];
	const char *ld;
	int page;
	int x, y;

	dest = resolve_dest(ctx, doc, dest);
	if (dest == NULL)
	{
		fz_warn(ctx, "undefined link destination");
		return NULL;
	}

	if (pdf_is_name(ctx, dest))
	{
		ld = pdf_to_name(ctx, dest);
		return fz_strdup(ctx, ld);
	}
	else if (pdf_is_string(ctx, dest))
	{
		ld = pdf_to_str_buf(ctx, dest);
		return fz_strdup(ctx, ld);
	}

	obj = pdf_array_get(ctx, dest, 0);
	if (pdf_is_int(ctx, obj))
		page = pdf_to_int(ctx, obj);
	else
	{
		fz_try(ctx)
			page = pdf_lookup_page_number(ctx, doc, obj);
		fz_catch(ctx)
			page = -1;
	}

	x = y = 0;
	obj = pdf_array_get(ctx, dest, 1);
	if (pdf_name_eq(ctx, obj, PDF_NAME_XYZ))
	{
		x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2));
		y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 3));
	}
	else if (pdf_name_eq(ctx, obj, PDF_NAME_FitR))
	{
		x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2));
		y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 5));
	}
	else if (pdf_name_eq(ctx, obj, PDF_NAME_FitH) || pdf_name_eq(ctx, obj, PDF_NAME_FitBH))
		y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2));
	else if (pdf_name_eq(ctx, obj, PDF_NAME_FitV) || pdf_name_eq(ctx, obj, PDF_NAME_FitBV))
		x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2));

	if (page >= 0)
	{
		if (x != 0 || y != 0)
			fz_snprintf(buf, sizeof buf, "#%d,%d,%d", page + 1, x, y);
		else
			fz_snprintf(buf, sizeof buf, "#%d", page + 1);
		return fz_strdup(ctx, buf);
	}

	return NULL;
}
Esempio n. 23
0
pdf_xobject *
pdf_load_xobject(pdf_document *xref, pdf_obj *dict)
{
	pdf_xobject *form;
	pdf_obj *obj;
	fz_context *ctx = xref->ctx;

	if ((form = pdf_find_item(ctx, pdf_free_xobject_imp, dict)))
	{
		return form;
	}

	form = fz_malloc_struct(ctx, pdf_xobject);
	FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp);
	form->resources = NULL;
	form->contents = NULL;
	form->colorspace = NULL;
	form->me = NULL;

	/* Store item immediately, to avoid possible recursion if objects refer back to this one */
	pdf_store_item(ctx, dict, form, pdf_xobject_size(form));

	obj = pdf_dict_gets(dict, "BBox");
	form->bbox = pdf_to_rect(ctx, obj);

	obj = pdf_dict_gets(dict, "Matrix");
	if (obj)
		form->matrix = pdf_to_matrix(ctx, obj);
	else
		form->matrix = fz_identity;

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

	obj = pdf_dict_gets(dict, "Group");
	if (obj)
	{
		pdf_obj *attrs = obj;

		form->isolated = pdf_to_bool(pdf_dict_gets(attrs, "I"));
		form->knockout = pdf_to_bool(pdf_dict_gets(attrs, "K"));

		obj = pdf_dict_gets(attrs, "S");
		if (pdf_is_name(obj) && !strcmp(pdf_to_name(obj), "Transparency"))
			form->transparency = 1;

		obj = pdf_dict_gets(attrs, "CS");
		if (obj)
		{
			form->colorspace = pdf_load_colorspace(xref, obj);
			if (!form->colorspace)
				fz_throw(ctx, "cannot load xobject colorspace");
		}
	}

	form->resources = pdf_dict_gets(dict, "Resources");
	if (form->resources)
		pdf_keep_obj(form->resources);

	fz_try(ctx)
	{
		form->contents = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
	}
	fz_catch(ctx)
	{
		pdf_remove_item(ctx, pdf_free_xobject_imp, dict);
		pdf_drop_xobject(ctx, form);
		fz_throw(ctx, "cannot load xobject content stream (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}
	form->me = pdf_keep_obj(dict);

	return form;
}
Esempio n. 24
0
static void
gatherimages(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict)
{
	int i, n;

	n = pdf_dict_len(dict);
	for (i = 0; i < n; i++)
	{
		pdf_obj *imagedict;
		pdf_obj *type;
		pdf_obj *width;
		pdf_obj *height;
		pdf_obj *bpc = NULL;
		pdf_obj *filter = NULL;
		pdf_obj *cs = NULL;
		pdf_obj *altcs;
		int k;

		imagedict = pdf_dict_get_val(dict, i);
		if (!pdf_is_dict(imagedict))
		{
			fz_warn(ctx, "not an image dict (%d %d R)", pdf_to_num(imagedict), pdf_to_gen(imagedict));
			continue;
		}

		type = pdf_dict_gets(imagedict, "Subtype");
		if (strcmp(pdf_to_name(type), "Image"))
			continue;

		filter = pdf_dict_gets(imagedict, "Filter");

		altcs = NULL;
		cs = pdf_dict_gets(imagedict, "ColorSpace");
		if (pdf_is_array(cs))
		{
			pdf_obj *cses = cs;

			cs = pdf_array_get(cses, 0);
			if (pdf_is_name(cs) && (!strcmp(pdf_to_name(cs), "DeviceN") || !strcmp(pdf_to_name(cs), "Separation")))
			{
				altcs = pdf_array_get(cses, 2);
				if (pdf_is_array(altcs))
					altcs = pdf_array_get(altcs, 0);
			}
		}

		width = pdf_dict_gets(imagedict, "Width");
		height = pdf_dict_gets(imagedict, "Height");
		bpc = pdf_dict_gets(imagedict, "BitsPerComponent");

		for (k = 0; k < images; k++)
			if (!pdf_objcmp(image[k].u.image.obj, imagedict))
				break;

		if (k < images)
			continue;

		image = fz_resize_array(ctx, image, images+1, sizeof(struct info));
		images++;

		image[images - 1].page = page;
		image[images - 1].pageref = pageref;
		image[images - 1].pageobj = pageobj;
		image[images - 1].u.image.obj = imagedict;
		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;
	}
}
Esempio n. 25
0
static void savefont(pdf_obj *dict, int num)
{
	char namebuf[1024];
	fz_buffer *buf;
	pdf_obj *stream = NULL;
	pdf_obj *obj;
	char *ext = "";
	fz_output *out;
	char *fontname = "font";
	size_t len;
	unsigned char *data;

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FontName);
	if (obj)
		fontname = pdf_to_name(ctx, obj);

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FontFile);
	if (obj)
	{
		stream = obj;
		ext = "pfa";
	}

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FontFile2);
	if (obj)
	{
		stream = obj;
		ext = "ttf";
	}

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FontFile3);
	if (obj)
	{
		stream = obj;

		obj = pdf_dict_get(ctx, obj, PDF_NAME_Subtype);
		if (obj && !pdf_is_name(ctx, obj))
			fz_throw(ctx, FZ_ERROR_GENERIC, "invalid font descriptor subtype");

		if (pdf_name_eq(ctx, obj, PDF_NAME_Type1C))
			ext = "cff";
		else if (pdf_name_eq(ctx, obj, PDF_NAME_CIDFontType0C))
			ext = "cid";
		else if (pdf_name_eq(ctx, obj, PDF_NAME_OpenType))
			ext = "otf";
		else
			fz_throw(ctx, FZ_ERROR_GENERIC, "unhandled font type '%s'", pdf_to_name(ctx, obj));
	}

	if (!stream)
	{
		fz_warn(ctx, "unhandled font type");
		return;
	}

	buf = pdf_load_stream(ctx, doc, pdf_to_num(ctx, stream));
	len = fz_buffer_storage(ctx, buf, &data);
	fz_try(ctx)
	{
		snprintf(namebuf, sizeof(namebuf), "%s-%04d.%s", fontname, num, ext);
		printf("extracting font %s\n", namebuf);
		out = fz_new_output_with_path(ctx, namebuf, 0);
		fz_try(ctx)
			fz_write(ctx, out, data, len);
		fz_always(ctx)
			fz_drop_output(ctx, out);
		fz_catch(ctx)
			fz_rethrow(ctx);
	}
	fz_always(ctx)
		fz_drop_buffer(ctx, buf);
	fz_catch(ctx)
		fz_rethrow(ctx);
}
Esempio n. 26
0
/*
 * Create a filter given a name and param dictionary.
 */
static fz_stream *
build_filter(fz_stream *chain, pdf_document * xref, pdf_obj * f, pdf_obj * p, int num, int gen, pdf_image_params *params)
{
    fz_context *ctx = chain->ctx;
    char *s = pdf_to_name(f);

    int predictor = pdf_to_int(pdf_dict_gets(p, "Predictor"));
    int columns = pdf_to_int(pdf_dict_gets(p, "Columns"));
    int colors = pdf_to_int(pdf_dict_gets(p, "Colors"));
    int bpc = pdf_to_int(pdf_dict_gets(p, "BitsPerComponent"));

    if (predictor == 0) predictor = 1;
    if (columns == 0) columns = 1;
    if (colors == 0) colors = 1;
    if (bpc == 0) bpc = 8;

    if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx"))
        return fz_open_ahxd(chain);

    else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85"))
        return fz_open_a85d(chain);

    else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF"))
    {
        pdf_obj *k = pdf_dict_gets(p, "K");
        pdf_obj *eol = pdf_dict_gets(p, "EndOfLine");
        pdf_obj *eba = pdf_dict_gets(p, "EncodedByteAlign");
        pdf_obj *columns = pdf_dict_gets(p, "Columns");
        pdf_obj *rows = pdf_dict_gets(p, "Rows");
        pdf_obj *eob = pdf_dict_gets(p, "EndOfBlock");
        pdf_obj *bi1 = pdf_dict_gets(p, "BlackIs1");
        if (params)
        {
            /* We will shortstop here */
            params->type = PDF_IMAGE_FAX;
            params->u.fax.k = (k ? pdf_to_int(k) : 0);
            params->u.fax.eol = (eol ? pdf_to_bool(eol) : 0);
            params->u.fax.eba = (eba ? pdf_to_bool(eba) : 0);
            params->u.fax.columns = (columns ? pdf_to_int(columns) : 1728);
            params->u.fax.rows = (rows ? pdf_to_int(rows) : 0);
            params->u.fax.eob = (eob ? pdf_to_bool(eob) : 1);
            params->u.fax.bi1 = (bi1 ? pdf_to_bool(bi1) : 0);
            return chain;
        }
        return fz_open_faxd(chain,
                            k ? pdf_to_int(k) : 0,
                            eol ? pdf_to_bool(eol) : 0,
                            eba ? pdf_to_bool(eba) : 0,
                            columns ? pdf_to_int(columns) : 1728,
                            rows ? pdf_to_int(rows) : 0,
                            eob ? pdf_to_bool(eob) : 1,
                            bi1 ? pdf_to_bool(bi1) : 0);
    }

    else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT"))
    {
        pdf_obj *ct = pdf_dict_gets(p, "ColorTransform");
        if (params)
        {
            /* We will shortstop here */
            params->type = PDF_IMAGE_JPEG;
            params->u.jpeg.ct = (ct ? pdf_to_int(ct) : -1);
            return chain;
        }
        return fz_open_dctd(chain, ct ? pdf_to_int(ct) : -1);
    }

    else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL"))
    {
        if (params)
        {
            /* We will shortstop here */
            params->type = PDF_IMAGE_RLD;
            return chain;
        }
        return fz_open_rld(chain);
    }
    else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl"))
    {
        if (params)
        {
            /* We will shortstop here */
            params->type = PDF_IMAGE_FLATE;
            params->u.flate.predictor = predictor;
            params->u.flate.columns = columns;
            params->u.flate.colors = colors;
            params->u.flate.bpc = bpc;
            return chain;
        }
        chain = fz_open_flated(chain);
        if (predictor > 1)
            chain = fz_open_predict(chain, predictor, columns, colors, bpc);
        return chain;
    }

    else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW"))
    {
        pdf_obj *ec = pdf_dict_gets(p, "EarlyChange");
        if (params)
        {
            /* We will shortstop here */
            params->type = PDF_IMAGE_LZW;
            params->u.lzw.predictor = predictor;
            params->u.lzw.columns = columns;
            params->u.lzw.colors = colors;
            params->u.lzw.bpc = bpc;
            params->u.lzw.ec = (ec ? pdf_to_int(ec) : 1);
            return chain;
        }
        chain = fz_open_lzwd(chain, ec ? pdf_to_int(ec) : 1);
        if (predictor > 1)
            chain = fz_open_predict(chain, predictor, columns, colors, bpc);
        return chain;
    }

    else if (!strcmp(s, "JBIG2Decode"))
    {
        fz_buffer *globals = NULL;
        pdf_obj *obj = pdf_dict_gets(p, "JBIG2Globals");
        if (obj)
            globals = pdf_load_stream(xref, pdf_to_num(obj), pdf_to_gen(obj));
        /* fz_open_jbig2d takes possession of globals */
        return fz_open_jbig2d(chain, globals);
    }

    else if (!strcmp(s, "JPXDecode"))
        return chain; /* JPX decoding is special cased in the image loading code */

    else if (!strcmp(s, "Crypt"))
    {
        pdf_obj *name;

        if (!xref->crypt)
        {
            fz_warn(ctx, "crypt filter in unencrypted document");
            return chain;
        }

        name = pdf_dict_gets(p, "Name");
        if (pdf_is_name(name))
            return pdf_open_crypt_with_filter(chain, xref->crypt, pdf_to_name(name), num, gen);

        return chain;
    }

    fz_warn(ctx, "unknown filter name (%s)", s);
    return chain;
}
Esempio n. 27
0
static pdf_font_desc *
pdf_load_simple_font(pdf_document *xref, pdf_obj *dict)
{
	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 *basefont;
	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;
	fz_context *ctx = xref->ctx;

	fz_var(fontdesc);
	fz_var(etable);

	basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont"));

	/* 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, xref, descriptor, NULL, basefont);
		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 = pdf_new_font_desc(ctx);
				pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]);
				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);

		/* 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++;
						}
					}
				}
			}
		}

		/* 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);

		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(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));
		}
		fz_catch(ctx)
		{
			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);
			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);
		}

		pdf_end_hmtx(ctx, fontdesc);
	}
	fz_catch(ctx)
	{
		if (fontdesc && etable != fontdesc->cid_to_gid)
			fz_free(ctx, etable);
		pdf_drop_font(ctx, fontdesc);
		fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}
	return fontdesc;
}
Esempio n. 28
0
fz_link_dest
pdf_parse_link_dest(pdf_document *xref, pdf_obj *dest)
{
	fz_link_dest ld;
	pdf_obj *obj;

	int l_from_2 = 0;
	int b_from_3 = 0;
	int r_from_4 = 0;
	int t_from_5 = 0;
	int t_from_3 = 0;
	int t_from_2 = 0;
	int z_from_4 = 0;

	dest = resolve_dest(xref, dest);
	if (dest == NULL || !pdf_is_array(dest))
	{
		ld.kind = FZ_LINK_NONE;
		return ld;
	}
	obj = pdf_array_get(dest, 0);
	if (pdf_is_int(obj))
		ld.ld.gotor.page = pdf_to_int(obj);
	else
		ld.ld.gotor.page = pdf_lookup_page_number(xref, obj);

	ld.kind = FZ_LINK_GOTO;
	ld.ld.gotor.flags = 0;
	ld.ld.gotor.lt.x = 0;
	ld.ld.gotor.lt.y = 0;
	ld.ld.gotor.rb.x = 0;
	ld.ld.gotor.rb.y = 0;
	ld.ld.gotor.file_spec = NULL;
	ld.ld.gotor.new_window = 0;

	obj = pdf_array_get(dest, 1);
	if (!pdf_is_name(obj))
		return ld;

	if (!strcmp("XYZ", pdf_to_name(obj)))
	{
		l_from_2 = t_from_3 = z_from_4 = 1;
		ld.ld.gotor.flags |= fz_link_flag_r_is_zoom;
	}
	else if ((!strcmp("Fit", pdf_to_name(obj))) || (!strcmp("FitB", pdf_to_name(obj))))
	{
		ld.ld.gotor.flags |= fz_link_flag_fit_h;
		ld.ld.gotor.flags |= fz_link_flag_fit_v;
	}
	else if ((!strcmp("FitH", pdf_to_name(obj))) || (!strcmp("FitBH", pdf_to_name(obj))))
	{
		t_from_2 = 1;
		ld.ld.gotor.flags |= fz_link_flag_fit_h;
	}
	else if ((!strcmp("FitV", pdf_to_name(obj))) || (!strcmp("FitBV", pdf_to_name(obj))))
	{
		l_from_2 = 1;
		ld.ld.gotor.flags |= fz_link_flag_fit_v;
	}
	else if (!strcmp("FitR", pdf_to_name(obj)))
	{
		l_from_2 = b_from_3 = r_from_4 = t_from_5 = 1;
		ld.ld.gotor.flags |= fz_link_flag_fit_h;
		ld.ld.gotor.flags |= fz_link_flag_fit_v;
	}

	if (l_from_2)
	{
		obj = pdf_array_get(dest, 2);
		if (pdf_is_int(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_l_valid;
			ld.ld.gotor.lt.x = pdf_to_int(obj);
		}
		else if (pdf_is_real(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_l_valid;
			ld.ld.gotor.lt.x = pdf_to_real(obj);
		}
	}
	if (b_from_3)
	{
		obj = pdf_array_get(dest, 3);
		if (pdf_is_int(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_b_valid;
			ld.ld.gotor.rb.y = pdf_to_int(obj);
		}
		else if (pdf_is_real(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_b_valid;
			ld.ld.gotor.rb.y = pdf_to_real(obj);
		}
	}
	if (r_from_4)
	{
		obj = pdf_array_get(dest, 4);
		if (pdf_is_int(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_r_valid;
			ld.ld.gotor.rb.x = pdf_to_int(obj);
		}
		else if (pdf_is_real(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_r_valid;
			ld.ld.gotor.rb.x = pdf_to_real(obj);
		}
	}
	if (t_from_5 || t_from_3 || t_from_2)
	{
		if (t_from_5)
			obj = pdf_array_get(dest, 5);
		else if (t_from_3)
			obj = pdf_array_get(dest, 3);
		else
			obj = pdf_array_get(dest, 2);
		if (pdf_is_int(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_t_valid;
			ld.ld.gotor.lt.y = pdf_to_int(obj);
		}
		else if (pdf_is_real(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_t_valid;
			ld.ld.gotor.lt.y = pdf_to_real(obj);
		}
	}
	if (z_from_4)
	{
		obj = pdf_array_get(dest, 4);
		if (pdf_is_int(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_r_valid;
			ld.ld.gotor.rb.x = pdf_to_int(obj);
		}
		else if (pdf_is_real(obj))
		{
			ld.ld.gotor.flags |= fz_link_flag_r_valid;
			ld.ld.gotor.rb.x = pdf_to_real(obj);
		}
	}

	/* Duplicate the values out for the sake of stupid clients */
	if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid)) == fz_link_flag_l_valid)
		ld.ld.gotor.rb.x = ld.ld.gotor.lt.x;
	if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid | fz_link_flag_r_is_zoom)) == fz_link_flag_r_valid)
		ld.ld.gotor.lt.x = ld.ld.gotor.rb.x;
	if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_t_valid)
		ld.ld.gotor.rb.y = ld.ld.gotor.lt.y;
	if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_b_valid)
		ld.ld.gotor.lt.y = ld.ld.gotor.rb.y;

	return ld;
}
Esempio n. 29
0
pdf_font_desc *
pdf_load_type3_font(pdf_document *doc, pdf_obj *rdb, pdf_obj *dict)
{
	char buf[256];
	char *estrings[256];
	pdf_font_desc *fontdesc = NULL;
	pdf_obj *encoding;
	pdf_obj *widths;
	pdf_obj *charprocs;
	pdf_obj *obj;
	int first, last;
	int i, k, n;
	fz_rect bbox;
	fz_matrix matrix;
	fz_context *ctx = doc->ctx;

	fz_var(fontdesc);

	/* Make a new type3 font entry in the document */
	if (doc->num_type3_fonts == doc->max_type3_fonts)
	{
		int new_max = doc->max_type3_fonts * 2;

		if (new_max == 0)
			new_max = 4;
		doc->type3_fonts = fz_resize_array(doc->ctx, doc->type3_fonts, new_max, sizeof(*doc->type3_fonts));
		doc->max_type3_fonts = new_max;
	}

	fz_try(ctx)
	{
		obj = pdf_dict_gets(dict, "Name");
		if (pdf_is_name(obj))
			fz_strlcpy(buf, pdf_to_name(obj), sizeof buf);
		else
			sprintf(buf, "Unnamed-T3");

		fontdesc = pdf_new_font_desc(ctx);

		obj = pdf_dict_gets(dict, "FontMatrix");
		pdf_to_matrix(ctx, obj, &matrix);

		obj = pdf_dict_gets(dict, "FontBBox");
		fz_transform_rect(pdf_to_rect(ctx, obj, &bbox), &matrix);

		fontdesc->font = fz_new_type3_font(ctx, buf, &matrix);
		fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float));

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

		/* SumatraPDF: expose Type3 FontDescriptor flags */
		fontdesc->flags = pdf_to_int(pdf_dict_gets(pdf_dict_gets(dict, "FontDescriptor"), "Flags"));

		/* Encoding */

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

		encoding = pdf_dict_gets(dict, "Encoding");
		if (!encoding)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing 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));

			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);
				}
			}
		}

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

		pdf_load_to_unicode(doc, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));

		/* SumatraPDF: trying to match Adobe Reader's behavior */
		if (!(fontdesc->flags & PDF_FD_SYMBOLIC) && fontdesc->cid_to_ucs_len >= 128)
			for (i = 32; i < 128; i++)
				if (fontdesc->cid_to_ucs[i] == '?' || fontdesc->cid_to_ucs[i] == '\0')
					fontdesc->cid_to_ucs[i] = i;

		/* Widths */

		pdf_set_default_hmtx(ctx, fontdesc, 0);

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

		/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1966 */
		if (first >= 256 && last - first < 256)
		{
			fz_warn(ctx, "ignoring out-of-bound values for FirstChar/LastChar: %d/%d", first, last);
			last -= first;
			first = 0;
		}

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

		widths = pdf_dict_gets(dict, "Widths");
		if (!widths)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing Widths");
		}

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

		pdf_end_hmtx(ctx, fontdesc);

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

		fontdesc->font->t3freeres = pdf_t3_free_resources;
		fontdesc->font->t3resources = pdf_dict_gets(dict, "Resources");
		if (!fontdesc->font->t3resources)
			fontdesc->font->t3resources = rdb;
		if (fontdesc->font->t3resources)
			pdf_keep_obj(fontdesc->font->t3resources);
		if (!fontdesc->font->t3resources)
			fz_warn(ctx, "no resource dictionary for type 3 font!");

		fontdesc->font->t3doc = doc;
		fontdesc->font->t3run = pdf_run_glyph_func;

		/* CharProcs */

		charprocs = pdf_dict_gets(dict, "CharProcs");
		if (!charprocs)
		{
			fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing CharProcs");
		}

		for (i = 0; i < 256; i++)
		{
			if (estrings[i])
			{
				/* SumatraPDF: don't reject fonts with few broken glyphs */
				fz_try(ctx)
				{

				obj = pdf_dict_gets(charprocs, estrings[i]);
				if (pdf_is_stream(doc, pdf_to_num(obj), pdf_to_gen(obj)))
				{
					fontdesc->font->t3procs[i] = pdf_load_stream(doc, pdf_to_num(obj), pdf_to_gen(obj));
					fontdesc->size += fontdesc->font->t3procs[i]->cap;
					fontdesc->size += 0; // TODO: display list size calculation
				}

				}
				fz_catch(ctx)
				{
					fz_warn(ctx, "failed to get data for type 3 glyph '%s'", estrings[i]);
				}
			}
		}
	}
	fz_catch(ctx)
	{
		if (fontdesc)
			pdf_drop_font(ctx, fontdesc);
		fz_rethrow_message(ctx, "cannot load type3 font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}

	doc->type3_fonts[doc->num_type3_fonts++] = fz_keep_font(ctx, fontdesc->font);

	return fontdesc;
}
Esempio n. 30
0
// just copy one of the resource sub-entries (e.g. /Font)
static int copy_and_rename_resource(fz_context *dest_ctx, pdf_obj *dest, 
	fz_context *src_ctx, pdf_obj *src, char *prefix, struct put_info *info)
{
	char new_name[64]; /* this buffer is big enough up to hold all digits for two 16-bit numbers */

    int i;
    for(i = 0; i < pdf_dict_len(src_ctx, src); i++) {
        pdf_obj *src_key = pdf_dict_get_key(src_ctx, src, i);
		pdf_obj *src_val = pdf_dict_get_val(src_ctx, src, i);

		if(!pdf_is_name(src_ctx, src_key)) {
			return(2);
		}
		
		/* if this is an inline resource, just copy this object into the new
		    resource dict */	
		if(!pdf_is_indirect(src_ctx, src_val)) {
			if(snprintf(new_name, sizeof(new_name) / sizeof(new_name[0]), 
					"%sinline_%d", prefix, info->next_inline_id++) >= sizeof(new_name) / sizeof(new_name[0]))
				return(1); // not enough space
		
			pdf_obj *new_res = copy_unassigned_object_continue(dest_ctx, 
				info->dest_doc, src_ctx, info->src_doc, src_val, &info->new_ids);
				
			//pdf_obj *new_res = pdf_new_dict(dest_ctx, info->dest_doc, 10);
			printf("dump it...\n");
			pdf_fprint_obj(dest_ctx, stdout, new_res, 0);
				
			/* now reference this new object in the resource object of this sheet */
			pdf_obj *dest_key = pdf_new_name(dest_ctx, info->dest_doc, new_name);

			pdf_dict_put(dest_ctx, dest, dest_key, new_res);
			pdf_drop_obj(dest_ctx, dest_key);
			pdf_drop_obj(dest_ctx, new_res);
		} else {
			/* The new name of resource objects is always the num/gen of the 
			   referenced object in the src-file. Thus we can check by that name
			   if the object was already referenced by another page of this sheet. */
			if(snprintf(new_name, sizeof(new_name) / sizeof(new_name[0]), 
					"%s%d_%d", prefix, pdf_to_num(dest_ctx, src_val), pdf_to_gen(dest_ctx, src_val)) >= 
					sizeof(new_name) / sizeof(new_name[0]))
				return(1); // not enough space
						
			if(pdf_dict_gets(dest_ctx, dest, new_name) == NULL) {
			   /* if this resource is not inlined and not already in the resource-dict 
				  of the current sheet... */
			
				/* ...copy the referenced resource to the new document!
				   If this object has copied already (for another sheet in dest_doc),
				   copy_object_continue() will do nothing */
				pdf_obj *new_res = copy_object_continue(dest_ctx, info->dest_doc, 
					src_ctx, info->src_doc, src_val, &info->new_ids);

				/* now reference this new object in the resource object of this sheet */
				pdf_obj *dest_key = pdf_new_name(dest_ctx, info->dest_doc, new_name);

				pdf_dict_put(dest_ctx, dest, dest_key, new_res);
				pdf_drop_obj(dest_ctx, dest_key);
				pdf_drop_obj(dest_ctx, new_res);	
			}
		}

		/* even if it was used on another sheet or on this sheet, add it to the 
		   rename-dict for this sheet! Because it could have different names
		   on different source-pages */
		pdf_obj *rename_key = pdf_new_name(dest_ctx, info->dest_doc, pdf_to_name(dest_ctx, src_key));
		pdf_obj *rename_val = pdf_new_name(dest_ctx, info->dest_doc, new_name);
		pdf_dict_put(dest_ctx, info->rename_dict, rename_key, rename_val);
		pdf_drop_obj(dest_ctx, rename_key);
		pdf_drop_obj(dest_ctx, rename_val);
	}

	return(0);
}