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