/**  File cairo_drv.c
 *
 * Driver using cairo library to make a PDF output
 */
#include <gtk/gtk.h>
#include <cairo.h>
#include <cairo-pdf.h>
#include <cairo-svg.h>

#include "device.h"
#include "draw.h"
#include "patterns.h"
#include "utils.h"


#include "cairo_drv.h"

extern GdkColor gg_colors[MAXCOLORS];

extern char print_file[];

//22 static cairo_t *cr;
static cairo_surface_t *surface;
static cairo_t         *cr;
static cairo_matrix_t  matrix;

//22 static unsigned long page_scale;
static double pixel_size;
static double dscale ,page_scalef ,page_heightf;
static double dheight ,dwidth;
static int bg;

static int    cr_color    = -1;
static int    cr_pattern  = -1;
static double cr_linew    = -1.0;
static int    cr_lines    = -1;
static int    cr_linecap  = -1;
static int    cr_linejoin = -1;


/******************** PDF driver ********************/

static Device_entry dev_cairo_pdf = {
  DEVICE_FILE,                              /* type */
  "PDFcairo",                               /* *name : name of device */
  cr_pdf_initgraphics,                      /* function to initialize device */
  NULL,  //22  cr_pdf_op_parser,            /* function to parse device-specific commands */
  NULL,  //22  cr_pdf_gui_setup,            /* function (GUI interface) to setup device */
  "pdf",                                    /* filename extension */
  FALSE, //  TRUE,                          /* device has its own fonts */
  TRUE,  // FALSE,		   	    /* font antialiasing */
   {3300, 2550, 300.0},                     /* device defaults */
  NULL				   	    /* device private data */
};

//35  static char *pdf_builtin_fonts[] =
//35  {
//35      "Times-Roman",
//35      "Times-Italic",
//35      "Times-Bold",
//35      "Times-BoldItalic",
//35      "Helvetica",
//35      "Helvetica-Oblique",
//35      "Helvetica-Bold",
//35      "Helvetica-BoldOblique",
//35      "Courier",
//35      "Courier-Oblique",
//35      "Courier-Bold",
//35      "Courier-BoldOblique",
//35      "Symbol",
//35      "ZapfDingbats"
//35  };
//35
//35  static int number_of_pdf_builtin_fonts = sizeof(pdf_builtin_fonts)/sizeof(char *);
//35
//35  void cr_pdf_puttext (VPoint vp, char *s, int len, int font,
//35       TextMatrix *tm, int underline, int overline, int kerning)
//35  {
//35    Pen pen;
//35    pen = getpen ();
//35    cr_setpen (&pen);
//35    if (pdf_font_ids[font] < 0) {
//35      char buf[GR_MAXPATHLEN];
//35      char *fontname, *encscheme;
//35      char *pdflibenc;
//35      int embed;
//35      fontname = get_fontalias (font);
//35      if (pdf_builtin_font(fontname)) {
//35        embed = 0;
//35      } else {
//35        sprintf (buf, "%s==%s" ,fontname ,get_afmfilename (font ,TRUE));
//35        PDF_set_parameter (phandle, "FontAFM", buf);
//35        sprintf(buf, "%s==%s", fontname, get_fontfilename(font, TRUE));
//35        PDF_set_parameter(phandle, "FontOutline", buf);
//35        embed = 1;
//35      }
//35      encscheme = get_encodingscheme (font);
//35      if (strcmp(encscheme, "FontSpecific") == 0) {
//35        pdflibenc = "builtin";
//35      } else {
//35        pdflibenc = "winansi";
//35      }
//35      pdf_font_ids[font] = PDF_findfont(phandle, fontname, pdflibenc, embed);
//35    }
//35
//35      PDF_save(phandle);
//35
//35      PDF_setfont(phandle, pdf_font_ids[font], 1.0);
//35
//35      PDF_set_parameter(phandle, "underline", true_or_false(underline));
//35      PDF_set_parameter(phandle, "overline",  true_or_false(overline));
//35      PDF_concat(phandle, (float) tm->cxx, (float) tm->cyx,
//35                          (float) tm->cxy, (float) tm->cyy,
//35                          vp.x, vp.y);
//35
//35      PDF_show2(phandle, s, len);
//35
//35      PDF_restore(phandle);
//35  }


int register_cairo_pdf_drv (void)
{
  return register_device (dev_cairo_pdf);
}

int cr_pdf_initgraphics (void)           /* initgraphics */
{
  Page_geometry pg;
  /* device-dependent routines */
  devupdatecmap    = NULL;
  devsetfrgbcolor  = cr_setfrgbcolor;
  devdrawpixel     = cr_drawpixel;
  devdrawpolyline  = cr_drawpolyline;
  devfillpolygon   = cr_fillpolygon;
  devdrawarc       = cr_drawarc;
  devfillarc       = cr_fillarc;
  devputpixmap     = cr_putpixmap;
  devputtext       = cr_puttext;
  devleavegraphics = cr_leavegraphics;
  /* undefine all graphics state parameters */
  cr_color = -1;
  cr_pattern = -1;
  cr_linew = -1.0;
  cr_lines = -1;
  cr_linecap = -1;
  cr_linejoin = -1;
  pg      = get_page_geometry();                 /* return page dimensions in pixels */
  dheight = pg.height * 72.0 / pg.dpi;           /* height in points  (1 point == 1/72.0 inch) */
  dwidth  = pg.width  * 72.0 / pg.dpi;
  dscale     = (double) MIN2 (pg.height ,pg.width);
  pixel_size = 1.0 / dscale;
  page_scalef = dscale * 72.0 / pg.dpi;
  page_heightf = ((double)pg.height) * 72.0 / pg.dpi;
  /* cairo_pdf_surface_create () needs a filename here */
  surface = cairo_pdf_surface_create (print_file ,dwidth ,dheight);
  cr      = cairo_create (surface);
  /*                               xx  	   yx  xy   yy  	 x0   y0       */
  cairo_matrix_init (&matrix ,page_scalef ,0. ,0. ,-page_scalef ,0. ,page_heightf);
  cairo_set_matrix  (cr ,&matrix);
  bg = getbgcolor ();
  return RETURN_SUCCESS;
}

void cr_leavegraphics(void)
{
  cairo_stroke (cr);
  cairo_surface_finish  (surface);
  cairo_surface_destroy (surface);
  cairo_destroy (cr);
}

/******************** PNG driver ********************/

static Device_entry dev_cairo_png = {
  DEVICE_FILE,                              /* type */
  "PNGcairo",                               /* *name : name of device */
  cr_png_initgraphics,                      /* function to initialize device */
  NULL,           			    /* function to parse device-specific commands */
  NULL,           			    /* function (GUI interface) to setup device */
  "png",                                    /* filename extension */
  FALSE,                          	    /* device has its own fonts */
  TRUE, 		   	    	    /* font antialiasing */
  {DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, 72.0},  /* device defaults */
  NULL				   	    /* device private data */
};

int register_cairo_png_drv (void)
{
  return register_device (dev_cairo_png);
}

int cr_png_initgraphics (void)           /* initgraphics */
{
  Page_geometry pg;
  /* device-dependent routines */
  devupdatecmap    = NULL;
  devsetfrgbcolor  = cr_setfrgbcolor;
  devdrawpixel     = cr_drawpixel;
  devdrawpolyline  = cr_drawpolyline;
  devfillpolygon   = cr_fillpolygon;
  devdrawarc       = cr_drawarc;
  devfillarc       = cr_fillarc;
  devputpixmap     = cr_putpixmap;
  devputtext       = cr_puttext;
  devleavegraphics = cr_png_leavegraphics;
  /* undefine all graphics state parameters */
  cr_color = -1;
  cr_pattern = -1;
  cr_linew = -1.0;
  cr_lines = -1;
  cr_linecap = -1;
  cr_linejoin = -1;
  pg      = get_page_geometry();                 /* return page dimensions in pixels */
  dheight = pg.height * 72.0 / pg.dpi;           /* height in points  (1 point == 1/72.0 inch) */
  dwidth  = pg.width  * 72.0 / pg.dpi;
  dscale     = (double) MIN2 (pg.height ,pg.width);
  pixel_size = 1.0 / dscale;
  page_scalef = dscale * 72.0 / pg.dpi;
  page_heightf = ((double)pg.height) * 72.0 / pg.dpi;
  /* cairo_pdf_surface_create () needs a filename here */
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32 ,(int)pg.width ,(int)pg.height);
  cr      = cairo_create (surface);
  /*                               xx  	   yx  xy   yy  	 x0   y0       */
  cairo_matrix_init (&matrix ,page_scalef ,0. ,0. ,-page_scalef ,0. ,page_heightf);
  cairo_set_matrix  (cr ,&matrix);
  bg = getbgcolor ();
  return RETURN_SUCCESS;
}

void cr_png_leavegraphics(void)
{
  cairo_stroke (cr);
  cairo_surface_write_to_png (surface ,print_file);
  cairo_surface_finish  (surface);
  cairo_surface_destroy (surface);
  cairo_destroy (cr);
}


/******************** SVG driver ********************/

static Device_entry dev_cairo_svg = {
  DEVICE_FILE,                              /* type */
  "SVGcairo",                               /* *name : name of device */
  cr_svg_initgraphics,                      /* function to initialize device */
  NULL,         			    /* function to parse device-specific commands */
  NULL,         			    /* function (GUI interface) to setup device */
  "svg",                                    /* filename extension */
  FALSE, //  TRUE,                          /* device has its own fonts */
  TRUE,  // FALSE,		   	    /* font antialiasing */
  {DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, 72.0},  /* device defaults */
  NULL				   	    /* device private data */
};

int register_cairo_svg_drv (void)
{
  return register_device (dev_cairo_svg);
}

int cr_svg_initgraphics (void)           /* initgraphics */
{
  Page_geometry pg;
  /* device-dependent routines */
  devupdatecmap    = NULL;
  devsetfrgbcolor  = cr_setfrgbcolor;
  devdrawpixel     = cr_drawpixel;
  devdrawpolyline  = cr_drawpolyline;
  devfillpolygon   = cr_fillpolygon;
  devdrawarc       = cr_drawarc;
  devfillarc       = cr_fillarc;
  devputpixmap     = cr_putpixmap;
  devputtext       = cr_puttext;
  devleavegraphics = cr_leavegraphics;
  /* undefine all graphics state parameters */
  cr_color = -1;
  cr_pattern = -1;
  cr_linew = -1.0;
  cr_lines = -1;
  cr_linecap = -1;
  cr_linejoin = -1;
  pg      = get_page_geometry();                 /* return page dimensions in pixels */
  dheight = pg.height * 72.0 / pg.dpi;           /* height in points  (1 point == 1/72.0 inch) */
  dwidth  = pg.width  * 72.0 / pg.dpi;
  dscale     = (double) MIN2 (pg.height ,pg.width);
  pixel_size = 1.0 / dscale;
  page_scalef = dscale * 72.0 / pg.dpi;
  page_heightf = ((double)pg.height) * 72.0 / pg.dpi;
  /* cairo_svg_surface_create () needs a filename here */
  surface = cairo_svg_surface_create (print_file ,dwidth ,dheight);
  cr      = cairo_create (surface);
  /*                               xx  	   yx  xy   yy  	 x0   y0       */
  cairo_matrix_init (&matrix ,page_scalef ,0. ,0. ,-page_scalef ,0. ,page_heightf);
  cairo_set_matrix  (cr ,&matrix);
  bg = getbgcolor ();
  return RETURN_SUCCESS;
}


/******************** Functions common to all drivers ********************/

void cr_setpen (const Pen *pen)   // pdf_setpen
{
  fRGB *frgb;
  if (pen->color != cr_color || pen->pattern != cr_pattern) {
    frgb = get_frgb (pen->color);
    cairo_set_source_rgb (cr ,frgb->red ,frgb->green ,frgb->blue);  /* setcolor */
    cr_color = pen->color;
    cr_pattern = pen->pattern;
  }
}

/**
 *  Set foreground color in cmap_table[fg] directly
 */
void cr_setfrgbcolor (double fred ,double fgreen ,double fblue)
{
  CMap_entry ce ,*ce_old;
  int fg;
  cairo_set_source_rgb (cr ,fred ,fgreen ,fblue);
  fg = getcolor ();
  ce_old = get_cmap_entry (fg);
  if (ce_old != NULL) {
    fred   *= (MAXCOLORS - 1);
    fgreen *= (MAXCOLORS - 1);
    fblue  *= (MAXCOLORS - 1);
    ce.rgb.red   = (int) fred;
    ce.rgb.green = (int) fgreen;
    ce.rgb.blue  = (int) fblue;
    ce.cname     = ce_old->cname;
    ce.ctype     = COLOR_MAIN;
    ce.tstamp    = 0;
    store_color (fg ,ce);
  }
}


void cr_setdrawbrush (void)  // pdf_setdrawbrush
{
  int i ,ls;
  double *cdarr ,darr_len ,scale ,lw;
  Pen pen;
  pen = getpen ();
  cr_setpen  (&pen);
  lw = getlinewidth ();
  cairo_set_line_width (cr,lw);
  ls = getlinestyle ();
  if (ls > 1) {
    darr_len = dash_array_length[ls];
    cdarr = xmalloc ( darr_len * SIZEOF_DOUBLE);
    scale = MAX2 (1., lw) / page_scalef;
    for (i = 0; i < darr_len; i++) {
      cdarr[i] = scale * (double)dash_array[ls][i];
    }
    cairo_set_dash (cr ,cdarr ,darr_len ,cdarr[0]);
  } else {
    /* dashing disabled */
    cairo_set_dash (cr ,NULL ,0 ,0.);
  }

//    int 	 lc = getlinecap   ();
//    int 	 lj = getlinejoin  ();
  // dash_array[style][i];

}

/* il semble que cette fonction n'est pas utilisée */
void cr_drawpixel (VPoint vp)  // drawpixel
{
  printf ("cr_drawpixel : A FAIRE\n");
}

void cr_drawpolyline (VPoint *vps ,int n ,int mode)   // gg_drawpolyline
{
  int i;
  if (getlinestyle() == 0) return;
  cr_setdrawbrush ();
  //22  pdf_setlineprops();
  cairo_move_to (cr ,vps[0].x ,vps[0].y);
  for (i = 1; i < n; i++) {
    cairo_line_to (cr ,vps[i].x ,vps[i].y);
  }
  if (mode == POLYLINE_CLOSED) cairo_line_to (cr ,vps[0].x ,vps[0].y);
  cairo_save (cr);                            /* stack-pen-size-color */
  cairo_stroke (cr);
  cairo_restore (cr);                          /* stack-pen-size-color */
}


void cr_fillpolygon (VPoint *vps ,int n)
{
  int i ,j ,k ,l ,stride ,cindex;
  cairo_pattern_t * source;
  Pen pen;
  cairo_surface_t *patsurf;
  unsigned char data[16][16][4];

  pen = getpen ();
  if (pen.pattern == 0) return;
  cr_setpen (&pen);
  cairo_save (cr);                            /* stack-pen-size-color */
  if (getfillrule () == FILLRULE_WINDING) {
    cairo_set_fill_rule (cr ,CAIRO_FILL_RULE_WINDING);
  } else {
    cairo_set_fill_rule (cr ,CAIRO_FILL_RULE_EVEN_ODD);
  }
  cairo_move_to (cr ,vps[0].x ,vps[0].y);
  for (i = 1; i < n; i++) {
    cairo_line_to (cr ,vps[i].x ,vps[i].y);
  }
  if (pen.pattern > 1) {
    cairo_clip (cr);
    /* set scale to render pixmap at correct scale */
    cairo_identity_matrix (cr);
    stride  = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32 ,16);
    patsurf = cairo_image_surface_create_for_data ((unsigned char*) data ,CAIRO_FORMAT_ARGB32 ,16 ,16 ,stride);
    /* Convert XBM to CAIRO_FORMAT_ARGB32   */
    cindex = pen.color;
    for (j = 0; j < 256; j++) {
      k = j%16;
      l = j/16;
      if ((pat_bits[pen.pattern][j/8] >> (j%8)) & 0x01) {
	/* the bit is set */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
	data[l][k][0] = gg_colors[cindex].blue;
	data[l][k][1] = gg_colors[cindex].green;
	data[l][k][2] = gg_colors[cindex].red;
	data[l][k][3] = 0xff;
#else
	data[l][k][0] = 0xff;
	data[l][k][1] = gg_colors[cindex].red;
	data[l][k][2] = gg_colors[cindex].green;
	data[l][k][3] = gg_colors[cindex].blue;
#endif
      } else {
	/* transparent */
	data[l][k][0] = data[l][k][1] = data[l][k][2] = data[l][k][3] = 0x00;
      }
    }
    cairo_set_source_surface  (cr ,patsurf ,0. ,0.);
    source  = cairo_get_source (cr);
    cairo_pattern_set_extend (source ,CAIRO_EXTEND_REPEAT);
    cairo_paint (cr);
    cairo_restore (cr);                          /* stack-pen-size-color */
  } else {
    cairo_fill (cr);
    cairo_restore (cr);                          /* stack-pen-size-color */
  }
}


/**
 *
 */
void cr_drawarc (VPoint vp1 ,VPoint vp2 ,int angle1 ,int angle2)  // pdf_drawarc
{
  double xc ,yc ,rx ,ry ,a1 ,a2;
  cr_setdrawbrush ();
  cairo_save (cr);
  xc = (vp1.x + vp2.x) / 2;
  yc = (vp1.y + vp2.y) / 2;
  rx    = fabs (vp2.x - vp1.x) / 2;
  ry    = fabs (vp2.y - vp1.y) / 2;
  a1 = ((double)angle1) * M_PI / 180.0;
  a2 = ((double)angle2) * M_PI / 180.0;
  cairo_new_sub_path (cr);
  if (rx == ry) {
    /* cairo_arc() draws only circles */
    cairo_arc (cr ,xc ,yc ,rx ,a1 ,a2);
  } else {
    /* we change the scale along Ox */
    double ell = rx / ry;
  /*                               xx  	         yx  xy   yy    	 x0                     y0       */
    cairo_matrix_init (&matrix ,page_scalef*ell ,0. ,0. ,-page_scalef ,(1.-ell)*page_scalef*xc ,page_heightf);
    cairo_set_matrix  (cr ,&matrix);
    cairo_arc (cr ,xc ,yc ,ry ,a1 ,a2);
  }
  cairo_stroke  (cr);
  cairo_restore (cr);                          /* stack-pen-size-color */
}

void cr_fillarc(VPoint vp1 ,VPoint vp2 ,int angle1 ,int angle2 ,int mode)
{
  double xc ,yc ,rx ,ry ,a1 ,a2;
  int j ,k ,l ,stride ,cindex;
  cairo_pattern_t * source;
  Pen pen;
  cairo_surface_t *patsurf;
  unsigned char data[16][16][4];

  pen = getpen ();
  if (pen.pattern == 0) return;
  cr_setpen (&pen);
  cairo_save (cr);
  xc = (vp1.x + vp2.x) / 2;
  yc = (vp1.y + vp2.y) / 2;
  rx    = fabs (vp2.x - vp1.x) / 2;
  ry    = fabs (vp2.y - vp1.y) / 2;
  a1 = ((double)angle1) * M_PI / 180.0;
  a2 = ((double)angle2) * M_PI / 180.0;
  cairo_new_sub_path (cr);
  if (mode == ARCFILL_PIESLICE) {
    cairo_move_to (cr ,xc ,yc);
  }
  if (rx == ry) {
    /* cairo_arc() draws only circles */
    cairo_arc (cr ,xc ,yc ,rx ,a1 ,a2);
  } else {
    /* we change the scale along Ox */
    double ell = rx / ry;
    /*                               xx  	         yx  xy   yy    	 x0                     y0       */
    cairo_matrix_init (&matrix ,page_scalef*ell ,0. ,0. ,-page_scalef ,(1.-ell)*page_scalef*xc ,page_heightf);
    cairo_set_matrix  (cr ,&matrix);
    cairo_arc (cr ,xc ,yc ,ry ,a1 ,a2);
  }
  if (mode == ARCFILL_PIESLICE) {
    cairo_close_path (cr);
  }
  if (pen.pattern > 1) {
    cairo_clip (cr);
    /* set scale to render pixmap at correct scale */
    cairo_identity_matrix (cr);
    stride  = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32 ,16);
    patsurf = cairo_image_surface_create_for_data ((unsigned char*) data ,CAIRO_FORMAT_ARGB32 ,16 ,16 ,stride);
    /* Convert XBM to CAIRO_FORMAT_ARGB32   */
    cindex = pen.color;
    for (j = 0; j < 256; j++) {
      k = j%16;
      l = j/16;
      if ((pat_bits[pen.pattern][j/8] >> (j%8)) & 0x01) {
	/* the bit is set */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
	data[l][k][0] = gg_colors[cindex].blue;
	data[l][k][1] = gg_colors[cindex].green;
	data[l][k][2] = gg_colors[cindex].red;
	data[l][k][3] = 0xff;
#else
	data[l][k][0] = 0xff;
	data[l][k][1] = gg_colors[cindex].red;
	data[l][k][2] = gg_colors[cindex].green;
	data[l][k][3] = gg_colors[cindex].blue;
#endif
      } else {
	/* transparent */
	data[l][k][0] = data[l][k][1] = data[l][k][2] = data[l][k][3] = 0x00;
      }
    }
    cairo_set_source_surface  (cr ,patsurf ,0. ,0.);
    source  = cairo_get_source (cr);
    cairo_pattern_set_extend (source ,CAIRO_EXTEND_REPEAT);
    cairo_paint (cr);
    cairo_restore (cr);                          /* stack-pen-size-color */
  } else {
    cairo_fill (cr);
    cairo_restore (cr);                          /* stack-pen-size-color */
  }
}

int cr_op_parser(char *opstring)
{
        return RETURN_SUCCESS;
}

/* TODO: transparent pixmaps */

/**
 * Used by t1fonts.c to draw glyphs via devputpixmap
 */
void cr_putpixmap (VPoint vp ,int width ,int height ,char *databits ,   // devputpixmap
			  int pixmap_bpp ,int bitmap_pad ,int pixmap_type)
{
  unsigned char *data;
  int cindex;
  int i ,j, k ,stride;
  double x ,y ,pixscale;
  cairo_surface_t  *s;
  Page_geometry    pg;
  cairo_save (cr);
  pg = get_page_geometry ();                 /* return page dimensions in pixels */
  pixscale = 72. / pg.dpi;                   /* scaling if page resolution differs from 72 dpi */
  cairo_matrix_init (&matrix ,pixscale ,0. ,0. ,pixscale ,0. ,0.0);
  cairo_set_matrix  (cr ,&matrix);
  data   = xmalloc (width * height * 4);
  stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32 ,width);
  s     = cairo_image_surface_create_for_data (data ,CAIRO_FORMAT_ARGB32 ,width ,height ,stride);
   i = 0;
   for (k = 0; k < height; k++) {
     for (j = 0; j < width; j++) {
       cindex = (unsigned char) (databits)[k*width+j];
       if (cindex != bg) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
	 data[i] = gg_colors[cindex].blue;  i++;
	 data[i] = gg_colors[cindex].green; i++;
	 data[i] = gg_colors[cindex].red;   i++;
#else
	 data[i] = gg_colors[cindex].red;   i++;
	 data[i] = gg_colors[cindex].green; i++;
	 data[i] = gg_colors[cindex].blue;  i++;
#endif
	 data[i] = 0xff;                    i++;  /* opaque */
       } else {
	 data[i] = 0; i++;
	 data[i] = 0; i++;
	 data[i] = 0; i++;
	 data[i] = 0; i++;                        /* transparent */
       }
     }
   }
  x = page_scalef  * vp.x      		 / pixscale;
  y = (page_heightf  -vp.y* page_scalef) / pixscale;
  cairo_set_source_surface (cr ,s ,x ,y);
  cairo_paint (cr);
  xfree (data);

  cairo_matrix_init (&matrix ,page_scalef ,0. ,0. ,-page_scalef ,0. ,page_heightf);
  cairo_set_matrix  (cr ,&matrix);
  cairo_surface_destroy (s);
  cairo_restore (cr);
}



void cr_puttext (VPoint vp ,char *s ,int len ,int font,
     TextMatrix *tm ,int underline ,int overline ,int kerning)
{
  fprintf (stderr ,"cr_puttext not yet implemented\n");
}




