Logo Search packages:      
Sourcecode: vertex version File versions

editorprintcb.c

#include <stdio.h>
#include <string.h> 
#include <stdlib.h>   
#include <sys/types.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>
        
#include "../include/string.h"
#include "../include/fio.h"

#include "guiutils.h"
#include "cdialog.h"

#include "view.h"
#include "viewdraw.h"

#include "editor.h"
#include "editorcb.h"
#include "editorprintcb.h"

#include "print.h"
#include "printwin.h"

#include "vmacfg.h"
#include "vmacfglist.h"
#include "vma.h"
#include "vmautils.h"
#include "config.h"

#ifdef MEMWATCH
# include "memwatch.h"
#endif


static void EditorPrintWinDoPrint(
        vma_core_struct *core_ptr,
        ma_editor_struct *editor,
        const gchar *print_command, /* Can be NULL if printing to file. */
        const gchar *print_file,    /* Can be NULL if printing to printer. */
        print_parms_struct *pp,
      gint width, gint height,      /* Size of buffer. */
        guint8 *buf
);
void EditorPrintWinPrintCB(
      gpointer pw, gpointer data, print_win_parms_struct *parms
);
void EditorPrintWinCancelCB(
      gpointer pw, gpointer data
);
void EditorPrintWinPreviewRequestCB(
        gpointer pw, gpointer data, gint source_type, gint visual,
      gint output_width, gint output_height
);
void EditorPrintCB(GtkWidget *widget, gpointer data);


#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))



/*
 *    Perform the print procedure, this will create a new print job on
 *    the core structure if successfully printing to printer or just
 *    create a new postscript file if printing to file.
 *
 *    width and height specify the size of buf in pixels.
 *
 *    The given buf is assumed to be in GL_RGBA format (4 bytes per 
 *    pixel), it will be converted to the right visual as needed by this
 *    function and deallocated afterwards. The calling function should
 *    not referance buf afterwards.
 */
static void EditorPrintWinDoPrint(
      vma_core_struct *core_ptr,
      ma_editor_struct *editor,
      const gchar *print_command,   /* Can be NULL if printing to file. */
      const gchar *print_file,      /* Can be NULL if printing to printer. */
      print_parms_struct *pp,
      gint width, gint height,      /* Size of buffer in pixels. */
      guint8 *buf
)
{
      int status;
      int pp_format = PrintFormatGamma;
      guint8 *buf_orig, *buf_ptr, *buf_end, r, g, b;
      guint8 *buf_bw_ptr, *buf_grey_ptr;
      guint8 *buf_scaled;


      buf_orig = buf;         /* For debugging purposes. */

      if((core_ptr == NULL) || (editor == NULL) || (pp == NULL) ||
           (buf == NULL) || (width <= 0) || (height <= 0)
      )
      {
          free(buf);
          buf = NULL;
          return;
      }

      /* Do not check if editor is processing, the calling function
       * should have checked that.
       */

      /* Pixels per inch resolution must be positive. */
      if(((gint)pp->ppi_x <= 0) || ((gint)pp->ppi_y <= 0))
      {
            free(buf);
            buf = NULL;
            return;
        }


        /* Rotate and flip image if orientation is landscape. */
        if(pp->orientation == PrintLandScape)
        {
          gint i, j;
          gint    new_width = height,     /* Swapped. */
                  new_height = width;
          gdouble swidth, sheight;
          guint32 *new_buf, *old_buf = (guint32 *)buf;


          new_buf = (guint32 *)malloc(
            new_width * new_height * 4
          );
          if(new_buf != NULL)
          {
            /* Itterate through buffers, note they are 32 bit 
             * pointers which will cover 4 bytes per pixel.
             */
            for(j = 0; j < height; j++)
            {
                for(i = 0; i < width; i++)
                  new_buf[((width - i - 1) * height) + (height - j - 1)] =
                      old_buf[(j * width) + i];
            }

            /* Deallocate old buffer and transfer new buffer to it. */
            free(buf);
            buf = (guint8 *)new_buf;
            new_buf = NULL;

            /* Set new width and height. */
            width = new_width;
            height = new_height;
          }

          /* Swap output width and height (correct for different
           * ppi scales).
           */
          swidth = (gdouble)pp->width / pp->ppi_x;
          sheight = (gdouble)pp->height / pp->ppi_y;
          pp->height = (int)(swidth * pp->ppi_y);
          pp->width = (int)(sheight * pp->ppi_x);
        }
        /* Flip image if orientation is portrait. */
        else if(pp->orientation == PrintPortrait)
        {
            gint i, j;
            gint new_width = width, new_height = height;
            guint32 *new_buf, *old_buf = (guint32 *)buf;


            new_buf = (guint32 *)malloc(
                new_width * new_height * 4
            );
            if(new_buf != NULL)
            {
                /* Itterate through buffers, note they are 32 bit
                 * pointers which will cover 4 bytes per pixel.
                 */
                for(j = 0; j < height; j++)
                {
                    for(i = 0; i < width; i++)
                        new_buf[((height - j - 1) * width) + i] =
                            old_buf[(j * width) + i];
                }

                /* Deallocate old buffer and transfer new buffer to it. */
                free(buf);
                buf = (guint8 *)new_buf;
                new_buf = NULL;

                /* Set new width and height. */
                width = new_width;
                height = new_height;
            }
      }

      /* Convert buffer as needed by visual and scale it. */
      buf_scaled = NULL;
      status = 0;
      switch(pp->visual)
      {
        case PrintColor:
          /* Update print parms format. */
          pp_format = PrintFormatRGBA;

            /* Allocate and scale image data. */
          buf_scaled = (guint8 *)malloc(
            pp->width * pp->height * 4
          );
            status = gluScaleImage(
                GL_RGBA,
                (GLsizei)width, (GLsizei)height,
                GL_UNSIGNED_BYTE,
                (const void *)buf,
            pp->width, pp->height,
            GL_UNSIGNED_BYTE,
            buf_scaled
          );

          /* Image data already in color, no need to convert. */
          buf_ptr = (guint8 *)buf_scaled;
          buf_end = buf_ptr + (pp->width * pp->height * 4);
          break;

        case PrintGreyScale:
          /* Update print parms format. */
            pp_format = PrintFormatGamma;

            /* Allocate and scale image data. */
            buf_scaled = (guint8 *)malloc(     
                pp->width * pp->height * 4
            );
            status = gluScaleImage(
                GL_RGBA,
                (GLsizei)width, (GLsizei)height,
                GL_UNSIGNED_BYTE,   
                (const void *)buf,
                pp->width, pp->height,
                GL_UNSIGNED_BYTE,
                buf_scaled
            );

          /* Convert to grey scale. */
            buf_grey_ptr = buf_ptr = (guint8 *)buf_scaled;
            buf_end = buf_ptr + (pp->width * pp->height * 4);
          while(buf_ptr < buf_end)
          {
            /* Get each color compoent for this 4 byte pixel. */
            r = *buf_ptr++;
            g = *buf_ptr++;
            b = *buf_ptr++;
            buf_ptr++;        /* Skip alpha. */

            /* Average red, green, and blue to get gamma. */
            *buf_grey_ptr++ = (gint)((gint)r + (gint)g + (gint)b) / 3;
          }
          break;

          case PrintBlackAndWhite:
            /* Update print parms format. */
            pp_format = PrintFormatGamma;

            /* Allocate and scale image data. */
            buf_scaled = (guint8 *)malloc(
                pp->width * pp->height * 4
            );
            status = gluScaleImage(
                GL_RGBA,
                (GLsizei)width, (GLsizei)height,
                GL_UNSIGNED_BYTE,
                (const void *)buf,
                pp->width, pp->height,
                GL_UNSIGNED_BYTE,
                buf_scaled
            );

            /* Convert to black and white. */  
            buf_bw_ptr = buf_ptr = (guint8 *)buf_scaled;
            buf_end = buf_ptr + (pp->width * pp->height * 4);
            while(buf_ptr < buf_end)
            {
                /* Get each color compoent for this 4 byte pixel. */
                r = *buf_ptr++;
                g = *buf_ptr++;
                b = *buf_ptr++;
                buf_ptr++;              /* Skip alpha. */

                /* Average red, green, and blue to get gamma. */
            if(((gint)((gint)r + (gint)g + (gint)b) / 3) >= 0x80)
                *buf_bw_ptr++ = 0xff;
            else
                *buf_bw_ptr++ = 0x00;
            }
            break;
      }
      /* Got scaled buffer? */
      if(buf_scaled != NULL)
      {
          switch(status)
          {
            case GLU_INVALID_VALUE:
            fprintf(stderr,
 "EditorPrintWinDoPrint(): Error scaling image: Invalid value.\n"
            );
            break;

              case GLU_INVALID_ENUM:
            fprintf(stderr,
 "EditorPrintWinDoPrint(): Error scaling image: Invalid enum.\n"  
                );
                break;
          }

          /* Get rid of current buffer and transfer scaled buffer
           * to it so that the current buffer is the scaled buffer.
           */
          free(buf);
          buf = buf_scaled;
          buf_scaled = NULL;

          /* Update new image size. */
          width = pp->width;
          height = pp->height;
      }


      /* Handle by print destination. */
      switch(pp->destination)
      {
        case PrintToPrinter:
          if(print_command != NULL)
          {
            char *new_name = NULL;
            FILE *fp;

            /* Generate tempory file. */
            fp = VMAMakeOpenTmpFile(
                core_ptr,
                dname.tmp,
                "print",
                &new_name
            );
            if(fp != NULL)
            {
                /* Write postscript file to be printed. */
                status = PrintWritePSImage(
                  fp, pp,
                  pp_format,
                  width, height, buf
                );
                    FClose(fp);           /* Close file. */
                fp = NULL;

                /* Post script file written successfully? */
                if(!status)
                {
                  /* Create a new print job. */
                  int pj_num;
                  print_job_struct *pj = PrintJobNew(
                      print_command,
                      new_name,
                      1,            /* One copy. */
                      1       /* Remove file when done. */
                  );

                  /* Allocate more print job pointers. */
                  if(core_ptr->total_print_jobs < 0)
                      core_ptr->total_print_jobs = 0;

                  /* Check for available NULL pointer in array. */
                  for(pj_num = 0; pj_num < core_ptr->total_print_jobs; pj_num++)
                  {
                      if(core_ptr->print_job[pj_num] == NULL)
                        break;
                  }
                  /* Pointer available? */
                  if(pj_num < core_ptr->total_print_jobs)
                  {
                      core_ptr->print_job[pj_num] = pj;
                  }
                  else
                  {
                      /* Need to allocate more pointers. */
                      pj_num = core_ptr->total_print_jobs;
                      core_ptr->total_print_jobs = pj_num + 1;

                      core_ptr->print_job = (print_job_struct **)realloc(
                        core_ptr->print_job,
                        core_ptr->total_print_jobs *
                            sizeof(print_job_struct *)
                      );
                      if(core_ptr->print_job == NULL)
                      {
                        core_ptr->total_print_jobs = 0;
                      }
                      else
                      {
                        core_ptr->print_job[pj_num] = pj;
                      }
                  }
                }
            }

            /* Deallocate tempory file name. */
            free(new_name);
            new_name = NULL;
          }
          break;

        case PrintToFile:
          if(print_file != NULL)
          {
            FILE *fp = FOpen(print_file, "wb");

            status = PrintWritePSImage(
                fp, pp,
                pp_format,
                width, height, buf
            );
            FClose(fp);
          }
          break;
      }

      /* Deallocate the given buffer. */
      free(buf);
      buf = NULL;

      return;
}

/*
 *    Print window print callback.
 */
void EditorPrintWinPrintCB(
        gpointer pw, gpointer data, print_win_parms_struct *parms
)
{
        GtkWidget *w;
      gint ww = 0, wh = 0;
        vma_view2d_struct *view2d;
        vma_view3d_struct *view3d;
      print_parms_struct *pp;

      guint flags;
      const gchar *print_command = NULL;
      const gchar *print_file = NULL;
      gint print_to = PRINT_WIN_PRINT_TO_PRINTER;
      gint source_type = 0;
      gdouble ppi_x = VMA_DEF_PRINT_PPI_X, ppi_y = VMA_DEF_PRINT_PPI_Y;
      gint orientation = 0;
      gint visual = PRINT_WIN_VISUAL_GREYSCALE;
      gint paper_size = PRINT_WIN_PAPER_SIZE_LETTER;
      gint output_offset_xp = 0, output_offset_yp = 0;
      gint output_widthp = 0, output_heightp = 0;

      char *strptr;
      int32_t i32;
      u_int32_t ui32;
      double d;

      vma_core_struct *core_ptr;
      ma_editor_struct *editor = (ma_editor_struct *)data;
      if((parms == NULL) || (editor == NULL))
          return;

      if(!editor->initialized || editor->processing)
          return;

      /* Get pointer to core structure. */
      core_ptr = (vma_core_struct *)editor->core_ptr;
      if(core_ptr == NULL)
          return;


        /* Mark as processing. */
        editor->processing = TRUE;


      /* Get print parameter values from input. */
      flags = parms->flags;

      if(flags & PRINT_WIN_PARM_FLAG_PRINT_TO)
          print_to = parms->print_to;
      if(flags & PRINT_WIN_PARM_FLAG_PRINT_COMMAND)
          print_command = (const gchar *)parms->print_command;
      if(flags & PRINT_WIN_PARM_FLAG_PRINT_FILE)
          print_file = (const gchar *)parms->print_file;
      if(flags & PRINT_WIN_PARM_FLAG_SOURCE_TYPE)
          source_type = parms->source_type;
      if(flags & PRINT_WIN_PARM_FLAG_ORIENTATION)
          orientation = parms->orientation;
      if(flags & PRINT_WIN_PARM_FLAG_VISUAL)
          visual = parms->visual;
      if(flags & PRINT_WIN_PARM_FLAG_PPI_X)
            ppi_x = parms->ppi_x;
        if(flags & PRINT_WIN_PARM_FLAG_PPI_Y) 
            ppi_y = parms->ppi_y;
      if(flags & PRINT_WIN_PARM_FLAG_PAPER_SIZE)
          paper_size = parms->paper_size;
        if(flags & PRINT_WIN_PARM_FLAG_OUTPUT_OFFSET_X)
            output_offset_xp = parms->output_offset_xp;
        if(flags & PRINT_WIN_PARM_FLAG_OUTPUT_OFFSET_Y)
            output_offset_yp = parms->output_offset_yp;
        if(flags & PRINT_WIN_PARM_FLAG_OUTPUT_WIDTH)
            output_widthp = parms->output_widthp;
        if(flags & PRINT_WIN_PARM_FLAG_OUTPUT_HEIGHT)
            output_heightp = parms->output_heightp;


      /* Update configuration options list values. */

        ui32 = print_to;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_PRINT_TO,
            &ui32, FALSE
        );

      strptr = strdup((print_command == NULL) ? "" : print_command);
      VMACFGItemListMatchSetValue(
          option, VMA_CFG_PARM_PRINT_COMMAND,
          strptr, FALSE
      );
      free(strptr);
      strptr = NULL;

        strptr = strdup((print_file == NULL) ? "" : print_file);
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_FILE,
            strptr, FALSE
        );
        free(strptr);
        strptr = NULL;


        ui32 = source_type;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_VIEW,
            &ui32, FALSE
        );

      ui32 = orientation;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_ORIENTATION,
            &ui32, FALSE
        );

        ui32 = visual;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_VISUAL,
            &ui32, FALSE
        );

      d = ppi_x;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_PPI_X,
            &d, FALSE
        );
        d = ppi_y;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_PPI_Y,
            &d, FALSE
        );

        ui32 = paper_size;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_PAPER_SIZE,
            &ui32, FALSE
        );

        i32 = output_offset_xp;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_OUTPUT_OFFSET_X,
            &i32, FALSE
        );
        i32 = output_offset_yp;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_OUTPUT_OFFSET_Y,
            &i32, FALSE
        );

        ui32 = output_widthp;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_OUTPUT_WIDTH,
            &ui32, FALSE
        );
        ui32 = output_heightp;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_PRINT_OUTPUT_HEIGHT,
            &ui32, FALSE
        );

/* Applies pixel per inch c to value n and returns new value. This converts
 * the given value n (assumed to be in inches * 100ppi) to the printer
 * resolution size. For example, if n = 850 and c = 72 then result will be
 * 637.5.
 */
#define APPLY_PPI(n,c)  (double)((double)(n) * (double)(c) / (double)100.0)

        /* Handle by source type. */
        switch(source_type)
        {
          /* First 3D view. */
          case 3:
            /* Get pointer to first 3D view. */
            if(VMA_MAX_3D_VIEWS_PER_EDITOR > 0)
                view3d = editor->view3d[0];
            else
                view3d = NULL;
            if(view3d != NULL)
          {
                /* Redraw the view and get its buffer, this will put the
             * 3d view into GL context.
             */
            View3DDraw(
                view3d, &view3d->palette,
                0, 0,         /* Viewport size. */
                FALSE         /* Swap buffers. */
            );
            /* Get view's glarea widget. */
            w = view3d->view;
                if(w != NULL)
                {
                    ww = w->allocation.width;
                    wh = w->allocation.height;
                }
          }
            break;

          /* Third 2D view. */
          case 2:
            /* Get pointer to third 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 2)
                view2d = editor->view2d[2];
            else
                view2d = NULL; 
            if(view2d != NULL)
          {
            /* Redraw the view and get its buffer, this will put the
             * 2d view into GL context.
             */
            View2DDraw(
                view2d, &view2d->palette,
                    0, 0,           /* Viewport size. */
                    FALSE           /* Swap buffers. */
            );
            /* Get view's glarea widget. */
            w = view2d->view;
                if(w != NULL)
                {
                    ww = w->allocation.width;
                    wh = w->allocation.height;
                }
          }
            break;

          /* Second 2D view. */
          case 1:
            /* Get pointer to second 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 1)
                view2d = editor->view2d[1];
            else
                view2d = NULL;
            if(view2d != NULL)
          {
                /* Redraw the view and get its buffer, this will put the
                 * 2d view into GL context.
                 */
                View2DDraw(
                    view2d, &view2d->palette,
                    0, 0,           /* Viewport size. */
                    FALSE           /* Swap buffers. */
                );
                /* Get view's glarea widget. */
                w = view2d->view;
                if(w != NULL)
                {
                    ww = w->allocation.width;
                    wh = w->allocation.height;
                }
          }
            break;

          /* First 2D view. */
          case 0:
            /* Get pointer to first 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 0)
                view2d = editor->view2d[0];
            else
                view2d = NULL;
            if(view2d != NULL)
          {
                /* Redraw the view and get its buffer, this will put the
                 * 2d view into GL context.
                 */
                View2DDraw(
                    view2d, &view2d->palette,
                    0, 0,           /* Viewport size. */
                    FALSE           /* Swap buffers. */
                );
                /* Get view's glarea widget. */
                w = view2d->view;
            if(w != NULL)
            {
                ww = w->allocation.width;
                wh = w->allocation.height;
            }
          }
            break;

          default:
            fprintf(
                stderr,
 "EditorPrintWinPreviewRequestCB(): Invalid source type `%i'\n",
                source_type
            );
            break;
      }

        /* At this point the proper glarea widget should have been
         * selected, put into GL context, and redrawn. So the frame
         * buffer (which is double buffered) is ready for reading.
         */

      /* If ww or wh are 0 then that implies there is nothing to
       * read.
         */
        if((ww <= 0) || (wh <= 0))
      {
            /* Mark as no longer processing. */
            editor->processing = FALSE;

            return;
      }

        /* Allocate a new print parameters structure. */
        pp = (print_parms_struct *)calloc(
            1, sizeof(print_parms_struct)
        );
        if(pp != NULL)
      {
          gint paper_width, paper_height;
          guint8 *buf;

          /* Set up print parameters from those recieved from the print
           * window's print parameters.
           */
          pp->flags = 0;
          pp->coppies = 1;
          pp->orientation = ((orientation) ?
            PrintLandScape : PrintPortrait
          );

          /* Visual. */
          switch(visual)
          {
            case PRINT_WIN_VISUAL_COLOR:
            pp->visual = PrintColor;
            break;

            default:
            pp->visual = PrintGreyScale;
            break;
          }

          /* Output geometry (in pixels). */
          pp->ppi_x = ppi_x;
          pp->ppi_y = ppi_y;
          pp->x = APPLY_PPI(output_offset_xp, ppi_x);
          pp->y = APPLY_PPI(output_offset_yp, ppi_y);
          pp->width = APPLY_PPI(output_widthp, ppi_x);
          pp->height = APPLY_PPI(output_heightp, ppi_y);

          /* Paper size (in pixels). */
          PrintWinGetPaperSizeFromCode(
            pw, paper_size,
            &paper_width, &paper_height
          );
          pp->paper_width = APPLY_PPI(paper_width, ppi_x);
            pp->paper_height = APPLY_PPI(paper_height, ppi_y);

          /* Output destination. */
          switch(print_to)
          {
            case PRINT_WIN_PRINT_TO_FILE:
            pp->destination = PrintToFile;
            break;

            default:
            pp->destination = PrintToPrinter;
            break;
          }
/*
printf("%i %i %i %i (%i %i)\n",
output_offset_xp, output_offset_yp,
output_widthp, output_heightp,
paper_width, paper_height
);
printf("%i %i %i %i (%i %i)\n", pp->x, pp->y, pp->width, pp->height,
 pp->paper_width, pp->paper_height
);
 */
#undef APPLY_PPI

          /* Allocate memory for reading the GL back buffer from the
           * current GL context in GL_RGBA format.
           */
          buf = (guint8 *)malloc(ww * wh * 4);
          if(buf != NULL)
          {
            glPixelStorei(GL_PACK_ALIGNMENT, 1);
            glReadBuffer(GL_BACK);
            glReadPixels(
                0, 0,
                (GLsizei)ww, (GLsizei)wh,
                GL_RGBA, GL_UNSIGNED_BYTE,
                (GLvoid *)buf
            );

            /* Perform the print procedure, this will create a new
             * print job on the core structure if successfully 
             * printing to printer or just create a new postscript
             * file if printing to file.
             *
             * The given buf will be deallocated by this call.
             */
            EditorPrintWinDoPrint(
                core_ptr,
                editor,
                print_command,
                print_file,
                pp,
                ww, wh, buf
            );

            buf = NULL;
          }

          /* Deallocate print parameters structure. */
          free(pp);
          pp = NULL;
      }


      /* Mark as no longer processing. */
      editor->processing = FALSE;

      return;
}

/*
 *    Print window cancel callback.
 */
void EditorPrintWinCancelCB(
        gpointer pw, gpointer data
)
{
      return;
}

/*
 *    Print window preview texture request callback.
 *
 *    The source_type specifies which view to get data from.
 *
 *    The visual specifies greyscale or color.
 *
 *    The output_width and output_height specify the recommended size
 *    in pixels.
 */
void EditorPrintWinPreviewRequestCB(
        gpointer pw, gpointer data, gint source_type, gint visual,
        gint output_width, gint output_height
)
{
      GtkWidget *w;
        gint ww = 0, wh = 0;
        guint8 *buf;
      vma_view2d_struct *view2d;
        vma_view3d_struct *view3d;
      print_win_struct *print_win = (print_win_struct *)pw;
      print_win_parms_struct *parms;
        ma_editor_struct *editor = (ma_editor_struct *)data;
        if((print_win == NULL) || (editor == NULL))
            return;

        if(!editor->initialized || editor->processing)
            return;

      /* Handle by source type. */
      switch(source_type)
      {
        /* First 3D view. */
        case 3:
          /* Get pointer to first 3D view. */
          if(VMA_MAX_3D_VIEWS_PER_EDITOR > 0)
            view3d = editor->view3d[0];
          else
            view3d = NULL;
          if(view3d == NULL)
            break;

            /* Redraw the view and get its buffer, this will put the 3d
             * view into GL context.
             */
            View3DDraw(view3d, &view3d->palette, 0, 0, FALSE);

            /* Get view's glarea widget. */
            w = view3d->view;
            if(w == NULL)
                break;

            ww = w->allocation.width;
            wh = w->allocation.height;
          break;

          /* Third 2D view. */
          case 2:
            /* Get pointer to third 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 2)
                view2d = editor->view2d[2];
            else
                view2d = NULL;
            if(view2d == NULL)
                break;

            /* Redraw the view and get its buffer, this will put the 2d
             * view into GL context.
             */
            View2DDraw(view2d, &view2d->palette, 0, 0, FALSE);

            /* Get view's glarea widget. */
            w = view2d->view;
            if(w == NULL)
                break;

            ww = w->allocation.width;
            wh = w->allocation.height;
            break;

          /* Second 2D view. */
          case 1:
            /* Get pointer to second 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 1)
                view2d = editor->view2d[1];
            else
                view2d = NULL;
            if(view2d == NULL)
                break;

            /* Redraw the view and get its buffer, this will put the 2d
             * view into GL context.
             */
            View2DDraw(view2d, &view2d->palette, 0, 0, FALSE);

            /* Get view's glarea widget. */
            w = view2d->view; 
            if(w == NULL)
                break;

            ww = w->allocation.width;
            wh = w->allocation.height;
            break;

          /* First 2D view. */
          case 0:
            /* Get pointer to first 2D view. */
            if(VMA_MAX_2D_VIEWS_PER_EDITOR > 0)
                view2d = editor->view2d[0];
            else
                view2d = NULL;
            if(view2d == NULL)
                break;

            /* Redraw the view and get its buffer, this will put the 2d
             * view into GL context.
             */
            View2DDraw(view2d, &view2d->palette, 0, 0, FALSE);

            /* Get view's glarea widget. */
            w = view2d->view; 
            if(w == NULL)
                break;

            ww = w->allocation.width;
            wh = w->allocation.height;
            break;

        default:
          fprintf(
            stderr,
 "EditorPrintWinPreviewRequestCB(): Invalid source type `%i'\n",
            source_type
          );
          break;
      }

        /* At this point the proper glarea widget should have been
         * selected, put into GL context, and redrawn. So the frame
         * buffer (which is double buffered) is ready for reading.
         */

        /* If output_widthp or output_heightp are 0 then that implies there
         * is nothing to read.
         */
      if((ww <= 0) || (wh <= 0))
          return;

        /* Allocate a new print parameters structure. */
        parms = (print_win_parms_struct *)calloc(
            1, sizeof(print_win_parms_struct)
        );
        if(parms == NULL)
            return;

      /* Handle rest by visual type. */
      switch(visual)
      {
        case PRINT_WIN_VISUAL_COLOR:
            /* Allocate memory for reading view's buffer in GL_RGBA
           * format.
           */
            buf = (guint8 *)malloc(ww * wh * 4);
          if(buf != NULL)
          {
                glPixelStorei(GL_PACK_ALIGNMENT, 1);
                glReadBuffer(GL_BACK);
                glReadPixels(
                    0, 0,
                    (GLsizei)ww, (GLsizei)wh,
                    GL_RGBA, GL_UNSIGNED_BYTE,
                    (GLvoid *)buf
                );
            }
            /* Load preview texture, this will put the print window's
           * preview glarea widget into GL context and create a new
           * colored texture on it. Any existing texture will be
           * unloaded.
           */
            PrintWinPreviewTextureLoadColor(
                pw, ww, wh, (const guint8 *)buf
            );
            /* Deallocate the read view buffer. */
            free(buf);
            buf = NULL;
          /* Update output size. */
          if(parms != NULL)
          {
            parms->flags = (PRINT_WIN_PARM_FLAG_OUTPUT_WIDTH |
                        PRINT_WIN_PARM_FLAG_OUTPUT_HEIGHT
            );
            parms->output_widthp = ww;
            parms->output_heightp = wh;
            PrintWinMapValues(pw, parms);
          }
          break;

        case PRINT_WIN_VISUAL_GREYSCALE:
            /* Allocate memory for reading view's buffer in GL_RGBA
             * format, we'll convert it to grey scale and pass it to
           * PrintWinPreviewTextureLoadGreyScale() as if it were
           * grey scale.
             */
            buf = (guint8 *)malloc(ww * wh * 4);
            if(buf != NULL)
            {
            guint8 *buf_grey_ptr, *buf_ptr, *buf_end, r, g, b;

                glPixelStorei(GL_PACK_ALIGNMENT, 1);
                glReadBuffer(GL_BACK);
                glReadPixels(
                    0, 0,
                    (GLsizei)ww, (GLsizei)wh,
                    GL_RGBA, GL_UNSIGNED_BYTE,
                    (GLvoid *)buf
                );

            /* Convert to grey scale. */
            buf_grey_ptr = buf_ptr = (guint8 *)buf;
            buf_end = buf_ptr + (ww * wh * 4);

            while(buf_ptr < buf_end)
            {
                r = *buf_ptr++;
                g = *buf_ptr++;
                b = *buf_ptr++;
                buf_ptr++;

                *buf_grey_ptr++ = (gint)((gint)r + (gint)g + (gint)b) / 3;
            }
            }
            /* Load preview texture, this will put the print window's
             * preview glarea widget into GL context and create a new
             * greyscale texture on it. Any existing texture will be
             * unloaded.
             */
            PrintWinPreviewTextureLoadGreyScale(
                pw, ww, wh, (const guint8 *)buf
            );
            /* Deallocate the read view buffer. */
            free(buf);
            buf = NULL;
            /* Update output size. */
            if(parms != NULL)
            {
                parms->flags = (PRINT_WIN_PARM_FLAG_OUTPUT_WIDTH |
                                PRINT_WIN_PARM_FLAG_OUTPUT_HEIGHT
                );
                parms->output_widthp = ww;
                parms->output_heightp = wh;
                PrintWinMapValues(pw, parms);
            }
            break;
      }

      /* Free print parameters structure. */
      free(parms->print_command);
      free(parms->print_file);
      free(parms);
      parms = NULL;

        return;
}



/*
 *      Map print window callback.
 */
void EditorPrintCB(GtkWidget *widget, gpointer data)
{
        vma_core_struct *core_ptr;
        print_win_struct *pw;
        ma_editor_struct *editor = (ma_editor_struct *)data;
        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;
  
        core_ptr = (vma_core_struct *)editor->core_ptr;
        if(core_ptr == NULL)
            return;

      /* Get pointer to print window, initialize it as needed. */
        pw = core_ptr->print_win;   
        if(pw == NULL)
        {
            core_ptr->print_win = pw = PrintWinNew(core_ptr);
        }
        if(pw == NULL)
            return;

        /* Print window initialized and not mapped? */
        if(pw->initialized && !pw->map_state)
        {
          char **name;
          int total_names;
          char lname[256];
          print_win_parms_struct *parms = (print_win_parms_struct *)calloc(
            1, sizeof(print_win_parms_struct)
          );


          /* Reset all values on the print window. */
            PrintWinReset(pw, FALSE);

          /* Set print window callbacks. */
          PrintWinSetCallbacks(
            pw,
            (gpointer)editor,
            EditorPrintWinPrintCB,
            EditorPrintWinCancelCB,
            EditorPrintWinPreviewRequestCB
          );

          /* Set up source type names. */
          total_names = VMA_MAX_2D_VIEWS_PER_EDITOR +
            VMA_MAX_3D_VIEWS_PER_EDITOR;
          name = (char **)calloc(
            total_names, sizeof(char *)
          );
          if(name != NULL)
          {
            int i = 0, n;

            n = 0;
            while(n < VMA_MAX_2D_VIEWS_PER_EDITOR)
            {
                sprintf(lname, "2D View #%i", (int)(n + 1));
                name[i] = strdup(lname);
                i++;
                n++;
            }
                n = 0;
                while(n < VMA_MAX_3D_VIEWS_PER_EDITOR)
                {
                    sprintf(lname, "3D View #%i", (int)(n + 1));
                    name[i] = strdup(lname);
                    i++;
                    n++;
                }

              PrintWinSetSourceTypeNames(pw, name, total_names);
              StringFreeArray(name, total_names);
          }


          /* Set up print parameters. */
          if(parms != NULL)
          {
            gint i;
            const gchar *cstrptr;
            vma_view2d_struct *view2d;
            vma_view3d_struct *view3d;

            parms->flags = (PRINT_WIN_PARM_FLAG_PRINT_TO |
                        PRINT_WIN_PARM_FLAG_PRINT_COMMAND |
                        PRINT_WIN_PARM_FLAG_PRINT_FILE |
                        PRINT_WIN_PARM_FLAG_SOURCE_TYPE |
                        PRINT_WIN_PARM_FLAG_ORIENTATION |
                        PRINT_WIN_PARM_FLAG_VISUAL |
                        PRINT_WIN_PARM_FLAG_PPI_X |
                        PRINT_WIN_PARM_FLAG_PPI_Y |
                        PRINT_WIN_PARM_FLAG_PAPER_SIZE |
                        PRINT_WIN_PARM_FLAG_OUTPUT_OFFSET_X |
                        PRINT_WIN_PARM_FLAG_OUTPUT_OFFSET_Y |
                        PRINT_WIN_PARM_FLAG_OUTPUT_WIDTH |
                        PRINT_WIN_PARM_FLAG_OUTPUT_HEIGHT
            );

            parms->print_to = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_PRINT_TO
                );

            cstrptr = (const gchar *)VMACFGItemListGetValueS(
                option, VMA_CFG_PARM_PRINT_COMMAND
            );
            parms->print_command = ((cstrptr == NULL) ?
                NULL : strdup(cstrptr)
            );

                cstrptr = (const gchar *)VMACFGItemListGetValueS(
                    option, VMA_CFG_PARM_PRINT_FILE
                );
                parms->print_file = ((cstrptr == NULL) ?
                    NULL : strdup(cstrptr)
                );

                parms->source_type = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_VIEW
                );
            /* Change source type if one of the views is maximized,
             * we check this case because we should not default to a
             * view last set if it is not currently visible.
             */
            for(i = 0; i < VMA_MAX_2D_VIEWS_PER_EDITOR; i++)
            {
                view2d = editor->view2d[i];
                if(view2d == NULL)
                  continue;

                if(view2d->flags & VMA_VIEW_FLAG_MAXIMIZED)
                  parms->source_type = i + 0;
            }
                for(i = 0; i < VMA_MAX_3D_VIEWS_PER_EDITOR; i++)
                {
                    view3d = editor->view3d[i];
                    if(view3d == NULL)
                        continue;

                    if(view3d->flags & VMA_VIEW_FLAG_MAXIMIZED)
                        parms->source_type = i + VMA_MAX_2D_VIEWS_PER_EDITOR;
                }

            parms->orientation = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_ORIENTATION
                );
            parms->visual = VMACFGItemListGetValueI( 
                    option, VMA_CFG_PARM_PRINT_VISUAL
                );
                parms->ppi_x = VMACFGItemListGetValueD(
                    option, VMA_CFG_PARM_PRINT_PPI_X
                );
                parms->ppi_y = VMACFGItemListGetValueD(
                    option, VMA_CFG_PARM_PRINT_PPI_Y
                );
            parms->paper_size = VMACFGItemListGetValueI(  
                    option, VMA_CFG_PARM_PRINT_PAPER_SIZE
                );
            parms->output_offset_xp = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_OUTPUT_OFFSET_X
                );
            parms->output_offset_yp = VMACFGItemListGetValueI( 
                    option, VMA_CFG_PARM_PRINT_OUTPUT_OFFSET_Y
                );
            parms->output_widthp = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_OUTPUT_WIDTH
                );
            parms->output_heightp = VMACFGItemListGetValueI(
                    option, VMA_CFG_PARM_PRINT_OUTPUT_HEIGHT
                );

            /* Set print parameters and map. */
            PrintWinMapValues(pw, parms);

            /* Deallocate print parameters. */
            free(parms->print_command);
            free(parms->print_file);
            free(parms);
            parms = NULL;
          }
        }

        return;
}

Generated by  Doxygen 1.6.0   Back to index