Ejemplo n.º 1
0
void
proc_str (PLStream *pls, EscText *args)
{
  PLFLT *t = args->xform;
  PLFLT a1, alpha, ft_ht, angle, ref;
  PLDev *dev = (PLDev *) pls->dev;
  PLINT clxmin, clxmax, clymin, clymax;
  int jst, font;

  /* font height */
  ft_ht = pls->chrht * 72.0/25.4; /* ft_ht in points. ht is in mm */

  /* calculate baseline text angle */
  angle = pls->diorot * 90.;
  a1 = acos(t[0]) * 180. / PI;
  if (t[2] > 0.)
    alpha = a1 - angle;
  else
    alpha = 360. - a1 - angle;

  alpha = alpha * PI / 180.;

  /* TODO: parse string for format (escape) characters */
  /* parse_str(args->string, return_string);*/

  /* apply transformations */
  difilt(&args->x, &args->y, 1, &clxmin, &clxmax, &clymin, &clymax);

  /* check clip limits. For now, only the reference point of the string is checked;
     but the the whole string should be checked -- using a postscript construct
     such as gsave/clip/grestore. This method can also be applied to the xfig and
     pstex drivers. Zoom side effect: the font size must be adjusted! */

  if ( args->x < clxmin || args->x > clxmax || args->y < clymin || args->y > clymax)
    return;

  /* 
   * Text justification.  Left, center and right justification, which
   *  are the more common options, are supported; variable justification is
   *  only approximate, based on plplot computation of it's string lenght
   */

  if (args->just == 0.5)
    jst = 1; /* center */
  else if (args->just == 1.)
    jst = 2; /* right */
  else {
    jst = 0; /* left */
    args->x = args->refx; /* use hints provided by plplot */
    args->y = args->refy;
  }

  /* 
   * Reference point (center baseline of string, not latex character reference point). 
   *  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
   *  xfig use base=1
   */ 

  if (args->base == 2) /* not supported by plplot */
    ref = - DPI/72. * ft_ht / 2.; /* half font height in xfig unities (1/1200 inches) */
  else if (args->base == 1)
    ref = 0.;
  else
    ref = DPI/72. * ft_ht / 2.;

  /* rotate point in xfig is lower left corner, compensate */
  args->y = offset + dev->ymax * (int)dev->xscale_dev - (args->y - ref*cos(alpha));
  args->x = args->x + ref*sin(alpha);

  /*
   *  font family, serie and shape. Currently not supported by plplot
   *
   *  Use Postscript Times
   *  1: Normal font
   *  2: Roman font
   *  3: Italic font
   *  4: sans serif
   */

  switch (pls->cfont) {
  case (1): font = 0; break;
  case (2): font = 1; break;
  case (3): font = 3; break;
  case (4): font = 4; break;
  default:  font = 0;
  }

  fprintf(pls->OutFile,"4 %d %d 50 0 %d %f %f 4 1 1 %d %d %s\\001\n",
	  jst, curcol, font, 1.8 /*!*/ * ft_ht, alpha, args->x, args->y, args->string);

}
Ejemplo n.º 2
0
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 );

     }
}