Пример #1
0
void
plD_tidy_plm(PLStream *pls)
{
    U_CHAR c = (U_CHAR) CLOSE;

    dbug_enter("plD_tidy_plm");

    plm_wr( pdf_wr_1byte(pls->pdfs, c) );
    pdf_close(pls->pdfs);
    free_mem(pls->dev);
}
Пример #2
0
FILE *
plLibOpen(const char *fn)		/* pmr: const */
{
    FILE *ret = NULL;

    PDFstrm *pdfs = plLibOpenPdfstrm(fn);
    if (pdfs == NULL) {
        return NULL;
    }
    if (pdfs->file != NULL) {
        ret = pdfs->file;
	pdfs->file = NULL;
    }
    pdf_close(pdfs);
    return ret;
}
Пример #3
0
int
pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user)
{
  pdf_obj *page_tree, *contents;
  int depth = 0, top = -1;
  const char *clip_path, *end_path;
  char *save_path, *temp;
  pdf_tmatrix M;
  double stack[6];
  pdf_file *pf;
  
  pf = pdf_open(NULL, image_file);
  if (!pf)
    return -1;

  pdf_dev_currentmatrix(&M);
  pdf_invertmatrix(&M);
  M.e += x_user; M.f += y_user;
  page_tree = pdf_get_page_obj (pf, pageNo, NULL, NULL);
  if (!page_tree) {
    pdf_close(pf);
    return -1;
  }

  contents = pdf_get_page_content(page_tree);
  pdf_release_obj(page_tree);
  if (!contents) {
    pdf_close(pf);
    return -1;
  }

  pdf_doc_add_page_content(" ", 1);

  save_path = malloc(pdf_stream_length(contents) + 1);
  strncpy(save_path, (const char *) pdf_stream_dataptr(contents),  pdf_stream_length(contents));
  clip_path = save_path;
  end_path = clip_path + pdf_stream_length(contents);
  depth = 0;

  for (; clip_path < end_path; clip_path++) {
    int color_dimen = 0;	/* silence uninitialized warning */
    char *token;
    skip_white(&clip_path, end_path);
    if (clip_path == end_path)
      break;
    if (depth > 1) {
      if (*clip_path == 'q')
        depth++;
      if (*clip_path == 'Q')
	depth--;
      parse_ident(&clip_path, end_path);
      continue;
    } else if (*clip_path == '-'
	    || *clip_path == '+'
	    || *clip_path == '.'
	    || isdigit((unsigned char)*clip_path)) {
      stack[++top] = strtod(clip_path, &temp);
      clip_path = temp;
    } else if (*clip_path == '[') {
      /* Ignore, but put a dummy value on the stack (in case of d operator) */
      parse_pdf_array(&clip_path, end_path, pf);
      stack[++top] = 0;
    } else if (*clip_path == '/') {
      if  (strncmp("/DeviceGray",	clip_path, 11) == 0
	|| strncmp("/Indexed",		clip_path, 8)  == 0
	|| strncmp("/CalGray",		clip_path, 8)  == 0) {
	color_dimen = 1;
	continue;
      }
      else if  (strncmp("/DeviceRGB",	clip_path, 10) == 0
	|| strncmp("/CalRGB",		clip_path, 7)  == 0
	|| strncmp("/Lab",		clip_path, 4)  == 0) {
	color_dimen = 3;
	continue;
      }
      else if  (strncmp("/DeviceCMYK",	clip_path, 11) == 0) {
	color_dimen = 4;
	continue;
      }
      else {
        clip_path++;
        parse_ident(&clip_path, end_path);
	skip_white(&clip_path, end_path);
	token = parse_ident(&clip_path, end_path);
        if (strcmp(token, "gs") == 0) {
	  continue;
	}
        return -1;
      }
    } else {
      int j;
      pdf_tmatrix T;
      pdf_coord  p0, p1, p2, p3;

      token = parse_ident(&clip_path, end_path);
      for (j = 0; j < sizeof(pdf_operators) / sizeof(pdf_operators[0]); j++)
        if (strcmp(token, pdf_operators[j].token) == 0)
	  break;
      if (j == sizeof(pdf_operators) / sizeof(pdf_operators[0])) {
        return -1;
      }
      switch (pdf_operators[j].opcode) {
	case  0:
	case -1:
	case -2:
	case -3:
	case -4:
	  /* Just pop the stack and do nothing. */
	  top += pdf_operators[j].opcode;
	  if (top < -1)
	    return -1;
	  break;
	case OP_SETCOLOR:
	  top -= color_dimen;
	  if (top < -1)
	    return -1;
	  break;
	case OP_CLOSEandCLIP:
	  pdf_dev_closepath();
	case OP_CLIP:
#if 0
	  pdf_dev_clip();
#else
	  pdf_dev_flushpath('W', PDF_FILL_RULE_NONZERO);
#endif
	  break;
	case OP_CONCATMATRIX:
	  if (top < 5)
	    return -1;
	  T.f = stack[top--];
	  T.e = stack[top--];
	  T.d = stack[top--];
	  T.c = stack[top--];
	  T.b = stack[top--];
	  T.a = stack[top--];
	  pdf_concatmatrix(&M, &T);
	  break;
	case OP_SETCOLORSPACE:
	  /* Do nothing. */
	  break;
	case OP_RECTANGLE:
	  if (top < 3)
	    return -1;
	  p1.y = stack[top--];
	  p1.x = stack[top--];
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  if (M.b == 0 && M.c == 0) {
	    pdf_tmatrix M0;
	    M0.a = M.a; M0.b = M.b; M0.c = M.c; M0.d = M.d;
	    M0.e = 0; M0.f = 0;
	    pdf_dev_transform(&p0, &M);
	    pdf_dev_transform(&p1, &M0);
	    pdf_dev_rectadd(p0.x, p0.y, p1.x, p1.y);
	  } else {
	    p2.x = p0.x + p1.x; p2.y = p0.y + p1.y;
	    p3.x = p0.x; p3.y = p0.y + p1.y;
	    p1.x += p0.x; p1.y = p0.y;
	    pdf_dev_transform(&p0, &M);
	    pdf_dev_transform(&p1, &M);
	    pdf_dev_transform(&p2, &M);
	    pdf_dev_transform(&p3, &M);
	    pdf_dev_moveto(p0.x, p0.y);
	    pdf_dev_lineto(p1.x, p1.y);
	    pdf_dev_lineto(p2.x, p2.y);
	    pdf_dev_lineto(p3.x, p3.y);
	    pdf_dev_closepath();
	  }
	  break;
	case OP_CURVETO:
	  if (top < 5)
	    return -1;
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  pdf_dev_transform(&p0, &M);
	  p1.y = stack[top--];
	  p1.x = stack[top--];
	  pdf_dev_transform(&p1, &M);
	  p2.y = stack[top--];
	  p2.x = stack[top--];
	  pdf_dev_transform(&p2, &M);
	  pdf_dev_curveto(p2.x, p2.y, p1.x, p1.y, p0.x, p0.y);
	  break;
	case OP_CLOSEPATH:
	  pdf_dev_closepath();
	  break;
	case OP_LINETO:
	  if (top < 1)
	    return -1;
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  pdf_dev_transform(&p0, &M);
	  pdf_dev_lineto(p0.x, p0.y);
	  break;
	case OP_MOVETO:
	  if (top < 1)
	    return -1;
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  pdf_dev_transform(&p0, &M);
	  pdf_dev_moveto(p0.x, p0.y);
	  break;
	case OP_NOOP:
	  pdf_doc_add_page_content(" n", 2);
	  break;
	case OP_GSAVE:
	  depth++;
	  break;
	case OP_GRESTORE:
	  depth--;
	  break;
	case OP_CURVETO1:
	  if (top < 3)
	    return -1;
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  pdf_dev_transform(&p0, &M);
	  p1.y = stack[top--];
	  p1.x = stack[top--];
	  pdf_dev_transform(&p1, &M);
	  pdf_dev_vcurveto(p1.x, p1.y, p0.x, p0.y);
	  break;
	case OP_CURVETO2:
	  if (top < 3)
	    return -1;
	  p0.y = stack[top--];
	  p0.x = stack[top--];
	  pdf_dev_transform(&p0, &M);
	  p1.y = stack[top--];
	  p1.x = stack[top--];
	  pdf_dev_transform(&p1, &M);
	  pdf_dev_ycurveto(p1.x, p1.y, p0.x, p0.y);
	  break;
	default:
	  return -1;
      }
    }
  }
  free(save_path);

  pdf_release_obj(contents);
  pdf_close(pf);

  return 0;
}
Пример #4
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;
}
Пример #5
0
int
main( void )
{
    short       j, k, ib, nindx, nchars, nleng, htab, zero;
    short       *hrshlst;
    signed char ix, iy;
    long        fpos;
    PDFstrm     *pdfs;

    hrshlst = (short *) malloc( 4 * 176 * sizeof ( short ) );

    ib = 0;
    for ( j = 0; j < 4; j++ )
        for ( k = 0; k < 176; k++ )
            hrshlst[ib++] = *( hersh[j] + k );

    pdfs = pdf_fopen( PL_XFONT, "wb+" );
    if ( !pdfs )
    {
        printf( "Error opening extended font file.\n" );
        exit( 1 );
    }

    htab = 4 * 256 + 176;

    pdf_wr_2bytes( pdfs, htab );
    pdf_wr_2nbytes( pdfs, (U_SHORT *) hrshlst, 4 * 176 );

    nleng = 1;
    zero  = 0;
    nindx = 0;
    fpos  = ftell( pdfs->file );
    pdf_wr_2bytes( pdfs, nindx );
    for ( j = 0; j < 30; j++ )
    {
        for ( k = 0; k < 100; k++ )
        {
            ib = *( findex[j] + k );
            if ( ib == 0 )
            {
                pdf_wr_2bytes( pdfs, zero );
                nindx++;
            }
            else
            {
                pdf_wr_2bytes( pdfs, nleng );
                nindx++;
                for (;; )
                {
                    ix = *( buffer[ib / 100] + ib % 100 ) / 128 - 64;
                    iy = *( buffer[ib / 100] + ib % 100 ) % 128 - 64;
                    ib++;
                    if ( ix == -64 )
                        ix = 64;
                    if ( iy == -64 )
                        iy = 64;
                    nleng++;
                    if ( ix == 64 && iy == 64 )
                        break;
                }
            }
        }
    }
    fseek( pdfs->file, fpos, 0 );
    pdf_wr_2bytes( pdfs, nindx );

    fseek( pdfs->file, 0, 2 );
    fpos   = ftell( pdfs->file );
    nleng  = 1;
    nchars = 0;
    pdf_wr_2bytes( pdfs, nleng );
    for ( j = 0; j < 30; j++ )
    {
        for ( k = 0; k < 100; k++ )
        {
            ib = *( findex[j] + k );
            if ( ib != 0 )
            {
                for (;; )
                {
                    ix = *( buffer[ib / 100] + ib % 100 ) / 128 - 64;
                    iy = *( buffer[ib / 100] + ib % 100 ) % 128 - 64;
                    ib++;
                    if ( ix == -64 )
                        ix = 64;
                    if ( iy == -64 )
                        iy = 64;
                    fputc( ix, pdfs->file );
                    fputc( iy, pdfs->file );
                    nleng++;
                    if ( ix == 64 && iy == 64 )
                        break;
                }
                nchars++;
            }
        }
    }
    nleng--;
    fseek( pdfs->file, fpos, 0 );
    pdf_wr_2bytes( pdfs, nleng );
    pdf_close( pdfs );

    printf( "There are %d characters in font set.\n", nchars - 1 );
    exit( 0 );
}
Пример #6
0
pdf_obj *pdf_include_page(FILE *image_file, struct xform_info *p, char *res_name)
{
  pdf_obj *trailer = NULL, *catalog = NULL, *page_tree = NULL;
  pdf_obj *kids_ref, *kids;
  pdf_obj *media_box = NULL, *crop_box = NULL, *resources = NULL,
    *contents = NULL, *contents_ref = NULL;
  pdf_obj *tmp1;
#ifdef MEM_DEBUG
MEM_START
#endif
  if (!(trailer = pdf_open (image_file))) {
    fprintf (stderr, "\nCorrupt PDF file?\n");
  }
 
  /* Now just lookup catalog location */
  /* Deref catalog */
  if (trailer && (catalog = pdf_deref_obj(pdf_lookup_dict (trailer,"Root"))) ==
      NULL) {
    fprintf (stderr, "\nCatalog isn't where I expect it.\n");
  }
  if (trailer)
    pdf_release_obj (trailer);

  /* Lookup page tree in catalog */
  if (catalog) {
    page_tree = pdf_deref_obj (pdf_lookup_dict (catalog, "Pages"));
    /* Should be finished with catalog */
    pdf_release_obj (catalog);
  }
  /* Media box and resources can be inherited so start looking for
     them here */
  if (page_tree) {
    if ((tmp1 = pdf_lookup_dict (page_tree, "CropBox")))
      crop_box = pdf_deref_obj (tmp1);
    if ((tmp1 = pdf_lookup_dict (page_tree, "MediaBox")))
      media_box = pdf_deref_obj (tmp1);
    resources = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources"));
    if (resources == NULL) {
      resources = pdf_new_dict();
    }
    while ((kids_ref = pdf_lookup_dict (page_tree, "Kids")) != NULL) {
      kids = pdf_deref_obj (kids_ref);
      pdf_release_obj (page_tree);
      page_tree = pdf_deref_obj (pdf_get_array(kids, 0));
      pdf_release_obj (kids);
      /* Replace MediaBox if it's here */
      tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "MediaBox"));
      if (tmp1 && media_box)
	pdf_release_obj (media_box);
      if (tmp1) 
	media_box = tmp1;
      /* Do same for CropBox */
      tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "CropBox"));
      if (tmp1 && crop_box)
	pdf_release_obj (crop_box);
      if (tmp1) 
	crop_box = tmp1;
      /* Add resources if they're here */
      tmp1 = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources"));
      if (tmp1) {
	pdf_merge_dict (tmp1, resources);
	pdf_release_obj (resources);
	resources = tmp1;
      }
    }
    /* At this point, page_tree contains the first page.  media_box,
       crop_box,  and resources should also be set. */
    /* If there's a crop_box, replace media_box with crop_box.
       The rest of this routine assumes crop_box has been released */
    if (crop_box) {
      pdf_release_obj (media_box);
      media_box = crop_box;
      crop_box = NULL;
    }
    /* This gets bit confusing.  In the following code,
       media_box is the box the image is cropped to. 
       The bounding box is the box the image is scaled to */
    /* If user did not supply bounding box, use media_box
       (which may really be cropbox) as bounding box */
    /* Set the crop box parameters in the xform_info structure */
    p->c_llx = pdf_number_value (pdf_get_array (media_box, 0));
    p->c_lly = pdf_number_value (pdf_get_array (media_box, 1));
    p->c_urx = pdf_number_value (pdf_get_array (media_box, 2));
    p->c_ury = pdf_number_value (pdf_get_array (media_box, 3));

    /* Adjust scaling and clipping information as necessary */
    pdf_scale_image (p);

    /* Set the media box to whatever pdf_scale_image() decided
       for the crop box (which may be unchanged) */
    pdf_release_obj (media_box);
    media_box = pdf_new_array ();
    pdf_add_array (media_box, pdf_new_number (p->c_llx));
    pdf_add_array (media_box, pdf_new_number (p->c_lly));
    pdf_add_array (media_box, pdf_new_number (p->c_urx));
    pdf_add_array (media_box, pdf_new_number (p->c_ury));

    if ((contents =
	 pdf_deref_obj(pdf_lookup_dict(page_tree,"Contents")))==NULL) {
      fprintf (stderr, "\nNo Contents found\n");
      return NULL;
    }
    pdf_release_obj (page_tree);
  }
  /* Arrays of contents must be handled very differently (not implemented) */
  if (contents && contents -> type != PDF_ARRAY) {
    doc_make_form_xobj (contents, media_box,
			p->user_bbox? p->u_llx: 0.0,
			p->user_bbox? p->u_lly: 0.0,
			1.0, 1.0,
			resources, res_name);
  } else {
    fprintf (stderr, "\nIgnoring stream with with multiple segments\n");
    contents = NULL;
  }
  if (contents) {
    contents_ref = pdf_ref_obj (contents);
    pdf_release_obj (contents);
  }
  pdf_close ();
#ifdef MEM_DEBUG
MEM_END
#endif
  return (contents_ref);
}
Пример #7
0
//--------------------------------------------------------------------------
//This is a function called by the front end map functions to do the map drawing. Its
//parameters are:
//mapform: The transform used to convert the data in raw coordinates to x, y positions
//on the plot
//name: either one of the plplot provided lat/lon maps or the path/file name of a
//shapefile
//dx/dy: the gradient of text/symbols drawn if text is non-null
//shapetype: one of ARC, SHPT_ARCZ, SHPT_ARCM, SHPT_POLYGON, SHPT_POLYGONZ,
//SHPT_POLYGONM, SHPT_POINT, SHPT_POINTM, SHPT_POINTZ. See drawmapdata() for the
//how each type is rendered. But Basically the ARC options are lines, the POLYGON
//options are filled polygons, the POINT options are points/text. Options beginning
//SHPT will only be defined if HAVE_SHAPELIB is true
//text: The text (which can be actual text or a unicode symbol) to be drawn at
//each point
//minx/maxx: The min/max longitude when using a plplot provided map or x value if
//using a shapefile
//miny/maxy: The min/max latitude when using a plplot provided map or y value if
//using a shapefile
//plotentries: used only for shapefiles, as one shapefile contains multiple vectors
//each representing a different item (e.g. multiple boundaries, multiple height
//contours etc. plotentries is an array containing the indices of the
//entries within the shapefile that you wish to plot. if plotentries is null all
//entries are plotted
//nplotentries: the number of elements in plotentries. Ignored if plplot was not built
//with shapefile support or if plotentries is null
//--------------------------------------------------------------------------
void
drawmap( void ( *mapform )( PLINT, PLFLT *, PLFLT * ), const char *name,
         PLFLT dx, PLFLT dy, int shapetype, PLFLT just, const char *text,
         PLFLT minx, PLFLT maxx, PLFLT miny, PLFLT maxy, const PLINT *plotentries, PLINT nplotentries )
{
#if defined ( HAVE_SHAPELIB ) || defined ( PL_DEPRECATED )
    int   i, j;
    char  *filename = NULL;
    char  truncatedfilename[900];
    char  warning[1024];
    int   nVertices = 200;
    PLFLT minsectlon, maxsectlon, minsectlat, maxsectlat;
    PLFLT *bufx   = NULL, *bufy = NULL;
    int   bufsize = 0;
    int   filenamelen;
    PLFLT **splitx             = NULL;
    PLFLT **splity             = NULL;
    int   *splitsectionlengths = NULL;
    int   nsplitsections;
    PLFLT lastsplitpointx;
    PLFLT lastsplitpointy;
    PLFLT penultimatesplitpointx;
    PLFLT penultimatesplitpointy;
    char  islatlon = 1;


#ifdef HAVE_SHAPELIB
    SHPHandle in;
    int       nentries;
    int       entryindex = 0;
    // Unnecessarily set nparts to quiet -O3 -Wuninitialized warnings.
    //int              nparts      = 0;
    int           entrynumber = 0;
    int           partnumber  = 0;
    double        mins[4];
    double        maxs[4];
    SHPObject     *object = NULL;
    double        *bufxraw;
    double        *bufyraw;
    char          *prjfilename = NULL;
    PDFstrm       *prjfile;
    char          prjtype[]    = { 0, 0, 0, 0, 0, 0, 0 };
    int           appendresult = 0;
#else
    PDFstrm       *in;
    //PLFLT            bufx[ncopies][200], bufy[ncopies][200];
    unsigned char n_buff[2], buff[800];
    long int      t;
#endif

    //
    // read map outline
    //

    //strip the .shp extension if a shapefile has been provided and add
    //the needed map file extension if we are not using shapefile
    if ( strstr( name, ".shp" ) )
        filenamelen = (int) ( name - strstr( name, ".shp" ) );
    else
        filenamelen = (int) strlen( name );
    filename = (char *) malloc( filenamelen + strlen( MAP_FILE ) + 1 );
    if ( !filename )
    {
        plabort( "Could not allocate memory for concatenating map filename" );
        return;
    }
    strncpy( filename, name, filenamelen );
    filename[ filenamelen ] = '\0';
    strcat( filename, MAP_FILE );

    //copy the filename to a fixed length array in case it is needed for warning messages
    if ( strlen( filename ) < 899 )
        strcpy( truncatedfilename, filename );
    else
    {
        memcpy( truncatedfilename, filename, 896 );
        truncatedfilename[896] = '.';
        truncatedfilename[897] = '.';
        truncatedfilename[898] = '.';
        truncatedfilename[899] = '\0';
    }

    strcpy( warning, "Could not find " );
    strcat( warning, filename );
    strcat( warning, " file." );
#ifdef HAVE_SHAPELIB
    //Open the shp and shx file using shapelib
    if ( ( in = OpenShapeFile( filename ) ) == NULL )
    {
        plabort( warning );
        free( filename );
        return;
    }
    SHPGetInfo( in, &nentries, &shapetype, mins, maxs );
    //also check for a prj file which will tell us if the data is lat/lon or projected
    //if it is projected then set ncopies to 1 - i.e. don't wrap round longitudes
    prjfilename = (char *) malloc( filenamelen + 5 );
    if ( !prjfilename )
    {
        free( filename );
        plabort( "Could not allocate memory for generating map projection filename" );
        return;
    }
    strncpy( prjfilename, name, filenamelen );
    prjfilename[ filenamelen ] = '\0';
    strcat( prjfilename, ".prj" );
    prjfile = plLibOpenPdfstrm( prjfilename );
    if ( prjfile && prjfile->file )
    {
        fread( prjtype, 1, 6, prjfile->file );
        if ( strcmp( prjtype, "PROJCS" ) == 0 )
            islatlon = 0;
        pdf_close( prjfile );
    }
    free( prjfilename );
    prjfilename = NULL;
#else
    if ( ( in = plLibOpenPdfstrm( filename ) ) == NULL )
    {
        plwarn( warning );
        return;
    }
#endif

    bufx = NULL;
    bufy = NULL;

    for (;; )
    {
#ifdef HAVE_SHAPELIB
        //each object in the shapefile is split into parts.
        //If we are need to plot the first part of an object then read in a new object
        //and check how many parts it has. Otherwise use the object->panPartStart vector
        //to check the offset of this part and the next part and allocate memory. Copy
        //the data to this memory converting it to PLFLT and draw it.
        //finally increment the part number or if we have finished with the object reset the
        //part numberand increment the object.

        //break condition if we've reached the end of the file
        if ( ( !plotentries && ( entrynumber == nentries ) ) || ( plotentries && ( entryindex == nplotentries ) ) )
            break;

        //if partnumber == 0 then we need to load the next object
        if ( partnumber == 0 )
        {
            if ( plotentries )
                object = SHPReadObject( in, plotentries[entryindex] );
            else
                object = SHPReadObject( in, entrynumber );
        }
        //if the object could not be read, increment the object index to read and
        //return to the top of the loop to try the next object.
        if ( object == NULL )
        {
            entrynumber++;
            entryindex++;
            partnumber = 0;
            continue;
        }

        //work out how many points are in the current part
        if ( object->nParts == 0 )
            nVertices = object->nVertices;                                                       //if object->nParts==0, we can still have 1 vertex. A bit odd but it's the way it goes
        else if ( partnumber == ( object->nParts - 1 ) )
            nVertices = object->nVertices - object->panPartStart[partnumber];                    //panPartStart holds the offset for each part
        else
            nVertices = object->panPartStart[partnumber + 1] - object->panPartStart[partnumber]; //panPartStart holds the offset for each part
#endif
        //allocate memory for the data
        if ( nVertices > bufsize )
        {
            bufsize = nVertices;
            free( bufx );
            free( bufy );
            bufx = (PLFLT *) malloc( (size_t) bufsize * sizeof ( PLFLT ) );
            bufy = (PLFLT *) malloc( (size_t) bufsize * sizeof ( PLFLT ) );
            if ( !bufx || !bufy )
            {
                plabort( "Could not allocate memory for map data" );
                free( filename );
                free( bufx );
                free( bufy );
                return;
            }
        }

#ifdef HAVE_SHAPELIB
        //point the plot buffer to the correct starting vertex
        //and copy it to the PLFLT arrays. If we had object->nParts == 0
        //then panPartStart will be NULL
        if ( object->nParts > 0 )
        {
            bufxraw = object->padfX + object->panPartStart[partnumber];
            bufyraw = object->padfY + object->panPartStart[partnumber];
        }
        else
        {
            bufxraw = object->padfX;
            bufyraw = object->padfY;
        }

        for ( i = 0; i < nVertices; i++ )
        {
            bufx[i] = (PLFLT) bufxraw[i];
            bufy[i] = (PLFLT) bufyraw[i];
        }

        //set the min x/y of the object
        minsectlon = object->dfXMin;
        maxsectlon = object->dfXMax;
        minsectlat = object->dfYMin;
        maxsectlat = object->dfYMax;

        //increment the partnumber or if we've reached the end of
        //an entry increment the entrynumber and set partnumber to 0
        if ( partnumber == object->nParts - 1 || object->nParts == 0 )
        {
            entrynumber++;
            entryindex++;
            partnumber = 0;
            SHPDestroyObject( object );
            object = NULL;
        }
        else
            partnumber++;

        if ( nVertices == 0 )
            continue;
#else
        // read in # points in segment
        if ( pdf_rdx( n_buff, (long) sizeof ( unsigned char ) * 2, in ) == 0 )
            break;
        nVertices = ( n_buff[0] << 8 ) + n_buff[1];
        if ( nVertices == 0 )
            break;

        pdf_rdx( buff, (long) sizeof ( unsigned char ) * 4 * nVertices, in );
        if ( nVertices == 1 )
            continue;

        for ( j = i = 0; i < nVertices; i++, j += 2 )
        {
            t       = ( buff[j] << 8 ) + buff[j + 1];
            bufx[i] = ( (PLFLT) t - OFFSET ) / SCALE;
        }
        for ( i = 0; i < nVertices; i++, j += 2 )
        {
            t       = ( buff[j] << 8 ) + buff[j + 1];
            bufy[i] = ( (PLFLT) t - OFFSET ) / SCALE;
        }
        //set the min/max section lat/lon with extreme values
        //to be overwritten later
        minsectlon = 1000.;
        maxsectlon = -1000.;
        minsectlat = 1000.;
        maxsectlat = -1000.;

#endif

        if ( islatlon )
        {
            //two obvious issues exist here with plotting longitudes:
            //
            //1) wraparound causing lines which go the wrong way round
            //   the globe
            //2) some people plot lon from 0-360 deg, others from -180 - +180
            //
            //we can cure these problems by conditionally adding/subtracting
            //360 degrees to each data point in order to ensure that the
            //distance between adgacent points is always less than 180
            //degrees, then plotting up to 2 out of 5 copies of the data
            //each separated by 360 degrees.

            //arrays of pointers to the starts of each section of data that
            //has been split due to longitude wrapping, and an array of ints
            //to hold their lengths. Start with splitx and splity having one
            //element pointing to the beginning of bufx and bufy
            splitx = (PLFLT **) malloc( sizeof ( PLFLT* ) );
            splity = (PLFLT **) malloc( sizeof ( PLFLT* ) );
            //lengths of the split sections
            splitsectionlengths = (int *) malloc( sizeof ( size_t ) );
            if ( !splitx || !splity || !splitsectionlengths )
            {
                plabort( "Could not allocate memory for longitudinally split map data" );
                free( filename );
                free( bufx );
                free( bufy );
                free( splitx );
                free( splity );
                free( splitsectionlengths );
                return;
            }
            splitsectionlengths[0] = nVertices;
            nsplitsections         = 1;
            splitx[0] = bufx;
            splity[0] = bufy;

            //set the min/max lats/lons
            minsectlon = MIN( minsectlon, bufx[0] );
            maxsectlon = MAX( minsectlon, bufx[0] );
            minsectlat = MIN( minsectlat, bufy[0] );
            maxsectlat = MAX( maxsectlat, bufy[0] );
            //ensure our lat and lon are on 0-360 grid and split the
            //data where it wraps.
            rebaselon( &bufx[0], ( minx + maxx ) / 2.0 );
            for ( i = 1; i < nVertices; i++ )
            {
                //put lon into 0-360 degree range
                rebaselon( &bufx[i], ( minx + maxx ) / 2.0 );

                //check if the previous point is more than 180 degrees away
                if ( bufx[i - 1] - bufx[i] > 180. || bufx[i - 1] - bufx[i] < -180. )
                {
                    //check if the map transform deals with wrapping itself, e.g. in a polar projection
                    //in this case give one point overlap to the sections so that lines are contiguous
                    if ( checkwrap( mapform, bufx[i], bufy[i] ) )
                    {
                        appendresult += appendfltptr( &splitx, nsplitsections, bufx + i );
                        appendresult += appendfltptr( &splity, nsplitsections, bufy + i );
                        appendresult += appendint( &splitsectionlengths, nsplitsections, nVertices - i );
                        splitsectionlengths[nsplitsections - 1] -= splitsectionlengths[nsplitsections] - 1;
                        nsplitsections++;
                    }
                    //if the transform doesn't deal with wrapping then allow 2 points overlap to fill in the
                    //edges
                    else
                    {
                        appendresult += appendfltptr( &splitx, nsplitsections, bufx + i - 1 );
                        appendresult += appendfltptr( &splity, nsplitsections, bufy + i - 1 );
                        appendresult += appendint( &splitsectionlengths, nsplitsections, nVertices - i + 1 );
                        splitsectionlengths[nsplitsections - 1] -= splitsectionlengths[nsplitsections] - 2;
                        nsplitsections++;
                    }
                    if ( appendresult > 0 )
                    {
                        plabort( "Could not allocate memory for appending to longitudinally split map data" );
                        free( filename );
                        free( bufx );
                        free( bufy );
                        free( splitx );
                        free( splity );
                        free( splitsectionlengths );
                        return;
                    }
                }

                //update the mins and maxs
                minsectlon = MIN( minsectlon, bufx[i] );
                maxsectlon = MAX( minsectlon, bufx[i] );
                minsectlat = MIN( minsectlat, bufy[i] );
                maxsectlat = MAX( maxsectlat, bufy[i] );
            }

            //check if the latitude and longitude range means we need to plot this section
            if ( ( maxsectlat > miny ) && ( minsectlat < maxy )
                 && ( maxsectlon > minx ) && ( minsectlon < maxx ) )
            {
                //plot each split in turn, now is where we deal with the end points to
                //ensure we draw to the edge of the map
                for ( i = 0; i < nsplitsections; ++i )
                {
                    //check if the first 2 or last 1 points of the split section need
                    //wrapping and add or subtract 360 from them. Note that when the next
                    //section is drawn the code below will undo this if needed
                    if ( splitsectionlengths[i] > 2 )
                    {
                        if ( splitx[i][1] - splitx[i][2] > 180. )
                            splitx[i][1] -= 360.0;
                        else if ( splitx[i][1] - splitx[i][2] < -180. )
                            splitx[i][1] += 360.0;
                    }

                    if ( splitx[i][0] - splitx[i][1] > 180. )
                        splitx[i][0] -= 360.0;
                    else if ( splitx[i][0] - splitx[i][1] < -180. )
                        splitx[i][0] += 360.0;

                    if ( splitx[i][splitsectionlengths[i] - 2] - splitx[i][splitsectionlengths[i] - 1] > 180. )
                        splitx[i][splitsectionlengths[i] - 1] += 360.0;
                    else if ( splitx[i][splitsectionlengths[i] - 2] - splitx[i][splitsectionlengths[i] - 1] < -180. )
                        splitx[i][splitsectionlengths[i] - 1] -= 360.0;

                    //save the last 2 points - they will be needed by the next
                    //split section and will be overwritten by the mapform
                    lastsplitpointx        = splitx[i][splitsectionlengths[i] - 1];
                    lastsplitpointy        = splity[i][splitsectionlengths[i] - 1];
                    penultimatesplitpointx = splitx[i][splitsectionlengths[i] - 2];
                    penultimatesplitpointy = splity[i][splitsectionlengths[i] - 2];

                    //draw the split section
                    drawmapdata( mapform, shapetype, splitsectionlengths[i], splitx[i], splity[i], dx, dy, just, text );

                    for ( j = 1; j < splitsectionlengths[i]; ++j )
                    {
                        if ( ( splitx[i][j] < 200.0 && splitx[i][j - 1] > 260.0 ) || ( splitx[i][j - 1] < 200.0 && splitx[i][j] > 260.0 ) )
                            plwarn( "wrapping error" );
                    }

                    //restore the last 2 points
                    splitx[i][splitsectionlengths[i] - 1] = lastsplitpointx;
                    splity[i][splitsectionlengths[i] - 1] = lastsplitpointy;
                    splitx[i][splitsectionlengths[i] - 2] = penultimatesplitpointx;
                    splity[i][splitsectionlengths[i] - 2] = penultimatesplitpointy;
                }
            }
        }
        else
        {
            drawmapdata( mapform, shapetype, nVertices, bufx, bufy, dx, dy, just, text );
        }

        free( splitx );
        free( splity );
        free( splitsectionlengths );
    }
    // Close map file
#ifdef HAVE_SHAPELIB
    SHPClose( in );
#else
    pdf_close( in );
#endif

    //free memory
    free( bufx );
    free( bufy );
    free( filename );
#else   // defined (HAVE_SHAPELIB) || defined (PL_DEPRECATED)
    plwarn( "Use of the old plplot map file format is deprecated.\nIt is recommended that the shapelib library be used to provide map support.\n" );
#endif  // defined (HAVE_SHAPELIB) || defined (PL_DEPRECATED)
}
Пример #8
0
int
main( void )
{
    size_t  i, j, k, ib, nstd;
    U_SHORT nchars, nleng, htab, nindx, zero;
    U_SHORT *hrshlst, *hrshidx;
    int     ix, iy;
    long    fpos;
    PDFstrm *pdfs;

    hrshlst = (U_SHORT *) malloc( 176 * sizeof ( U_SHORT ) );
    hrshidx = (U_SHORT *) malloc( 176 * sizeof ( U_SHORT ) );

    ib = 0;
    for ( k = 0; k < 176; k++ )
        hrshlst[ib++] = (U_SHORT) *( hersh[0] + k );

// Sort list

    qsort( (char *) hrshlst, ib, sizeof ( U_SHORT ), compare );

// Remove duplicates

    k = 0;
    j = 0;
    do
    {
        if ( hrshlst[k] == hrshlst[j] )
            j++;
        else
            hrshlst[++k] = hrshlst[j];
    } while ( j < ib );

    nstd = k + 1;

// Now reindex the fonts

    for ( k = 0; k < 176; k++ )
        for ( i = 0; i < nstd; i++ )
            if ( *( hersh[0] + k ) == hrshlst[i] )
            {
                hrshidx[k] = (U_SHORT) ( i + 1 );
                break;
            }

    pdfs = pdf_fopen( PL_SFONT, "wb+" );
    if ( !pdfs )
    {
        printf( "Error opening standard font file.\n" );
        exit( 1 );
    }

    htab = 1 * 256 + 176;
    pdf_wr_2bytes( pdfs, htab );
    pdf_wr_2nbytes( pdfs, hrshidx, 176 );

    zero  = 0;
    nindx = 0;
    nleng = 1;
    fpos  = ftell( pdfs->file );

    pdf_wr_2bytes( pdfs, nindx );
    for ( j = 0; j < nstd; j++ )
    {
        ib = (size_t) *( findex[( hrshlst[j] - 1 ) / 100] + ( hrshlst[j] - 1 ) % 100 );
        if ( ib == 0 )
        {
            pdf_wr_2bytes( pdfs, zero );
            nindx++;
        }
        else
        {
            pdf_wr_2bytes( pdfs, nleng );
            nindx++;
            for (;; )
            {
                ix = *( buffer[ib / 100] + ib % 100 ) / 128 - 64;
                iy = *( buffer[ib / 100] + ib % 100 ) % 128 - 64;
                ib++;
                if ( ix == -64 )
                    ix = 64;
                if ( iy == -64 )
                    iy = 64;
                nleng++;
                if ( ix == 64 && iy == 64 )
                    break;
            }
        }
    }
    fseek( pdfs->file, fpos, 0 );
    pdf_wr_2bytes( pdfs, nindx );

    nchars = 0;
    nleng  = 1;
    fseek( pdfs->file, 0, 2 );            // Go to end of file
    fpos = ftell( pdfs->file );           // Save current position
    pdf_wr_2bytes( pdfs, nleng );

    for ( j = 0; j < nstd; j++ )
    {
        ib = (size_t) *( findex[( hrshlst[j] - 1 ) / 100] + ( hrshlst[j] - 1 ) % 100 );
        if ( ib != 0 )
        {
            for (;; )
            {
                ix = *( buffer[ib / 100] + ib % 100 ) / 128 - 64;
                iy = *( buffer[ib / 100] + ib % 100 ) % 128 - 64;
                ib++;
                if ( ix == -64 )
                    ix = 64;
                if ( iy == -64 )
                    iy = 64;
                fputc( ix, pdfs->file );
                fputc( iy, pdfs->file );
                nleng++;
                if ( ix == 64 && iy == 64 )
                    break;
            }
            nchars++;
        }
    }
    nleng--;
    fseek( pdfs->file, fpos, 0 );
    pdf_wr_2bytes( pdfs, nleng );
    pdf_close( pdfs );
    free( hrshlst );
    free( hrshidx );
    printf( "There are %d characters in standard font set.\n", nchars - 1 );
    exit( 0 );
}
Пример #9
0
void
plfntld(PLINT fnt)
{
    static PLINT charset;
    short bffrleng;
    PDFstrm *pdfs;

    if (fontloaded && (charset == fnt))
	return;

    plfontrel();
    fontloaded = 1;
    charset = fnt;

    if (fnt)
	pdfs = plLibOpenPdfstrm(PL_XFONT);
    else
	pdfs = plLibOpenPdfstrm(PL_SFONT);

    if (pdfs == NULL)
	plexit("Unable to open or allocate memory for font file");

/* Read fntlkup[] */

    pdf_rd_2bytes(pdfs, (U_SHORT *) &bffrleng);
    numberfonts = bffrleng / 256;
    numberchars = bffrleng & 0xff;
    bffrleng = numberfonts * numberchars;
    fntlkup = (short int *) malloc(bffrleng * sizeof(short int));
    if ( ! fntlkup)
	plexit("plfntld: Out of memory while allocating font buffer.");

    pdf_rd_2nbytes(pdfs, (U_SHORT *) fntlkup, bffrleng);

/* Read fntindx[] */

    pdf_rd_2bytes(pdfs, (U_SHORT *) &indxleng);
    fntindx = (short int *) malloc(indxleng * sizeof(short int));
    if ( ! fntindx)
	plexit("plfntld: Out of memory while allocating font buffer.");

    pdf_rd_2nbytes(pdfs, (U_SHORT *) fntindx, indxleng);

/* Read fntbffr[] */
/* Since this is an array of char, there are no endian problems */

    pdf_rd_2bytes(pdfs, (U_SHORT *) &bffrleng);
    fntbffr = (signed char *) malloc(2 * bffrleng * sizeof(signed char));
    if ( ! fntbffr)
	plexit("plfntld: Out of memory while allocating font buffer.");

#if PLPLOT_USE_TCL_CHANNELS
    pdf_rdx(fntbffr, sizeof(signed char)*(2 * bffrleng), pdfs);
#else
    fread((void *) fntbffr, (size_t) sizeof(signed char),
	  (size_t) (2 * bffrleng), pdfs->file);
#endif

/* Done */

    pdf_close(pdfs);
}