void plD_line_ps(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PSDev *dev = (PSDev *) pls->dev; PLINT x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a; /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2); if (x1 == dev->xold && y1 == dev->yold && dev->ptcnt < 40) { if (pls->linepos + 12 > LINELENGTH) { putc('\n', OF); pls->linepos = 0; } else putc(' ', OF); sprintf(outbuf, "%d %d D", x2, y2); dev->ptcnt++; pls->linepos += 12; } else { fprintf(OF, " Z\n"); pls->linepos = 0; if (x1 == x2 && y1 == y2) /* must be a single dot, draw a circle */ sprintf(outbuf, "%d %d A", x1, y1); else sprintf(outbuf, "%d %d M %d %d D", x1, y1, x2, y2); dev->llx = MIN(dev->llx, x1); dev->lly = MIN(dev->lly, y1); dev->urx = MAX(dev->urx, x1); dev->ury = MAX(dev->ury, y1); dev->ptcnt = 1; pls->linepos += 24; } dev->llx = MIN(dev->llx, x2); dev->lly = MIN(dev->lly, y2); dev->urx = MAX(dev->urx, x2); dev->ury = MAX(dev->ury, y2); fprintf(OF, "%s", outbuf); pls->bytecnt += 1 + strlen(outbuf); dev->xold = x2; dev->yold = y2; }
static void fill_polygon(PLStream *pls) { PSDev *dev = (PSDev *) pls->dev; PLINT n, ix = 0, iy = 0; PLINT x, y; fprintf(OF, " Z\n"); for (n = 0; n < pls->dev_npts; n++) { x = pls->dev_x[ix++]; y = pls->dev_y[iy++]; /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x, &y); /* First time through start with a x y moveto */ if (n == 0) { sprintf(outbuf, "%d %d M", x, y); dev->llx = MIN(dev->llx, x); dev->lly = MIN(dev->lly, y); dev->urx = MAX(dev->urx, x); dev->ury = MAX(dev->ury, y); fprintf(OF, "%s", outbuf); pls->bytecnt += strlen(outbuf); continue; } if (pls->linepos + 21 > LINELENGTH) { putc('\n', OF); pls->linepos = 0; } else putc(' ', OF); pls->bytecnt++; sprintf(outbuf, "%d %d D", x, y); dev->llx = MIN(dev->llx, x); dev->lly = MIN(dev->lly, y); dev->urx = MAX(dev->urx, x); dev->ury = MAX(dev->ury, y); fprintf(OF, "%s", outbuf); pls->bytecnt += strlen(outbuf); pls->linepos += 21; } dev->xold = PL_UNDEFINED; dev->yold = PL_UNDEFINED; fprintf(OF, " F "); }
void plD_line_ljii(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int i; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; PLINT x1b, y1b, x2b, y2b; PLFLT length, fx, fy, dx, dy; /* Take mirror image, since PCL expects (0,0) to be at top left */ yy1 = dev->ymax - (yy1 - dev->ymin); yy2 = dev->ymax - (yy2 - dev->ymin); /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx1, &yy1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx2, &yy2); x1b = xx1, x2b = xx2, y1b = yy1, y2b = yy2; length = (PLFLT) sqrt((double) ((x2b - x1b) * (x2b - x1b) + (y2b - y1b) * (y2b - y1b))); if (length == 0.) length = 1.; dx = (xx2 - xx1) / length; dy = (yy2 - yy1) / length; fx = xx1; fy = yy1; setpoint((PLINT) xx1, (PLINT) yy1); setpoint((PLINT) xx2, (PLINT) yy2); for (i = 1; i <= (int) length; i++) setpoint((PLINT) (fx += dx), (PLINT) (fy += dy)); }
void plD_line_ljiip(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; int abs_dx, abs_dy, dx, dy, incx, incy; int i, j, width, residual; PLFLT tmp; width = MIN(pls->width, MAX_WID); /* Take mirror image, since PCL expects (0,0) to be at top left */ yy1 = dev->ymax - (yy1 - dev->ymin); yy2 = dev->ymax - (yy2 - dev->ymin); /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx1, &yy1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx2, &yy2); dx = xx2 - xx1; dy = yy2 - yy1; if (dx < 0) { abs_dx = -dx; incx = -1; } else { abs_dx = dx; incx = 1; } if (dy < 0) { abs_dy = -dy; incy = -1; } else { abs_dy = dy; incy = 1; } /* make pixel width narrower for diag lines */ if (abs_dy <= abs_dx) { if (abs_dx == 0) tmp = 1.0; else tmp = 1.0 - (PLFLT) abs_dy / abs_dx; } else { tmp = 1.0 - (PLFLT) abs_dx / abs_dy; } width = floor(0.5 + width * (tmp*tmp*tmp*(1.0-0.707107) + 0.707107)); if (width < 1) width = 1; if (width > 1) { for (i = 0; i < width; i++) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1+i), (PLINT) (yy1+j)); setpoint((PLINT) (xx2+i), (PLINT) (yy2+j)); } } } if (abs_dx >= abs_dy) { residual = -(abs_dx >> 1); if (width == 1) { for (i = 0; i <= abs_dx; i++, xx1 += incx) { setpoint((PLINT) (xx1), (PLINT) (yy1)); if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } else { for (i = 0; i <= abs_dx; i++, xx1 += incx) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1), (PLINT) (yy1+j)); setpoint((PLINT) (xx1+width-1), (PLINT) (yy1+j)); } if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } }
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 ); } }