Пример #1
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 );

     }
}
//--------------------------------------------------------------------------
//  void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
//
//  This is the main function which processes the unicode text strings.
//  Font size, rotation and color are set, width and height of the
//  text string is determined and then the string is drawn to the canvas.
//--------------------------------------------------------------------------
void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
{
    // Check that we got unicode, warning message and return if not
    if ( args->unicode_array_len == 0 )
    {
        printf( "Non unicode string passed to the wxWidgets driver, ignoring\n" );
        return;
    }

    // Check that unicode string isn't longer then the max we allow
    if ( args->unicode_array_len >= 500 )
    {
        printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
        return;
    }

    // Calculate the font size (in pixels)
    fontSize = pls->chrht * VIRTUAL_PIXELS_PER_MM / scaley * 1.3;

    // Use PLplot core routine to get the corners of the clipping rectangle
    PLINT rcx[4], rcy[4];
    difilt_clip( rcx, rcy );

    wxPoint cpoints[4];
    for ( int i = 0; i < 4; i++ )
    {
        cpoints[i].x = rcx[i] / scalex;
        cpoints[i].y = height - rcy[i] / scaley;
    }
    wxDCClipper clip( *m_dc, wxRegion( 4, cpoints ) );

    // calculate rotation of text
    plRotationShear( args->xform, &rotation, &shear, &stride );
    rotation -= pls->diorot * M_PI / 2.0;
    cos_rot   = cos( rotation );
    sin_rot   = sin( rotation );

    // Set font color
    m_dc->SetTextForeground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );
    m_dc->SetTextBackground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );

    PLUNICODE *lineStart     = args->unicode_array;
    int       lineLen        = 0;
    bool      lineFeed       = false;
    bool      carriageReturn = false;
    wxCoord   paraHeight     = 0;
    // Get the curent font
    fontScale = 1.0;
    yOffset   = 0.0;
    plgfci( &fci );
    PSSetFont( fci );
    while ( lineStart != args->unicode_array + args->unicode_array_len )
    {
        while ( lineStart + lineLen != args->unicode_array + args->unicode_array_len
                && *( lineStart + lineLen ) != (PLUNICODE) '\n' )
        {
            lineLen++;
        }
        //set line feed for the beginning of this line and
        //carriage return for the end
        lineFeed       = carriageReturn;
        carriageReturn = lineStart + lineLen != args->unicode_array + args->unicode_array_len
                         && *( lineStart + lineLen ) == (PLUNICODE) ( '\n' );
        if ( lineFeed )
            paraHeight += textHeight + subscriptDepth;

        //remember the text parameters so they can be restored
        double    startingFontScale = fontScale;
        double    startingYOffset   = yOffset;
        PLUNICODE startingFci       = fci;

        // determine extent of text
        posX = args->x / scalex;
        posY = args->y / scaley;

        PSDrawText( lineStart, lineLen, false );

        if ( lineFeed && superscriptHeight > textHeight )
            paraHeight += superscriptHeight - textHeight;

        // actually draw text, resetting the font first
        fontScale = startingFontScale;
        yOffset   = startingYOffset;
        fci       = startingFci;
        PSSetFont( fci );
        posX = (PLINT) ( args->x / scalex - ( args->just * textWidth ) * cos_rot - ( 0.5 * textHeight - paraHeight * lineSpacing ) * sin_rot ); //move to set alignment
        posY = (PLINT) ( args->y / scaley - ( args->just * textWidth ) * sin_rot + ( 0.5 * textHeight - paraHeight * lineSpacing ) * cos_rot );
        PSDrawText( lineStart, lineLen, true );                                                                                                 //draw text

        lineStart += lineLen;
        if ( carriageReturn )
            lineStart++;
        lineLen = 0;
    }
    //posX = args->x;
    //posY = args->y;
    //PSDrawText( args->unicode_array, args->unicode_array_len, false );

    //posX = (PLINT) ( args->x - ( ( args->just * textWidth ) * cos_rot + ( 0.5 * textHeight ) * sin_rot ) * scalex );
    //posY = (PLINT) ( args->y - ( ( args->just * textWidth ) * sin_rot - ( 0.5 * textHeight ) * cos_rot ) * scaley );
    //PSDrawText( args->unicode_array, args->unicode_array_len, true );

    AddtoClipRegion( 0, 0, width, height );
}
Пример #3
0
void wxPLDevBase::PSDrawText( PLUNICODE* ucs4, int ucs4Len, bool drawText )
{
  int i = 0;

  char utf8_string[max_string_length];
  char utf8[5];
  memset( utf8_string, '\0', max_string_length );

  /* Get PLplot escape character */
  char plplotEsc;
  plgesc( &plplotEsc );

  /* Get the curent font */
  fontScale = 1.0;
  yOffset = 0.0;
  PLUNICODE fci;
  plgfci( &fci );
  PSSetFont( fci );
  textWidth=0;
  textHeight=0;

  while( i < ucs4Len ) {
    if( ucs4[i] < PL_FCI_MARK ) {	/* not a font change */
      if( ucs4[i] != (PLUNICODE)plplotEsc ) {  /* a character to display */
        ucs4_to_utf8( ucs4[i], utf8 );
        strncat( utf8_string, utf8, max_string_length );
      	i++;
      	continue;
      }
      i++;
      if( ucs4[i] == (PLUNICODE)plplotEsc ) {   /* a escape character to display */
        ucs4_to_utf8( ucs4[i], utf8 );
        strncat( utf8_string, utf8, max_string_length );
        i++;
        continue;
      } else {
      	if( ucs4[i] == (PLUNICODE)'u' ) {	/* Superscript */
          // draw string so far
          PSDrawTextToDC( utf8_string, drawText );

          // change font scale
      		if( yOffset<0.0 )
            fontScale *= 1.25;  /* Subscript scaling parameter */
      		else
            fontScale *= 0.8;  /* Subscript scaling parameter */
          PSSetFont( fci );

      		yOffset += scaley * fontSize * fontScale / 2.;
      	}
      	if( ucs4[i] == (PLUNICODE)'d' ) {	/* Subscript */
          // draw string so far
          PSDrawTextToDC( utf8_string, drawText );

          // change font scale
          double old_fontScale=fontScale;
      		if( yOffset>0.0 )
            fontScale *= 1.25;  /* Subscript scaling parameter */
      		else
            fontScale *= 0.8;  /* Subscript scaling parameter */
          PSSetFont( fci );

      		yOffset -= scaley * fontSize * old_fontScale / 2.;
      	}
      	if( ucs4[i] == (PLUNICODE)'-' ) {	/* underline */
          // draw string so far
          PSDrawTextToDC( utf8_string, drawText );

          underlined = !underlined;
          PSSetFont( fci );
      	}
      	if( ucs4[i] == (PLUNICODE)'+' ) {	/* overline */
          /* not implemented yet */
        }
        i++;
      }
    } else { /* a font change */
      // draw string so far
      PSDrawTextToDC( utf8_string, drawText );

      // get new font
      fci = ucs4[i];
      PSSetFont( fci );
      i++;
    }
  }

  PSDrawTextToDC( utf8_string, drawText );
}
Пример #4
0
static void
plhrsh(PLINT ch, PLINT x, PLINT y)
{
EscText args;
int idx;
PLUNICODE unicode_char;

  /* Check to see if the device understands unicode and wants to draw
   * symbols.
   */
  if ((plsc->dev_text)&&(plsc->dev_unicode)&&(!plsc->dev_hrshsym))       
    {
      idx=plhershey2unicode(ch); /* Get the index in the lookup table */
      unicode_char=hershey_to_unicode_lookup_table[idx].Unicode;

    /*
     *  Test to see if there is a defined unicode glyph for this hershey code;
     *  if there isn't, then we pass the glyph to plhersh, and have it
     *  rendered the old fashioned way.
     *  Otherwise, we let the driver render it as unicode
     */

      if ((unicode_char==0)||(idx==-1))
        {
#ifndef TEST_FOR_MISSING_GLYPHS
          plhrsh2(ch, x, y);
#endif
        }
      else
        {
	  PLUNICODE  plhrsh_unicode_buffer[3], fci;
	  PLFLT xform[] = {1.0, 0.0, 0.0, 1.0};
	  char esc;
          args.unicode_char=unicode_char;
          args.font_face=hershey_to_unicode_lookup_table[idx].Font;
          args.base = 1;
          args.just = .5;
          args.xform = 0;
          args.x = x;
          args.y = y;
	  args.string=NULL;  /* Since we are using unicode, we want this to be NULL */
	  /* "array method" */
	  plgesc(&esc);
	  args.xform = xform;
	  args.unicode_array_len=2;
	  /* Temporary Symbol font for every character. */
	  plgfci(&fci);
	  plP_hex2fci(PL_FCI_SYMBOL, PL_FCI_FAMILY, &fci);
	  plhrsh_unicode_buffer[0] = fci;
	  plhrsh_unicode_buffer[1] = unicode_char;
	  /* watch out for escape character and unescape it by appending
	   * one extra. */
	  if (unicode_char == esc) {
	     args.unicode_array_len=3;
	     plhrsh_unicode_buffer[2] = unicode_char;
	  }
	   
	  /* No need to change font back since only one character. */
	  args.unicode_array=&plhrsh_unicode_buffer[0];   /* Get address of the unicode buffer (even though it is currently static) */

          plP_esc(PLESC_HAS_TEXT, &args);
        }

    }
  else
    {
       plhrsh2(ch, x, y);
    }
}