void c_plfill(PLINT n, PLFLT *x, PLFLT *y) { PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; PLINT i; if (plsc->level < 3) { plabort("plfill: Please set up window first"); return; } if (n < 3) { plabort("plfill: Not enough points in object"); return; } if (n > PL_MAXPOLY-1) { plwarn("plfill: too many points in polygon"); n = PL_MAXPOLY; } for (i = 0; i < n; i++) { xpoly[i] = plP_wcpcx(x[i]); ypoly[i] = plP_wcpcy(y[i]); } if (x[0] != x[n-1] || y[0] != y[n-1]) { n++; xpoly[n-1] = plP_wcpcx(x[0]); ypoly[n-1] = plP_wcpcy(y[0]); } plP_plfclp(xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma, plsc->clpymi, plsc->clpyma, plP_fill); }
void plio_fgets( char *buf, int size, FILE *stream ) { char *s; dbug_enter( "plio_fgets" ); // If the buffer has a size of zero, we should complain if ( size == 0 ) { plwarn( "Zero length buffer size in plio_fgets, returning" ); return; } // Clear the error flag for this steam clearerr( stream ); s = fgets( buf, size, stream ); if ( s == NULL && ferror( stream ) ) { // The read resulted in an error plabort( "Error reading from file" ); } }
void plio_fread( void *buf, size_t size, size_t nmemb, FILE *stream ) { size_t bytes; dbug_enter( "plio_fread" ); // If the buffer has a size of zero, we should complain if ( size == 0 || nmemb == 0 ) { plwarn( "Zero length buffer size in plio_fread, returning" ); return; } // Clear the error flag for this steam clearerr( stream ); bytes = fread( buf, size, nmemb, stream ); if ( ( bytes < nmemb ) && ferror( stream ) ) { // The read resulted in an error plabort( "Error reading from file" ); } }
void stcmap1(PLStream *pls) { long cur_pos; int i; if (pls->ncol1 > cmap1_ncol) plwarn("Too much colors for cmap1. Preallocate using command line '-ncol1 n.\n'"); cur_pos = ftell(pls->OutFile); if (fseek(pls->OutFile, cmap1_pos, SEEK_SET)) plexit("Sorry, only file based output, no pipes.\n"); /* fill the colormap */ for (i=0; i<pls->ncol1; i++) fprintf(pls->OutFile,"0 %d #%.2x%.2x%.2x\n", i+XFIG_COLBASE+cmap0_ncol, pls->cmap1[i].r, pls->cmap1[i].g, pls->cmap1[i].b); /* fill the nonspecified entries colormap */ for (i=pls->ncol1; i<cmap1_ncol; i++) fprintf(pls->OutFile,"0 %d #000000\n", i+XFIG_COLBASE+cmap0_ncol); if (cur_pos != cmap1_pos) fseek(pls->OutFile, cur_pos, SEEK_SET); }
void c_plfill3(PLINT n, PLFLT *x, PLFLT *y, PLFLT *z) { PLFLT tx[PL_MAXPOLY], ty[PL_MAXPOLY], tz[PL_MAXPOLY]; PLFLT *V[3]; PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; PLINT i; PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale; if (plsc->level < 3) { plabort("plfill3: Please set up window first"); return; } if (n < 3) { plabort("plfill3: Not enough points in object"); return; } if (n > PL_MAXPOLY-1) { plwarn("plfill3: too many points in polygon"); n = PL_MAXPOLY; } plP_gdom(&xmin, &xmax, &ymin, &ymax); plP_grange(&zscale, &zmin, &zmax); /* copy the vertices so we can clip without corrupting the input */ for( i=0; i < n; i++ ) { tx[i] = x[i]; ty[i] = y[i]; tz[i] = z[i]; } if (tx[0] != tx[n-1] || ty[0] != ty[n-1] || tz[0] != tz[n-1]) { tx[n] = tx[0]; ty[n] = ty[0]; tz[n] = tz[0]; n++; } V[0] = tx; V[1] = ty; V[2] = tz; n = plP_clip_poly(n, V, 0, 1, -xmin); n = plP_clip_poly(n, V, 0, -1, xmax); n = plP_clip_poly(n, V, 1, 1, -ymin); n = plP_clip_poly(n, V, 1, -1, ymax); n = plP_clip_poly(n, V, 2, 1, -zmin); n = plP_clip_poly(n, V, 2, -1, zmax); for( i=0; i < n; i++ ) { xpoly[i] = plP_wcpcx(plP_w3wcx( tx[i], ty[i], tz[i] )); ypoly[i] = plP_wcpcy(plP_w3wcy( tx[i], ty[i], tz[i] )); } /* AWI: in the past we have used * plP_fill(xpoly, ypoly, n); * here, but our educated guess is this fill should be done via the clipping * interface instead as below. * No example tests this code so one of our users will end up inadvertently * testing this for us. * * jc: I have checked, and both versions does give the same result, i.e., clipping * to the window boundaries. The reason is that the above plP_clip_poly() does * the clipping. To check this, is enough to diminish the x/y/z min/max arguments in * plw3d() in x08c. But let's keep it, although 10% slower... */ plP_plfclp(xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma, plsc->clpymi, plsc->clpyma, plP_fill); }
static void init_freetype_lv2( PLStream *pls ) { // Log_Verbose( "init_freetype_lv2" ); wxPLDevBase *dev=(wxPLDevBase *)pls->dev; FT_Data *FT=(FT_Data *)pls->FT; FT->scalex=dev->scalex; FT->scaley=dev->scaley; FT->ymax=dev->height; FT->invert_y=1; FT->smooth_text=0; if ((FT->want_smooth_text==1)&&(FT->BLENDED_ANTIALIASING==0)) /* do we want to at least *try* for smoothing ? */ { FT->ncol0_org=pls->ncol0; /* save a copy of the original size of ncol0 */ FT->ncol0_xtra=16777216-(pls->ncol1+pls->ncol0); /* work out how many free slots we have */ FT->ncol0_width=FT->ncol0_xtra/(pls->ncol0-1); /* find out how many different shades of anti-aliasing we can do */ if (FT->ncol0_width>4) /* are there enough colour slots free for text smoothing ? */ { if (FT->ncol0_width>max_number_of_grey_levels_used_in_text_smoothing) FT->ncol0_width=max_number_of_grey_levels_used_in_text_smoothing; /* set a maximum number of shades */ plscmap0n(FT->ncol0_org+(FT->ncol0_width*pls->ncol0)); /* redefine the size of cmap0 */ /* the level manipulations are to turn off the plP_state(PLSTATE_CMAP0) * call in plscmap0 which (a) leads to segfaults since the GD image is * not defined at this point and (b) would be inefficient in any case since * setcmap is always called later (see plD_bop_png) to update the driver * color palette to be consistent with cmap0. */ { PLINT level_save; level_save = pls->level; pls->level = 0; pl_set_extended_cmap0(pls, FT->ncol0_width, FT->ncol0_org); /* call the function to add the extra cmap0 entries and calculate stuff */ pls->level = level_save; } FT->smooth_text=1; /* Yippee ! We had success setting up the extended cmap0 */ } else plwarn("Insufficient colour slots available in CMAP0 to do text smoothing."); } else if ((FT->want_smooth_text==1)&&(FT->BLENDED_ANTIALIASING==1)) /* If we have a truecolour device, we wont even bother trying to change the palette */ { FT->smooth_text=1; } }
void plio_fread(void *buf, size_t size, size_t nmemb, FILE *stream) { /* size_t bytes; */ dbug_enter("plio_fread"); /* If the buffer has a size of zero, we should complain */ if(size == 0 || nmemb == 0) { plwarn("Zero length buffer size in plio_read, returning"); return; } /* Clear the error flag for this steam */ clearerr(stream); /* bytes = */ fread(buf, size, nmemb, stream); if(ferror(stream)) { /* The read resulted in an error */ plabort("Error reading from file"); } }
void plio_fgets(char *buf, int size, FILE *stream) { /* size_t bytes; */ /* pmr: unused */ char *s; dbug_enter("plio_fgets"); /* If the buffer has a size of zero, we should complain */ if(size == 0) { plwarn("Zero length buffer size in plio_fgets, returning"); return; } /* Clear the error flag for this steam */ clearerr(stream); s = fgets(buf, size, stream); if(s == NULL && ferror(stream)) { /* The read resulted in an error */ plabort("Error reading from file"); } }
static void c_plenvi(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis, PLINT old) { PLFLT lb, rb, tb, bb, dx, dy; PLFLT xsize, ysize, size, xscale, yscale, scale; PLFLT spxmin, spxmax, spymin, spymax; PLFLT vpxmin, vpxmax, vpymin, vpymax; if (plsc->level < 1) { plabort("plenv: Please call plinit first"); return; } if (xmin == xmax) { plabort("plenv: Invalid xmin and xmax arguments"); return; } if (ymin == ymax) { plabort("plenv: Invalid ymin and ymax arguments"); return; } if (just < -1 || just > 2) { plabort("plenv: Invalid just option"); return; } if (plsc->nsubx * plsc->nsuby == 1) /* not multiplot mode */ old = 1; if (old == 1) pladv(0); else plclear(); if (just == 0) plvsta(); else if (just == 1){ lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; dx = ABS(xmax - xmin); dy = ABS(ymax - ymin); plgspa(&spxmin, &spxmax, &spymin, &spymax); xsize = spxmax - spxmin; ysize = spymax - spymin; xscale = dx / (xsize - lb - rb); yscale = dy / (ysize - tb - bb); scale = MAX(xscale, yscale); vpxmin = MAX(lb, 0.5 * (xsize - dx / scale)); vpxmax = vpxmin + (dx / scale); vpymin = MAX(bb, 0.5 * (ysize - dy / scale)); vpymax = vpymin + (dy / scale); plsvpa(vpxmin, vpxmax, vpymin, vpymax); } else if(just == 2) { lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; plgspa(&spxmin, &spxmax, &spymin, &spymax); xsize = spxmax - spxmin; ysize = spymax - spymin; size = MIN(xsize-lb-rb, ysize-tb-bb); dx = (xsize-size-lb-rb)/2; vpxmin = lb + dx; vpxmax = vpxmin + size; dy = (ysize-size-bb-tb)/2; vpymin = bb + dy; vpymax = vpymin + size; plsvpa(vpxmin, vpxmax, vpymin, vpymax); } plwind(xmin, xmax, ymin, ymax); switch (axis) { case -2: break; case -1: plbox("bc", (PLFLT) 0.0, 0, "bc", (PLFLT) 0.0, 0); break; case 0: plbox("bcnst", (PLFLT) 0.0, 0, "bcnstv", (PLFLT) 0.0, 0); break; case 1: plbox("abcnst", (PLFLT) 0.0, 0, "abcnstv", (PLFLT) 0.0, 0); break; case 2: plbox("abcgnst", (PLFLT) 0.0, 0, "abcgnstv", (PLFLT) 0.0, 0); break; case 3: plbox("abcgnsth", (PLFLT) 0.0, 0, "abcgnstvh", (PLFLT) 0.0, 0); break; case 10: plbox("bclnst", (PLFLT) 0.0, 0, "bcnstv", (PLFLT) 0.0, 0); break; case 11: plbox("abclnst", (PLFLT) 0.0, 0, "abcnstv", (PLFLT) 0.0, 0); break; case 12: plbox("abcglnst", (PLFLT) 0.0, 0, "abcgnstv", (PLFLT) 0.0, 0); break; case 13: plbox("abcglnsth", (PLFLT) 0.0, 0, "abcgnstvh", (PLFLT) 0.0, 0); break; case 20: plbox("bcnst", (PLFLT) 0.0, 0, "bclnstv", (PLFLT) 0.0, 0); break; case 21: plbox("abcnst", (PLFLT) 0.0, 0, "abclnstv", (PLFLT) 0.0, 0); break; case 22: plbox("abcgnst", (PLFLT) 0.0, 0, "abcglnstv", (PLFLT) 0.0, 0); break; case 23: plbox("abcgnsth", (PLFLT) 0.0, 0, "abcglnstvh", (PLFLT) 0.0, 0); break; case 30: plbox("bclnst", (PLFLT) 0.0, 0, "bclnstv", (PLFLT) 0.0, 0); break; case 31: plbox("abclnst", (PLFLT) 0.0, 0, "abclnstv", (PLFLT) 0.0, 0); break; case 32: plbox("abcglnst", (PLFLT) 0.0, 0, "abcglnstv", (PLFLT) 0.0, 0); break; case 33: plbox("abcglnsth", (PLFLT) 0.0, 0, "abcglnstvh", (PLFLT) 0.0, 0); break; default: plwarn("plenv: Invalid axis argument"); } }
void c_plwind(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax) { PLFLT dx, dy, mmxmi, mmxma, mmymi, mmyma; PLWindow w; if (plsc->level < 2) { plabort("plwind: Please set up viewport first"); return; } /* Best to just warn and recover on bounds errors */ if (xmin == xmax) { plwarn("plwind: Invalid window limits in x."); xmin--; xmax++; } if (ymin == ymax) { plwarn("plwind: Invalid window limits in y."); ymin--; ymax++; } dx = (xmax - xmin) * 1.0e-5; dy = (ymax - ymin) * 1.0e-5; /* The true plot window is made slightly larger than requested so that */ /* the end limits will be on the graph */ plsc->vpwxmi = xmin - dx; plsc->vpwxma = xmax + dx; plsc->vpwymi = ymin - dy; plsc->vpwyma = ymax + dy; /* Compute the scaling between coordinate systems */ dx = plsc->vpwxma - plsc->vpwxmi; dy = plsc->vpwyma - plsc->vpwymi; plsc->wpxscl = (plsc->vppxma - plsc->vppxmi) / dx; plsc->wpxoff = (xmax * plsc->vppxmi - xmin * plsc->vppxma) / dx; plsc->wpyscl = (plsc->vppyma - plsc->vppymi) / dy; plsc->wpyoff = (ymax * plsc->vppymi - ymin * plsc->vppyma) / dy; mmxmi = plP_dcmmx(plsc->vpdxmi); mmxma = plP_dcmmx(plsc->vpdxma); mmymi = plP_dcmmy(plsc->vpdymi); mmyma = plP_dcmmy(plsc->vpdyma); /* Set transformation variables for world coordinates to mm */ plsc->wmxscl = (mmxma - mmxmi) / dx; plsc->wmxoff = (xmax * mmxmi - xmin * mmxma) / dx; plsc->wmyscl = (mmyma - mmymi) / dy; plsc->wmyoff = (ymax * mmymi - ymin * mmyma) / dy; /* Set transformation variables for world coordinates to device coords */ plsc->wdxscl = plsc->wmxscl * plsc->xpmm / (plsc->phyxma - plsc->phyxmi); plsc->wdxoff = plsc->wmxoff * plsc->xpmm / (plsc->phyxma - plsc->phyxmi); plsc->wdyscl = plsc->wmyscl * plsc->ypmm / (plsc->phyyma - plsc->phyymi); plsc->wdyoff = plsc->wmyoff * plsc->ypmm / (plsc->phyyma - plsc->phyymi); /* Register plot window attributes */ w.dxmi = plsc->vpdxmi; w.dxma = plsc->vpdxma; w.dymi = plsc->vpdymi; w.dyma = plsc->vpdyma; w.wxmi = plsc->vpwxmi; w.wxma = plsc->vpwxma; w.wymi = plsc->vpwymi; w.wyma = plsc->vpwyma; plP_swin(&w); /* Go to level 3 */ plsc->level = 3; }
void pltr2(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data) { PLINT ul, ur, vl, vr; PLFLT du, dv; PLFLT xll, xlr, xrl, xrr; PLFLT yll, ylr, yrl, yrr; PLFLT xmin, xmax, ymin, ymax; PLcGrid2 *grid = (PLcGrid2 *) pltr_data; PLFLT **xg = grid->xg; PLFLT **yg = grid->yg; PLINT nx = grid->nx; PLINT ny = grid->ny; ul = (PLINT) x; ur = ul + 1; du = x - ul; vl = (PLINT) y; vr = vl + 1; dv = y - vl; xmin = 0; xmax = nx - 1; ymin = 0; ymax = ny - 1; if (x < xmin || x > xmax || y < ymin || y > ymax) { plwarn("pltr2: Invalid coordinates"); if (x < xmin) { if (y < ymin) { *tx = xg[0][0]; *ty = yg[0][0]; } else if (y > ymax) { *tx = xg[0][ny-1]; *ty = yg[0][ny-1]; } else { xll = xg[0][vl]; yll = yg[0][vl]; xlr = xg[0][vr]; ylr = yg[0][vr]; *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } } else if (x > xmax) { if (y < ymin) { *tx = xg[nx-1][0]; *ty = yg[nx-1][0]; } else if (y > ymax) { *tx = xg[nx-1][ny-1]; *ty = yg[nx-1][ny-1]; } else { xll = xg[nx-1][vl]; yll = yg[nx-1][vl]; xlr = xg[nx-1][vr]; ylr = yg[nx-1][vr]; *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } } else { if (y < ymin) { xll = xg[ul][0]; xrl = xg[ur][0]; yll = yg[ul][0]; yrl = yg[ur][0]; *tx = xll * (1 - du) + xrl * (du); *ty = yll * (1 - du) + yrl * (du); } else if (y > ymax) { xlr = xg[ul][ny-1]; xrr = xg[ur][ny-1]; ylr = yg[ul][ny-1]; yrr = yg[ur][ny-1]; *tx = xlr * (1 - du) + xrr * (du); *ty = ylr * (1 - du) + yrr * (du); } } } /* Normal case. * Look up coordinates in row-dominant array. * Have to handle right boundary specially -- if at the edge, we'd * better not reference the out of bounds point. */ else { xll = xg[ul][vl]; yll = yg[ul][vl]; /* ur is out of bounds */ if (ur == nx && vr < ny) { xlr = xg[ul][vr]; ylr = yg[ul][vr]; *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } /* vr is out of bounds */ else if (ur < nx && vr == ny) { xrl = xg[ur][vl]; yrl = yg[ur][vl]; *tx = xll * (1 - du) + xrl * (du); *ty = yll * (1 - du) + yrl * (du); } /* both ur and vr are out of bounds */ else if (ur == nx && vr == ny) { *tx = xll; *ty = yll; } /* everything in bounds */ else { xrl = xg[ur][vl]; xlr = xg[ul][vr]; xrr = xg[ur][vr]; yrl = yg[ur][vl]; ylr = yg[ul][vr]; yrr = yg[ur][vr]; *tx = xll * (1 - du) * (1 - dv) + xlr * (1 - du) * (dv) + xrl * (du) * (1 - dv) + xrr * (du) * (dv); *ty = yll * (1 - du) * (1 - dv) + ylr * (1 - du) * (dv) + yrl * (du) * (1 - dv) + yrr * (du) * (dv); } } }
static void rdbuf_state(PLStream *pls) { U_CHAR op; dbug_enter("rdbuf_state"); fread(&op, sizeof(U_CHAR), 1, pls->plbufFile); switch (op) { case PLSTATE_WIDTH:{ U_CHAR width; fread(&width, sizeof(U_CHAR), 1, pls->plbufFile); pls->width = width; plP_state(PLSTATE_WIDTH); break; } case PLSTATE_COLOR0:{ U_CHAR icol0, r, g, b; fread(&icol0, sizeof(U_CHAR), 1, pls->plbufFile); if (icol0 == PL_RGB_COLOR) { fread(&r, sizeof(U_CHAR), 1, pls->plbufFile); fread(&g, sizeof(U_CHAR), 1, pls->plbufFile); fread(&b, sizeof(U_CHAR), 1, pls->plbufFile); } else { if ((int) icol0 > 15) { plwarn("rdbuf_state: Color map 0 entry hosed"); icol0 = 1; } r = pls->cmap0[icol0].r; g = pls->cmap0[icol0].g; b = pls->cmap0[icol0].b; } pls->icol0 = icol0; pls->curcolor.r = r; pls->curcolor.g = g; pls->curcolor.b = b; plP_state(PLSTATE_COLOR0); break; } case PLSTATE_COLOR1: { U_CHAR icol1; fread(&icol1, sizeof(U_CHAR), 1, pls->plbufFile); pls->icol1 = icol1; pls->curcolor.r = pls->cmap1[icol1].r; pls->curcolor.g = pls->cmap1[icol1].g; pls->curcolor.b = pls->cmap1[icol1].b; plP_state(PLSTATE_COLOR1); break; } case PLSTATE_FILL: { signed char patt; fread(&patt, sizeof(signed char), 1, pls->plbufFile); pls->patt = patt; plP_state(PLSTATE_FILL); break; } } }
void proc_str (PLStream *pls, EscText *args) { PLFLT *t = args->xform, tt[4]; /* Transform matrices */ PLFLT theta; /* Rotation angle and shear from the matrix */ PLFLT ft_ht, offset; /* Font height and offset */ PLFLT cs,sn,l1,l2; PSDev *dev = (PSDev *) pls->dev; char *font, esc; /* Be generous. Used to store lots of font changes which take * 3 characters per change.*/ #define PROC_STR_STRING_LENGTH 1000 unsigned char *strp, str[PROC_STR_STRING_LENGTH], *cur_strp, cur_str[PROC_STR_STRING_LENGTH]; float font_factor = 1.4; PLINT clxmin, clxmax, clymin, clymax; /* Clip limits */ PLINT clipx[4],clipy[4]; /* Current clip limits */ PLFLT scale = 1., up = 0.; /* Font scaling and shifting parameters */ int i=0; /* String index */ short text_len; /* unicode only! so test for it. */ if (args->unicode_array_len>0) { int j,s,f; char *fonts[PROC_STR_STRING_LENGTH]; int nlookup; const Unicode_to_Type1_table *lookup; const PLUNICODE *cur_text; const PLUNICODE *cur_text_limit; PLUNICODE fci; /* translate from unicode into type 1 font index. */ /* * Choose the font family, style, variant, and weight using * the FCI (font characterization integer). */ plgesc(&esc); plgfci(&fci); font = plP_FCI2FontName(fci, Type1Lookup, N_Type1Lookup); if (font == NULL) { fprintf(stderr, "fci = 0x%x, font name pointer = NULL \n", fci); plabort("proc_str: FCI inconsistent with Type1Lookup; " "internal PLplot error"); return; } /*pldebug("proc_str", "fci = 0x%x, font name = %s\n", fci, font);*/ if (!strcmp(font, "Symbol")) { nlookup = number_of_entries_in_unicode_to_symbol_table; lookup = unicode_to_symbol_lookup_table; } else { nlookup = number_of_entries_in_unicode_to_standard_table; lookup = unicode_to_standard_lookup_table; } cur_text = args->unicode_array; for (f=s=j=0; j < args->unicode_array_len; j++) { if (cur_text[j] & PL_FCI_MARK) { /* process an FCI by saving it and escaping cur_str * with an escff to make it a 2-character escape * that is not used in legacy Hershey code */ if ((f < PROC_STR_STRING_LENGTH) && (s+3 < PROC_STR_STRING_LENGTH)) { fonts[f] = plP_FCI2FontName(cur_text[j], Type1Lookup, N_Type1Lookup); if (fonts[f] == NULL) { fprintf(stderr, "string-supplied FCI = 0x%x, font name pointer = NULL \n", cur_text[j]); plabort("proc_str: string-supplied FCI inconsistent with Type1Lookup;"); return; } /*pldebug("proc_str", "string-supplied FCI = 0x%x, font name = %s\n", cur_text[j], fonts[f]);*/ if (!strcmp(fonts[f++], "Symbol")) { lookup = unicode_to_symbol_lookup_table; nlookup = number_of_entries_in_unicode_to_symbol_table; } else { lookup = unicode_to_standard_lookup_table; nlookup = number_of_entries_in_unicode_to_standard_table; } cur_str[s++] = esc; cur_str[s++] = 'f'; cur_str[s++] = 'f'; } } else if (s+1 < PROC_STR_STRING_LENGTH) { cur_str[s++] = plunicode2type1(cur_text[j], lookup, nlookup); /*pldebug("proc_str", "unicode = 0x%x, type 1 code = %d\n", cur_text[j], cur_str[j]);*/ } } cur_str[s] = '\0'; /* finish previous polyline */ dev->xold = PL_UNDEFINED; dev->yold = PL_UNDEFINED; /* Determine the font height */ ft_ht = pls->chrht * 72.0/25.4; /* ft_ht in points, ht is in mm */ /* The transform matrix has only rotations and shears; extract them */ theta = acos(t[0]) * 180. / PI; /* Determine the rotation (in degrees)... */ if (t[2] < 0.) theta *= -1.; /* ... and sign ... */ cs = cos(theta*PI/180.); sn = sin(theta*PI/180.); tt[0] = t[0]*cs + t[2]*sn; tt[1] = t[1]*cs + t[3]*sn; tt[2] = -t[0]*sn + t[2]*cs; tt[3] = -t[1]*sn + t[3]*cs; /* * Reference point conventions: * If base = 0, it is aligned with the center of the text box * If base = 1, it is aligned with the baseline of the text box * If base = 2, it is aligned with the top of the text box * * Currently plplot only uses base=0 * Postscript uses base=1 * * We must calculate the difference between the two and apply the offset. */ if (args->base == 2) /* not supported by plplot */ offset = ENLARGE * ft_ht / 2.; /* half font height */ else if (args->base == 1) offset = 0.; else offset = -ENLARGE * ft_ht / 2.; args->y += offset*cos(theta*PI/180.); args->x -= offset*sin(theta*PI/180.); /* Apply plplot difilt transformations */ difilt(&args->x, &args->y, 1, &clxmin, &clxmax, &clymin, &clymax); /* ps driver is rotated by default */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &(args->x), &(args->y)); /* Determine the adjustment for page orientation */ theta += 90. - 90.*pls->diorot; /* Output */ /* Set clipping */ clipx[0]=pls->clpxmi; clipx[2]=pls->clpxma; clipy[0]=pls->clpymi; clipy[2]=pls->clpyma; clipx[1]=clipx[2]; clipy[1]=clipy[0]; clipx[3]=clipx[0]; clipy[3]=clipy[2]; difilt(clipx, clipy, 4, &clxmin, &clxmax, &clymin, &clymax); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &clipx[0], &clipy[0]); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &clipx[1], &clipy[1]); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &clipx[2], &clipy[2]); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &clipx[3], &clipy[3]); fprintf(OF," gsave %d %d %d %d %d %d %d %d CL\n",clipx[0],clipy[0],clipx[1],clipy[1],clipx[2],clipy[2],clipx[3],clipy[3]); /* move to string reference point */ fprintf(OF, " %d %d M\n", args->x, args->y ); /* Save the current position and set the string rotation */ fprintf(OF, "gsave %.3f R\n",theta); /* Purge escape sequences from string, so that postscript can find it's * length. The string length is computed with the current font, and can * thus be wrong if there are font change escape sequences in the string */ esc_purge(str, cur_str); fprintf(OF, "/%s %.3f SF\n", font,font_factor * ENLARGE * ft_ht); /* Output string, while escaping the '(', ')' and '\' characters. * this string is output for measurement purposes only. */ fprintf(OF, "%.3f (", - args->just); while (str[i]!='\0') { if (str[i]=='(' || str[i]==')' || str[i]=='\\') fprintf(OF,"\\%c",str[i]); else fprintf(OF,"%c",str[i]); i++; } fprintf(OF,") SW\n"); /* Parse string for PLplot escape sequences and print everything out */ cur_strp = cur_str; f = 0; do { strp = str; if (*cur_strp == esc) { cur_strp++; if (*cur_strp == esc) { /* <esc><esc> */ *strp++ = *cur_strp++; } else if (*cur_strp == 'f') { cur_strp++; if (*cur_strp++ != 'f') { /* escff occurs because of logic above. But any suffix * other than "f" should never happen. */ plabort("proc_str, internal PLplot logic error;" "wrong escf escape sequence"); return; } font = fonts[f++]; /*pldebug("proc_str", "string-specified fci = 0x%x, font name = %s\n", fci, font);*/ continue; } else switch (*cur_strp++) { case 'd': case 'D': if(up>0.) scale *= 1.25; /* Subscript scaling parameter */ else scale *= 0.8; /* Subscript scaling parameter */ up -= font_factor * ENLARGE * ft_ht / 2.; break; case 'u': case 'U': if(up<0.) scale *= 1.25; /* Subscript scaling parameter */ else scale *= 0.8; /* Subscript scaling parameter */ up += font_factor * ENLARGE * ft_ht / 2.; break; /* ignore the next sequences */ case '+': case '-': case 'b': case 'B': plwarn("'+', '-', and 'b/B' text escape sequences not processed."); break; } } /* copy from current to next token, adding a postscript escape * char '\' if necessary */ while(*cur_strp && *cur_strp != esc) { if (*cur_strp == '(' || *cur_strp == ')' || *cur_strp == '\\') *strp++ = '\\'; *strp++ = *cur_strp++; } *strp = '\0'; if(fabs(up)<0.001) up = 0.; /* Watch out for small differences */ /* Apply the scaling and the shear */ fprintf(OF, "/%s [%.3f %.3f %.3f %.3f 0 0] SF\n", font, tt[0]*font_factor * ENLARGE * ft_ht * scale, tt[2]*font_factor * ENLARGE * ft_ht * scale, tt[1]*font_factor * ENLARGE * ft_ht * scale, tt[3]*font_factor * ENLARGE * ft_ht * scale); /* if up/down escape sequences, save current point and adjust baseline; * take the shear into account */ if(up!=0.) fprintf(OF, "gsave %.3f %.3f rmoveto\n",up*tt[1],up*tt[3]); /* print the string */ fprintf(OF, "(%s) show\n", str); /* back to baseline */ if (up!=0.) fprintf(OF, "grestore (%s) stringwidth rmoveto\n", str); }while(*cur_strp); fprintf(OF, "grestore\n"); fprintf(OF, "grestore\n"); /* * keep driver happy -- needed for background and orientation. * arghhh! can't calculate it, as I only have the string reference * point, not its extent! * Still a hack - but at least it takes into account the string * length and justification. Character width is assumed to be * 0.6 * character height. Add on an extra 1.5 * character height * for safety. */ cs = cos(theta/180.*PI); sn = sin(theta/180.*PI); l1 = -i*args->just; l2 = i*(1.-args->just); /* Factor of 0.6 is an empirical fudge to convert character * height to average character width */ l1 *= 0.6; l2 *= 0.6; dev->llx = MIN(dev->llx, args->x + (MIN(l1*cs,l2*cs)-1.5) * font_factor * ft_ht * ENLARGE ); dev->lly = MIN(dev->lly, args->y + (MIN(l1*sn,l2*sn)-1.5) * font_factor * ft_ht * ENLARGE ); dev->urx = MAX(dev->urx, args->x + (MAX(l1*cs,l2*cs)+1.5) * font_factor * ft_ht * ENLARGE ); dev->ury = MAX(dev->ury, args->y + (MAX(l1*sn,l2*sn)+1.5) * font_factor * ft_ht * ENLARGE ); } }
static void setcmap(PLStream *pls) { int i, ncol1=pls->ncol1; int ncol0=pls->ncol0, total_colours; PLColor cmap1col; png_Dev *dev=(png_Dev *)pls->dev; PLFLT tmp_colour_pos; /* * Yuckky fix to get rid of the previosuly allocated palette from the * GD image */ if (dev->im_out != NULL) { for (i=0;i<256;i++) { gdImageColorDeallocate(dev->im_out,i); } } if (ncol0>NCOLOURS/2) /* Check for ridiculous number of colours */ { /* in ncol0, and appropriately adjust the */ plwarn("Too many colours in cmap0."); /* number, issuing a */ ncol0=NCOLOURS/2; /* warning if it does */ pls->ncol0=ncol0; } dev->totcol=0; /* Reset the number of colours counter to zero */ total_colours=ncol0+ncol1; /* Work out how many colours are wanted */ if (total_colours>NCOLOURS) /* Do some rather modest error */ { /* checking to make sure that */ total_colours=NCOLOURS; /* we are not defining more colours */ ncol1=total_colours-ncol0; /* than we have room for. */ if (ncol1<=0) { plexit("Problem setting colourmap in PNG or JPEG driver."); } } dev->ncol1=ncol1; /* The actual size of ncol1, regardless of what was asked. * This is dependent on colour slots available. * It might well be the same as ncol1. */ /* Initialize cmap 0 colors */ if ((ncol0>0)&&(dev->im_out != NULL)) /* make sure the program actually asked for cmap0 first */ { for (i = 0; i < ncol0; i++) { gdImageColorAllocate(dev->im_out, pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b); ++dev->totcol; /* count the number of colours we use as we use them */ } } /* Initialize any remaining slots for cmap1 */ if ((ncol1>0)&&(dev->im_out != NULL)) /* make sure that we want to define cmap1 first */ { for (i = 0; i < ncol1; i++) { if (ncol1<pls->ncol1) /* Check the dynamic range of colours */ { /* * Ok, now if we have less colour slots available than are being * defined by pls->ncol1, then we still want to use the full * dynamic range of cmap1 as best we can, so what we do is work * out an approximation to the index in the full dynamic range * in cases when pls->ncol1 exceeds the number of free colours. */ tmp_colour_pos= i>0 ? pls->ncol1*((PLFLT)i/ncol1) : 0; plcol_interp(pls, &cmap1col, (int) tmp_colour_pos, pls->ncol1); } else { plcol_interp(pls, &cmap1col, i, ncol1); } gdImageColorAllocate(dev->im_out, cmap1col.r, cmap1col.g, cmap1col.b); ++dev->totcol; /* count the number of colours we use as we go */ } } }
// // pl_create_tempfile() // // Securely create a temporary file and return a file handle to it. // This provides cross-platform compatibility and also adds some // additional functionality over mkstemp in that it honours the TMP / // TMPDIR / TEMP environment variables. // // The function returns the file handle. // // If the fname variable is not NULL, then on return it will contain // a pointer to the full temporary file name. This will be allocated // with malloc. It is the caller's responsibility to ensure this // memory is free'd and to ensure the file is deleted after use. // If fname is NULL then the file will be automatically deleted // when it is closed. // FILE * pl_create_tempfile( char **fname ) { FILE *fd; const char *tmpdir; char *templte; const char *tmpname = "plplot_XXXXXX"; #if !defined PL_HAVE_MKSTEMP int flags; #endif #if defined ( MSDOS ) || defined ( WIN32 ) tmpdir = getenv( "TEMP" ); #else tmpdir = getenv( "TMPDIR" ); #endif // The P_TMPDIR macro is defined in stdio.h on many UNIX systems - try that #ifdef P_TMPDIR if ( tmpdir == NULL ) tmpdir = P_TMPDIR; #endif if ( tmpdir == NULL ) { #if defined ( MSDOS ) || defined ( WIN32 ) tmpdir = "c:\\windows\\Temp"; #else tmpdir = "/tmp"; #endif } // N.B. Malloc ensures templte is long enough so strcpy and strcat are safe here templte = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + 2 ) ); strcpy( templte, tmpdir ); #if defined ( MSDOS ) || defined ( WIN32 ) strcat( templte, "\\" ); #else strcat( templte, "/" ); #endif strcat( templte, tmpname ); #ifdef PL_HAVE_MKSTEMP fd = fdopen( mkstemp( templte ), "wb+" ); if ( fd == NULL ) { plwarn( "pl_create_tempfile: Unable to open temporary file - returning" ); if ( fname != NULL ) *fname = NULL; free( templte ); return NULL; } // If we are not returning the file name then unlink the file so it is // automatically deleted. #ifdef PL_HAVE_UNLINK if ( fname == NULL ) unlink( templte ); #endif #else #if !defined ( _S_IREAD ) #define _S_IREAD 256 #endif #if !defined ( _S_IWRITE ) #define _S_IWRITE 128 #endif fd = NULL; flags = O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED; // If we are not returning the file name then add flag to automatically // delete file once all file handles are closed. if ( fname == NULL ) flags = flags | _O_TEMPORARY; mktemp( templte ); fd = fdopen( open( templte, flags, _S_IREAD | _S_IWRITE ), "wb+" ); #endif if ( fname != NULL ) { *fname = templte; } else { free( templte ); } return fd; }
//-------------------------------------------------------------------------- //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) }
// // pl_create_tempfifo() // // Securely create a temporary fifo and return the file name. // This only works on POSIX compliant platforms at the moment. // It creates a secure directory first using mkdtemp, then // creates the named fifo in this directory. The combination of // a private directory and mkfifo failing if the file name already exists // makes this secure against race conditions / DoS attacks. This function // includes additional functionality over mkdtemp in that it honours the // TMP / TMPDIR / TEMP environment variables. // // The function returns the file name of the fifo. // char * pl_create_tempfifo( const char **p_fifoname, const char **p_dirname ) { #if !defined PL_HAVE_MKDTEMP || !defined PL_HAVE_MKFIFO plwarn( "Creating fifos not supported on this platform" ); return NULL; #else const char *tmpdir; char *templte; char *dirname; const char *tmpname = "plplot_dir_XXXXXX"; const char *fifoname = "plplot_fifo"; #if defined ( MSDOS ) || defined ( WIN32 ) tmpdir = getenv( "TEMP" ); #else tmpdir = getenv( "TMPDIR" ); #endif // The P_TMPDIR macro is defined in stdio.h on many UNIX systems - try that #ifdef P_TMPDIR if ( tmpdir == NULL ) tmpdir = P_TMPDIR; #endif if ( tmpdir == NULL ) { #if defined ( MSDOS ) || defined ( WIN32 ) tmpdir = "c:\\windows\\Temp"; #else tmpdir = "/tmp"; #endif } // N.B. Malloc ensures templte is long enough so strcpy and strcat are safe here dirname = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + 2 ) ); strcpy( dirname, tmpdir ); #if defined ( MSDOS ) || defined ( WIN32 ) strcat( dirname, "\\" ); #else strcat( dirname, "/" ); #endif strcat( dirname, tmpname ); // Create the temporary directory dirname = mkdtemp( dirname ); *p_dirname = dirname; // Now create the fifo in the directory templte = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + strlen( fifoname ) + 4 ) ); strcpy( templte, dirname ); #if defined ( MSDOS ) || defined ( WIN32 ) strcat( templte, "\\" ); #else strcat( templte, "/" ); #endif strcat( templte, fifoname ); *p_fifoname = templte; // Check that mkfifo succeeds safely if ( mkfifo( templte, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) { plwarn( "mkfifo error" ); free( templte ); *p_fifoname = NULL; free( dirname ); *p_dirname = NULL; return NULL; } return templte; #endif }
void pltr2f(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, void *pltr_data) { PLINT ul, ur, vl, vr; PLFLT du, dv; PLFLT xll, xlr, xrl, xrr; PLFLT yll, ylr, yrl, yrr; PLFLT xmin, xmax, ymin, ymax; PLcGrid *cgrid = (PLcGrid *) pltr_data; PLFLT *xg = cgrid->xg; PLFLT *yg = cgrid->yg; PLINT nx = cgrid->nx; PLINT ny = cgrid->ny; ul = (PLINT) x; ur = ul + 1; du = x - ul; vl = (PLINT) y; vr = vl + 1; dv = y - vl; xmin = 0; xmax = nx - 1; ymin = 0; ymax = ny - 1; if (x < xmin || x > xmax || y < ymin || y > ymax) { plwarn("pltr2f: Invalid coordinates"); if (x < xmin) { if (y < ymin) { *tx = *xg; *ty = *yg; } else if (y > ymax) { *tx = *(xg + (ny - 1) * nx); *ty = *(yg + (ny - 1) * nx); } else { ul = 0; xll = *(xg + ul + vl * nx); yll = *(yg + ul + vl * nx); xlr = *(xg + ul + vr * nx); ylr = *(yg + ul + vr * nx); *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } } else if (x > xmax) { if (y < ymin) { *tx = *(xg + (nx - 1)); *ty = *(yg + (nx - 1)); } else if (y > ymax) { *tx = *(xg + (nx - 1) + (ny - 1) * nx); *ty = *(yg + (nx - 1) + (ny - 1) * nx); } else { ul = nx - 1; xll = *(xg + ul + vl * nx); yll = *(yg + ul + vl * nx); xlr = *(xg + ul + vr * nx); ylr = *(yg + ul + vr * nx); *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } } else { if (y < ymin) { vl = 0; xll = *(xg + ul + vl * nx); xrl = *(xg + ur + vl * nx); yll = *(yg + ul + vl * nx); yrl = *(yg + ur + vl * nx); *tx = xll * (1 - du) + xrl * (du); *ty = yll * (1 - du) + yrl * (du); } else if (y > ymax) { vr = ny - 1; xlr = *(xg + ul + vr * nx); xrr = *(xg + ur + vr * nx); ylr = *(yg + ul + vr * nx); yrr = *(yg + ur + vr * nx); *tx = xlr * (1 - du) + xrr * (du); *ty = ylr * (1 - du) + yrr * (du); } } } /* Normal case. Look up coordinates in row-dominant array. Have to handle right boundary specially -- if at the edge, we'd better not reference the out of bounds point. */ else { xll = *(xg + ul + vl * nx); yll = *(yg + ul + vl * nx); /* ur is out of bounds */ if (ur == nx && vr < ny) { xlr = *(xg + ul + vr * nx); ylr = *(yg + ul + vr * nx); *tx = xll * (1 - dv) + xlr * (dv); *ty = yll * (1 - dv) + ylr * (dv); } /* vr is out of bounds */ else if (ur < nx && vr == ny) { xrl = *(xg + ur + vl * nx); yrl = *(yg + ur + vl * nx); *tx = xll * (1 - du) + xrl * (du); *ty = yll * (1 - du) + yrl * (du); } /* both ur and vr are out of bounds */ else if (ur == nx && vr == ny) { *tx = xll; *ty = yll; } /* everything in bounds */ else { xrl = *(xg + ur + vl * nx); xlr = *(xg + ul + vr * nx); xrr = *(xg + ur + vr * nx); yrl = *(yg + ur + vl * nx); ylr = *(yg + ul + vr * nx); yrr = *(yg + ur + vr * nx); /* INDENT OFF */ *tx = xll * (1 - du) * (1 - dv) + xlr * (1 - du) * (dv) + xrl * (du) * (1 - dv) + xrr * (du) * (dv); *ty = yll * (1 - du) * (1 - dv) + ylr * (1 - du) * (dv) + yrl * (du) * (1 - dv) + yrr * (du) * (dv); /* INDENT ON */ } } }
static void plD_init_png_Dev(PLStream *pls) { png_Dev *dev; /* Stuff for the driver options, these vars are copied into the driver * structure so that everything is thread safe and reenterant. */ static int optimise=0; static int black15=0; static int red15=0; #if GD2_VERS >= 2 static int truecolour=0; static int palette=0; #endif #ifdef HAVE_FREETYPE static int freetype=1; static int smooth_text=1; FT_Data *FT; #endif DrvOpt gd_options[] = {{"optimise", DRV_INT, 0, &optimise, "Optimise PNG palette when possible"}, {"def_black15", DRV_INT, 0, &black15, "Define idx 15 as black. If the background is \"whiteish\" (from \"-bg\" option), force index 15 (traditionally white) to be \"black\""}, {"swp_red15", DRV_INT, 0, &red15, "Swap index 1 (usually red) and 1 (usually white); always done after \"black15\"; quite useful for quick changes to web pages"}, #if GD2_VERS >= 2 {"8bit", DRV_INT, 0, &palette, "Palette (8 bit) mode"}, {"24bit", DRV_INT, 0, &truecolour, "Truecolor (24 bit) mode"}, #endif #ifdef HAVE_FREETYPE {"text", DRV_INT, 0, &freetype, "Use driver text (FreeType)"}, {"smooth", DRV_INT, 0, &smooth_text, "Turn text smoothing on (1) or off (0)"}, #endif {NULL, DRV_INT, 0, NULL, NULL}}; /* Allocate and initialize device-specific data */ if (pls->dev != NULL) free((void *) pls->dev); pls->dev = calloc(1, (size_t) sizeof(png_Dev)); if (pls->dev == NULL) plexit("plD_init_png_Dev: Out of memory."); dev = (png_Dev *) pls->dev; dev->colour=1; /* Set a fall back pen colour in case user doesn't */ /* * Set the compression/quality level for JPEG files * The higher the value, the bigger/better the image is */ if ( (pls->dev_compression<=0)||(pls->dev_compression>99) ) pls->dev_compression=90; /* Check for and set up driver options */ plParseDrvOpts(gd_options); dev->black15=black15; dev->red15=red15; dev->optimise=optimise; #if GD2_VERS >= 2 dev->palette=palette; dev->truecolour=truecolour; if ((dev->truecolour>0) && (dev->palette>0)) plwarn("Selecting both \"truecolor\" AND \"palette\" driver options is contradictory, so\nI will just use my best judgment.\n"); else if (dev->truecolour>0) NCOLOURS=16777216; else if ((dev->truecolour==0)&&(dev->palette==0)&&((pls->ncol1+pls->ncol0)>NCOLOURS)) { NCOLOURS=16777216; } #ifdef HAVE_FREETYPE if ((dev->palette==0)&&(dev->optimise==0)&&(smooth_text>1)) dev->smooth=1; /* Allow smoothing of lines if we have a truecolour device */ #endif #endif #ifdef HAVE_FREETYPE if (freetype) { pls->dev_text = 1; /* want to draw text */ pls->dev_unicode = 1; /* want unicode */ /* As long as we aren't optimising, we'll try to use better antialaising * We can also only do this if the user wants smoothing, and hasn't * selected a palette mode. */ init_freetype_lv1(pls); FT=(FT_Data *)pls->FT; FT->want_smooth_text=smooth_text>0 ? 1 : 0; if ((dev->optimise==0)&&(dev->palette==0)&&(smooth_text!=0)) { FT->BLENDED_ANTIALIASING=1; dev->truecolour=1; } } #endif }