Logo Search packages:      
Sourcecode: gretl version File versions

psplot.c

/* postscript driver, based on gtkplot code,
 * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
 * Slimmed down for use with gretl by Allin Cottrell <cottrell@wfu.edu>
 *
 * Some few lines of code borrowed from
 * DiaCanvas -- a technical canvas widget
 * Copyright (C) 1999 Arjan Molenaar
 * Dia -- an diagram creation/manipulation program
 * Copyright (C) 1998 Alexander Larsson
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#include <gtk/gtk.h>

#include "gtkpsfontpango.h"
#include "psplot.h"

#define PLOT_LETTER_W   612   /* Width and Height in ps points */
#define PLOT_LETTER_H   792

#define PLOT_A4_W       595
#define PLOT_A4_H       842

struct _PSPlot
{
   FILE *psfile;
   gchar *psname;
 
   gint orientation;
   gint epsflag;

   gint page_size;
   gint page_width;
   gint page_height;

   gdouble scalex, scaley;

   gboolean gsaved;
};

PSPlot *ps_plot_new (const gchar *fname,
                 FILE *fp,
                 gint orientation,
                 gint epsflag,
                 gint page_size,
                 gdouble epswidth,
                 gdouble epsheight,
                 gdouble scalex,
                 gdouble scaley)
{
    PSPlot *ps = malloc(sizeof *ps);
    const char *s;

    if (ps == NULL) {
      return NULL;
    }

    s = strrchr(fname, G_DIR_SEPARATOR);
    if (s != NULL) {
      ps->psname = g_strdup(s + 1);
    } else {
      ps->psname = g_strdup(fname);
    }

    ps->psfile = fp;
    ps->gsaved = FALSE;
    ps->orientation = orientation;
    ps->epsflag = epsflag;
    ps->page_size = page_size;
    ps->scalex = scalex;
    ps->scaley = scaley;

    if (epsflag) {
      ps->page_width = epswidth;
      ps->page_height = epsheight;
    } else if (page_size == PS_PLOT_A4) {
        ps->page_width = PLOT_A4_W;
        ps->page_height = PLOT_A4_H;
    } else {      
        ps->page_width = PLOT_LETTER_W;
        ps->page_height = PLOT_LETTER_H;
    }

    return ps;
}

static void pssetcolor (PSPlot *ps, const GdkColor *color)
{
    fprintf(ps->psfile, "%g %g %g setrgbcolor\n",
          (gdouble) color->red / 65535.0,
          (gdouble) color->green / 65535.0,
          (gdouble) color->blue / 65535.0);
}

static void pssetlineattr (PSPlot *ps, 
                     gfloat line_width,
                     GdkLineStyle line_style,
                     GdkCapStyle cap_style,
                     GdkJoinStyle join_style)
{
    fprintf(ps->psfile, "%g slw\n", line_width);
    fprintf(ps->psfile, "%d slc\n", abs(cap_style - 1));
    fprintf(ps->psfile, "%d slj\n", join_style);

    if (line_style == 0) {
      fputs("[] 0 sd\n", ps->psfile);  /* solid line */
    }
}

static void pssetdash (PSPlot *ps,
                   gdouble offset, 
                   gdouble *values,
                   gint num_values)
{
    FILE *psout = ps->psfile;

    switch (num_values) {
    case 0:
        fputs("[] 0 sd\n", psout);
        break;
    case 2:
        fprintf(psout, "[%g %g] %g sd\n", values[0], values[1], offset);
        break;
    case 4:
        fprintf(psout, "[%g %g %g %g] %g sd\n", values[0], values[1],
            values[2], values[3], 
            offset);
        break;
    case 6:
        fprintf(psout, "[%g %g %g %g %g %g] %g sd\n",  values[0], values[1],
            values[2], values[3], 
            values[4], values[5], 
            offset);
        break;
    default:
        break;
    }
}

void ps_plot_draw_line (PSPlot *ps, gdouble x0, gdouble y0, 
                  gdouble xf, gdouble yf)
{
    fprintf(ps->psfile, "%g %g m\n", x0, y0);
    fprintf(ps->psfile, "%g %g l\n", xf, yf);
    fputs("s\n", ps->psfile);
}

void ps_plot_draw_circle (PSPlot *ps, gboolean filled, gdouble x, 
                    gdouble y, gdouble size)
{
    fprintf(ps->psfile,"n %g %g %g %g 0 360 ellipse\n", 
          x, y, size / 2., size / 2.);

    if (filled) {
      fputs("f\n", ps->psfile);
    }

    fputs("s\n", ps->psfile);
}

void ps_plot_draw_polygon (PSPlot *ps, gboolean filled, PlotPoint *points, 
                     gint numpoints)
{
    FILE *psout = ps->psfile;
    gint i;

    fputs("n\n", psout);
    fprintf(psout, "%g %g m\n", points[0].x, points[0].y);

    for (i=1; i<numpoints; i++) {
      fprintf(psout,"%g %g l\n", points[i].x, points[i].y);
    }

    if (filled) {
      fputs("f\n", psout);
    } else {
      fputs("cp\n", psout);
    }

    fputs("s\n", psout);
}

void ps_plot_draw_rectangle (PSPlot *ps, gboolean filled, gdouble x, gdouble y, 
                       gdouble width, gdouble height)
{
    PlotPoint point[4];

    point[0].x = x;
    point[0].y = y;
    point[1].x = x + width;
    point[1].y = y;
    point[2].x = x + width;
    point[2].y = y + height;
    point[3].x = x;
    point[3].y = y + height;

    ps_plot_draw_polygon(ps, filled, point, 4);
}

static void pssetfont (PSPlot *ps, GtkPSFont *psfont, gint height)
{
    FILE *psout = ps->psfile;

    if (psfont->i18n_latinfamily && psfont->vertical) {
      fprintf(psout,
            "/%s ff [0 1 -1 0 0 0.3] makefont [%d 0 0 %d 0 0] makefont sf\n",
            psfont->psname, height, height);
    } else {
      fprintf(psout, "/%s-latin1 ff %g scf sf\n", psfont->psname, (double) height);
    }
}

static void psgsave (PSPlot *ps)
{
    fputs("gsave\n", ps->psfile);
    ps->gsaved = TRUE;
}

static void psgrestore (PSPlot *ps)
{
    if (ps->gsaved) {
      fputs("grestore\n", ps->psfile);
      ps->gsaved = FALSE;
    }
}

static void
psoutputstring (PSPlot *ps,
            GtkPSFont *psfont,
            GtkPSFont *latin_psfont,
            gint height,
            const GdkWChar *wstring,
            const gchar *addstring)
{
    const GdkWChar *p;
    GdkWChar wcs[2];
    gint curcode = 0, code; /* 0..neither 1..latin 2..i18n */
    gchar begin[] = { 0, '(', '<' };
    gchar end[] = { 0, ')', '>' };
    GtkPSFont *fonts[] = { NULL, latin_psfont, psfont };
    FILE *out = ps->psfile;
    gchar *mbs, *c;

    p = wstring;
  
    if (psfont->i18n_latinfamily) {
      while (*p) {
          code = (*p <= 0x7f) ? 1 : 2;
          if (curcode && curcode != code)
            fprintf(out, "%c %s\n", end[curcode], addstring);
          if (curcode != code) {
            pssetfont(ps, fonts[code], height);
            fputc(begin[code], out);
          }
      
          curcode = code;

          wcs[0] = *p++;
          wcs[1] = 0;
          c = mbs = gdk_wcstombs(wcs);
      
          if (code == 2) {
            while (*c) {
                fprintf(out, "%02x", (unsigned char)(*c++));
            }
          } else {
            if (*c == '(' || *c == ')') {
                fputc('\\', out);
            }
            fputc(*c, out);
          }
      
          g_free(mbs);
      }
    } else {
      c = mbs = gdk_wcstombs(wstring);
    
      while (*c) {
          if (curcode == 0) {
            pssetfont(ps, psfont, height);
            fputc(begin[1], out);
            curcode = 1;
          }

          if (*c == '(' || *c == ')') {
            fputc('\\', out);
          }
          fputc(*c++, out);
      }

      g_free(mbs);
    }

    if (curcode) {
      fprintf(out, "%c %s\n", end[curcode], addstring);
    }
}

static void maybe_nullify_latin (GdkFont **latin_font)
{
    if (*latin_font) {
      gdk_font_unref(*latin_font);
      *latin_font = NULL;
    }
}

static void
plot_text_get_size(const gchar *text, gint angle, 
               const gchar* text_font, 
               gint text_height,   
               gint *width, gint *height,
               gint *ascent, gint *descent)
{
    GdkFont *font = NULL, *latin_font = NULL;
    GtkPSFont *psfont, *base_psfont, *latin_psfont;
    gint old_width, old_height;
    gboolean italic = FALSE, bold = FALSE;
    gint fontsize;
    gint x, y, y0, w;
    GList *family;
    gint numf;
    GdkWChar *aux, *wtext, *lastchar = NULL;
    gint i, a, d;

    gtk_psfont_get_families(&family, &numf);
    base_psfont = psfont = gtk_psfont_get_by_name(text_font);
    font = gtk_psfont_get_gdkfont(psfont, text_height);
    old_width = gdk_string_width (font, text);
    old_height = font->ascent + font->descent;

    if (psfont->i18n_latinfamily) {
      latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic,
                                    bold);
      latin_font = gtk_psfont_get_gdkfont(latin_psfont, text_height);
    } else {
      latin_font = NULL;
      latin_psfont = NULL;
    }

    italic = psfont->italic;
    bold = psfont->bold;
    fontsize = text_height;
  
    x = 0;
    y0 = y = font->ascent;
    old_width = 0;

    *ascent = font->ascent;
    *descent = font->descent;

    i = strlen(text) + 2;
    aux = wtext = g_malloc0(i * sizeof(GdkWChar));
    gdk_mbstowcs(wtext, text, i - 1);

    while (aux && *aux != '\0' && *aux != '\n') {
      if (*aux == '\\'){
          aux++;
          switch (*aux) {
          case '0': case '1': case '2': case '3':
          case '4': case '5': case '6': case '7': case '9':
            psfont = gtk_psfont_get_by_family((gchar *) g_list_nth_data(family, *aux-'0'), 
                                      italic, bold);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            aux++;
            break;
          case '8': case 'g':
            psfont = gtk_psfont_get_by_family("Symbol", italic, bold);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            aux++;
            break;
          case 'B':
            bold = TRUE;
            psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily,
                                              italic, bold);
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            aux++;
            break;
          case 'i':
            italic = TRUE;
            psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily,
                                              italic, bold);
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            aux++;
            break;
          case 'S': case '^':
            fontsize = (int) ((gdouble)fontsize * 0.6 + 0.5);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            y -= font->ascent;
            aux++;
            break;
          case 's': case '_':
            fontsize = (int) ((gdouble)fontsize * 0.6 + 0.5);
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            y += font->descent;
            aux++;
            break;
          case '+':
            fontsize += 3;
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            aux++;
            break;
          case '-':
            fontsize -= 3;
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, fontsize);
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            aux++;
            break;
          case 'N':
            psfont = base_psfont;
            gdk_font_unref(font);
            font = gtk_psfont_get_gdkfont(psfont, text_height);
            y = y0;
            italic = psfont->italic;
            bold = psfont->bold;
            fontsize = text_height;
            maybe_nullify_latin(&latin_font);
            if (psfont->i18n_latinfamily) {
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily,
                                              italic, bold);
                latin_font = gtk_psfont_get_gdkfont(latin_psfont, fontsize);
            }
            aux++;
            break;
          case 'b':
            if (lastchar) {
                gtk_psfont_get_char_size(psfont, font, latin_font, *lastchar, &w,
                                   NULL, NULL);
                x -= w;
           
                if (lastchar == wtext) {
                  lastchar = NULL;
                } else {
                  lastchar--;
                }
            } else {
                gtk_psfont_get_char_size(psfont, font, latin_font, 'X', &w, NULL, NULL);
                x -= w;
            }
            aux++;
            break;
          default:
            if (aux && *aux != '\0' && *aux !='\n') {
                gtk_psfont_get_char_size(psfont, font, latin_font, *aux, &w, &a, &d);
                x += w;
                lastchar = aux;
                aux++;
            }
            break;
          }
      } else {
          if (aux && *aux != '\0' && *aux != '\n') {
            gtk_psfont_get_char_size(psfont, font, latin_font, *aux, &w, &a, &d);
            x += w;
            lastchar = aux;
            aux++;
            if (x > old_width) old_width = x;
            if (y + d - y0 > *descent) *descent = y + d - y0;
            if (y0 - y + a > *ascent) *ascent = y0 - y + a;
          }
      }
    }

    old_height = *ascent + *descent;
    *width = old_width;
    *height = old_height;
    if (angle == 90 || angle == 270) {
      *width = old_height;
      *height = old_width;
    }

    g_free(wtext);
    gdk_font_unref(font);
}

static void
ps_plot_text_get_area(const gchar *text, gint angle, GtkJustification just, 
                  const gchar *font, gint font_height,
                  gint *x, gint *y,
                  gint *width, gint *height)
{
    gint ascent, descent;

    if (text == NULL) return;

    plot_text_get_size(text, angle, font, font_height, 
                   width, height, &ascent, &descent);

    *x = 0;
    *y = 0;

    switch (just) {
    case GTK_JUSTIFY_LEFT:
      switch (angle){
        case 0:
            *y -= ascent;
            break;
        case 90:
            *y -= *height;
            *x -= ascent;
            break;
        case 180:
            *x -= *width;
            *y -= descent;
            break;
        case 270:
            *x -= descent;
            break;
      }
      break;
    case GTK_JUSTIFY_RIGHT:
      switch (angle) {
        case 0:
            *x -= *width;
            *y -= ascent;
            break;
        case 90:
            *x -= ascent;
            break;
        case 180:
            *y -= descent; 
            break;
        case 270:
            *y -= *height;
            *x -= descent; 
            break;
      }
      break;
    case GTK_JUSTIFY_CENTER:
    default:
      switch (angle) {
        case 0:
            *x -= *width / 2.;
            *y -= ascent;
          break;
        case 90:
            *x -= ascent;
            *y -= *height / 2.;
          break;
        case 180:
            *x -= *width / 2.;
            *y -= descent;
            break;
        case 270:
            *x -= descent;
            *y -= *height / 2.;
            break;
      }
    }
}

void ps_plot_draw_string (PSPlot *ps,
                    gint x, gint y,
                    gint angle,
                    const GdkColor *fg,
                    const GdkColor *bg,
                    gboolean transparent,
                    gint border,
                    gint border_space,
                    gint border_width,
                    gint shadow_width,
                    const gchar *font,
                    gint font_height,
                    GtkJustification justification,
                    const gchar *text)
{
    gchar *currfont;
    const gchar *c;
    GtkPSFont *psfont, *base_psfont, *latin_psfont = NULL;
    gint curcnt = 0, offset = 0;
    gint numf;
    gdouble scale;
    gboolean italic, bold;
    gboolean special = FALSE;
    GList *family;
    FILE *psout;
    gint twidth, theight, tdescent, tascent;
    gint tx, ty, width, height; 
    gint i;
    GdkWChar *curstr, *wtext, *lastchar = NULL, bkspchar[2], *aux, *xaux;
    gchar num[4];

    if (text == NULL || *text == '\0') {
      return;
    }

    psout = ps->psfile;

    gtk_psfont_get_families(&family, &numf);
    base_psfont = psfont = gtk_psfont_get_by_name(font);
    italic = psfont->italic;
    bold = psfont->bold;

    currfont = psfont->psname;

    if (psfont->i18n_latinfamily) {
      latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic,
                                    bold);
    }

    ps_plot_text_get_area(text, angle, justification, font, font_height,
                    &tx, &ty, &width, &height);

    tx += x;
    ty += y;

    if (!transparent) {
      pssetcolor(ps, bg);
      ps_plot_draw_rectangle(ps,
                         TRUE,
                         tx - border_space, ty - border_space,
                         width + 2*border_space, height + 2*border_space);
    }
    /* border */

    pssetcolor(ps, fg);
    pssetdash(ps, 0, NULL, 0);
    pssetlineattr(ps, border_width, 0, 0, 0);
 
    switch (border){
    case PS_PLOT_BORDER_SHADOW:
      ps_plot_draw_rectangle(ps, TRUE, 
                         tx - border_space + shadow_width,
                         ty + height + border_space, 
                         width + 2 * border_space, shadow_width);
      ps_plot_draw_rectangle(ps, TRUE, 
                         tx + width + border_space, 
                         ty - border_space + shadow_width, 
                         shadow_width, height + 2 * border_space);
    case PS_PLOT_BORDER_LINE: 
      ps_plot_draw_rectangle(ps, FALSE, 
                         tx - border_space, ty - border_space, 
                         width + 2*border_space, height + 2*border_space);
    case PS_PLOT_BORDER_NONE:
    default:
        break;
    }

    plot_text_get_size(text, angle, psfont->psname, font_height, 
                   &twidth, &theight, &tascent, &tdescent);

    if (angle == 90 || angle == 270) {
      angle = 360 - angle;
    }

    psgsave(ps);
    fprintf(psout, "%d %d translate\n", x, y);
    fprintf(psout, "%d rotate\n", angle);

    fprintf(psout, "0 0 m\n");
    fprintf(psout, "1 -1 sc\n");

    if (psfont->i18n_latinfamily) {
      special = TRUE;
    }

    c = text;
    while (c && *c != '\0' && *c != '\n') {
      if(*c == '\\'){
          c++;
          switch (*c) {
          case '0': case '1': case '2': case '3':
          case '4': case '5': case '6': case '7': case '9':
          case '8': case'g': case 'B': case 'b': case 'x': case 'N':
          case 's': case 'S': case 'i': case '-': case '+': case '^':
            special = TRUE;
            break;
          default:
            break;
          }
      } else {
          c++;
      }
    }

    if (special) {
      switch (justification) {
      case GTK_JUSTIFY_LEFT:
          break;
      case GTK_JUSTIFY_RIGHT:
          if (angle == 0 || angle == 180) {
            fprintf(psout, "%d JR\n", twidth);
          } else {
            fprintf(psout, "%d JR\n", theight);
          }
          break;
      case GTK_JUSTIFY_CENTER:
      default:
          if (angle == 0 || angle == 180) {
            fprintf(psout, "%d JC\n", twidth);
          } else {
            fprintf(psout, "%d JC\n", theight);
          }
          break;
      }
    } else {
      pssetfont(ps, psfont, font_height);
    
      switch (justification) {
      case GTK_JUSTIFY_LEFT:
          break;
      case GTK_JUSTIFY_RIGHT:
          fprintf(psout, "(%s) sw JR\n", text);
          break;
      case GTK_JUSTIFY_CENTER:
      default:
          fprintf(psout, "(%s) sw JC\n", text);
          break;
      }
      fprintf(psout, "(%s) show\n", text);

      psgrestore(ps);  
      fputs("n\n", psout);  
      return;
    }

    i = strlen(text) + 2;
    curstr = g_malloc0(i * sizeof(GdkWChar));
    aux = wtext = g_malloc0(i * sizeof(GdkWChar));
    gdk_mbstowcs(wtext, text, i - 1);

    scale = font_height;
    curcnt = 0;

    while (aux && *aux != '\0' && *aux != '\n') {
      if (*aux == '\\'){
          aux++;
          switch(*aux){
          case '0': case '1': case '2': case '3':
          case '4': case '5': case '6': case '7': case '9':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            psfont = gtk_psfont_get_by_family((gchar *)g_list_nth_data(family, *aux-'0'), 
                                      italic, bold);
            aux++;
            break;
          case '8': case 'g':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            psfont = gtk_psfont_get_by_family("Symbol", italic, bold);
            aux++;
            break;
          case 'B':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            bold = TRUE;
            psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
            if (psfont->i18n_latinfamily) {
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold);
            }
            aux++;
            break;
          case 'x':
            xaux = aux + 1;
            for (i=0; i<3; i++) {
                if (xaux[i] >= '0' && xaux[i] <= '9') {
                  num[i] = xaux[i];
                } else {
                  break;
                }
            }
            if (i < 3){
                aux++;
                break;
            }
            num[3] = '\0';
              
            i = atoi(num);
            g_snprintf(num, 4, "%o", i % (64 * 8));

            curstr[curcnt++] = '\\';
            i = 0;
            while (num[i]) {
                curstr[curcnt++] = num[i++];
            }
              
            aux += 4;
            break;
          case 'i':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            italic = TRUE;
            psfont = gtk_psfont_get_by_family(psfont->family, italic, bold);
            if (psfont->i18n_latinfamily)
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold);
            aux++;
            break;
          case 's': case '_':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            scale = 0.6 * font_height;
            offset -= (gint)scale / 2;
            fprintf(psout, "0 %d rmoveto\n", -((gint)scale / 2));
            aux++;
            break;
          case 'S': case '^':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            scale = 0.6 * font_height;
            offset += 0.5 * font_height;
            fprintf(psout, "0 %d rmoveto\n", (gint)(0.5*font_height));
            aux++;
            break;
          case 'N':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            psfont = base_psfont;
            italic = psfont->italic;
            bold = psfont->bold;
            if (psfont->i18n_latinfamily) {
                latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily,
                                              italic, bold);
            }
            scale = font_height;
            fprintf(psout, "0 %d rmoveto\n", -offset);
            offset = 0;
            aux++;
            break;
          case 'b':
            curstr[curcnt] = '\0';
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            bkspchar[1] = 0;
            if (lastchar) {
                bkspchar[0] = *lastchar;
                lastchar--;
            } else {
                bkspchar[0] = 'X';
                lastchar = NULL;
            }
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         bkspchar,
                         "stringwidth pop 0 exch neg exch rmoveto");
            aux++;
            break;
          case '-':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            scale -= 3;
            if (scale < 6) {
                scale = 6;
            }
            aux++;
            break;
          case '+':
            curstr[curcnt] = 0;
            psoutputstring(ps, psfont, latin_psfont, (gint)scale,
                         curstr, "show");
            curcnt = 0;
            scale += 3;
            aux++;
            break;
          default:
            if(aux && *aux != '\0' && *aux != '\n'){
                    curstr[curcnt++] = *aux;
                    aux++;
            }
            break;
          }
      } else if (aux && *aux != '\0' && *aux != '\n') {
          curstr[curcnt++] = *aux;
          lastchar = aux;
          aux++;
      }
    }

    curstr[curcnt] = 0;
    psoutputstring(ps, psfont, latin_psfont, (gint) scale, curstr, "show");

    psgrestore(ps);  
    fputs("n\n", psout);  

    g_free(wtext);
    g_free(curstr);
}

static void ps_reencode_font (FILE *file, char *fontname)
{
    /* Don't reencode the Symbol font, as it doesn't work in latin1 encoding.
     * Instead, just define Symbol-latin1 to be the same as Symbol. */
    if (!strcmp(fontname, "Symbol")) {
      fprintf(file,
            "/%s-latin1\n"
            "    /%s findfont\n"
            "definefont pop\n", fontname, fontname);
    } else {
      fprintf(file,
            "/%s-latin1\n"
            "    /%s findfont\n"
            "    dup length dict begin\n"
            "   {1 index /FID ne {def} {pop pop} ifelse} forall\n"
            "   /Encoding isolatin1encoding def\n"
            "    currentdict end\n"
            "definefont pop\n", fontname, fontname);
    }
}

void ps_plot_init (PSPlot *ps)
{
    time_t now = time(NULL);
    FILE *psout = ps->psfile;

    if (ps->epsflag) {
      fputs("%%!PS-Adobe-2.0 PCF-2.0\n", psout);
    } else {
      fputs("%%!PS-Adobe-2.0\n", psout);
    }

    fprintf(psout,
          "%%%%Title: %s\n"
          "%%%%Creator: gretl (based on Adrian E. Feiguin's GtkPlot)\n"
          "%%%%CreationDate: %s"
          "%%%%Magnification: 1.0000\n",
          ps->psname,
          ctime(&now));

    if (ps->orientation == PS_PLOT_PORTRAIT) {
      fputs("%%%%Orientation: Portrait\n", psout);
    } else {
      fputs("%%%%Orientation: Landscape\n", psout);
    }

    if (ps->epsflag) {
      fprintf(psout,
            "%%%%BoundingBox: 0 0 %d %d\n"
            "%%%%Pages: 1\n"
            "%%%%EndComments\n",
            ps->page_width,
            ps->page_height);
    }

    fputs ("/cp {closepath} bind def\n"
         "/c {curveto} bind def\n"
         "/f {fill} bind def\n"
         "/a {arc} bind def\n"
         "/ef {eofill} bind def\n"
         "/ex {exch} bind def\n"
         "/gr {grestore} bind def\n"
         "/gs {gsave} bind def\n"
         "/sa {save} bind def\n"
         "/rs {restore} bind def\n"
         "/l {lineto} bind def\n"
         "/m {moveto} bind def\n"
         "/rm {rmoveto} bind def\n"
         "/n {newpath} bind def\n"
         "/s {stroke} bind def\n"
         "/sh {show} bind def\n"
         "/slc {setlinecap} bind def\n"
         "/slj {setlinejoin} bind def\n"
         "/slw {setlinewidth} bind def\n"
         "/srgb {setrgbcolor} bind def\n"
         "/rot {rotate} bind def\n"
         "/sc {scale} bind def\n"
         "/sd {setdash} bind def\n"
         "/ff {findfont} bind def\n"
         "/sf {setfont} bind def\n"
         "/scf {scalefont} bind def\n"
         "/sw {stringwidth pop} bind def\n"
         "/tr {translate} bind def\n"

         "/JR {\n"
         " neg 0\n"
         " rmoveto\n"
         "} bind def\n"

         "/JC {\n"
         " 2 div neg 0\n"
         " rmoveto\n"
         "} bind def\n"
  
         "\n/ellipsedict 8 dict def\n"
         "ellipsedict /mtrx matrix put\n"
         "/ellipse\n"
         "{ ellipsedict begin\n"
         "   /endangle exch def\n"
         "   /startangle exch def\n"
         "   /yrad exch def\n"
         "   /xrad exch def\n"
         "   /y exch def\n"
         "   /x exch def"
         "   /savematrix mtrx currentmatrix def\n"
         "   x y tr xrad yrad sc\n"
         "   0 0 1 startangle endangle arc\n"
         "   savematrix setmatrix\n"
         "   end\n"
         "} def\n\n", psout);
  
    fputs("[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
        "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one\n"
        "/two /three /four /five /six /seven /eight /nine /colon /semicolon\n"          "/less /equal /greater /question /at /A /B /C /D /E\n"
        "/F /G /H /I /J /K /L /M /N /O\n"
        "/P /Q /R /S /T /U /V /W /X /Y\n"
        "/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
        "/d /e /f /g /h /i /j /k /l /m\n"
        "/n /o /p /q /r /s /t /u /v /w\n"
        "/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
        "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
        "/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior\n"
        "/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf\n"
        "/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
        "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde\n"
        "/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex\n"
        "/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring\n"
        "/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
        "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n"
        "/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def\n", psout);
 
    ps_reencode_font(psout, "Times-Roman");
    ps_reencode_font(psout, "Times-Italic");
    ps_reencode_font(psout, "Times-Bold");
    ps_reencode_font(psout, "Times-BoldItalic");
    ps_reencode_font(psout, "AvantGarde-Book");
    ps_reencode_font(psout, "AvantGarde-BookOblique");
    ps_reencode_font(psout, "AvantGarde-Demi");
    ps_reencode_font(psout, "AvantGarde-DemiOblique");
    ps_reencode_font(psout, "Bookman-Light");
    ps_reencode_font(psout, "Bookman-LightItalic");
    ps_reencode_font(psout, "Bookman-Demi");
    ps_reencode_font(psout, "Bookman-DemiItalic");
    ps_reencode_font(psout, "Courier");
    ps_reencode_font(psout, "Courier-Oblique");
    ps_reencode_font(psout, "Courier-Bold");
    ps_reencode_font(psout, "Courier-BoldOblique");
    ps_reencode_font(psout, "Helvetica");
    ps_reencode_font(psout, "Helvetica-Oblique");
    ps_reencode_font(psout, "Helvetica-Bold");
    ps_reencode_font(psout, "Helvetica-BoldOblique");
    ps_reencode_font(psout, "Helvetica-Narrow");
    ps_reencode_font(psout, "Helvetica-Narrow-Oblique");
    ps_reencode_font(psout, "Helvetica-Narrow-Bold");
    ps_reencode_font(psout, "Helvetica-Narrow-BoldOblique");
    ps_reencode_font(psout, "NewCenturySchoolbook-Roman");
    ps_reencode_font(psout, "NewCenturySchoolbook-Italic");
    ps_reencode_font(psout, "NewCenturySchoolbook-Bold");
    ps_reencode_font(psout, "NewCenturySchoolbook-BoldItalic");
    ps_reencode_font(psout, "Palatino-Roman");
    ps_reencode_font(psout, "Palatino-Italic");
    ps_reencode_font(psout, "Palatino-Bold");
    ps_reencode_font(psout, "Palatino-BoldItalic");
    ps_reencode_font(psout, "Symbol");
    ps_reencode_font(psout, "ZapfChancery-MediumItalic");
    ps_reencode_font(psout, "ZapfDingbats");
   
    if (ps->orientation == PS_PLOT_PORTRAIT) {
      fprintf(psout, "%d %d translate\n"
            "%g %g scale\n",
            0, ps->page_height,
            ps->scalex, -ps->scaley);
    } else if (ps->orientation == PS_PLOT_LANDSCAPE) {
      fprintf(psout, "%g %g scale\n"
            "-90 rotate \n",
            ps->scalex, -ps->scaley);
    }

    fputs("%%%%EndProlog\n\n\n", psout);

    gtk_psfont_init();
}

void ps_plot_finalize (PSPlot *ps)
{
    FILE *fp = ps->psfile;

    fputs("showpage\n", fp);
    fputs("%%%%Trailer\n", fp);
    fputs("%%%%EOF\n", fp);

    gtk_psfont_unref();

    g_free(ps->psname);
    free(ps);
}

Generated by  Doxygen 1.6.0   Back to index