Beispiel #1
0
/* Creates the PDF Encoding entry for the encoding.
 * If baseenc is non-null, it is used as BaseEncoding entry.
 */
static pdf_obj *
create_encoding_resource (pdf_encoding *encoding, pdf_encoding *baseenc)
{
  pdf_obj *differences;
  ASSERT(encoding);
  ASSERT(!encoding->resource);

  differences = make_encoding_differences(encoding->glyphs,
					  baseenc ? baseenc->glyphs : NULL,
					  encoding->is_used);
  
  if (differences) {
    pdf_obj *resource = pdf_new_dict();
    if (baseenc)
      pdf_add_dict(resource, pdf_new_name("BaseEncoding"),
		   pdf_link_obj(baseenc->resource));
    pdf_add_dict(resource, pdf_new_name("Differences"),  differences);
    return resource; 
  } else {
    /* Fix a bug with the MinionPro package using MnSymbol fonts
     * in its virtual fonts:
     *
     * Some font may have font_id even if no character is used.
     * For example, suppose that a virtual file A.vf uses two
     * other fonts, B and C. Even if only characters of B are used
     * in a DVI document, C will have font_id too.
     * In this case, both baseenc and differences can be NULL.
     *
     * Actually these fonts will be ignored in pdffont.c.
     */
    return baseenc ? pdf_link_obj(baseenc->resource) : NULL;
  }
}
Beispiel #2
0
static void
pdf_flush_font (pdf_font *font)
{
  char *fontname, *uniqueTag;

  if (!font) {
    return;
  }

  if (font->resource && font->reference) {
    if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) {
      if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
	pdf_add_dict(font->resource,
		     pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
	if (font->descriptor) {
	  pdf_add_dict(font->descriptor,
		       pdf_new_name("FontName"), pdf_new_name(font->fontname));
	}
      } else {
	if (!font->fontname) {
	  ERROR("Undefined in fontname... (%s)", font->ident);
	}
	fontname  = NEW(7+strlen(font->fontname)+1, char);
	uniqueTag = pdf_font_get_uniqueTag(font);
	sprintf(fontname, "%6s+%s", uniqueTag, font->fontname);
	pdf_add_dict(font->resource,
		     pdf_new_name("BaseFont"), pdf_new_name(fontname));
	if (font->descriptor) {
	  pdf_add_dict(font->descriptor,
		       pdf_new_name("FontName"), pdf_new_name(fontname));
	}
	RELEASE(fontname);
      }
      if (font->descriptor) {
	pdf_add_dict(font->resource,
		     pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));
      }
    }
  }

  if (font->resource)
    pdf_release_obj(font->resource);
  if (font->descriptor)
    pdf_release_obj(font->descriptor);
  if (font->reference)
    pdf_release_obj(font->reference);

  font->reference  = NULL;
  font->resource   = NULL;
  font->descriptor = NULL;

  return;
}
Beispiel #3
0
void
Type0Font_set_ToUnicode (Type0Font *font, pdf_obj *cmap_ref)
{
  ASSERT(font);

  pdf_add_dict(font->fontdict,
	       pdf_new_name("ToUnicode"), cmap_ref);
}
Beispiel #4
0
static pdf_obj *
create_cspace_ICCBased (png_structp png_ptr, png_infop info_ptr)
{
  pdf_obj   *colorspace;
  int        csp_id, colortype;
  png_byte   color_type;
  png_charp  name;
  int        compression_type;  /* Manual page for libpng does not
				 * clarify whether profile data is inflated by libpng.
				 */
#if PNG_LIBPNG_VER_MINOR < 5
  png_charp   profile;
#else
  png_bytep   profile;
#endif
  png_uint_32 proflen;

  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP) ||
      !png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile, &proflen))
    return NULL;

  color_type = png_get_color_type(png_ptr, info_ptr);

  if (color_type & PNG_COLOR_MASK_COLOR) {
    colortype = PDF_COLORSPACE_TYPE_RGB;
#if 0
    alternate = create_cspace_CalRGB(png_ptr, info_ptr);
#endif
  } else {
    colortype = PDF_COLORSPACE_TYPE_GRAY;
#if 0
    alternate = create_cspace_CalGray(png_ptr, info_ptr);
#endif
  }

#if 0
  if (alternate)
    pdf_add_dict(dict, pdf_new_name("Alternate"), alternate);
#endif

  if (iccp_check_colorspace(colortype, profile, proflen) < 0)
    colorspace = NULL;
  else {
    csp_id = iccp_load_profile(name, profile, proflen);
    if (csp_id < 0) {
      colorspace = NULL;
    } else {
      colorspace = pdf_get_colorspace_reference(csp_id);
    }
  }

  /* Rendering intent ... */

  return colorspace;
}
Beispiel #5
0
int
jp2_include_image (pdf_ximage *ximage, FILE *fp)
{
  int      smask = 0;
  pdf_obj *stream, *stream_dict;
  ximage_info info;

  if (pdf_check_version(1, 5) < 0) {
    WARN("JPEG 2000 support requires PDF version >= 1.5.\n");
    return -1;
  }

  pdf_ximage_init_image_info(&info);
  stream = stream_dict = NULL;

  rewind(fp);
  if (scan_file(&info, &smask, fp) < 0) {
    WARN("JPEG2000: Reading JPEG 2000 file failed.");
    return -1;
  }

  stream      = pdf_new_stream(0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
               pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
  if (smask)
    pdf_add_dict(stream_dict,
                 pdf_new_name("SMaskInData"), pdf_new_number(1));
  /* Read whole file */
  {
    int nb_read;
    rewind(fp);
    while ((nb_read =
        fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0)
      pdf_add_stream(stream, work_buffer, nb_read);
  }

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Beispiel #6
0
static pdf_obj *
create_soft_mask (png_structp png_ptr, png_infop info_ptr,
		  png_bytep image_data_ptr, png_uint_32 width, png_uint_32 height)
{
  pdf_obj    *smask, *dict;
  png_bytep   smask_data_ptr;
  png_bytep   trans;
  int         num_trans;
  png_uint_32 i;

  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
      !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
    WARN("%s: PNG does not have valid tRNS chunk but tRNS is requested.", PNG_DEBUG_STR);
    return NULL;
  }

  smask = pdf_new_stream(STREAM_COMPRESS);
  dict  = pdf_stream_dict(smask);
  smask_data_ptr = (png_bytep) NEW(width*height, png_byte);
  pdf_add_dict(dict, pdf_new_name("Type"),    pdf_new_name("XObject"));
  pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image"));
  pdf_add_dict(dict, pdf_new_name("Width"),      pdf_new_number(width));
  pdf_add_dict(dict, pdf_new_name("Height"),     pdf_new_number(height));
  pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray"));
  pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(8));
  for (i = 0; i < width*height; i++) {
    png_byte idx = image_data_ptr[i];
    smask_data_ptr[i] = (idx < num_trans) ? trans[idx] : 0xff;
  }
  pdf_add_stream(smask, (char *)smask_data_ptr, width*height);
  RELEASE(smask_data_ptr);

  return smask;
}
Beispiel #7
0
pdf_obj *parse_pdf_dict (char **start, char *end)
{
  pdf_obj *result, *tmp1, *tmp2;
  char *save = *start;
  skip_white(start, end);
  if (*((*start)++) != '<' ||
      *((*start)++) != '<') {
    *start = save;
    dump (*start, end);
    return NULL;
  }
  result = pdf_new_dict ();
    skip_white(start, end);
  while (*start < end &&
	 **start != '>') {
    if ((tmp1 = parse_pdf_name (start, end)) == NULL) {
      pdf_release_obj (result); 
      {
	*start = save;
	dump (*start, end);
	return NULL;
      }
    };
    if ((tmp2 = parse_pdf_object (start, end)) == NULL) {
      pdf_release_obj (result);
      pdf_release_obj (tmp1); 
      {
	*start = save;
	dump (*start, end);
	return NULL;
      }
    }
    pdf_add_dict (result, tmp1, tmp2);
    skip_white(start, end);
  }
  if (*start >= end) {
    pdf_release_obj (result);
    *start = save;
    dump (*start, end);
    return NULL;
  }
  if (*((*start)++) == '>' &&
      *((*start)++) == '>') {
    return result;
  } else {
    pdf_release_obj (result);
    fprintf (stderr, "\nDictionary object ended prematurely\n");
    *start = save;
    dump (*start, end);
    return NULL;
  }
}
Beispiel #8
0
pdf_obj *
Type0Font_get_resource (Type0Font *font)
{
  ASSERT(font);

  /*
   * This looks somewhat strange.
   */
  if (!font->indirect) {
    pdf_obj *array;

    array = pdf_new_array();
    pdf_add_array(array, CIDFont_get_resource(font->descendant));
    pdf_add_dict(font->fontdict, pdf_new_name("DescendantFonts"), array);
    font->indirect = pdf_ref_obj(font->fontdict);
  }

  return pdf_link_obj(font->indirect);
}
Beispiel #9
0
static void html_make_link_dict (char *name)
{
  pdf_obj *color;
  if (!link_dict) {
    link_dict = pdf_new_dict();
    pdf_add_dict(link_dict, pdf_new_name("Type"), pdf_new_name ("Annot"));
    pdf_add_dict(link_dict, pdf_new_name("Subtype"), pdf_new_name ("Link"));
    color = pdf_new_array ();
    pdf_add_array (color, pdf_new_number (0));
    pdf_add_array (color, pdf_new_number (1));
    pdf_add_array (color, pdf_new_number (1));
    pdf_add_dict(link_dict, pdf_new_name("C"), color);
    if (name && *name == '#' && !(base_value)) {
      pdf_add_dict (link_dict, pdf_new_name("Dest"), pdf_new_string(name+1,strlen(name+1)));
    } else if (name) {    /* Assume its a URL */
      char *url;
      int len;
      pdf_obj *action;
      len = strlen(name)+1;
      if (base_value)
	len+=strlen(base_value);
      url = NEW (len, char);
      if (base_value)
	strcpy (url, base_value);
      else
	url[0] = 0;
      strcat (url, name);
      action = pdf_new_dict();
      pdf_add_dict (action, pdf_new_name ("Type"), pdf_new_name ("Action"));
      pdf_add_dict (action, pdf_new_name ("S"), pdf_new_name ("URI"));
      pdf_add_dict (action, pdf_new_name ("URI"),
		    pdf_new_string (url, len));
      pdf_add_dict (link_dict, pdf_new_name ("A"), pdf_ref_obj (action));
      pdf_release_obj (action);
      RELEASE (url);
    }
    pdf_doc_begin_annot (link_dict);
  } else {
Beispiel #10
0
int
jp2_include_image (pdf_ximage *ximage, FILE *fp)
{
  unsigned pdf_version;
  pdf_obj *stream, *stream_dict;
  ximage_info info;

  pdf_version = pdf_get_version();
  if (pdf_version < 5) {
    WARN("JPEG 2000 support requires PDF version >= 1.5 (Current setting 1.%d)\n", pdf_version);
    return -1;
  }

  pdf_ximage_init_image_info(&info);
  stream = stream_dict = NULL;

  rewind(fp);
  if (scan_file(&info, fp) < 0) {
    WARN("Reading JPEG 2000 file failed.");
    return -1;
  }

  stream      = pdf_new_stream(0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
        pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
  /* Read whole file */
  {
    long nb_read;
    rewind(fp);
    while ((nb_read =
        fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0)
      pdf_add_stream(stream, work_buffer, nb_read);
  }

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Beispiel #11
0
static pdf_obj *
make_param_Cal (png_byte color_type,
		double G, /* Gamma */
		double xw, double yw,
		double xr, double yr, double xg, double yg, double xb, double yb)
{
  pdf_obj *cal_param;
  pdf_obj *white_point, *matrix, *dev_gamma;
  double Xw, Yw, Zw; /* Yw = 1.0 */
  double Xr, Xg, Xb, Yr, Yb, Yg, Zr, Zg, Zb;

#ifndef ABS
#define ABS(x) ((x) < 0 ? -(x) : (x))
#endif
  /*
   * TODO: Check validity
   *
   * Conversion found in
   *
   *  com.sixlegs.image.png - Java package to read and display PNG images
   *  Copyright (C) 1998, 1999, 2001 Chris Nokleberg
   *
   *  http://www.sixlegs.com/software/png/
   *
   */
  {
    double zw, zr, zg, zb;
    double fr, fg, fb;
    double det;

    /* WhitePoint */
    zw = 1 - (xw + yw);
    zr = 1 - (xr + yr); zg = 1 - (xg + yg); zb = 1 - (xb + yb);
    Xw = xw / yw; Yw = 1.0; Zw = zw / yw;

    /* Matrix */
    det = xr * (yg * zb - zg * yb) - xg * (yr * zb - zr * yb) + xb * (yr * zg - zr * yg);
    if (ABS(det) < 1.0e-10) {
      WARN("Non invertible matrix: Maybe invalid value(s) specified in cHRM chunk.");
      return NULL;
    }
    fr  = (Xw * (yg * zb - zg * yb) - xg * (zb - Zw * yb) + xb * (zg - Zw * yg)) / det;
    fg  = (xr * (zb - Zw * yb) - Xw * (yr * zb - zr * yb) + xb * (yr * Zw - zr)) / det;
    fb  = (xr * (yg * Zw - zg) - xg * (yr * Zw - zr) + Xw * (yr * zg - zr * yg)) / det;
    Xr = fr * xr; Yr = fr * yr; Zr = fr * zr;
    Xg = fg * xg; Yg = fg * yg; Zg = fg * zg;
    Xb = fb * xb; Yb = fb * yb; Zb = fb * zb;
  }

  if (G < 1.0e-2) {
    WARN("Unusual Gamma specified: 1.0 / %g", G);
    return NULL;
  }

  cal_param = pdf_new_dict();

  /* White point is always required. */
  white_point = pdf_new_array();
  pdf_add_array(white_point, pdf_new_number(ROUND(Xw, 0.00001)));
  pdf_add_array(white_point, pdf_new_number(ROUND(Yw, 0.00001)));
  pdf_add_array(white_point, pdf_new_number(ROUND(Zw, 0.00001)));
  pdf_add_dict(cal_param, pdf_new_name("WhitePoint"), white_point);

  /* Matrix - default: Identity */
  if (color_type & PNG_COLOR_MASK_COLOR) {
    if (G != 1.0) {
      dev_gamma = pdf_new_array();
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_dict(cal_param, pdf_new_name("Gamma"), dev_gamma);
    }

    matrix = pdf_new_array();
    pdf_add_array(matrix, pdf_new_number(ROUND(Xr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Xg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Xb, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yb, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zb, 0.00001)));
    pdf_add_dict (cal_param, pdf_new_name("Matrix"), matrix);
  } else { /* Gray */
    if (G != 1.0)
      pdf_add_dict(cal_param,
		   pdf_new_name("Gamma"),
		   pdf_new_number(ROUND(G, 0.00001)));
  }

  return cal_param;
}
Beispiel #12
0
pdf_obj *start_png_image (FILE *file, char *res_name)
{
  pdf_obj *result = NULL, *dict = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned long width, height;
  unsigned bit_depth, color_type;
  rewind (file);
  if (!(png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,    
					  NULL, NULL, NULL)) ||
      !(info_ptr = png_create_info_struct (png_ptr))) {
    fprintf (stderr, "\n\nLibpng failed to initialize\n");
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return NULL;
  }
  png_init_io (png_ptr, file);
  /*  png_set_sig_bytes (png_ptr, 0); */
  /* Read PNG header */
  png_read_info (png_ptr, info_ptr);
  {
    png_color_16 default_background;
    png_color_16p file_background;

    default_background.red=255; default_background.green=255;
    default_background.blue=255; default_background.gray=0;
    default_background.index = 0;

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    /* Convert paletted images to true color */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
      png_set_expand(png_ptr);
    }
    /* Limit image component depth to 8 bits */
    if (bit_depth == 16) {
      png_set_strip_16 (png_ptr);
    }
    if (png_get_bKGD(png_ptr, info_ptr, &file_background)) {
      png_set_background(png_ptr, file_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    } else {
      png_set_background(png_ptr, &default_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
    }
  }
  { /* Read the image in raw RGB format */
    int i, rowbytes, pdf_bit_depth;
    png_bytep *rows;
    png_read_update_info(png_ptr, info_ptr);
    rows = NEW (height, png_bytep);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    rows[0] = NEW (rowbytes*height, png_byte);
    for (i=1; i<height; i++) {
      rows[i] = rows[0] + rowbytes * i;
    }
    png_read_image(png_ptr, rows);
    result = pdf_new_stream(STREAM_COMPRESS);
    dict = pdf_stream_dict(result);
    pdf_add_dict (dict, pdf_new_name ("Width"),
		  pdf_new_number(width));
    pdf_add_dict (dict, pdf_new_name ("Height"),
		  pdf_new_number(height));
    if (color_type == PNG_COLOR_TYPE_GRAY) {
      pdf_bit_depth = bit_depth;
    } else {
      pdf_bit_depth = 8;
    }
    pdf_add_dict (dict, pdf_new_name ("BitsPerComponent"),
		  pdf_new_number(pdf_bit_depth));
    if (color_type == PNG_COLOR_TYPE_GRAY ||
	color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceGray"));
    } else{
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceRGB"));
    }
    pdf_add_stream (result, (char *)rows[0], rowbytes*height);
    RELEASE (rows[0]);
    RELEASE (rows);
  }
  { /* Cleanup  */
    if (info_ptr)
      png_destroy_info_struct(png_ptr, &info_ptr);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
  }
  return result;
}
Beispiel #13
0
static void
add_ToUnicode (Type0Font *font)
{
  pdf_obj    *tounicode;
  CIDFont    *cidfont;
  CIDSysInfo *csi;
  char       *fontname;

  /*
   * ToUnicode CMap:
   *
   *  ToUnicode CMaps are usually not required for standard character
   *  collections such as Adobe-Japan1. Identity-H is used for UCS
   *  ordering CID-keyed fonts. External resource must be loaded for
   *  others.
   */

  cidfont = font->descendant;
  if (!cidfont) {
    ERROR("%s: No descendant CID-keyed font.", TYPE0FONT_DEBUG_STR);
    return;
  }

  if (CIDFont_is_ACCFont(cidfont)) {
    /* No need to embed ToUnicode */
    return;
  } else if (CIDFont_is_UCSFont(cidfont)) {
    /*
     * Old version of dvipdfmx mistakenly used Adobe-Identity as Unicode.
     */
    tounicode = pdf_read_ToUnicode_file("Adobe-Identity-UCS2");
    if (!tounicode) { /* This should work */
      tounicode = pdf_new_name("Identity-H");
    }
    pdf_add_dict(font->fontdict, pdf_new_name("ToUnicode"), tounicode);
    return;
  }

  tounicode = NULL;
  csi       = CIDFont_get_CIDSysInfo(cidfont);
  fontname  = CIDFont_get_fontname(cidfont);
  if (CIDFont_get_embedding(cidfont)) {
    fontname += 7; /* FIXME */
  }

  if (!strcmp(csi->registry, "Adobe")    &&
      !strcmp(csi->ordering, "Identity")) {
    switch (CIDFont_get_subtype(cidfont)) {
    case CIDFONT_TYPE2:
      /* PLEASE FIX THIS */
      tounicode = Type0Font_create_ToUnicode_stream(font);
      break;
    default:
      if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1C)) { /* FIXME */
        tounicode = Type0Font_create_ToUnicode_stream(font);
      } else if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1)) { /* FIXME */
	/* Font loader will create ToUnicode and set. */
	return;
      } else {
        tounicode = Type0Font_try_load_ToUnicode_stream(font, fontname);
      }
      break;
    }
  } else {
    char *cmap_base = NEW(strlen(csi->registry) + strlen(csi->ordering) + 2, char);
    sprintf(cmap_base, "%s-%s", csi->registry, csi->ordering);
    tounicode = Type0Font_try_load_ToUnicode_stream(font, cmap_base);
    RELEASE(cmap_base);
  }

  if (tounicode) {
    pdf_add_dict(font->fontdict,
		 pdf_new_name("ToUnicode"), tounicode);
  } else {
    WARN("Failed to load ToUnicode CMap for font \"%s\"", fontname);
  }

  return;
}
Beispiel #14
0
/* ximage here is the result. DONT USE IT FOR PASSING OPTIONS! */
int
pdf_include_page (pdf_ximage        *ximage,
                  FILE              *image_file,
                  const char        *ident,
                  load_options       options)
{
  pdf_file *pf;
  xform_info info;
  pdf_obj *contents = NULL, *catalog;
  pdf_obj *page = NULL, *resources = NULL, *markinfo = NULL;

  pf = pdf_open(ident, image_file);
  if (!pf)
    return -1;

  if (pdf_file_get_version(pf) > pdf_get_version()) {
    WARN("Trying to include PDF file which has newer version number " \
         "than output PDF: 1.%d.", pdf_get_version());
  }

  pdf_ximage_init_form_info(&info);

  if (options.page_no == 0)
    options.page_no = 1;
  page = pdf_doc_get_page(pf,
                          options.page_no, options.bbox_type,
                          &info.bbox, &resources);

  if(!page)
    goto error_silent;

  catalog = pdf_file_get_catalog(pf);
  markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo"));
  if (markinfo) {
    pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(markinfo, "Marked"));
    pdf_release_obj(markinfo);
    if (!PDF_OBJ_BOOLEANTYPE(tmp)) {
      if (tmp)
	pdf_release_obj(tmp);
      goto error;
    } else if (pdf_boolean_value(tmp)) {
      WARN("PDF file is tagged... Ignoring tags.");
    }
    pdf_release_obj(tmp);
  }

  contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents"));
  pdf_release_obj(page);
  page = NULL;

  /*
   * Handle page content stream.
   */
  {
    pdf_obj *content_new;

    if (!contents) {
      /*
       * Empty page
       */
      content_new = pdf_new_stream(0);
      /* TODO: better don't include anything if the page is empty */
    } else if (PDF_OBJ_STREAMTYPE(contents)) {
      /* 
       * We must import the stream because its dictionary
       * may contain indirect references.
       */
      content_new = pdf_import_object(contents);
    } else if (PDF_OBJ_ARRAYTYPE(contents)) {
      /*
       * Concatenate all content streams.
       */
      int idx, len = pdf_array_length(contents);
      content_new = pdf_new_stream(STREAM_COMPRESS);
      for (idx = 0; idx < len; idx++) {
	pdf_obj *content_seg = pdf_deref_obj(pdf_get_array(contents, idx));
	if (!PDF_OBJ_STREAMTYPE(content_seg) ||
	    pdf_concat_stream(content_new, content_seg) < 0) {
	  pdf_release_obj(content_seg);
	  pdf_release_obj(content_new);
	  goto error;
	}
	pdf_release_obj(content_seg);
      }
    } else {
      goto error;
    }

    if (contents)
      pdf_release_obj(contents);
    contents = content_new;
  }

  /*
   * Add entries to contents stream dictionary.
   */
  {
    pdf_obj *contents_dict, *bbox, *matrix;

    contents_dict = pdf_stream_dict(contents);
    pdf_add_dict(contents_dict,
                 pdf_new_name("Type"), pdf_new_name("XObject"));
    pdf_add_dict(contents_dict,
                 pdf_new_name("Subtype"), pdf_new_name("Form"));
    pdf_add_dict(contents_dict,
                 pdf_new_name("FormType"), pdf_new_number(1.0));

    bbox = pdf_new_array();
    pdf_add_array(bbox, pdf_new_number(info.bbox.llx));
    pdf_add_array(bbox, pdf_new_number(info.bbox.lly));
    pdf_add_array(bbox, pdf_new_number(info.bbox.urx));
    pdf_add_array(bbox, pdf_new_number(info.bbox.ury));

    pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox);

    matrix = pdf_new_array();
    pdf_add_array(matrix, pdf_new_number(1.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(1.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(0.0));

    pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix);

    pdf_add_dict(contents_dict, pdf_new_name("Resources"),
                 pdf_import_object(resources));
    pdf_release_obj(resources);
  }

  pdf_close(pf);

  pdf_ximage_set_form(ximage, &info, contents);

  return 0;

 error:
  WARN("Cannot parse document. Broken PDF file?");
 error_silent:
  if (resources)
    pdf_release_obj(resources);
  if (markinfo)
    pdf_release_obj(markinfo);
  if (page)
    pdf_release_obj(page);
  if (contents)
    pdf_release_obj(contents);

  pdf_close(pf);

  return -1;
}
Beispiel #15
0
int
pdf_font_load_pkfont (pdf_font *font)
{
  pdf_obj  *fontdict;
  char     *usedchars;
  char     *ident;
  unsigned  dpi;
  FILE     *fp;
  double    point_size, pix2charu;
  int       opcode, code, firstchar, lastchar, prev;
  pdf_obj  *charprocs, *procset, *encoding, *tmp_array;
  double    widths[256];
  pdf_rect  bbox;
  char      charavail[256];
#if  ENABLE_GLYPHENC
  int       encoding_id;
  char    **enc_vec;
#endif /* ENABLE_GLYPHENC */
  int       error = 0;

  if (!pdf_font_is_in_use(font)) {
    return 0;
  }

  ident       = pdf_font_get_ident(font);
  point_size  = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE);
  usedchars   = pdf_font_get_usedchars(font);
#if  ENABLE_GLYPHENC
  encoding_id = pdf_font_get_encoding(font);
  if (encoding_id < 0)
    enc_vec = NULL;
  else {
    enc_vec = pdf_encoding_get_encoding(encoding_id);
  }
#endif /* ENABLE_GLYPHENC */

  ASSERT(ident && usedchars && point_size > 0.0);

  dpi  = truedpi(ident, point_size, base_dpi);
  
  {
    char *fontfile =   pdf_font_get_fontfile  (font);
    
    if (fontfile)
      fp = MFOPEN(fontfile, FOPEN_RBIN_MODE);
    else
      fp = dpx_open_pk_font_at(ident, dpi);
  }
  
  
  
  if (!fp) {
    ERROR("Could not find/open PK font file: %s (at %udpi)", ident, dpi);
  }

  memset(charavail, 0, 256);
  charprocs  = pdf_new_dict();
  /* Include bitmap as 72dpi image:
   * There seems to be problems in "scaled" bitmap glyph
   * rendering in several viewers.
   */
  pix2charu  = 72. * 1000. / ((double) base_dpi) / point_size;
  bbox.llx = bbox.lly =  HUGE_VAL;
  bbox.urx = bbox.ury = -HUGE_VAL;
  while ((opcode = fgetc(fp)) >= 0 && opcode != PK_POST) {
    if (opcode < 240) {
      struct pk_header_  pkh;

      error = read_pk_char_header(&pkh, opcode, fp);
      if (error)
        ERROR("Error in reading PK character header.");
      else if (charavail[pkh.chrcode & 0xff])
        WARN("More than two bitmap image for single glyph?: font=\"%s\" code=0x%02x",
             ident, pkh.chrcode);

      if (!usedchars[pkh.chrcode & 0xff])
        do_skip(fp, pkh.pkt_len);
      else {
        char          *charname;
        pdf_obj       *charproc;
        unsigned char *pkt_ptr;
        size_t         bytesread;
        double         charwidth;

        /* Charwidth in PDF units */
        charwidth = ROUND(1000.0 * pkh.wd / (((double) (1<<20))*pix2charu), 0.1);
        widths[pkh.chrcode & 0xff] = charwidth;

        /* Update font BBox info */
        bbox.llx = MIN(bbox.llx, -pkh.bm_hoff);
        bbox.lly = MIN(bbox.lly,  pkh.bm_voff - pkh.bm_ht);
        bbox.urx = MAX(bbox.urx,  pkh.bm_wd - pkh.bm_hoff);
        bbox.ury = MAX(bbox.ury,  pkh.bm_voff);

        pkt_ptr = NEW(pkh.pkt_len, unsigned char);
        if ((bytesread = fread(pkt_ptr, 1, pkh.pkt_len, fp))!= pkh.pkt_len) {
          ERROR("Only %ld bytes PK packet read. (expected %ld bytes)",
                bytesread, pkh.pkt_len);
        }
        charproc = create_pk_CharProc_stream(&pkh, charwidth, pkt_ptr, bytesread);
        RELEASE(pkt_ptr);
        if (!charproc)
          ERROR("Unpacking PK character data failed.");
#if  ENABLE_GLYPHENC
        if (encoding_id >= 0 && enc_vec) {
          charname = (char *) enc_vec[pkh.chrcode & 0xff];
          if (!charname) {
            WARN("\".notdef\" glyph used in font (code=0x%02x): %s", pkh.chrcode, ident);
            charname = work_buffer;
            pk_char2name(charname, pkh.chrcode);
          }
        }
        else
#endif /* ENABLE_GLYPHENC */
        {
          charname = work_buffer;
          pk_char2name(charname, pkh.chrcode);
        }

        pdf_add_dict(charprocs, pdf_new_name(charname), pdf_ref_obj(charproc)); /* _FIXME_ */
        pdf_release_obj(charproc);
      }
      charavail[pkh.chrcode & 0xff] = 1;
    } else { /* A command byte */
      switch (opcode) {
      case PK_NO_OP: break;
      case PK_XXX1: do_skip(fp, get_unsigned_byte(fp));   break;
      case PK_XXX2: do_skip(fp, get_unsigned_pair(fp));   break;
      case PK_XXX3: do_skip(fp, get_unsigned_triple(fp)); break;
      case PK_XXX4: do_skip(fp, get_unsigned_quad(fp));   break;
      case PK_YYY:  do_skip(fp, 4);  break;
      case PK_PRE:  do_preamble(fp); break;
      }
    }
  }
Beispiel #16
0
static int
CIDFont_base_open (CIDFont *font, const char *name, CIDSysInfo *cmap_csi, cid_opt *opt)
{
  pdf_obj *fontdict, *descriptor;
  char    *fontname = NULL;
  int      idx;

  ASSERT(font);

  for (idx = 0; cid_basefont[idx].fontname != NULL; idx++) {
    if (!strcmp(name, cid_basefont[idx].fontname) ||
        (strlen(name) == strlen(cid_basefont[idx].fontname) - strlen("-Acro") &&
         !strncmp(name, cid_basefont[idx].fontname,
                  strlen(cid_basefont[idx].fontname)-strlen("-Acro")))
        )
      break;
  }

  if (cid_basefont[idx].fontname == NULL)
    return -1;

  fontname = NEW(strlen(name)+12, char);
  memset(fontname, 0, strlen(name)+12);
  strcpy(fontname, name);

  switch (opt->style) {
  case FONT_STYLE_BOLD:
    strcat(fontname, ",Bold");
    break;
  case FONT_STYLE_ITALIC:
    strcat(fontname, ",Italic");
    break;
  case FONT_STYLE_BOLDITALIC:
    strcat(fontname, ",BoldItalic");
    break;
  }
  {
    const char *start;
    const char *end;

    start = cid_basefont[idx].fontdict;
    end   = start + strlen(start);
    fontdict   = parse_pdf_dict(&start, end, NULL);
    start = cid_basefont[idx].descriptor;
    end   = start + strlen(start);
    descriptor = parse_pdf_dict(&start, end, NULL);

    ASSERT(fontdict && descriptor);
  }

  font->fontname = fontname;
  font->flags   |= FONT_FLAG_BASEFONT;
  {
    char    *registry, *ordering;
    int      supplement;
    pdf_obj *tmp;

    tmp = pdf_lookup_dict(fontdict, "CIDSystemInfo");

    ASSERT( tmp && pdf_obj_typeof(tmp) == PDF_DICT );

    registry   = pdf_string_value(pdf_lookup_dict(tmp, "Registry"));
    ordering   = pdf_string_value(pdf_lookup_dict(tmp, "Ordering"));
    supplement = pdf_number_value(pdf_lookup_dict(tmp, "Supplement"));
    if (cmap_csi) { /* NULL for accept any */
      if (strcmp(registry, cmap_csi->registry) ||
          strcmp(ordering, cmap_csi->ordering))
        ERROR("Inconsistent CMap used for CID-keyed font %s.",
              cid_basefont[idx].fontname);
      else if (supplement < cmap_csi->supplement) {
        WARN("CMap has higher supplement number than CIDFont: %s", fontname);
        WARN("Some chracters may not be displayed or printed.");
      }
    }
    font->csi = NEW(1, CIDSysInfo);
    font->csi->registry = NEW(strlen(registry)+1, char);
    font->csi->ordering = NEW(strlen(ordering)+1, char);
    strcpy(font->csi->registry, registry);
    strcpy(font->csi->ordering, ordering);
    font->csi->supplement = supplement;
  }

  {
    pdf_obj *tmp;
    char    *type;

    tmp  = pdf_lookup_dict(fontdict, "Subtype");
    ASSERT( tmp != NULL && pdf_obj_typeof(tmp) == PDF_NAME );

    type = pdf_name_value(tmp);
    if (!strcmp(type, "CIDFontType0"))
      font->subtype = CIDFONT_TYPE0;
    else if (!strcmp(type, "CIDFontType2"))
      font->subtype = CIDFONT_TYPE2;
    else {
      ERROR("Unknown CIDFontType \"%s\"", type);
    }
  }

  if (cidoptflags & CIDFONT_FORCE_FIXEDPITCH) {
    if (pdf_lookup_dict(fontdict, "W")) {
       pdf_remove_dict(fontdict, "W");
    }
    if (pdf_lookup_dict(fontdict, "W2")) {
       pdf_remove_dict(fontdict, "W2");
    }
  }

  pdf_add_dict(fontdict,   pdf_new_name("Type"),     pdf_new_name("Font"));
  pdf_add_dict(fontdict,   pdf_new_name("BaseFont"), pdf_new_name(fontname));
  pdf_add_dict(descriptor, pdf_new_name("Type"),     pdf_new_name("FontDescriptor"));
  pdf_add_dict(descriptor, pdf_new_name("FontName"), pdf_new_name(fontname));

  font->fontdict   = fontdict;
  font->descriptor = descriptor;

  opt->embed = 0;

  return  0;
}
Beispiel #17
0
/* bitdepth is always 8 (16 is not supported) */
static pdf_obj *
strip_soft_mask (png_structp png_ptr, png_infop info_ptr,
		 /* next two values will be modified. */
		 png_bytep image_data_ptr, png_uint_32p rowbytes_ptr,
		 png_uint_32 width, png_uint_32 height)
{
  pdf_obj    *smask, *dict;
  png_byte    color_type, bpc;
  png_bytep   smask_data_ptr;
  png_uint_32 i;

  color_type = png_get_color_type(png_ptr, info_ptr);
  bpc        = png_get_bit_depth (png_ptr, info_ptr);
  if (color_type & PNG_COLOR_MASK_COLOR) {
    int bps = (bpc == 8) ? 4 : 8;
    if (*rowbytes_ptr != bps*width*sizeof(png_byte)) { /* Something wrong */
      WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR);
      return NULL;
    }
  } else {
    int bps = (bpc == 8) ? 2 : 4;
    if (*rowbytes_ptr != bps*width*sizeof(png_byte)) { /* Something wrong */
      WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR);
      return NULL;
    }
  }

  smask = pdf_new_stream(STREAM_COMPRESS);
  dict  = pdf_stream_dict(smask);
  pdf_add_dict(dict, pdf_new_name("Type"),    pdf_new_name("XObject"));
  pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image"));
  pdf_add_dict(dict, pdf_new_name("Width"),      pdf_new_number(width));
  pdf_add_dict(dict, pdf_new_name("Height"),     pdf_new_number(height));
  pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray"));
  pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(bpc));

  smask_data_ptr = (png_bytep) NEW((bpc/8)*width*height, png_byte);

  switch (color_type) {
  case PNG_COLOR_TYPE_RGB_ALPHA:
    if (bpc == 8) {
    for (i = 0; i < width*height; i++) {
      memmove(image_data_ptr+(3*i), image_data_ptr+(4*i), 3);
      smask_data_ptr[i] = image_data_ptr[4*i+3];
    }
    *rowbytes_ptr = 3*width*sizeof(png_byte);
    } else {
      for (i = 0; i < width*height; i++) {
        memmove(image_data_ptr+(6*i), image_data_ptr+(8*i), 6);
        smask_data_ptr[2*i]   = image_data_ptr[8*i+6];
        smask_data_ptr[2*i+1] = image_data_ptr[8*i+7];
      }
      *rowbytes_ptr = 6*width*sizeof(png_byte);
    }
    break;
  case PNG_COLOR_TYPE_GRAY_ALPHA:
    if (bpc == 8) {
    for (i = 0; i < width*height; i++) {
      image_data_ptr[i] = image_data_ptr[2*i];
      smask_data_ptr[i] = image_data_ptr[2*i+1];
    }
    *rowbytes_ptr = width*sizeof(png_byte);
    } else {
      for (i = 0; i < width*height; i++) {
        image_data_ptr[2*i]   = image_data_ptr[4*i];
        image_data_ptr[2*i+1] = image_data_ptr[4*i+1];
        smask_data_ptr[2*i]   = image_data_ptr[4*i+2];
        smask_data_ptr[2*i+1] = image_data_ptr[4*i+3];
      }
      *rowbytes_ptr = 2*width*sizeof(png_byte);      
    }
    break;
  default:
    WARN("You found a bug in pngimage.c!");
    pdf_release_obj(smask);
    RELEASE(smask_data_ptr);
    return NULL;
  }

  pdf_add_stream(smask, smask_data_ptr, (bpc/8)*width*height);
  RELEASE(smask_data_ptr);

  return smask;
}
Beispiel #18
0
pdf_obj *
CMap_create_stream (CMap *cmap)
{
  pdf_obj         *stream;
  pdf_obj         *stream_dict;
  CIDSysInfo      *csi;
  struct sbuf      wbuf;
  struct rangeDef *ranges;
  unsigned char   *codestr;
  int              i, j, count = 0;

  if (!cmap || !CMap_is_valid(cmap)) {
    WARN("Invalid CMap");
    return NULL;
  }

  if (cmap->type == CMAP_TYPE_IDENTITY)
    return NULL;

  stream      = pdf_new_stream(STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  csi = CMap_get_CIDSysInfo(cmap);
  if (!csi) {
    csi = (cmap->type != CMAP_TYPE_TO_UNICODE) ?
      &CSI_IDENTITY : &CSI_UNICODE;
  }

  if (cmap->type != CMAP_TYPE_TO_UNICODE) {
    pdf_obj *csi_dict;

    csi_dict = pdf_new_dict();
    pdf_add_dict(csi_dict,
		 pdf_new_name("Registry"),
		 pdf_new_string(csi->registry, strlen(csi->registry)));
    pdf_add_dict(csi_dict,
		 pdf_new_name("Ordering"),
		 pdf_new_string(csi->ordering, strlen(csi->ordering)));
    pdf_add_dict(csi_dict,
		 pdf_new_name("Supplement"),
		 pdf_new_number(csi->supplement));

    pdf_add_dict(stream_dict,
		 pdf_new_name("Type"),
		 pdf_new_name("CMap"));
    pdf_add_dict(stream_dict,
		 pdf_new_name("CMapName"),
		 pdf_new_name(cmap->name));
    pdf_add_dict(stream_dict,
		 pdf_new_name("CIDSystemInfo"), csi_dict);
    if (cmap->wmode != 0)
      pdf_add_dict(stream_dict,
		   pdf_new_name("WMode"),
		   pdf_new_number(cmap->wmode));
  }

  /* TODO:
   * Predefined CMaps need not to be embedded.
   */
  if (cmap->useCMap) {
    ERROR("UseCMap found (not supported yet)...");
    if (CMap_is_Identity(cmap->useCMap)) { /* not sure */
      if (CMap_get_wmode(cmap) == 1) {
	pdf_add_dict(stream_dict,
		     pdf_new_name("UseCMap"),
		     pdf_new_name("Identity-V"));
      } else {
    	pdf_add_dict(stream_dict,
		     pdf_new_name("UseCMap"),
		     pdf_new_name("Identity-H"));
      }
    } else {
      int      res_id;
      pdf_obj *ucmap_ref;

      res_id = pdf_findresource("CMap", CMap_get_name(cmap->useCMap));
      if (res_id >= 0) {
	ucmap_ref = pdf_get_resource_reference(res_id);
      } else {
	pdf_obj *ucmap_obj;

	ucmap_obj = CMap_create_stream(cmap->useCMap);
	if (!ucmap_obj) {
	  ERROR("Uh ah. I cannot continue...");
	}

	res_id = pdf_defineresource("CMap",
				    CMap_get_name(cmap->useCMap),
				    ucmap_obj, PDF_RES_FLUSH_IMMEDIATE);
	ucmap_ref = pdf_get_resource_reference(res_id);
      }
      pdf_add_dict(stream_dict, pdf_new_name("UseCMap"), ucmap_ref);
    }
  }

#define WBUF_SIZE 40960
  wbuf.buf = NEW(WBUF_SIZE, char);
  codestr  = NEW(cmap->profile.maxBytesIn, unsigned char);
  memset(codestr, 0, cmap->profile.maxBytesIn);

  wbuf.curptr = wbuf.buf;
  wbuf.limptr = wbuf.buf + WBUF_SIZE -
    2 * (cmap->profile.maxBytesIn + cmap->profile.maxBytesOut) + 16;

  /* Start CMap */
  pdf_add_stream(stream, (const void *) CMAP_BEGIN, strlen(CMAP_BEGIN));

  wbuf.curptr += sprintf(wbuf.curptr, "/CMapName ");
  write_name(&wbuf.curptr, wbuf.limptr, cmap->name);
  wbuf.curptr += sprintf(wbuf.curptr, " def\n");
  wbuf.curptr += sprintf(wbuf.curptr, "/CMapType %d def\n" , cmap->type);
  if (cmap->wmode != 0 &&
      cmap->type != CMAP_TYPE_TO_UNICODE)
    wbuf.curptr += sprintf(wbuf.curptr, "/WMode %d def\n", cmap->wmode);

#define CMAP_CSI_FMT "/CIDSystemInfo <<\n\
  /Registry (%s)\n\
  /Ordering (%s)\n\
  /Supplement %d\n\
>> def\n"
  wbuf.curptr += sprintf(wbuf.curptr, "/CIDSystemInfo <<\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Registry ");
  write_string(&wbuf.curptr, wbuf.limptr, csi->registry);
  wbuf.curptr += sprintf(wbuf.curptr, "\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Ordering ");
  write_string(&wbuf.curptr, wbuf.limptr, csi->ordering);
  wbuf.curptr += sprintf(wbuf.curptr, "\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Supplement %d\n>> def\n",
    csi->supplement);
  pdf_add_stream(stream, wbuf.buf, (int)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;

  /* codespacerange */
  ranges = cmap->codespace.ranges;
  wbuf.curptr += sprintf(wbuf.curptr,
			 "%d begincodespacerange\n", cmap->codespace.num);
  for (i = 0; i < cmap->codespace.num; i++) {
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeLo[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = ' ';
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeHi[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = '\n';
  }
  pdf_add_stream(stream, wbuf.buf, (int)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;
  pdf_add_stream(stream,
		 "endcodespacerange\n", strlen("endcodespacerange\n"));

  /* CMap body */
  if (cmap->mapTbl) {
    count = write_map(cmap->mapTbl,
		      0, codestr, 0, &wbuf, stream); /* Top node */
    if (count > 0) { /* Flush */
      char fmt_buf[32];
      if (count > 100)
	ERROR("Unexpected error....: %d", count);
      sprintf(fmt_buf, "%d beginbfchar\n", count);
      pdf_add_stream(stream, fmt_buf,  strlen(fmt_buf));
      pdf_add_stream(stream,
		     wbuf.buf, (int) (wbuf.curptr - wbuf.buf));
      pdf_add_stream(stream,
		     "endbfchar\n", strlen("endbfchar\n"));
      count = 0;
      wbuf.curptr = wbuf.buf;
    }
  }
  /* End CMap */
  pdf_add_stream(stream, CMAP_END, strlen(CMAP_END));

  RELEASE(codestr);
  RELEASE(wbuf.buf);

  return stream;
}
Beispiel #19
0
int
jpeg_include_image (pdf_ximage *ximage, FILE *fp)
{
  pdf_obj    *stream;
  pdf_obj    *stream_dict;
  pdf_obj    *colorspace;
  int         colortype;
  ximage_info info;
  struct JPEG_info j_info;

  if (!check_for_jpeg(fp)) {
    WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR);
    rewind(fp);
    return -1;
  }
  /* File position is 2 here... */

  pdf_ximage_init_image_info(&info);

  JPEG_info_init(&j_info);

  if (JPEG_scan_file(&j_info, fp) < 0) {
    WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR);
    JPEG_info_clear(&j_info);
    return -1;
  }

  switch (j_info.num_components) {
  case 1:
    colortype = PDF_COLORSPACE_TYPE_GRAY;
    break;
  case 3:
    colortype = PDF_COLORSPACE_TYPE_RGB;
    break;
  case 4:
    colortype = PDF_COLORSPACE_TYPE_CMYK;
    break;
  default:
    WARN("%s: Unknown color space (num components: %d)",
	 JPEG_DEBUG_STR, info.num_components);
    JPEG_info_clear(&j_info);
    return -1;
  }

  /* JPEG image use DCTDecode. */
  stream      = pdf_new_stream (0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
	       pdf_new_name("Filter"), pdf_new_name("DCTDecode"));

  colorspace  = NULL;
  if (j_info.flags & HAVE_APPn_ICC) {
    pdf_obj *icc_stream, *intent;

    icc_stream = JPEG_get_iccp(&j_info);

    if (!icc_stream)
      colorspace = NULL;
    else {
      int   cspc_id;

      if (iccp_check_colorspace(colortype,
				pdf_stream_dataptr(icc_stream),
				pdf_stream_length (icc_stream)) < 0)
	colorspace = NULL;
      else {
	cspc_id = iccp_load_profile(NULL, /* noname */
				    pdf_stream_dataptr(icc_stream),
				    pdf_stream_length (icc_stream));
	if (cspc_id < 0)
	  colorspace = NULL;
	else {
	  colorspace = pdf_get_colorspace_reference(cspc_id);
	  intent     = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream),
						 pdf_stream_length (icc_stream));
	  if (intent)
	    pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);
	}
      }
      pdf_release_obj(icc_stream);
    }
  }

  /* No ICC or invalid ICC profile. */
  if (!colorspace) {
    switch (colortype) {
    case PDF_COLORSPACE_TYPE_GRAY:
      colorspace = pdf_new_name("DeviceGray");
      break;
    case PDF_COLORSPACE_TYPE_RGB:
      colorspace = pdf_new_name("DeviceRGB");
      break;
    case PDF_COLORSPACE_TYPE_CMYK:
      colorspace = pdf_new_name("DeviceCMYK");
      break;
    }
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4)

  if (IS_ADOBE_CMYK(j_info)) {
    pdf_obj *decode;
    int      i;

    WARN("Adobe CMYK JPEG: Inverted color assumed.");
    decode = pdf_new_array();
    for (i = 0; i < j_info.num_components; i++) {
      pdf_add_array(decode, pdf_new_number(1.0));
      pdf_add_array(decode, pdf_new_number(0.0));
    }
    pdf_add_dict(stream_dict, pdf_new_name("Decode"), decode);
  }

  /* Copy file */
  JPEG_copy_stream(&j_info, stream, fp);

  info.width              = j_info.width;
  info.height             = j_info.height;
  info.bits_per_component = j_info.bits_per_component;
  info.num_components     = j_info.num_components;

  jpeg_get_density(&j_info, &info.xdensity, &info.ydensity);

  pdf_ximage_set_image(ximage, &info, stream);
  JPEG_info_clear(&j_info);

  return 0;
}
Beispiel #20
0
int
png_include_image (pdf_ximage *ximage, FILE *png_file)
{
  pdf_obj  *stream;
  pdf_obj  *stream_dict;
  pdf_obj  *colorspace, *mask, *intent;
  png_bytep stream_data_ptr;
  int       trans_type;
  ximage_info info;
  /* Libpng stuff */
  png_structp png_ptr;
  png_infop   png_info_ptr;
  png_byte    bpc, color_type;
  png_uint_32 width, height, rowbytes;

  pdf_ximage_init_image_info(&info);

  stream      = NULL;
  stream_dict = NULL;
  colorspace  = mask = intent = NULL;

  rewind (png_file);
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn);
  if (png_ptr == NULL ||
      (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) {
    WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return -1;
  }

#if PNG_LIBPNG_VER >= 10603
  /* ignore possibly incorrect CMF bytes */
  png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
#endif

  /* Inititializing file IO. */
  png_init_io (png_ptr, png_file);

  /* Read PNG info-header and get some info. */
  png_read_info(png_ptr, png_info_ptr);
  color_type = png_get_color_type  (png_ptr, png_info_ptr);
  width      = png_get_image_width (png_ptr, png_info_ptr);
  height     = png_get_image_height(png_ptr, png_info_ptr);
  bpc        = png_get_bit_depth   (png_ptr, png_info_ptr);

  /* Ask libpng to convert down to 8-bpc. */
  if (bpc > 8) {
    if (pdf_get_version() < 5) {
      WARN("%s: 16-bpc PNG requires PDF version 1.5.", PNG_DEBUG_STR);
    png_set_strip_16(png_ptr);
    bpc = 8;
  }
  }
  /* Ask libpng to gamma-correct.
   * It is wrong to assume screen gamma value 2.2 but...
   * We do gamma correction here only when uncalibrated color space is used. 
   */
  if (!png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM) &&
       png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) {
    double G = 1.0;
    png_get_gAMA (png_ptr, png_info_ptr, &G);
    png_set_gamma(png_ptr, 2.2, G);
  }

  trans_type = check_transparency(png_ptr, png_info_ptr);
  /* check_transparency() does not do updata_info() */
  png_read_update_info(png_ptr, png_info_ptr);
  rowbytes = png_get_rowbytes(png_ptr, png_info_ptr);

  /* Values listed below will not be modified in the remaining process. */
  info.width  = width;
  info.height = height;
  info.bits_per_component = bpc;

  if (compat_mode)
    info.xdensity = info.ydensity = 72.0 / 100.0;
  else
  {
    png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr);
    png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr);

    if (xppm > 0)
      info.xdensity = 72.0 / 0.0254 / xppm;
    if (yppm > 0)
      info.ydensity = 72.0 / 0.0254 / yppm;
  }

  stream      = pdf_new_stream (STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte);
  read_image_data(png_ptr, stream_data_ptr, height, rowbytes);

  /* Non-NULL intent means there is valid sRGB chunk. */
  intent = get_rendering_intent(png_ptr, png_info_ptr);
  if (intent)
    pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);

  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:

    colorspace = create_cspace_Indexed(png_ptr, png_info_ptr);

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      /* Color-key masking */
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      /* Soft mask */
      mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height);
      break;
    default:
      /* Nothing to be done here.
       * No tRNS chunk or image already composited with background color.
       */
      break;
    }
    info.num_components = 1;

    break;
  case PNG_COLOR_TYPE_RGB:
  case PNG_COLOR_TYPE_RGB_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceRGB");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    /* rowbytes changes 4 to 3 at here */
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 3;
    break;

  case PNG_COLOR_TYPE_GRAY:
  case PNG_COLOR_TYPE_GRAY_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalGray(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceGray");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 1;
    break;

  default:
    WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type);
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

  pdf_add_stream(stream, stream_data_ptr, rowbytes*height);
  RELEASE(stream_data_ptr);

  if (mask) {
    if (trans_type == PDF_TRANS_TYPE_BINARY)
      pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask);
    else if (trans_type == PDF_TRANS_TYPE_ALPHA) {
      if (info.bits_per_component >= 8 && info.width > 64) {
        pdf_stream_set_predictor(mask, 2, info.width,
                                 info.bits_per_component, 1);
      }
      pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask));
      pdf_release_obj(mask);
    } else {
      WARN("%s: Unknown transparency type...???", PNG_DEBUG_STR);
      pdf_release_obj(mask);
    }
  }

  /* Finally read XMP Metadata
   * See, XMP Specification Part 3, Storage in Files
   * http://www.adobe.com/jp/devnet/xmp.html
   *
   * We require libpng version >= 1.6.14 since prior versions
   * of libpng had a bug that incorrectly treat the compression
   * flag of iTxt chunks.
   */
#if PNG_LIBPNG_VER >= 10614
  if (pdf_get_version() >= 4) {
    png_textp text_ptr;
    pdf_obj  *XMP_stream, *XMP_stream_dict;
    int       i, num_text;
    int       have_XMP = 0;

    num_text = png_get_text(png_ptr, png_info_ptr, &text_ptr, NULL);
    for (i = 0; i < num_text; i++) {
      if (!memcmp(text_ptr[i].key, "XML:com.adobe.xmp", 17)) {
        /* XMP found */
        if (text_ptr[i].compression != PNG_ITXT_COMPRESSION_NONE ||
            text_ptr[i].itxt_length == 0)
          WARN("%s: Invalid value(s) in iTXt chunk for XMP Metadata.", PNG_DEBUG_STR);
        else if (have_XMP)
          WARN("%s: Multiple XMP Metadata. Don't know how to treat it.", PNG_DEBUG_STR);
        else {
          /* We compress XMP metadata for included images here.
           * It is not recommended to compress XMP metadata for PDF documents but
           * we compress XMP metadata for included images here to avoid confusing
           * application programs that only want PDF document global XMP metadata
           * and scan for that.
           */
          XMP_stream = pdf_new_stream(STREAM_COMPRESS);
          XMP_stream_dict = pdf_stream_dict(XMP_stream);
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Type"), pdf_new_name("Metadata"));
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Subtype"), pdf_new_name("XML"));
          pdf_add_stream(XMP_stream, text_ptr[i].text, text_ptr[i].itxt_length);
          pdf_add_dict(stream_dict,
                       pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream));
          pdf_release_obj(XMP_stream);
          have_XMP = 1;
        }
      }
    }
  }
#endif /* PNG_LIBPNG_VER */

  png_read_end(png_ptr, NULL);

  /* Cleanup */
  if (png_info_ptr)
    png_destroy_info_struct(png_ptr, &png_info_ptr);
  if (png_ptr)
    png_destroy_read_struct(&png_ptr, NULL, NULL);
  if (color_type != PNG_COLOR_TYPE_PALETTE &&
      info.bits_per_component >= 8 &&
      info.height > 64) {
    pdf_stream_set_predictor(stream, 15, info.width,
                             info.bits_per_component, info.num_components);
  }
  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}