2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
* PostScript file plugin
|
|
|
|
* PostScript writing and GhostScript interfacing code
|
1999-01-04 06:41:12 +08:00
|
|
|
* Copyright (C) 1997-98 Peter Kirchgessner
|
|
|
|
* (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
|
1997-11-25 06:05:25 +08:00
|
|
|
*
|
|
|
|
* Added controls for TextAlphaBits and GraphicsAlphaBits
|
|
|
|
* George White <aa056@chebucto.ns.ca>
|
|
|
|
*
|
2000-01-23 06:26:20 +08:00
|
|
|
* Added Ascii85 encoding
|
|
|
|
* Austin Donnelly <austin@gimp.org>
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Event history:
|
|
|
|
* V 0.90, PK, 28-Mar-97: Creation.
|
|
|
|
* V 0.91, PK, 03-Apr-97: Clip everything outside BoundingBox.
|
|
|
|
* 24-Apr-97: Multi page read support.
|
|
|
|
* V 1.00, PK, 30-Apr-97: PDF support.
|
|
|
|
* V 1.01, PK, 05-Oct-97: Parse rc-file.
|
|
|
|
* V 1.02, GW, 09-Oct-97: Antialiasing support.
|
|
|
|
* PK, 11-Oct-97: No progress bars when running non-interactive.
|
|
|
|
* New procedure file_ps_load_setargs to set
|
|
|
|
* load-arguments non-interactively.
|
|
|
|
* If GS_OPTIONS are not set, use at least "-dSAFER"
|
1997-12-26 15:08:20 +08:00
|
|
|
* V 1.03, nn, 20-Dec-97: Initialize some variables
|
|
|
|
* V 1.04, PK, 20-Dec-97: Add Encapsulated PostScript output and preview
|
1999-01-04 06:41:12 +08:00
|
|
|
* V 1.05, PK, 21-Sep-98: Write b/w-images (indexed) using image-operator
|
|
|
|
* V 1.06, PK, 22-Dec-98: Fix problem with writing color PS files.
|
|
|
|
* Ghostview may hang when displaying the files.
|
1999-09-15 04:54:02 +08:00
|
|
|
* V 1.07, PK, 14-Sep-99: Add resolution to image
|
2000-01-23 06:26:20 +08:00
|
|
|
* V 1.08, PK, 16-Jan-2000: Add PostScript-Level 2 by Austin Donnelly
|
2000-03-11 01:27:25 +08:00
|
|
|
* V 1.09, PK, 15-Feb-2000: Force showpage on EPS-files
|
|
|
|
* Add "RunLength" compression
|
|
|
|
* Fix problem with "Level 2" toggle
|
2000-04-05 18:26:08 +08:00
|
|
|
* V 1.10, PK, 15-Mar-2000: For load EPSF, allow negative Bounding Box Values
|
2018-04-19 02:57:03 +08:00
|
|
|
* Save PS: don't start lines of image data with %%
|
2000-03-26 06:19:17 +08:00
|
|
|
* to prevent problems with stupid PostScript
|
|
|
|
* analyzer programs (Stanislav Brabec)
|
2000-04-05 18:26:08 +08:00
|
|
|
* Add BeginData/EndData comments
|
|
|
|
* Save PS: Set default rotation to 0
|
2000-08-21 07:26:11 +08:00
|
|
|
* V 1.11, PK, 20-Aug-2000: Fix problem with BoundingBox recognition
|
|
|
|
* for Mac files.
|
|
|
|
* Fix problem with loop when reading not all
|
|
|
|
* images of a multi page file.
|
2000-10-07 02:16:58 +08:00
|
|
|
* PK, 31-Aug-2000: Load PS: Add checks for space in filename.
|
2001-06-21 17:25:06 +08:00
|
|
|
* V 1.12 PK, 19-Jun-2001: Fix problem with command line switch --
|
|
|
|
* (reported by Ferenc Wagner)
|
2002-04-11 18:58:19 +08:00
|
|
|
* V 1.13 PK, 07-Apr-2002: Fix problem with DOS binary EPS files
|
2002-05-15 04:04:29 +08:00
|
|
|
* V 1.14 PK, 14-May-2002: Workaround EPS files of Adb. Ill. 8.0
|
2002-10-08 18:53:10 +08:00
|
|
|
* V 1.15 PK, 04-Oct-2002: Be more accurate with using BoundingBox
|
2004-01-26 07:46:24 +08:00
|
|
|
* V 1.16 PK, 22-Jan-2004: Don't use popen(), use g_spawn_async_with_pipes()
|
|
|
|
* or g_spawn_sync().
|
2004-09-19 18:54:48 +08:00
|
|
|
* V 1.17 PK, 19-Sep-2004: Fix problem with interpretation of bounding box
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
|
|
|
|
1999-05-30 00:35:47 +08:00
|
|
|
#include "config.h"
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2003-06-13 22:37:00 +08:00
|
|
|
#include <errno.h>
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2004-01-26 07:46:24 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2005-03-04 23:12:29 +08:00
|
|
|
#include <glib/gstdio.h>
|
|
|
|
|
2000-01-08 23:23:28 +08:00
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
1999-05-30 00:35:47 +08:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
|
|
|
|
2012-01-22 12:26:08 +08:00
|
|
|
#include <ghostscript/ierrors.h>
|
|
|
|
#include <ghostscript/iapi.h>
|
|
|
|
#include <ghostscript/gdevdsp.h>
|
2004-01-26 07:46:24 +08:00
|
|
|
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
#define VERSION 1.17
|
|
|
|
static const gchar dversion[] = "v1.17 19-Sep-2004";
|
2005-08-15 18:30:39 +08:00
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
#define LOAD_PS_PROC "file-ps-load"
|
|
|
|
#define LOAD_EPS_PROC "file-eps-load"
|
|
|
|
#define LOAD_PS_THUMB_PROC "file-ps-load-thumb"
|
|
|
|
#define SAVE_PS_PROC "file-ps-save"
|
|
|
|
#define SAVE_EPS_PROC "file-eps-save"
|
|
|
|
#define PLUG_IN_BINARY "file-ps"
|
|
|
|
#define PLUG_IN_ROLE "gimp-file-ps"
|
2005-08-15 18:30:39 +08:00
|
|
|
|
2014-02-22 16:40:49 +08:00
|
|
|
#define STR_LENGTH 64
|
|
|
|
#define MIN_RESOLUTION 5
|
|
|
|
#define MAX_RESOLUTION 8192
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2007-11-13 04:52:17 +08:00
|
|
|
guint resolution; /* resolution (dpi) at which to run ghostscript */
|
|
|
|
guint width, height; /* desired size (ghostscript may ignore this) */
|
|
|
|
gboolean use_bbox; /* 0: use width/height, 1: try to use BoundingBox */
|
|
|
|
gchar pages[STR_LENGTH]; /* Pages to load (eg.: 1,3,5-7) */
|
|
|
|
gint pnm_type; /* 4: pbm, 5: pgm, 6: ppm, 7: automatic */
|
|
|
|
gint textalpha; /* antialiasing: 1,2, or 4 TextAlphaBits */
|
|
|
|
gint graphicsalpha; /* antialiasing: 1,2, or 4 GraphicsAlphaBits */
|
1997-11-25 06:05:25 +08:00
|
|
|
} PSLoadVals;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2007-11-13 04:52:17 +08:00
|
|
|
gdouble width, height; /* Size of image */
|
|
|
|
gdouble x_offset, y_offset; /* Offset to image on page */
|
|
|
|
gboolean unit_mm; /* Unit of measure (0: inch, 1: mm) */
|
|
|
|
gboolean keep_ratio; /* Keep aspect ratio */
|
|
|
|
gint rotate; /* Rotation (0, 90, 180, 270) */
|
|
|
|
gint level; /* PostScript Level */
|
|
|
|
gboolean eps; /* Encapsulated PostScript flag */
|
|
|
|
gboolean preview; /* Preview Flag */
|
|
|
|
gint preview_size; /* Preview size */
|
1997-11-25 06:05:25 +08:00
|
|
|
} PSSaveVals;
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
typedef struct _PostScript PostScript;
|
|
|
|
typedef struct _PostScriptClass PostScriptClass;
|
|
|
|
|
|
|
|
struct _PostScript
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2019-08-18 23:04:53 +08:00
|
|
|
GimpPlugIn parent_instance;
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
struct _PostScriptClass
|
|
|
|
{
|
|
|
|
GimpPlugInClass parent_class;
|
|
|
|
};
|
2008-12-04 00:07:32 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
#define PS_TYPE (ps_get_type ())
|
|
|
|
#define PS (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PS_TYPE, PostScript))
|
|
|
|
|
|
|
|
GType ps_get_type (void) G_GNUC_CONST;
|
|
|
|
|
|
|
|
static GList * ps_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * ps_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
|
|
|
static GimpValueArray * ps_load (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data);
|
|
|
|
static GimpValueArray * ps_load_thumb (GimpProcedure *procedure,
|
2019-08-19 20:04:00 +08:00
|
|
|
GFile *file,
|
|
|
|
gint size,
|
2019-08-18 23:04:53 +08:00
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data);
|
|
|
|
static GimpValueArray * ps_save (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
2020-04-14 17:46:17 +08:00
|
|
|
gint n_drawables,
|
|
|
|
GimpDrawable **drawables,
|
2019-08-18 23:04:53 +08:00
|
|
|
GFile *file,
|
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data);
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
static GimpImage * load_image (GFile *file,
|
2019-08-18 23:04:53 +08:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_image (GFile *file,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2019-08-18 23:04:53 +08:00
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static void ps_set_save_size (PSSaveVals *vals,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
static gboolean save_ps_header (GOutputStream *output,
|
|
|
|
GFile *file,
|
|
|
|
GError **error);
|
|
|
|
static gboolean save_ps_setup (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
gint bpp,
|
|
|
|
GError **error);
|
|
|
|
static gboolean save_ps_trailer (GOutputStream *output,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean save_ps_preview (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean save_gray (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_bw (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_index (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error);
|
|
|
|
static gboolean save_rgb (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static gboolean print (GOutputStream *output,
|
|
|
|
GError **error,
|
|
|
|
const gchar *format,
|
|
|
|
...) G_GNUC_PRINTF (3, 4);
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
static GimpImage * create_new_image (GFile *file,
|
2019-08-19 21:46:53 +08:00
|
|
|
guint pagenum,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
|
|
|
GimpImageBaseType type,
|
|
|
|
GimpLayer **layer);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
static void check_load_vals (void);
|
|
|
|
static void check_save_vals (void);
|
|
|
|
|
|
|
|
static gint page_in_list (gchar *list,
|
|
|
|
guint pagenum);
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
static gint get_bbox (GFile *file,
|
2014-10-27 01:54:42 +08:00
|
|
|
gint *x0,
|
|
|
|
gint *y0,
|
|
|
|
gint *x1,
|
|
|
|
gint *y1);
|
|
|
|
|
2022-05-16 22:31:50 +08:00
|
|
|
static FILE * ps_open (GFile *file,
|
|
|
|
const PSLoadVals *loadopt,
|
|
|
|
gint *llx,
|
|
|
|
gint *lly,
|
|
|
|
gint *urx,
|
|
|
|
gint *ury,
|
|
|
|
gboolean *is_epsf,
|
|
|
|
gchar **tmp_filename);
|
|
|
|
|
|
|
|
static void ps_close (FILE *ifp,
|
|
|
|
gchar *tmp_filename);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
static gboolean skip_ps (FILE *ifp);
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
static GimpImage * load_ps (GFile *file,
|
2014-10-27 01:54:42 +08:00
|
|
|
guint pagenum,
|
|
|
|
FILE *ifp,
|
|
|
|
gint llx,
|
|
|
|
gint lly,
|
|
|
|
gint urx,
|
|
|
|
gint ury);
|
|
|
|
|
|
|
|
static void dither_grey (const guchar *grey,
|
|
|
|
guchar *bw,
|
|
|
|
gint npix,
|
|
|
|
gint linecount);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* Dialog-handling */
|
1999-10-04 02:54:54 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
static gint32 count_ps_pages (GFile *file);
|
|
|
|
static gboolean load_dialog (GFile *file);
|
2007-03-01 20:48:00 +08:00
|
|
|
static void load_pages_entry_callback (GtkWidget *widget,
|
|
|
|
gpointer data);
|
2007-05-15 15:12:15 +08:00
|
|
|
|
2007-03-01 20:48:00 +08:00
|
|
|
static gboolean resolution_change_callback (GtkAdjustment *adjustment,
|
2019-09-12 03:48:34 +08:00
|
|
|
gpointer data);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkAdjustment *adjustment[4];
|
|
|
|
gint level;
|
1997-11-25 06:05:25 +08:00
|
|
|
} SaveDialogVals;
|
|
|
|
|
2004-05-20 01:53:21 +08:00
|
|
|
static gboolean save_dialog (void);
|
|
|
|
static void save_unit_toggle_update (GtkWidget *widget,
|
|
|
|
gpointer data);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
G_DEFINE_TYPE (PostScript, ps, GIMP_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
GIMP_MAIN (PS_TYPE)
|
2022-05-26 06:59:36 +08:00
|
|
|
DEFINE_STD_SET_I18N
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
static PSLoadVals plvals =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2019-08-18 23:04:53 +08:00
|
|
|
100, /* 100 dpi */
|
|
|
|
826, 1170, /* default width/height (A4) */
|
|
|
|
TRUE, /* try to use BoundingBox */
|
|
|
|
"1", /* pages to load */
|
|
|
|
6, /* use ppm (color) */
|
|
|
|
1, /* don't use text antialiasing */
|
|
|
|
1 /* don't use graphics antialiasing */
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
/* Widgets for width and height of PostScript image to
|
|
|
|
* be loaded, so that they can be updated when desired resolution is
|
|
|
|
* changed
|
|
|
|
*/
|
|
|
|
static GtkWidget *ps_width_spinbutton;
|
|
|
|
static GtkWidget *ps_height_spinbutton;
|
|
|
|
|
|
|
|
static PSSaveVals psvals =
|
|
|
|
{
|
|
|
|
287.0, 200.0, /* Image size (A4) */
|
|
|
|
5.0, 5.0, /* Offset */
|
|
|
|
TRUE, /* Unit is mm */
|
|
|
|
TRUE, /* Keep edge ratio */
|
|
|
|
0, /* Rotate */
|
|
|
|
2, /* PostScript Level */
|
|
|
|
FALSE, /* Encapsulated PostScript flag */
|
|
|
|
FALSE, /* Preview flag */
|
|
|
|
256 /* Preview size */
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char hex[] = "0123456789abcdef";
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* The run mode */
|
2001-12-19 08:13:16 +08:00
|
|
|
static GimpRunMode l_run_mode;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
ps_class_init (PostScriptClass *klass)
|
|
|
|
{
|
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
|
|
|
|
|
|
|
plug_in_class->query_procedures = ps_query_procedures;
|
|
|
|
plug_in_class->create_procedure = ps_create_procedure;
|
2022-05-26 06:59:36 +08:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
2019-08-18 23:04:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ps_init (PostScript *ps)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
ps_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
GList *list = NULL;
|
|
|
|
|
2019-09-11 01:36:54 +08:00
|
|
|
list = g_list_append (list, g_strdup (LOAD_PS_THUMB_PROC));
|
2019-08-18 23:04:53 +08:00
|
|
|
list = g_list_append (list, g_strdup (LOAD_PS_PROC));
|
|
|
|
list = g_list_append (list, g_strdup (LOAD_EPS_PROC));
|
|
|
|
list = g_list_append (list, g_strdup (SAVE_PS_PROC));
|
|
|
|
list = g_list_append (list, g_strdup (SAVE_EPS_PROC));
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpProcedure *
|
|
|
|
ps_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
GimpProcedure *procedure = NULL;
|
|
|
|
|
|
|
|
if (! strcmp (name, LOAD_PS_PROC) ||
|
|
|
|
! strcmp (name, LOAD_EPS_PROC))
|
|
|
|
{
|
2019-08-30 18:52:28 +08:00
|
|
|
procedure = gimp_load_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
2019-08-18 23:04:53 +08:00
|
|
|
ps_load, NULL, NULL);
|
|
|
|
|
|
|
|
if (! strcmp (name, LOAD_PS_PROC))
|
|
|
|
{
|
2022-07-05 04:50:53 +08:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("PostScript document"));
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Load PostScript documents",
|
|
|
|
"Load PostScript documents",
|
|
|
|
name);
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/postscript");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"ps");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,string,%!,0,long,0xc5d0d3c6");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_procedure_set_menu_label (procedure,
|
2022-07-05 04:50:53 +08:00
|
|
|
_("Encapsulated PostScript image"));
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"load Encapsulated PostScript images",
|
|
|
|
"load Encapsulated PostScript images",
|
|
|
|
name);
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"image/x-eps");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"eps");
|
|
|
|
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"0,string,%!,0,long,0xc5d0d3c6");
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
|
|
|
|
gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure),
|
|
|
|
LOAD_PS_THUMB_PROC);
|
|
|
|
|
2019-08-19 16:02:07 +08:00
|
|
|
GIMP_PROC_ARG_INT (procedure, "resolution",
|
|
|
|
"Resolution",
|
|
|
|
"Resolution to interpret image (dpi)",
|
|
|
|
MIN_RESOLUTION, MAX_RESOLUTION, 100,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "width",
|
|
|
|
"Width",
|
|
|
|
"Desired width",
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE, 826,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "height",
|
|
|
|
"Height",
|
|
|
|
"Desired height",
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE, 1170,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_BOOLEAN (procedure, "check-bbox",
|
|
|
|
"Check bbox",
|
|
|
|
"FALSE: Use width/height, TRUE: Use BoundingBox",
|
|
|
|
TRUE,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_STRING (procedure, "pages",
|
|
|
|
"Pages",
|
|
|
|
"Pages to load (e.g.: 1,3,5-7)",
|
|
|
|
"1",
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "coloring",
|
|
|
|
"Coloring",
|
|
|
|
"4: b/w, 5: grey, 6: color image, 7: automatic",
|
|
|
|
4, 7, 6,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "text-alpha-bits",
|
|
|
|
"Text alpha bits",
|
|
|
|
"1, 2 or 4",
|
|
|
|
1, 4, 1,
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "graphoc-alpha-bits",
|
|
|
|
"Graphic alpha bits",
|
|
|
|
"1, 2 or 4",
|
|
|
|
1, 4, 1,
|
|
|
|
GIMP_PARAM_READWRITE);
|
2019-08-18 23:04:53 +08:00
|
|
|
}
|
|
|
|
else if (! strcmp (name, LOAD_PS_THUMB_PROC))
|
|
|
|
{
|
2019-08-30 18:52:28 +08:00
|
|
|
procedure = gimp_thumbnail_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
2019-08-19 20:04:00 +08:00
|
|
|
ps_load_thumb, NULL, NULL);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Loads a small preview from a "
|
|
|
|
"PostScript or PDF document",
|
|
|
|
"",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
}
|
|
|
|
else if (! strcmp (name, SAVE_PS_PROC) ||
|
|
|
|
! strcmp (name, SAVE_EPS_PROC))
|
|
|
|
{
|
2019-08-30 18:52:28 +08:00
|
|
|
procedure = gimp_save_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
2019-08-18 23:04:53 +08:00
|
|
|
ps_save, NULL, NULL);
|
|
|
|
|
|
|
|
if (! strcmp (name, SAVE_PS_PROC))
|
|
|
|
{
|
2022-07-05 04:50:53 +08:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("PostScript document"));
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Export image as PostScript document",
|
|
|
|
"PostScript exporting handles all "
|
|
|
|
"image types except those with alpha "
|
|
|
|
"channels.",
|
|
|
|
name);
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/postscript");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"ps");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_procedure_set_menu_label (procedure,
|
2022-07-05 04:50:53 +08:00
|
|
|
_("Encapsulated PostScript image"));
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
|
|
"Export image as Encapsulated "
|
|
|
|
"PostScript image",
|
|
|
|
"PostScript exporting handles all "
|
|
|
|
"image types except those with alpha "
|
|
|
|
"channels.",
|
|
|
|
name);
|
|
|
|
|
|
|
|
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"application/x-eps");
|
|
|
|
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
"eps");
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_procedure_set_image_types (procedure, "RGB, GRAY, INDEXED");
|
|
|
|
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Peter Kirchgessner <peter@kirchgessner.net>",
|
|
|
|
"Peter Kirchgessner",
|
|
|
|
dversion);
|
|
|
|
|
2019-08-19 18:05:12 +08:00
|
|
|
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
|
|
|
|
TRUE);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
2019-08-19 16:02:07 +08:00
|
|
|
GIMP_PROC_ARG_DOUBLE (procedure, "width",
|
|
|
|
"Width",
|
|
|
|
"Width of the image in PostScript file "
|
|
|
|
"(0: use input image size)",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_DOUBLE (procedure, "height",
|
|
|
|
"Height",
|
|
|
|
"Height of the image in PostScript file "
|
|
|
|
"(0: use input image size)",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_DOUBLE (procedure, "x-offset",
|
|
|
|
"X offset",
|
|
|
|
"X-offset to image from lower left corner",
|
|
|
|
-GIMP_MAX_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_DOUBLE (procedure, "y-offset",
|
|
|
|
"Y offset",
|
|
|
|
"Y-offset to image from lower left corner",
|
|
|
|
-GIMP_MAX_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "unit",
|
|
|
|
"Unit",
|
|
|
|
"Unit for width/height/offset. "
|
|
|
|
"0: inches, 1: millimeters",
|
|
|
|
0, 1, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_BOOLEAN (procedure, "keep-ratio",
|
|
|
|
"Keep ratio",
|
|
|
|
"FALSE: use width/height, TRUE: keep aspect ratio",
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "rotation",
|
|
|
|
"Rotation",
|
|
|
|
"0, 90, 180, 270",
|
|
|
|
0, 270, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_BOOLEAN (procedure, "eps-flag",
|
|
|
|
"EPG flag",
|
|
|
|
"FALSE: PostScript, TRUE: Encapsulated PostScript",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "preview",
|
|
|
|
"Preview",
|
|
|
|
"0: no preview, >0: max. size of preview",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
GIMP_PROC_ARG_INT (procedure, "level",
|
|
|
|
"Level",
|
|
|
|
"1: PostScript Level 1, 2: PostScript Level 2",
|
|
|
|
1, 2, 2,
|
|
|
|
G_PARAM_READWRITE);
|
2019-08-18 23:04:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
|
|
|
ps_load (GimpProcedure *procedure,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpRunMode run_mode,
|
|
|
|
GFile *file,
|
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data)
|
2019-08-18 23:04:53 +08:00
|
|
|
{
|
|
|
|
GimpValueArray *return_vals;
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image;
|
2019-08-18 23:04:53 +08:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
l_run_mode = run_mode;
|
|
|
|
|
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
gimp_get_data (LOAD_PS_PROC, &plvals);
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
if (! load_dialog (file))
|
2019-08-18 23:04:53 +08:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CANCEL,
|
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
2019-08-20 07:03:38 +08:00
|
|
|
plvals.resolution = GIMP_VALUES_GET_INT (args, 0);
|
|
|
|
plvals.width = GIMP_VALUES_GET_INT (args, 1);
|
|
|
|
plvals.height = GIMP_VALUES_GET_INT (args, 2);
|
|
|
|
plvals.use_bbox = GIMP_VALUES_GET_BOOLEAN (args, 3);
|
|
|
|
if (GIMP_VALUES_GET_STRING (args, 4))
|
2019-08-18 23:04:53 +08:00
|
|
|
g_strlcpy (plvals.pages,
|
2019-08-20 07:03:38 +08:00
|
|
|
GIMP_VALUES_GET_STRING (args, 4),
|
2019-08-18 23:04:53 +08:00
|
|
|
sizeof (plvals.pages));
|
|
|
|
else
|
|
|
|
plvals.pages[0] = '\0';
|
2019-08-20 07:03:38 +08:00
|
|
|
plvals.pnm_type = GIMP_VALUES_GET_INT (args, 5);
|
|
|
|
plvals.textalpha = GIMP_VALUES_GET_INT (args, 6);
|
|
|
|
plvals.graphicsalpha = GIMP_VALUES_GET_INT (args, 7);
|
2019-08-18 23:04:53 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
|
|
gimp_get_data (LOAD_PS_PROC, &plvals);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
check_load_vals ();
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
image = load_image (file, &error);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! image)
|
2019-08-18 23:04:53 +08:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
|
|
|
|
|
|
|
gimp_set_data (LOAD_PS_PROC, &plvals, sizeof (PSLoadVals));
|
|
|
|
|
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
|
|
|
ps_load_thumb (GimpProcedure *procedure,
|
2019-08-19 20:04:00 +08:00
|
|
|
GFile *file,
|
|
|
|
gint size,
|
2019-08-18 23:04:53 +08:00
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data)
|
|
|
|
{
|
|
|
|
GimpValueArray *return_vals;
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image;
|
2019-08-18 23:04:53 +08:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
/* We should look for an embedded preview but for now we
|
|
|
|
* just load the document at a small resolution and the
|
|
|
|
* first page only.
|
|
|
|
*/
|
|
|
|
plvals.resolution = size / 4;
|
|
|
|
plvals.width = size;
|
|
|
|
plvals.height = size;
|
|
|
|
g_strlcpy (plvals.pages, "1", sizeof (plvals.pages));
|
|
|
|
|
|
|
|
check_load_vals ();
|
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
image = load_image (file, &error);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! image)
|
2019-08-18 23:04:53 +08:00
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_EXECUTION_ERROR,
|
|
|
|
error);
|
|
|
|
|
|
|
|
return_vals = gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_SUCCESS,
|
|
|
|
NULL);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
2019-08-19 20:04:00 +08:00
|
|
|
gimp_value_array_truncate (return_vals, 2);
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
|
|
|
ps_save (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
2020-04-14 17:46:17 +08:00
|
|
|
gint n_drawables,
|
|
|
|
GimpDrawable **drawables,
|
2019-08-18 23:04:53 +08:00
|
|
|
GFile *file,
|
|
|
|
const GimpValueArray *args,
|
|
|
|
gpointer run_data)
|
|
|
|
{
|
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
|
|
|
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *orig_image;
|
2019-08-18 23:04:53 +08:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
psvals.eps = strcmp (gimp_procedure_get_name (procedure), SAVE_PS_PROC);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
orig_image = image;
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
2019-09-21 01:39:00 +08:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
export = gimp_export_image (&image, &n_drawables, &drawables,
|
2019-08-18 23:04:53 +08:00
|
|
|
psvals.eps ? "EPS" : "PostScript",
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED);
|
|
|
|
|
|
|
|
if (export == GIMP_EXPORT_CANCEL)
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CANCEL,
|
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
if (n_drawables != 1)
|
|
|
|
{
|
|
|
|
g_set_error (&error, G_FILE_ERROR, 0,
|
|
|
|
_("PostScript plug-in does not support multiple layers."));
|
|
|
|
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CALLING_ERROR,
|
|
|
|
error);
|
|
|
|
}
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
switch (run_mode)
|
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
gimp_get_data (gimp_procedure_get_name (procedure), &psvals);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
ps_set_save_size (&psvals, orig_image);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
if (! save_dialog ())
|
|
|
|
status = GIMP_PDB_CANCEL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
2019-08-20 07:03:38 +08:00
|
|
|
psvals.width = GIMP_VALUES_GET_DOUBLE (args, 0);
|
|
|
|
psvals.height = GIMP_VALUES_GET_DOUBLE (args, 1);
|
|
|
|
psvals.x_offset = GIMP_VALUES_GET_DOUBLE (args, 2);
|
|
|
|
psvals.y_offset = GIMP_VALUES_GET_DOUBLE (args, 3);
|
|
|
|
psvals.unit_mm = GIMP_VALUES_GET_INT (args, 4);
|
|
|
|
psvals.keep_ratio = GIMP_VALUES_GET_BOOLEAN (args, 5);
|
|
|
|
psvals.rotate = GIMP_VALUES_GET_INT (args, 6);
|
|
|
|
psvals.eps = GIMP_VALUES_GET_INT (args, 7);
|
|
|
|
psvals.preview_size = GIMP_VALUES_GET_INT (args, 8);
|
2019-08-18 23:04:53 +08:00
|
|
|
psvals.preview = psvals.preview_size != 0;
|
2019-08-20 07:03:38 +08:00
|
|
|
psvals.level = GIMP_VALUES_GET_INT (args, 9);
|
2019-08-18 23:04:53 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
|
|
gimp_get_data (gimp_procedure_get_name (procedure), &psvals);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
|
|
|
if ((psvals.width == 0.0) || (psvals.height == 0.0))
|
2019-08-19 21:46:53 +08:00
|
|
|
ps_set_save_size (&psvals, orig_image);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
check_save_vals ();
|
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
if (save_image (file, image, drawables[0], &error))
|
2019-08-18 23:04:53 +08:00
|
|
|
{
|
|
|
|
gimp_set_data (gimp_procedure_get_name (procedure),
|
|
|
|
&psvals, sizeof (PSSaveVals));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2020-04-14 17:46:17 +08:00
|
|
|
{
|
|
|
|
gimp_image_delete (image);
|
|
|
|
g_free (drawables);
|
|
|
|
}
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
return gimp_procedure_new_return_values (procedure, status, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-27 20:28:46 +08:00
|
|
|
static void compress_packbits (int nin,
|
2000-03-11 01:27:25 +08:00
|
|
|
unsigned char *src,
|
2003-11-27 20:28:46 +08:00
|
|
|
int *nout,
|
2000-03-11 01:27:25 +08:00
|
|
|
unsigned char *dst);
|
|
|
|
|
2005-10-28 22:57:32 +08:00
|
|
|
static guint32 ascii85_buf = 0;
|
|
|
|
static gint ascii85_len = 0;
|
|
|
|
static gint ascii85_linewidth = 0;
|
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
static GimpPageSelectorTarget ps_pagemode = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
|
2000-01-23 06:26:20 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
ascii85_init (void)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
ascii85_len = 0;
|
2000-01-26 01:46:56 +08:00
|
|
|
ascii85_linewidth = 0;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
ascii85_flush (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
gchar c[5];
|
|
|
|
gint i;
|
2000-01-26 01:46:56 +08:00
|
|
|
gboolean zero_case = (ascii85_buf == 0);
|
2014-10-27 01:54:42 +08:00
|
|
|
GString *string = g_string_new (NULL);
|
|
|
|
|
|
|
|
static gint max_linewidth = 75;
|
2000-01-23 06:26:20 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
for (i = 4; i >= 0; i--)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
c[i] = (ascii85_buf % 85) + '!';
|
|
|
|
ascii85_buf /= 85;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
/* check for special case: "!!!!!" becomes "z", but only if not
|
|
|
|
* at end of data. */
|
|
|
|
if (zero_case && (ascii85_len == 4))
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2000-03-26 06:19:17 +08:00
|
|
|
if (ascii85_linewidth >= max_linewidth)
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
ascii85_linewidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_append_c (string, 'z');
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
ascii85_linewidth++;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
for (i = 0; i < ascii85_len + 1; i++)
|
2000-03-26 06:19:17 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((ascii85_linewidth >= max_linewidth) && (c[i] != '%'))
|
|
|
|
{
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
ascii85_linewidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_append_c (string, c[i]);
|
|
|
|
|
|
|
|
ascii85_linewidth++;
|
2000-03-26 06:19:17 +08:00
|
|
|
}
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
ascii85_len = 0;
|
|
|
|
ascii85_buf = 0;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (string->len > 0 &&
|
|
|
|
! g_output_stream_write_all (output,
|
|
|
|
string->str, string->len, NULL,
|
|
|
|
NULL, error))
|
|
|
|
{
|
|
|
|
g_string_free (string, TRUE);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_free (string, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static inline gboolean
|
|
|
|
ascii85_out (GOutputStream *output,
|
|
|
|
guchar byte,
|
|
|
|
GError **error)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
if (ascii85_len == 4)
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! ascii85_flush (output, error))
|
|
|
|
return FALSE;
|
2000-01-23 06:26:20 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
ascii85_buf <<= 8;
|
|
|
|
ascii85_buf |= byte;
|
|
|
|
ascii85_len++;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
ascii85_nout (GOutputStream *output,
|
|
|
|
gint n,
|
|
|
|
guchar *uptr,
|
|
|
|
GError **error)
|
2000-03-11 01:27:25 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
while (n-- > 0)
|
|
|
|
{
|
|
|
|
if (! ascii85_out (output, *uptr, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
uptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2000-03-11 01:27:25 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
ascii85_done (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
if (ascii85_len)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
/* zero any unfilled buffer portion, then flush */
|
2014-10-27 01:54:42 +08:00
|
|
|
ascii85_buf <<= (8 * (4 - ascii85_len));
|
|
|
|
|
|
|
|
if (! ascii85_flush (output, error))
|
|
|
|
return FALSE;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "~>\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2000-01-23 06:26:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
static void
|
|
|
|
compress_packbits (int nin,
|
|
|
|
unsigned char *src,
|
|
|
|
int *nout,
|
|
|
|
unsigned char *dst)
|
|
|
|
|
2013-05-15 02:52:38 +08:00
|
|
|
{
|
|
|
|
unsigned char c;
|
2000-03-11 01:27:25 +08:00
|
|
|
int nrepeat, nliteral;
|
|
|
|
unsigned char *run_start;
|
|
|
|
unsigned char *start_dst = dst;
|
|
|
|
unsigned char *last_literal = NULL;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (nin <= 0) break;
|
|
|
|
|
|
|
|
run_start = src;
|
|
|
|
c = *run_start;
|
|
|
|
|
|
|
|
/* Search repeat bytes */
|
|
|
|
if ((nin > 1) && (c == src[1]))
|
|
|
|
{
|
|
|
|
nrepeat = 1;
|
|
|
|
nin -= 2;
|
|
|
|
src += 2;
|
|
|
|
while ((nin > 0) && (c == *src))
|
|
|
|
{
|
|
|
|
nrepeat++;
|
|
|
|
src++;
|
|
|
|
nin--;
|
|
|
|
if (nrepeat == 127) break; /* Maximum repeat */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add two-byte repeat to last literal run ? */
|
|
|
|
if ( (nrepeat == 1)
|
|
|
|
&& (last_literal != NULL) && (((*last_literal)+1)+2 <= 128))
|
|
|
|
{
|
|
|
|
*last_literal += 2;
|
|
|
|
*(dst++) = c;
|
|
|
|
*(dst++) = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add repeat run */
|
|
|
|
*(dst++) = (unsigned char)((-nrepeat) & 0xff);
|
|
|
|
*(dst++) = c;
|
|
|
|
last_literal = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Search literal bytes */
|
|
|
|
nliteral = 1;
|
|
|
|
nin--;
|
|
|
|
src++;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (nin <= 0) break;
|
|
|
|
|
|
|
|
if ((nin >= 2) && (src[0] == src[1])) /* A two byte repeat ? */
|
|
|
|
break;
|
|
|
|
|
|
|
|
nliteral++;
|
|
|
|
nin--;
|
|
|
|
src++;
|
|
|
|
if (nliteral == 128) break; /* Maximum literal run */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Could be added to last literal run ? */
|
|
|
|
if ((last_literal != NULL) && (((*last_literal)+1)+nliteral <= 128))
|
|
|
|
{
|
|
|
|
*last_literal += nliteral;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last_literal = dst;
|
|
|
|
*(dst++) = (unsigned char)(nliteral-1);
|
|
|
|
}
|
|
|
|
while (nliteral-- > 0) *(dst++) = *(run_start++);
|
|
|
|
}
|
|
|
|
*nout = dst - start_dst;
|
|
|
|
}
|
|
|
|
|
2000-01-23 06:26:20 +08:00
|
|
|
|
2000-04-05 18:26:08 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
goffset eol;
|
|
|
|
goffset begin_data;
|
2000-04-05 18:26:08 +08:00
|
|
|
} PS_DATA_POS;
|
|
|
|
|
|
|
|
static PS_DATA_POS ps_data_pos = { 0, 0 };
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
ps_begin_data (GOutputStream *output,
|
|
|
|
GError **error)
|
2000-04-05 18:26:08 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
/* %%BeginData: 123456789012 ASCII Bytes */
|
|
|
|
if (! print (output, error, "%s", "%%BeginData: "))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ps_data_pos.eol = g_seekable_tell (G_SEEKABLE (output));
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ps_data_pos.begin_data = g_seekable_tell (G_SEEKABLE (output));
|
|
|
|
|
|
|
|
return TRUE;
|
2000-04-05 18:26:08 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
ps_end_data (GOutputStream *output,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
goffset end_data;
|
|
|
|
gchar s[64];
|
2000-04-05 18:26:08 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((ps_data_pos.begin_data > 0) && (ps_data_pos.eol > 0))
|
|
|
|
{
|
|
|
|
end_data = g_seekable_tell (G_SEEKABLE (output));
|
2000-04-05 18:26:08 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (end_data > 0)
|
|
|
|
{
|
|
|
|
g_snprintf (s, sizeof (s),
|
2020-05-26 18:12:10 +08:00
|
|
|
"%"G_GOFFSET_FORMAT" ASCII Bytes", end_data - ps_data_pos.begin_data);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! g_seekable_seek (G_SEEKABLE (output),
|
|
|
|
ps_data_pos.eol - strlen (s), G_SEEK_SET,
|
|
|
|
NULL, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error, "%s", s))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! g_seekable_seek (G_SEEKABLE (output),
|
|
|
|
end_data, G_SEEK_SET,
|
|
|
|
NULL, error))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error, "%s\n", "%%EndData"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2000-04-05 18:26:08 +08:00
|
|
|
}
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
static GimpImage *
|
2019-09-12 03:48:34 +08:00
|
|
|
load_image (GFile *file,
|
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2021-10-13 05:17:38 +08:00
|
|
|
GimpImage *image = NULL;
|
|
|
|
GimpImage **image_list, **nl;
|
|
|
|
const gchar *filename;
|
|
|
|
guint page_count;
|
|
|
|
FILE *ifp;
|
|
|
|
gchar *temp;
|
|
|
|
gint llx, lly, urx, ury;
|
|
|
|
gint k, n_images, max_images, max_pagenum;
|
|
|
|
gboolean is_epsf;
|
2022-05-16 22:31:50 +08:00
|
|
|
GdkPixbuf *pixbuf = NULL;
|
|
|
|
gchar *tmp_filename = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#ifdef PS_DEBUG
|
2000-01-26 01:46:56 +08:00
|
|
|
g_print ("load_image:\n resolution = %d\n", plvals.resolution);
|
|
|
|
g_print (" %dx%d pixels\n", plvals.width, plvals.height);
|
|
|
|
g_print (" BoundingBox: %d\n", plvals.use_bbox);
|
2013-06-07 05:26:16 +08:00
|
|
|
g_print (" Coloring: %d\n", plvals.pnm_type);
|
2000-01-26 01:46:56 +08:00
|
|
|
g_print (" TextAlphaBits: %d\n", plvals.textalpha);
|
|
|
|
g_print (" GraphicsAlphaBits: %d\n", plvals.graphicsalpha);
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
2014-07-23 22:39:00 +08:00
|
|
|
gimp_progress_init_printf (_("Opening '%s'"),
|
2019-09-12 03:48:34 +08:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 22:39:00 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
/* Try to see if PostScript file is available */
|
2021-08-08 05:22:27 +08:00
|
|
|
filename = gimp_file_get_utf8_name (file);
|
2005-03-04 23:12:29 +08:00
|
|
|
ifp = g_fopen (filename, "r");
|
2019-09-12 03:48:34 +08:00
|
|
|
|
|
|
|
if (! ifp)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2008-08-18 14:53:21 +08:00
|
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
|
|
_("Could not open '%s' for reading: %s"),
|
2019-09-12 03:48:34 +08:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2019-08-19 21:46:53 +08:00
|
|
|
return NULL;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
fclose (ifp);
|
|
|
|
|
2022-05-16 22:31:50 +08:00
|
|
|
ifp = ps_open (file, &plvals, &llx, &lly, &urx, &ury, &is_epsf, &tmp_filename);
|
2000-01-26 01:46:56 +08:00
|
|
|
if (!ifp)
|
|
|
|
{
|
2008-08-20 22:00:44 +08:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR,
|
2016-03-20 05:45:16 +08:00
|
|
|
_("Could not interpret PostScript file '%s'"),
|
2019-09-12 03:48:34 +08:00
|
|
|
gimp_file_get_utf8_name (file));
|
2019-08-19 21:46:53 +08:00
|
|
|
return NULL;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
image_list = g_new (GimpImage *, 10);
|
2000-01-26 01:46:56 +08:00
|
|
|
n_images = 0;
|
|
|
|
max_images = 10;
|
|
|
|
|
|
|
|
max_pagenum = 9999; /* Try to get the maximum pagenumber to read */
|
2004-11-19 05:10:12 +08:00
|
|
|
if (is_epsf)
|
2022-05-16 22:31:50 +08:00
|
|
|
{
|
|
|
|
max_pagenum = 1;
|
|
|
|
/* Use pixbuf to load transparent EPS as PNGs */
|
|
|
|
pixbuf = gdk_pixbuf_new_from_file (tmp_filename, error);
|
|
|
|
if (! pixbuf)
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (!page_in_list (plvals.pages, max_pagenum)) /* Is there a limit in list ? */
|
|
|
|
{
|
|
|
|
max_pagenum = -1;
|
|
|
|
for (temp = plvals.pages; *temp != '\0'; temp++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
if ((*temp < '0') || (*temp > '9'))
|
2004-11-19 05:10:12 +08:00
|
|
|
continue; /* Search next digit */
|
2006-05-08 20:23:32 +08:00
|
|
|
sscanf (temp, "%d", &k);
|
|
|
|
if (k > max_pagenum)
|
2004-11-19 05:10:12 +08:00
|
|
|
max_pagenum = k;
|
2006-05-08 20:23:32 +08:00
|
|
|
while ((*temp >= '0') && (*temp <= '9'))
|
2004-11-19 05:10:12 +08:00
|
|
|
temp++;
|
2006-05-08 20:23:32 +08:00
|
|
|
temp--;
|
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
|
|
|
if (max_pagenum < 1)
|
|
|
|
max_pagenum = 9999;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Load all images */
|
|
|
|
for (page_count = 1; page_count <= max_pagenum; page_count++)
|
|
|
|
{
|
|
|
|
if (page_in_list (plvals.pages, page_count))
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2019-09-12 03:48:34 +08:00
|
|
|
image = load_ps (file, page_count, ifp, llx, lly, urx, ury);
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! image)
|
2004-11-19 05:10:12 +08:00
|
|
|
break;
|
2001-05-22 08:36:38 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
gimp_image_set_resolution (image,
|
2014-10-27 01:54:42 +08:00
|
|
|
(gdouble) plvals.resolution,
|
|
|
|
(gdouble) plvals.resolution);
|
2006-05-08 20:23:32 +08:00
|
|
|
|
|
|
|
if (n_images == max_images)
|
|
|
|
{
|
2019-08-19 21:46:53 +08:00
|
|
|
nl = (GimpImage **) g_realloc (image_list,
|
|
|
|
(max_images+10)*sizeof (GimpImage *));
|
2006-05-08 20:23:32 +08:00
|
|
|
if (nl == NULL) break;
|
|
|
|
image_list = nl;
|
|
|
|
max_images += 10;
|
|
|
|
}
|
2019-08-19 21:46:53 +08:00
|
|
|
image_list[n_images++] = image;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else /* Skip an image */
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2019-08-19 21:46:53 +08:00
|
|
|
image = NULL;
|
2006-05-08 20:23:32 +08:00
|
|
|
if (! skip_ps (ifp))
|
2004-11-19 05:10:12 +08:00
|
|
|
break;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
2022-05-16 22:31:50 +08:00
|
|
|
ps_close (ifp, tmp_filename);
|
|
|
|
|
|
|
|
/* EPS are now imported using pngalpha, so they can be converted
|
|
|
|
* to a layer with gimp_layer_new_from_pixbuf () and exported at
|
|
|
|
* this part of the loading process
|
|
|
|
*/
|
|
|
|
if (is_epsf)
|
|
|
|
{
|
|
|
|
GimpLayer *layer;
|
|
|
|
|
|
|
|
image = gimp_image_new (urx, ury, GIMP_RGB);
|
|
|
|
|
|
|
|
gimp_image_undo_disable (image);
|
|
|
|
|
|
|
|
gimp_image_set_file (image, file);
|
|
|
|
gimp_image_set_resolution (image,
|
|
|
|
plvals.resolution,
|
|
|
|
plvals.resolution);
|
|
|
|
|
|
|
|
layer = gimp_layer_new_from_pixbuf (image, _("Rendered EPS"), pixbuf,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image),
|
|
|
|
0.0, 1.0);
|
|
|
|
gimp_image_insert_layer (image, layer, NULL, 0);
|
|
|
|
|
|
|
|
gimp_image_undo_enable (image);
|
|
|
|
|
|
|
|
g_free (image_list);
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
if (ps_pagemode == GIMP_PAGE_SELECTOR_TARGET_LAYERS)
|
|
|
|
{
|
|
|
|
for (k = 0; k < n_images; k++)
|
|
|
|
{
|
|
|
|
if (k == 0)
|
|
|
|
{
|
2019-09-12 03:48:34 +08:00
|
|
|
GFile *new_file;
|
|
|
|
gchar *uri;
|
|
|
|
gchar *new_uri;
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
image = image_list[0];
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
|
|
|
|
new_uri = g_strdup_printf (_("%s-pages"), uri);
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
new_file = g_file_new_for_uri (new_uri);
|
|
|
|
g_free (new_uri);
|
|
|
|
|
|
|
|
gimp_image_set_file (image, new_file);
|
|
|
|
g_object_unref (new_file);
|
2005-08-15 16:48:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpLayer *current_layer;
|
|
|
|
GimpDrawable *tmp_drawable;
|
2019-09-12 03:48:34 +08:00
|
|
|
gchar *name;
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
tmp_drawable = gimp_image_get_active_drawable (image_list[k]);
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
name = gimp_item_get_name (GIMP_ITEM (tmp_drawable));
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
current_layer = gimp_layer_new_from_drawable (tmp_drawable, image);
|
|
|
|
gimp_item_set_name (GIMP_ITEM (current_layer), name);
|
|
|
|
gimp_image_insert_layer (image, current_layer, NULL, -1);
|
2005-08-15 16:48:45 +08:00
|
|
|
gimp_image_delete (image_list[k]);
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
gimp_image_undo_enable (image);
|
2005-08-15 16:48:45 +08:00
|
|
|
}
|
|
|
|
else
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2005-08-15 16:48:45 +08:00
|
|
|
/* Display images in reverse order.
|
|
|
|
* The last will be displayed by GIMP itself
|
|
|
|
*/
|
|
|
|
for (k = n_images - 1; k >= 0; k--)
|
|
|
|
{
|
|
|
|
gimp_image_undo_enable (image_list[k]);
|
|
|
|
gimp_image_clean_all (image_list[k]);
|
|
|
|
|
|
|
|
if (l_run_mode != GIMP_RUN_NONINTERACTIVE && k > 0)
|
|
|
|
gimp_display_new (image_list[k]);
|
|
|
|
}
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
image = (n_images > 0) ? image_list[0] : NULL;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (image_list);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
return image;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
2019-08-19 21:46:53 +08:00
|
|
|
save_image (GFile *file,
|
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
GOutputStream *output;
|
2018-11-27 19:27:20 +08:00
|
|
|
GCancellable *cancellable;
|
2014-10-27 01:54:42 +08:00
|
|
|
GimpImageType drawable_type;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2016-02-16 09:35:43 +08:00
|
|
|
/* Make sure we're not exporting an image with an alpha channel */
|
2019-08-19 21:46:53 +08:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2008-08-20 22:00:44 +08:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
2016-02-16 09:35:43 +08:00
|
|
|
_("PostScript export cannot handle images with alpha channels"));
|
2000-01-26 01:46:56 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
switch (drawable_type)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
case GIMP_RGB_IMAGE:
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
default:
|
2014-10-27 01:54:42 +08:00
|
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
|
|
|
_("Cannot operate on unknown image types."));
|
2004-11-19 05:10:12 +08:00
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2016-02-16 09:35:43 +08:00
|
|
|
gimp_progress_init_printf (_("Exporting '%s'"),
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_file_get_utf8_name (file));
|
2014-07-23 22:39:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
output = G_OUTPUT_STREAM (g_file_replace (file,
|
|
|
|
NULL, FALSE, G_FILE_CREATE_NONE,
|
|
|
|
NULL, error));
|
|
|
|
if (output)
|
|
|
|
{
|
|
|
|
GOutputStream *buffered;
|
|
|
|
|
|
|
|
buffered = g_buffered_output_stream_new (output);
|
|
|
|
g_object_unref (output);
|
|
|
|
|
|
|
|
output = buffered;
|
|
|
|
}
|
|
|
|
else
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2004-11-19 05:10:12 +08:00
|
|
|
return FALSE;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! save_ps_header (output, file, error))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2011-10-10 12:26:32 +08:00
|
|
|
switch (drawable_type)
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_index (output, image, drawable, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
2011-10-10 12:26:32 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-10-10 12:26:32 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_gray (output, image, drawable, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
2011-10-10 12:26:32 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-10-10 12:26:32 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_rgb (output, image, drawable, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
2011-10-10 12:26:32 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-10-10 12:26:32 +08:00
|
|
|
default:
|
2014-10-27 01:54:42 +08:00
|
|
|
g_return_val_if_reached (FALSE);
|
2011-10-10 12:26:32 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! save_ps_trailer (output, error))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! g_output_stream_close (output, NULL, error))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
g_object_unref (output);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
2018-11-27 19:27:20 +08:00
|
|
|
cancellable = g_cancellable_new ();
|
|
|
|
g_cancellable_cancel (cancellable);
|
|
|
|
g_output_stream_close (output, cancellable, NULL);
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
g_object_unref (output);
|
2018-11-27 19:27:20 +08:00
|
|
|
g_object_unref (cancellable);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check (and correct) the load values plvals */
|
|
|
|
static void
|
|
|
|
check_load_vals (void)
|
|
|
|
{
|
2014-02-22 16:40:49 +08:00
|
|
|
if (plvals.resolution < MIN_RESOLUTION)
|
|
|
|
plvals.resolution = MIN_RESOLUTION;
|
|
|
|
else if (plvals.resolution > MAX_RESOLUTION)
|
|
|
|
plvals.resolution = MAX_RESOLUTION;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
if (plvals.width < 2)
|
|
|
|
plvals.width = 2;
|
|
|
|
if (plvals.height < 2)
|
|
|
|
plvals.height = 2;
|
1997-11-25 06:05:25 +08:00
|
|
|
plvals.use_bbox = (plvals.use_bbox != 0);
|
|
|
|
if (plvals.pages[0] == '\0')
|
2019-08-15 05:52:38 +08:00
|
|
|
g_strlcpy (plvals.pages, "1-99", sizeof (plvals.pages));
|
1997-11-25 06:05:25 +08:00
|
|
|
if ((plvals.pnm_type < 4) || (plvals.pnm_type > 7))
|
|
|
|
plvals.pnm_type = 6;
|
|
|
|
if ( (plvals.textalpha != 1) && (plvals.textalpha != 2)
|
|
|
|
&& (plvals.textalpha != 4))
|
|
|
|
plvals.textalpha = 1;
|
|
|
|
if ( (plvals.graphicsalpha != 1) && (plvals.graphicsalpha != 2)
|
|
|
|
&& (plvals.graphicsalpha != 4))
|
|
|
|
plvals.graphicsalpha = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check (and correct) the save values psvals */
|
|
|
|
static void
|
|
|
|
check_save_vals (void)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
|
|
|
int i;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
i = psvals.rotate;
|
|
|
|
if ((i != 0) && (i != 90) && (i != 180) && (i != 270))
|
|
|
|
psvals.rotate = 90;
|
|
|
|
if (psvals.preview_size <= 0)
|
|
|
|
psvals.preview = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2019-08-18 23:04:53 +08:00
|
|
|
static void
|
|
|
|
ps_set_save_size (PSSaveVals *vals,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image)
|
2019-08-18 23:04:53 +08:00
|
|
|
{
|
|
|
|
gdouble xres, yres, factor, iw, ih;
|
|
|
|
guint width, height;
|
|
|
|
GimpUnit unit;
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
gimp_image_get_resolution (image, &xres, &yres);
|
2019-08-18 23:04:53 +08:00
|
|
|
|
|
|
|
if ((xres < 1e-5) || (yres < 1e-5))
|
|
|
|
xres = yres = 72.0;
|
|
|
|
|
|
|
|
/* Calculate size of image in inches */
|
2021-04-06 06:47:07 +08:00
|
|
|
width = gimp_image_get_width (image);
|
|
|
|
height = gimp_image_get_height (image);
|
2019-08-18 23:04:53 +08:00
|
|
|
iw = width / xres;
|
|
|
|
ih = height / yres;
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
unit = gimp_image_get_unit (image);
|
2019-08-18 23:04:53 +08:00
|
|
|
factor = gimp_unit_get_factor (unit);
|
|
|
|
|
|
|
|
if (factor == 0.0254 ||
|
|
|
|
factor == 0.254 ||
|
|
|
|
factor == 2.54 ||
|
|
|
|
factor == 25.4)
|
|
|
|
{
|
|
|
|
vals->unit_mm = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vals->unit_mm)
|
|
|
|
{
|
|
|
|
iw *= 25.4;
|
|
|
|
ih *= 25.4;
|
|
|
|
}
|
|
|
|
|
|
|
|
vals->width = iw;
|
|
|
|
vals->height = ih;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Check if a page is in a given list */
|
|
|
|
static gint
|
2000-01-26 01:46:56 +08:00
|
|
|
page_in_list (gchar *list,
|
|
|
|
guint page_num)
|
|
|
|
{
|
|
|
|
char tmplist[STR_LENGTH], *c0, *c1;
|
|
|
|
int state, start_num, end_num;
|
1997-11-25 06:05:25 +08:00
|
|
|
#define READ_STARTNUM 0
|
|
|
|
#define READ_ENDNUM 1
|
|
|
|
#define CHK_LIST(a,b,c) {int low=(a),high=(b),swp; \
|
|
|
|
if ((low>0) && (high>0)) { \
|
|
|
|
if (low>high) {swp=low; low=high; high=swp;} \
|
|
|
|
if ((low<=(c))&&(high>=(c))) return (1); } }
|
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
if ((list == NULL) || (*list == '\0'))
|
|
|
|
return 1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-15 05:52:38 +08:00
|
|
|
g_strlcpy (tmplist, list, STR_LENGTH);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
c0 = c1 = tmplist;
|
|
|
|
while (*c1) /* Remove all whitespace and break on unsupported characters */
|
|
|
|
{
|
|
|
|
if ((*c1 >= '0') && (*c1 <= '9'))
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else if ((*c1 == '-') || (*c1 == ','))
|
2013-01-27 23:52:38 +08:00
|
|
|
{ /* Try to remove double occurrences of these characters */
|
2006-05-08 20:23:32 +08:00
|
|
|
if (c0 == tmplist)
|
|
|
|
{
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*(c0-1) != *c1)
|
|
|
|
*(c0++) = *c1;
|
|
|
|
}
|
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
c1++;
|
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
|
|
|
if (c0 == tmplist)
|
|
|
|
return 1;
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
*c0 = '\0';
|
|
|
|
|
|
|
|
/* Now we have a comma separated list like 1-4-1,-3,1- */
|
|
|
|
|
|
|
|
start_num = end_num = -1;
|
|
|
|
state = READ_STARTNUM;
|
|
|
|
for (c0 = tmplist; *c0 != '\0'; c0++)
|
|
|
|
{
|
|
|
|
switch (state)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
case READ_STARTNUM:
|
|
|
|
if (*c0 == ',')
|
|
|
|
{
|
|
|
|
if ((start_num > 0) && (start_num == (int)page_num))
|
2004-11-19 05:10:12 +08:00
|
|
|
return -1;
|
2006-05-08 20:23:32 +08:00
|
|
|
start_num = -1;
|
|
|
|
}
|
|
|
|
else if (*c0 == '-')
|
|
|
|
{
|
|
|
|
if (start_num < 0) start_num = 1;
|
|
|
|
state = READ_ENDNUM;
|
|
|
|
}
|
|
|
|
else /* '0' - '9' */
|
|
|
|
{
|
|
|
|
if (start_num < 0) start_num = 0;
|
|
|
|
start_num *= 10;
|
|
|
|
start_num += *c0 - '0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_ENDNUM:
|
|
|
|
if (*c0 == ',')
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 9999;
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
start_num = end_num = -1;
|
|
|
|
state = READ_STARTNUM;
|
|
|
|
}
|
|
|
|
else if (*c0 == '-')
|
|
|
|
{
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
start_num = end_num;
|
|
|
|
end_num = -1;
|
|
|
|
}
|
|
|
|
else /* '0' - '9' */
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 0;
|
|
|
|
end_num *= 10;
|
|
|
|
end_num += *c0 - '0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
if (state == READ_STARTNUM)
|
|
|
|
{
|
|
|
|
if (start_num > 0)
|
2006-05-08 20:23:32 +08:00
|
|
|
return (start_num == (int) page_num);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (end_num < 0) end_num = 9999;
|
|
|
|
CHK_LIST (start_num, end_num, (int)page_num);
|
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
|
|
|
return 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
#undef CHK_LIST
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-21 07:26:11 +08:00
|
|
|
/* A function like fgets, but treats single CR-character as line break. */
|
|
|
|
/* As a line break the newline-character is returned. */
|
|
|
|
static char *psfgets (char *s, int size, FILE *stream)
|
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
char *sptr = s;
|
2000-08-21 07:26:11 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
if (size <= 0)
|
|
|
|
return NULL;
|
2000-08-21 07:26:11 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
if (size == 1)
|
|
|
|
{
|
|
|
|
*s = '\0';
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = getc (stream);
|
|
|
|
if (c == EOF)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* At this point we have space in sptr for at least two characters */
|
|
|
|
if (c == '\n') /* Got end of line (UNIX line end) ? */
|
|
|
|
{
|
|
|
|
*(sptr++) = '\n';
|
|
|
|
break;
|
|
|
|
}
|
2018-05-13 00:13:12 +08:00
|
|
|
else if (c == '\r') /* Got a carriage return. Check next character */
|
2004-11-19 05:10:12 +08:00
|
|
|
{
|
|
|
|
c = getc (stream);
|
|
|
|
if ((c == EOF) || (c == '\n')) /* EOF or DOS line end ? */
|
|
|
|
{
|
|
|
|
*(sptr++) = '\n'; /* Return UNIX line end */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else /* Single carriage return. Return UNIX line end. */
|
|
|
|
{
|
|
|
|
ungetc (c, stream); /* Save the extra character */
|
|
|
|
*(sptr++) = '\n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* no line end character */
|
|
|
|
{
|
|
|
|
*(sptr++) = (char)c;
|
|
|
|
size--;
|
|
|
|
}
|
|
|
|
if (size == 1)
|
|
|
|
break; /* Only space for the nul-character ? */
|
|
|
|
|
|
|
|
c = getc (stream);
|
|
|
|
if (c == EOF)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*sptr = '\0';
|
|
|
|
|
|
|
|
return s;
|
2000-08-21 07:26:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Get the BoundingBox of a PostScript file. On success, 0 is returned. */
|
|
|
|
/* On failure, -1 is returned. */
|
|
|
|
static gint
|
2019-09-12 03:48:34 +08:00
|
|
|
get_bbox (GFile *file,
|
|
|
|
gint *x0,
|
|
|
|
gint *y0,
|
|
|
|
gint *x1,
|
|
|
|
gint *y1)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2019-09-12 03:48:34 +08:00
|
|
|
char line[1024], *src;
|
|
|
|
FILE *ifp;
|
|
|
|
int retval = -1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2021-10-02 00:56:12 +08:00
|
|
|
ifp = g_fopen (g_file_peek_path (file), "rb");
|
2019-09-12 03:48:34 +08:00
|
|
|
|
|
|
|
if (! ifp)
|
2004-11-19 05:10:12 +08:00
|
|
|
return -1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
2000-08-21 07:26:11 +08:00
|
|
|
if (psfgets (line, sizeof (line)-1, ifp) == NULL) break;
|
2000-01-26 01:46:56 +08:00
|
|
|
if ((line[0] != '%') || (line[1] != '%')) continue;
|
|
|
|
src = &(line[2]);
|
|
|
|
while ((*src == ' ') || (*src == '\t')) src++;
|
|
|
|
if (strncmp (src, "BoundingBox", 11) != 0) continue;
|
|
|
|
src += 11;
|
|
|
|
while ((*src == ' ') || (*src == '\t') || (*src == ':')) src++;
|
|
|
|
if (strncmp (src, "(atend)", 7) == 0) continue;
|
|
|
|
if (sscanf (src, "%d%d%d%d", x0, y0, x1, y1) == 4)
|
2006-05-08 20:23:32 +08:00
|
|
|
retval = 0;
|
2000-01-26 01:46:56 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fclose (ifp);
|
2004-11-19 05:10:12 +08:00
|
|
|
|
|
|
|
return retval;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the PostScript file. On failure, NULL is returned. */
|
|
|
|
/* The filepointer returned will give a PNM-file generated */
|
|
|
|
/* by the PostScript-interpreter. */
|
|
|
|
static FILE *
|
2019-09-12 03:48:34 +08:00
|
|
|
ps_open (GFile *file,
|
1997-11-25 06:05:25 +08:00
|
|
|
const PSLoadVals *loadopt,
|
2000-01-26 01:46:56 +08:00
|
|
|
gint *llx,
|
|
|
|
gint *lly,
|
|
|
|
gint *urx,
|
2000-03-11 01:27:25 +08:00
|
|
|
gint *ury,
|
2022-05-16 22:31:50 +08:00
|
|
|
gboolean *is_epsf,
|
|
|
|
gchar **tmp_filename)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2021-10-13 05:17:38 +08:00
|
|
|
const gchar *filename;
|
2007-05-29 23:29:37 +08:00
|
|
|
const gchar *driver;
|
|
|
|
GPtrArray *cmdA;
|
|
|
|
gchar **pcmdA;
|
|
|
|
FILE *fd_popen = NULL;
|
|
|
|
FILE *eps_file;
|
|
|
|
gint width, height;
|
|
|
|
gint resolution;
|
|
|
|
gint x0, y0, x1, y1;
|
|
|
|
gint offx = 0;
|
|
|
|
gint offy = 0;
|
|
|
|
gboolean is_pdf;
|
|
|
|
gboolean maybe_epsf = FALSE;
|
2012-01-22 12:26:08 +08:00
|
|
|
int code;
|
2019-07-09 21:36:13 +08:00
|
|
|
void *instance = NULL;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
resolution = loadopt->resolution;
|
|
|
|
*llx = *lly = 0;
|
|
|
|
width = loadopt->width;
|
|
|
|
height = loadopt->height;
|
2004-01-26 07:46:24 +08:00
|
|
|
*urx = width - 1;
|
|
|
|
*ury = height - 1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2013-01-27 23:52:38 +08:00
|
|
|
/* Check if the file is a PDF. For PDF, we can't set geometry */
|
2007-05-29 23:29:37 +08:00
|
|
|
is_pdf = FALSE;
|
2004-01-26 07:46:24 +08:00
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
/* Check if it is a EPS-file */
|
2007-05-29 23:29:37 +08:00
|
|
|
*is_epsf = FALSE;
|
2004-01-26 07:46:24 +08:00
|
|
|
|
2021-08-08 05:22:27 +08:00
|
|
|
filename = gimp_file_get_utf8_name (file);
|
2019-09-12 03:48:34 +08:00
|
|
|
|
2005-03-04 23:12:29 +08:00
|
|
|
eps_file = g_fopen (filename, "rb");
|
2004-01-26 07:46:24 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
if (eps_file)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2007-05-29 23:29:37 +08:00
|
|
|
gchar hdr[512];
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2004-01-26 07:46:24 +08:00
|
|
|
fread (hdr, 1, sizeof(hdr), eps_file);
|
2000-01-26 01:46:56 +08:00
|
|
|
is_pdf = (strncmp (hdr, "%PDF", 4) == 0);
|
2000-03-11 01:27:25 +08:00
|
|
|
|
|
|
|
if (!is_pdf) /* Check for EPSF */
|
2004-01-26 07:46:24 +08:00
|
|
|
{
|
|
|
|
char *adobe, *epsf;
|
|
|
|
int ds = 0;
|
|
|
|
static unsigned char doseps[5] = { 0xc5, 0xd0, 0xd3, 0xc6, 0 };
|
|
|
|
|
|
|
|
hdr[sizeof(hdr)-1] = '\0';
|
|
|
|
adobe = strstr (hdr, "PS-Adobe-");
|
|
|
|
epsf = strstr (hdr, "EPSF-");
|
|
|
|
|
|
|
|
if ((adobe != NULL) && (epsf != NULL))
|
|
|
|
ds = epsf - adobe;
|
|
|
|
|
|
|
|
*is_epsf = ((ds >= 11) && (ds <= 15));
|
|
|
|
|
|
|
|
/* Illustrator uses negative values in BoundingBox without marking */
|
|
|
|
/* files as EPSF. Try to handle that. */
|
|
|
|
maybe_epsf =
|
|
|
|
(strstr (hdr, "%%Creator: Adobe Illustrator(R) 8.0") != 0);
|
|
|
|
|
|
|
|
/* Check DOS EPS binary file */
|
|
|
|
if ((!*is_epsf) && (strncmp (hdr, (char *)doseps, 4) == 0))
|
|
|
|
*is_epsf = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose (eps_file);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((!is_pdf) && (loadopt->use_bbox)) /* Try the BoundingBox ? */
|
|
|
|
{
|
2019-09-12 03:48:34 +08:00
|
|
|
if (get_bbox (file, &x0, &y0, &x1, &y1) == 0)
|
2000-03-26 06:19:17 +08:00
|
|
|
{
|
2002-05-15 04:04:29 +08:00
|
|
|
if (maybe_epsf && ((x0 < 0) || (y0 < 0)))
|
|
|
|
*is_epsf = 1;
|
|
|
|
|
2000-03-26 06:19:17 +08:00
|
|
|
if (*is_epsf) /* Handle negative BoundingBox for EPSF */
|
|
|
|
{
|
|
|
|
offx = -x0; x1 += offx; x0 += offx;
|
|
|
|
offy = -y0; y1 += offy; y0 += offy;
|
|
|
|
}
|
|
|
|
if ((x0 >= 0) && (y0 >= 0) && (x1 > x0) && (y1 > y0))
|
|
|
|
{
|
2002-10-08 18:53:10 +08:00
|
|
|
*llx = (int)((x0/72.0) * resolution + 0.0001);
|
|
|
|
*lly = (int)((y0/72.0) * resolution + 0.0001);
|
2004-09-19 18:54:48 +08:00
|
|
|
/* Use upper bbox values as image size */
|
|
|
|
width = (int)((x1/72.0) * resolution + 0.5);
|
|
|
|
height = (int)((y1/72.0) * resolution + 0.5);
|
|
|
|
/* Pixel coordinates must be one less */
|
|
|
|
*urx = width - 1;
|
|
|
|
*ury = height - 1;
|
|
|
|
if (*urx < *llx) *urx = *llx;
|
|
|
|
if (*ury < *lly) *ury = *lly;
|
2000-03-26 06:19:17 +08:00
|
|
|
}
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2004-01-26 07:46:24 +08:00
|
|
|
|
2007-05-29 23:29:37 +08:00
|
|
|
switch (loadopt->pnm_type)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
driver = "pbmraw";
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
driver = "pgmraw";
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
driver = "pnmraw";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
driver = "ppmraw";
|
|
|
|
break;
|
|
|
|
}
|
1999-06-21 08:23:55 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
/* For instance, the Win32 port of ghostscript doesn't work correctly when
|
|
|
|
* using standard output as output file.
|
|
|
|
* Thus, use a real output file.
|
|
|
|
*/
|
2022-05-16 22:31:50 +08:00
|
|
|
if (*is_epsf)
|
|
|
|
{
|
|
|
|
driver = "pngalpha";
|
|
|
|
*tmp_filename = g_file_get_path (gimp_temp_file ("png"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tmp_filename = g_file_get_path (gimp_temp_file ("pnm"));
|
|
|
|
}
|
2003-03-22 09:12:48 +08:00
|
|
|
|
2004-01-26 07:46:24 +08:00
|
|
|
/* Build command array */
|
|
|
|
cmdA = g_ptr_array_new ();
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2012-01-22 12:26:08 +08:00
|
|
|
g_ptr_array_add (cmdA, g_strdup (g_get_prgname ()));
|
2004-01-26 07:46:24 +08:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-sDEVICE=%s", driver));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-r%d", resolution));
|
|
|
|
|
2005-04-21 18:46:52 +08:00
|
|
|
if (is_pdf)
|
|
|
|
{
|
|
|
|
/* Acrobat Reader honors CropBox over MediaBox, so let's match that
|
|
|
|
* behavior.
|
|
|
|
*/
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dUseCropBox"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* For PDF, we can't set geometry */
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-g%dx%d", width, height));
|
|
|
|
}
|
2004-01-26 07:46:24 +08:00
|
|
|
|
|
|
|
/* Antialiasing not available for PBM-device */
|
|
|
|
if ((loadopt->pnm_type != 4) && (loadopt->textalpha != 1))
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-dTextAlphaBits=%d",
|
|
|
|
loadopt->textalpha));
|
|
|
|
if ((loadopt->pnm_type != 4) && (loadopt->graphicsalpha != 1))
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-dGraphicsAlphaBits=%d",
|
|
|
|
loadopt->graphicsalpha));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-q"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dBATCH"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dNOPAUSE"));
|
|
|
|
|
|
|
|
/* If no additional options specified, use at least -dSAFER */
|
2005-03-04 23:12:29 +08:00
|
|
|
if (g_getenv ("GS_OPTIONS") == NULL)
|
2004-01-26 07:46:24 +08:00
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-dSAFER"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-01-26 07:46:24 +08:00
|
|
|
/* Output file name */
|
2022-05-16 22:31:50 +08:00
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("-sOutputFile=%s", *tmp_filename));
|
2000-03-26 06:19:17 +08:00
|
|
|
|
|
|
|
/* Offset command for gs to get image part with negative x/y-coord. */
|
|
|
|
if ((offx != 0) || (offy != 0))
|
2004-01-26 07:46:24 +08:00
|
|
|
{
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offx));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup_printf ("%d", offy));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("translate"));
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-01-26 07:46:24 +08:00
|
|
|
/* input file name */
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-f"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup (filename));
|
|
|
|
|
|
|
|
if (*is_epsf)
|
|
|
|
{
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("showpage"));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("-c"));
|
|
|
|
g_ptr_array_add (cmdA, g_strdup ("quit"));
|
|
|
|
g_ptr_array_add (cmdA, NULL);
|
|
|
|
|
|
|
|
pcmdA = (gchar **) cmdA->pdata;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#ifdef PS_DEBUG
|
2004-01-26 07:46:24 +08:00
|
|
|
{
|
|
|
|
gchar **p = pcmdA;
|
2012-01-22 12:26:08 +08:00
|
|
|
g_print ("Passing args (argc=%d):\n", cmdA->len - 1);
|
2004-01-26 07:46:24 +08:00
|
|
|
|
|
|
|
while (*p)
|
|
|
|
{
|
|
|
|
g_print ("%s\n", *p);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
1999-06-21 08:23:55 +08:00
|
|
|
|
2012-01-22 12:26:08 +08:00
|
|
|
code = gsapi_new_instance (&instance, NULL);
|
|
|
|
if (code == 0) {
|
2021-08-08 05:22:27 +08:00
|
|
|
code = gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8);
|
2012-01-22 12:26:08 +08:00
|
|
|
code = gsapi_init_with_args (instance, cmdA->len - 1, pcmdA);
|
|
|
|
code = gsapi_exit (instance);
|
|
|
|
gsapi_delete_instance (instance);
|
|
|
|
}
|
2004-01-26 07:46:24 +08:00
|
|
|
|
|
|
|
/* Don't care about exit status of ghostscript. */
|
|
|
|
/* Just try to read what it wrote. */
|
2004-10-06 21:18:37 +08:00
|
|
|
|
2022-05-16 22:31:50 +08:00
|
|
|
fd_popen = g_fopen (*tmp_filename, "rb");
|
2004-01-26 07:46:24 +08:00
|
|
|
|
|
|
|
g_ptr_array_free (cmdA, FALSE);
|
|
|
|
g_strfreev (pcmdA);
|
|
|
|
|
|
|
|
return fd_popen;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Close the PNM-File of the PostScript interpreter */
|
|
|
|
static void
|
2022-05-16 22:31:50 +08:00
|
|
|
ps_close (FILE *ifp, gchar *tmp_filename)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-21 08:23:55 +08:00
|
|
|
/* If a real outputfile was used, close the file and remove it. */
|
2000-01-26 01:46:56 +08:00
|
|
|
fclose (ifp);
|
2022-05-16 22:31:50 +08:00
|
|
|
g_unlink (tmp_filename);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the header of a raw PNM-file and return type (4-6) or -1 on failure */
|
|
|
|
static gint
|
|
|
|
read_pnmraw_type (FILE *ifp,
|
2000-01-26 01:46:56 +08:00
|
|
|
gint *width,
|
|
|
|
gint *height,
|
|
|
|
gint *maxval)
|
|
|
|
{
|
2013-05-15 02:52:38 +08:00
|
|
|
int frst, scnd, thrd;
|
2007-05-29 23:29:37 +08:00
|
|
|
gint pnmtype;
|
|
|
|
gchar line[1024];
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* GhostScript may write some informational messages infront of the header. */
|
|
|
|
/* We are just looking at a Px\n in the input stream. */
|
|
|
|
frst = getc (ifp);
|
|
|
|
scnd = getc (ifp);
|
|
|
|
thrd = getc (ifp);
|
|
|
|
for (;;)
|
|
|
|
{
|
2004-11-19 05:10:12 +08:00
|
|
|
if (thrd == EOF) return -1;
|
2012-01-22 12:26:08 +08:00
|
|
|
#ifdef G_OS_WIN32
|
2000-01-26 01:46:56 +08:00
|
|
|
if (thrd == '\r') thrd = getc (ifp);
|
1999-05-02 00:10:36 +08:00
|
|
|
#endif
|
2000-01-26 01:46:56 +08:00
|
|
|
if ((thrd == '\n') && (frst == 'P') && (scnd >= '1') && (scnd <= '6'))
|
2006-05-08 20:23:32 +08:00
|
|
|
break;
|
2000-01-26 01:46:56 +08:00
|
|
|
frst = scnd;
|
|
|
|
scnd = thrd;
|
|
|
|
thrd = getc (ifp);
|
|
|
|
}
|
|
|
|
pnmtype = scnd - '0';
|
2018-04-19 02:57:03 +08:00
|
|
|
/* We don't use the ASCII-versions */
|
2004-11-19 05:10:12 +08:00
|
|
|
if ((pnmtype >= 1) && (pnmtype <= 3))
|
|
|
|
return -1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* Read width/height */
|
|
|
|
for (;;)
|
|
|
|
{
|
2004-11-19 05:10:12 +08:00
|
|
|
if (fgets (line, sizeof (line)-1, ifp) == NULL)
|
|
|
|
return -1;
|
|
|
|
if (line[0] != '#')
|
|
|
|
break;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
if (sscanf (line, "%d%d", width, height) != 2)
|
|
|
|
return -1;
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
*maxval = 255;
|
|
|
|
|
|
|
|
if (pnmtype != 4) /* Read maxval */
|
|
|
|
{
|
|
|
|
for (;;)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
if (fgets (line, sizeof (line)-1, ifp) == NULL)
|
2004-11-19 05:10:12 +08:00
|
|
|
return -1;
|
2006-05-08 20:23:32 +08:00
|
|
|
if (line[0] != '#')
|
2004-11-19 05:10:12 +08:00
|
|
|
break;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
if (sscanf (line, "%d", maxval) != 1)
|
|
|
|
return -1;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
|
|
|
|
return pnmtype;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
/* Create an image. Sets layer, drawable and rgn. Returns image */
|
|
|
|
static GimpImage *
|
2019-09-12 03:48:34 +08:00
|
|
|
create_new_image (GFile *file,
|
2003-11-27 20:28:46 +08:00
|
|
|
guint pagenum,
|
|
|
|
guint width,
|
|
|
|
guint height,
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpImageBaseType type,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpLayer **layer)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image;
|
2003-11-27 20:28:46 +08:00
|
|
|
GimpImageType gdtype;
|
2019-09-12 03:48:34 +08:00
|
|
|
GFile *new_file;
|
|
|
|
gchar *uri;
|
|
|
|
gchar *new_uri;
|
2005-08-15 16:48:45 +08:00
|
|
|
gchar *tmp;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2013-05-13 20:29:17 +08:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GIMP_GRAY:
|
|
|
|
gdtype = GIMP_GRAY_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
gdtype = GIMP_INDEXED_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_RGB:
|
|
|
|
default:
|
|
|
|
gdtype = GIMP_RGB_IMAGE;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
image = gimp_image_new_with_precision (width, height, type,
|
|
|
|
GIMP_PRECISION_U8_NON_LINEAR);
|
|
|
|
gimp_image_undo_disable (image);
|
2003-11-27 20:28:46 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
uri = g_file_get_uri (file);
|
|
|
|
|
|
|
|
new_uri = g_strdup_printf ("%s-%d", uri, pagenum);
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
new_file = g_file_new_for_uri (new_uri);
|
|
|
|
g_free (new_uri);
|
|
|
|
|
|
|
|
gimp_image_set_file (image, new_file);
|
|
|
|
g_object_unref (new_file);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
tmp = g_strdup_printf (_("Page %d"), pagenum);
|
2019-08-19 21:46:53 +08:00
|
|
|
*layer = gimp_layer_new (image, tmp, width, height,
|
|
|
|
gdtype,
|
|
|
|
100,
|
|
|
|
gimp_image_get_default_new_layer_mode (image));
|
2005-08-15 16:48:45 +08:00
|
|
|
g_free (tmp);
|
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
gimp_image_insert_layer (image, *layer, NULL, 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
return image;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Skip PNM image generated from PostScript file. */
|
2004-11-19 05:10:12 +08:00
|
|
|
/* Return TRUE on success, FALSE otherwise. */
|
|
|
|
static gboolean
|
1997-11-25 06:05:25 +08:00
|
|
|
skip_ps (FILE *ifp)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2004-11-19 05:10:12 +08:00
|
|
|
guchar buf[8192];
|
|
|
|
gsize len;
|
|
|
|
gint pnmtype, width, height, maxval, bpl;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (pnmtype == 4) /* Portable bitmap */
|
2004-11-19 05:10:12 +08:00
|
|
|
bpl = (width + 7) / 8;
|
2000-01-26 01:46:56 +08:00
|
|
|
else if (pnmtype == 5)
|
|
|
|
bpl = width;
|
|
|
|
else if (pnmtype == 6)
|
2004-11-19 05:10:12 +08:00
|
|
|
bpl = width * 3;
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2004-11-19 05:10:12 +08:00
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
len = bpl * height;
|
|
|
|
while (len)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2004-11-19 21:34:07 +08:00
|
|
|
gsize bytes = fread (buf, 1, MIN (len, sizeof (buf)), ifp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
if (bytes < MIN (len, sizeof (buf)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
len -= bytes;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
return TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Load PNM image generated from PostScript file */
|
2019-08-19 21:46:53 +08:00
|
|
|
static GimpImage *
|
2019-09-12 03:48:34 +08:00
|
|
|
load_ps (GFile *file,
|
|
|
|
guint pagenum,
|
|
|
|
FILE *ifp,
|
|
|
|
gint llx,
|
|
|
|
gint lly,
|
|
|
|
gint urx,
|
|
|
|
gint ury)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2013-05-15 02:52:38 +08:00
|
|
|
guchar *dest;
|
2000-01-26 01:46:56 +08:00
|
|
|
guchar *data, *bitline = NULL, *byteline = NULL, *byteptr, *temp;
|
2019-09-12 03:48:34 +08:00
|
|
|
guchar bit2byte[256*8];
|
|
|
|
int width, height, tile_height, scan_lines, total_scan_lines;
|
|
|
|
int image_width, image_height;
|
|
|
|
int skip_left, skip_bottom;
|
|
|
|
int i, j, pnmtype, maxval, bpp, nread;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpImageBaseType imagetype;
|
2019-09-12 03:48:34 +08:00
|
|
|
GimpImage *image;
|
|
|
|
GimpLayer *layer;
|
2013-05-13 20:31:35 +08:00
|
|
|
GeglBuffer *buffer = NULL;
|
2019-09-12 03:48:34 +08:00
|
|
|
int err = 0;
|
|
|
|
int e;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
pnmtype = read_pnmraw_type (ifp, &width, &height, &maxval);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if ((width == urx+1) && (height == ury+1)) /* gs respected BoundingBox ? */
|
|
|
|
{
|
|
|
|
skip_left = llx; skip_bottom = lly;
|
|
|
|
image_width = width - skip_left;
|
|
|
|
image_height = height - skip_bottom;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skip_left = skip_bottom = 0;
|
|
|
|
image_width = width;
|
|
|
|
image_height = height;
|
|
|
|
}
|
|
|
|
if (pnmtype == 4) /* Portable Bitmap */
|
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
imagetype = GIMP_INDEXED;
|
2000-01-26 01:46:56 +08:00
|
|
|
nread = (width+7)/8;
|
|
|
|
bpp = 1;
|
2007-05-29 23:29:37 +08:00
|
|
|
bitline = g_new (guchar, nread);
|
|
|
|
byteline = g_new (guchar, nread * 8);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* Get an array for mapping 8 bits in a byte to 8 bytes */
|
|
|
|
temp = bit2byte;
|
|
|
|
for (j = 0; j < 256; j++)
|
2006-05-08 20:23:32 +08:00
|
|
|
for (i = 7; i >= 0; i--)
|
|
|
|
*(temp++) = ((j & (1 << i)) != 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
else if (pnmtype == 5) /* Portable Greymap */
|
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
imagetype = GIMP_GRAY;
|
2000-01-26 01:46:56 +08:00
|
|
|
nread = width;
|
|
|
|
bpp = 1;
|
2007-05-29 23:29:37 +08:00
|
|
|
byteline = g_new (guchar, nread);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
else if (pnmtype == 6) /* Portable Pixmap */
|
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
imagetype = GIMP_RGB;
|
2000-01-26 01:46:56 +08:00
|
|
|
nread = width * 3;
|
|
|
|
bpp = 3;
|
2007-05-29 23:29:37 +08:00
|
|
|
byteline = g_new (guchar, nread);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2004-11-19 05:10:12 +08:00
|
|
|
else
|
2019-08-19 21:46:53 +08:00
|
|
|
return NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
image = create_new_image (file, pagenum,
|
2019-08-19 21:46:53 +08:00
|
|
|
image_width, image_height, imagetype,
|
|
|
|
&layer);
|
|
|
|
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
data = g_malloc (tile_height * image_width * bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
dest = data;
|
|
|
|
total_scan_lines = scan_lines = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (pnmtype == 4) /* Read bitimage ? Must be mapped to indexed */
|
2007-05-29 23:29:37 +08:00
|
|
|
{
|
|
|
|
const guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
gimp_image_set_colormap (image, BWColorMap, 2);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-05-29 23:29:37 +08:00
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
e = (fread (bitline, 1, nread, ifp) != nread);
|
2013-05-13 20:31:35 +08:00
|
|
|
if (total_scan_lines >= image_height)
|
|
|
|
continue;
|
2007-05-29 23:29:37 +08:00
|
|
|
err |= e;
|
2013-05-13 20:31:35 +08:00
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 20:23:32 +08:00
|
|
|
|
2007-05-29 23:29:37 +08:00
|
|
|
j = width; /* Map 1 byte of bitimage to 8 bytes of indexed image */
|
|
|
|
temp = bitline;
|
|
|
|
byteptr = byteline;
|
|
|
|
while (j >= 8)
|
|
|
|
{
|
|
|
|
memcpy (byteptr, bit2byte + *(temp++)*8, 8);
|
|
|
|
byteptr += 8;
|
|
|
|
j -= 8;
|
|
|
|
}
|
|
|
|
if (j > 0)
|
|
|
|
memcpy (byteptr, bit2byte + *temp*8, j);
|
|
|
|
|
|
|
|
memcpy (dest, byteline+skip_left, image_width);
|
|
|
|
dest += image_width;
|
|
|
|
scan_lines++;
|
|
|
|
total_scan_lines++;
|
2006-05-08 20:23:32 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == image_height))
|
2007-05-29 23:29:37 +08:00
|
|
|
{
|
2013-05-13 20:31:35 +08:00
|
|
|
gegl_buffer_set (buffer,
|
|
|
|
GEGL_RECTANGLE (0, i-scan_lines+1,
|
|
|
|
image_width, scan_lines),
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
2007-05-29 23:29:37 +08:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
2013-05-13 20:31:35 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) image_height);
|
2013-05-13 20:31:35 +08:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
2007-05-29 23:29:37 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
else /* Read gray/rgb-image */
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
e = (fread (byteline, bpp, width, ifp) != width);
|
2013-05-13 20:31:35 +08:00
|
|
|
if (total_scan_lines >= image_height)
|
|
|
|
continue;
|
2006-05-08 20:23:32 +08:00
|
|
|
err |= e;
|
2013-05-13 20:31:35 +08:00
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 20:23:32 +08:00
|
|
|
|
|
|
|
memcpy (dest, byteline+skip_left*bpp, image_width*bpp);
|
|
|
|
dest += image_width*bpp;
|
|
|
|
scan_lines++;
|
|
|
|
total_scan_lines++;
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((scan_lines == tile_height) || ((i + 1) == image_height))
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2013-05-13 20:31:35 +08:00
|
|
|
gegl_buffer_set (buffer,
|
|
|
|
GEGL_RECTANGLE (0, i-scan_lines+1,
|
|
|
|
image_width, scan_lines),
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
data,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
2006-05-08 20:23:32 +08:00
|
|
|
scan_lines = 0;
|
|
|
|
dest = data;
|
|
|
|
}
|
2013-05-13 20:31:35 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) (i + 1) / (gdouble) image_height);
|
2013-05-13 20:31:35 +08:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
break;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
g_free (data);
|
2007-05-29 23:29:37 +08:00
|
|
|
g_free (byteline);
|
|
|
|
g_free (bitline);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
if (err)
|
|
|
|
g_message ("EOF encountered on reading");
|
|
|
|
|
2013-05-13 20:31:35 +08:00
|
|
|
g_object_unref (buffer);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
return (err ? NULL : image);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out the PostScript file header */
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_ps_header (GOutputStream *output,
|
|
|
|
GFile *file,
|
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
gchar *basename = g_path_get_basename (gimp_file_get_utf8_name (file));
|
2004-08-09 06:26:17 +08:00
|
|
|
time_t cutime = time (NULL);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error,
|
|
|
|
"%%!PS-Adobe-3.0%s\n", psvals.eps ? " EPSF-3.0" : ""))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
2017-03-22 00:45:50 +08:00
|
|
|
"%%%%Creator: GIMP PostScript file plug-in V %4.2f "
|
2019-08-18 23:04:53 +08:00
|
|
|
"by Peter Kirchgessner\n", VERSION))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%Title: %s\n"
|
|
|
|
"%%%%CreationDate: %s"
|
|
|
|
"%%%%DocumentData: Clean7Bit\n",
|
|
|
|
basename, ctime (&cutime)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (psvals.eps || (psvals.level > 1))
|
|
|
|
if (! print (output, error,"%%%%LanguageLevel: 2\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%%%%Pages: 1\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
g_free (basename);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
2004-08-09 06:26:17 +08:00
|
|
|
|
|
|
|
g_free (basename);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
return FALSE;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Write out transformation for image */
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_ps_setup (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
gint bpp,
|
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
gdouble x_offset, y_offset, x_size, y_size;
|
|
|
|
gdouble urx, ury;
|
|
|
|
gdouble width_inch, height_inch;
|
|
|
|
gdouble f1, f2, dx, dy;
|
|
|
|
gint xtrans, ytrans;
|
|
|
|
gint i_urx, i_ury;
|
|
|
|
gchar tmpbuf1[G_ASCII_DTOSTR_BUF_SIZE];
|
|
|
|
gchar tmpbuf2[G_ASCII_DTOSTR_BUF_SIZE];
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* initialize */
|
|
|
|
|
|
|
|
dx = 0.0;
|
|
|
|
dy = 0.0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
x_offset = psvals.x_offset;
|
|
|
|
y_offset = psvals.y_offset;
|
|
|
|
width_inch = fabs (psvals.width);
|
1997-11-25 06:05:25 +08:00
|
|
|
height_inch = fabs (psvals.height);
|
|
|
|
|
|
|
|
if (psvals.unit_mm)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
|
|
|
x_offset /= 25.4; y_offset /= 25.4;
|
|
|
|
width_inch /= 25.4; height_inch /= 25.4;
|
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (psvals.keep_ratio) /* Proportions to keep ? */
|
2000-01-26 01:46:56 +08:00
|
|
|
{ /* Fit the image into the allowed size */
|
|
|
|
f1 = width_inch / width;
|
|
|
|
f2 = height_inch / height;
|
|
|
|
if (f1 < f2)
|
2014-10-27 01:54:42 +08:00
|
|
|
height_inch = width_inch * (gdouble) height / (gdouble) width;
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
width_inch = fabs (height_inch) * (gdouble) width / (gdouble) height;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if ((psvals.rotate == 0) || (psvals.rotate == 180))
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
x_size = width_inch;
|
|
|
|
y_size = height_inch;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
y_size = width_inch;
|
|
|
|
x_size = height_inch;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-10-08 18:53:10 +08:00
|
|
|
/* Round up upper right corner only for non-integer values */
|
2014-10-27 01:54:42 +08:00
|
|
|
urx = (x_offset + x_size) * 72.0;
|
|
|
|
ury = (y_offset + y_size) * 72.0;
|
|
|
|
i_urx = (gint) urx;
|
|
|
|
i_ury = (gint) ury;
|
|
|
|
if (urx != (gdouble) i_urx) i_urx++; /* Check for non-integer value */
|
|
|
|
if (ury != (gdouble) i_ury) i_ury++;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BoundingBox: %d %d %d %d\n"
|
|
|
|
"%%%%EndComments\n",
|
|
|
|
(gint) (x_offset * 72.0), (gint) (y_offset * 72.0), i_urx, i_ury))
|
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1997-12-26 15:08:20 +08:00
|
|
|
if (psvals.preview && (psvals.preview_size > 0))
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_ps_preview (output, drawable, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
return FALSE;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-12-26 15:08:20 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BeginProlog\n"
|
|
|
|
"%% Use own dictionary to avoid conflicts\n"
|
|
|
|
"10 dict begin\n"
|
|
|
|
"%%%%EndProlog\n"
|
|
|
|
"%%%%Page: 1 1\n"
|
|
|
|
"%% Translate for offset\n"
|
|
|
|
"%s %s translate\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), x_offset * 72.0),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), y_offset * 72.0)))
|
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Calculate translation to startpoint of first scanline */
|
|
|
|
switch (psvals.rotate)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
case 0: dx = 0.0; dy = y_size * 72.0;
|
2000-01-26 01:46:56 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
case 90: dx = dy = 0.0;
|
2000-01-26 01:46:56 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
case 180: dx = x_size * 72.0; dy = 0.0;
|
2000-01-26 01:46:56 +08:00
|
|
|
break;
|
2014-10-27 01:54:42 +08:00
|
|
|
case 270: dx = x_size * 72.0; dy = y_size * 72.0;
|
2000-01-26 01:46:56 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if ((dx != 0.0) || (dy != 0.0))
|
2002-12-17 03:24:05 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error,
|
|
|
|
"%% Translate to begin of first scanline\n"
|
|
|
|
"%s %s translate\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), dx),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), dy)))
|
|
|
|
return FALSE;
|
2002-12-17 03:24:05 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (psvals.rotate)
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "%d rotate\n", (gint) psvals.rotate))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%s %s scale\n",
|
|
|
|
g_ascii_dtostr (tmpbuf1, sizeof (tmpbuf1), 72.0 * width_inch),
|
|
|
|
g_ascii_dtostr (tmpbuf2, sizeof (tmpbuf2), -72.0 * height_inch)))
|
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Write the PostScript procedures to read the image */
|
2000-01-23 06:26:20 +08:00
|
|
|
if (psvals.level <= 1)
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Variable to keep one line of raster data\n"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (bpp == 1)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"/scanline %d string def\n", (width + 7) / 8))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"/scanline %d %d mul string def\n", width, bpp / 8))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Image geometry\n%d %d %d\n"
|
|
|
|
"%% Transformation matrix\n",
|
|
|
|
width, height, (bpp == 1) ? 1 : 8))
|
|
|
|
return FALSE;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
xtrans = ytrans = 0;
|
2014-10-27 01:54:42 +08:00
|
|
|
if (psvals.width < 0.0) { width = -width; xtrans = -width; }
|
1997-11-25 06:05:25 +08:00
|
|
|
if (psvals.height < 0.0) { height = -height; ytrans = -height; }
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error,
|
|
|
|
"[ %d 0 0 %d %d %d ]\n", width, height, xtrans, ytrans))
|
|
|
|
return FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
save_ps_trailer (GOutputStream *output,
|
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
return print (output, error,
|
|
|
|
"%%%%Trailer\n"
|
|
|
|
"end\n%%%%EOF\n");
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2013-06-07 05:26:16 +08:00
|
|
|
/* Do a Floyd-Steinberg dithering on a grayscale scanline. */
|
1997-12-26 15:08:20 +08:00
|
|
|
/* linecount must keep the counter for the actual scanline (0, 1, 2, ...). */
|
|
|
|
/* If linecount is less than zero, all used memory is freed. */
|
|
|
|
|
|
|
|
static void
|
2006-08-29 21:32:22 +08:00
|
|
|
dither_grey (const guchar *grey,
|
|
|
|
guchar *bw,
|
|
|
|
gint npix,
|
|
|
|
gint linecount)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean do_init_arrays = TRUE;
|
|
|
|
static gint *fs_error = NULL;
|
|
|
|
static gint limit[1278];
|
|
|
|
static gint east_error[256];
|
|
|
|
static gint seast_error[256];
|
|
|
|
static gint south_error[256];
|
|
|
|
static gint swest_error[256];
|
2006-08-29 21:32:22 +08:00
|
|
|
|
2013-05-15 02:52:38 +08:00
|
|
|
const guchar *greyptr;
|
2014-10-27 01:54:42 +08:00
|
|
|
guchar *bwptr, mask;
|
|
|
|
gint *fse;
|
|
|
|
gint x, greyval, fse_inline;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
if (linecount <= 0)
|
|
|
|
{
|
2006-08-29 21:32:22 +08:00
|
|
|
g_free (fs_error);
|
|
|
|
|
|
|
|
if (linecount < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fs_error = g_new0 (gint, npix + 2);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* Initialize some arrays that speed up dithering */
|
|
|
|
if (do_init_arrays)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2006-08-29 21:32:22 +08:00
|
|
|
gint i;
|
|
|
|
|
|
|
|
do_init_arrays = FALSE;
|
|
|
|
|
|
|
|
for (i = 0, x = -511; x <= 766; i++, x++)
|
|
|
|
limit[i] = (x < 0) ? 0 : ((x > 255) ? 255 : x);
|
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
for (greyval = 0; greyval < 256; greyval++)
|
|
|
|
{
|
2006-08-29 21:32:22 +08:00
|
|
|
east_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 79) >> 8) : (((greyval - 255) * 79) >> 8);
|
|
|
|
seast_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 34) >> 8) : (((greyval - 255) * 34) >> 8);
|
|
|
|
south_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 56) >> 8) : (((greyval - 255) * 56) >> 8);
|
|
|
|
swest_error[greyval] = (greyval < 128) ?
|
|
|
|
((greyval * 12) >> 8) : (((greyval - 255) * 12) >> 8);
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
2006-08-29 21:32:22 +08:00
|
|
|
g_return_if_fail (fs_error != NULL);
|
|
|
|
|
|
|
|
memset (bw, 0, (npix + 7) / 8); /* Initialize with white */
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
greyptr = grey;
|
|
|
|
bwptr = bw;
|
|
|
|
mask = 0x80;
|
2006-08-29 21:32:22 +08:00
|
|
|
|
|
|
|
fse_inline = fs_error[1];
|
|
|
|
|
|
|
|
for (x = 0, fse = fs_error + 1; x < npix; x++, fse++)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2006-08-29 21:32:22 +08:00
|
|
|
greyval =
|
|
|
|
limit[*(greyptr++) + fse_inline + 512]; /* 0 <= greyval <= 255 */
|
|
|
|
|
|
|
|
if (greyval < 128)
|
|
|
|
*bwptr |= mask; /* Set a black pixel */
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
/* Error distribution */
|
|
|
|
fse_inline = east_error[greyval] + fse[1];
|
|
|
|
fse[1] = seast_error[greyval];
|
|
|
|
fse[0] += south_error[greyval];
|
|
|
|
fse[-1] += swest_error[greyval];
|
|
|
|
|
|
|
|
mask >>= 1; /* Get mask for next b/w-pixel */
|
2006-08-29 21:32:22 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (!mask)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
mask = 0x80;
|
|
|
|
bwptr++;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-12-26 15:08:20 +08:00
|
|
|
}
|
|
|
|
|
2012-09-11 00:22:12 +08:00
|
|
|
/* Write a device independent screen preview */
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_ps_preview (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2013-05-14 22:13:19 +08:00
|
|
|
GimpImageType drawable_type;
|
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
2014-10-27 01:54:42 +08:00
|
|
|
gint bpp;
|
|
|
|
guchar *bwptr, *greyptr;
|
|
|
|
gint width, height, x, y, nbsl, out_count;
|
|
|
|
gint nchar_pl = 72, src_y;
|
|
|
|
gdouble f1, f2;
|
|
|
|
guchar *grey, *bw, *src_row, *src_ptr;
|
|
|
|
guchar *cmap;
|
|
|
|
gint ncols, cind;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2013-05-14 22:13:19 +08:00
|
|
|
if (psvals.preview_size <= 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
return TRUE;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 22:13:19 +08:00
|
|
|
cmap = NULL;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
2013-05-14 22:13:19 +08:00
|
|
|
switch (drawable_type)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2013-05-14 22:13:19 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2019-08-19 21:46:53 +08:00
|
|
|
cmap = gimp_image_get_colormap (gimp_item_get_image (GIMP_ITEM (drawable)),
|
2013-05-14 22:13:19 +08:00
|
|
|
&ncols);
|
2019-08-19 21:46:53 +08:00
|
|
|
format = gimp_drawable_get_format (drawable);
|
2013-05-14 22:13:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RGB_IMAGE:
|
|
|
|
default:
|
|
|
|
format = babl_format ("R'G'B' u8");
|
|
|
|
break;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2013-05-14 22:13:19 +08:00
|
|
|
|
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
|
|
|
/* Calculate size of preview */
|
|
|
|
if ((width > psvals.preview_size) ||
|
|
|
|
(height > psvals.preview_size))
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
f1 = (gdouble) psvals.preview_size / (gdouble) width;
|
|
|
|
f2 = (gdouble) psvals.preview_size / (gdouble) height;
|
2007-05-29 23:29:37 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (f1 < f2)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
width = psvals.preview_size;
|
2013-05-14 22:13:19 +08:00
|
|
|
height *= f1;
|
|
|
|
if (height <= 0)
|
|
|
|
height = 1;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
height = psvals.preview_size;
|
2013-05-14 22:13:19 +08:00
|
|
|
width *= f1;
|
|
|
|
if (width <= 0)
|
|
|
|
width = 1;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
nbsl = (width + 7) / 8; /* Number of bytes per scanline in bitmap */
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
grey = g_new (guchar, width);
|
|
|
|
bw = g_new (guchar, nbsl);
|
2013-05-14 22:13:19 +08:00
|
|
|
src_row = g_new (guchar, gegl_buffer_get_width (buffer) * bpp);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error,
|
|
|
|
"%%%%BeginPreview: %d %d 1 %d\n",
|
|
|
|
width, height,
|
|
|
|
((nbsl * 2 + nchar_pl - 1) / nchar_pl) * height))
|
|
|
|
goto fail;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
for (y = 0; y < height; y++)
|
|
|
|
{
|
2013-05-14 22:13:19 +08:00
|
|
|
/* Get a scanline from the input image and scale it to the desired
|
|
|
|
width */
|
|
|
|
src_y = (y * gegl_buffer_get_height (buffer)) / height;
|
|
|
|
gegl_buffer_get (buffer,
|
|
|
|
GEGL_RECTANGLE (0, src_y,
|
|
|
|
gegl_buffer_get_width (buffer), 1),
|
|
|
|
1.0, format, src_row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
greyptr = grey;
|
2013-05-14 22:13:19 +08:00
|
|
|
if (bpp == 3) /* RGB-image */
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{ /* Convert to grey */
|
2013-05-14 22:13:19 +08:00
|
|
|
src_ptr = src_row + ((x * gegl_buffer_get_width (buffer)) / width) * 3;
|
2006-05-08 20:23:32 +08:00
|
|
|
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
|
|
|
|
}
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else if (cmap) /* Indexed image */
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{
|
2013-05-14 22:13:19 +08:00
|
|
|
src_ptr = src_row + ((x * gegl_buffer_get_width (buffer)) / width);
|
2013-06-07 05:26:16 +08:00
|
|
|
cind = *src_ptr; /* Get color index and convert to grey */
|
2006-05-08 20:23:32 +08:00
|
|
|
src_ptr = (cind >= ncols) ? cmap : (cmap + 3*cind);
|
|
|
|
*(greyptr++) = (3*src_ptr[0] + 6*src_ptr[1] + src_ptr[2]) / 10;
|
|
|
|
}
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else /* Grey image */
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
2013-05-14 22:13:19 +08:00
|
|
|
*(greyptr++) = *(src_row + ((x * gegl_buffer_get_width (buffer)) / width));
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2013-06-07 05:26:16 +08:00
|
|
|
/* Now we have a grayscale line for the desired width. */
|
2000-01-26 01:46:56 +08:00
|
|
|
/* Dither it to b/w */
|
|
|
|
dither_grey (grey, bw, width, y);
|
|
|
|
|
|
|
|
/* Write out the b/w line */
|
|
|
|
out_count = 0;
|
|
|
|
bwptr = bw;
|
|
|
|
for (x = 0; x < nbsl; x++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (out_count == 0)
|
|
|
|
if (! print (output, error, "%% "))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%02x", *(bwptr++)))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
out_count += 2;
|
|
|
|
if (out_count >= nchar_pl)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
out_count = 0;
|
|
|
|
}
|
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2003-06-13 22:37:00 +08:00
|
|
|
if ((y % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) y / (gdouble) height);
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "%%%%EndPreview\n"))
|
|
|
|
goto fail;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
|
|
|
dither_grey (grey, bw, width, -1);
|
|
|
|
g_free (src_row);
|
|
|
|
g_free (bw);
|
|
|
|
g_free (grey);
|
|
|
|
|
2013-05-14 22:13:19 +08:00
|
|
|
g_object_unref (buffer);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (src_row);
|
|
|
|
g_free (bw);
|
|
|
|
g_free (grey);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return FALSE;
|
1997-12-26 15:08:20 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_gray (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *data;
|
|
|
|
guchar *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
gboolean level2 = (psvals.level > 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 16:54:00 +08:00
|
|
|
format = babl_format ("Y' u8");
|
2014-10-27 01:54:42 +08:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 16:54:00 +08:00
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 16:54:00 +08:00
|
|
|
src = data = (guchar *) g_malloc (tile_height * width * bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, 1 * 8, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop }\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-23 06:26:20 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"currentfile /ASCII85Decode filter /RunLengthDecode filter\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = (guchar *) g_malloc ((width * 105) / 100 + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "image\n"))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#define GET_GRAY_TILE(begin) \
|
2014-10-27 01:54:42 +08:00
|
|
|
{ gint scan_lines; \
|
1997-11-25 06:05:25 +08:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 16:54:00 +08:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-25 06:05:25 +08:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_GRAY_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "%c", hex[(*src) >> 4]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c", hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j + 1) % 39) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
gint nout;
|
2000-03-11 01:27:25 +08:00
|
|
|
|
|
|
|
compress_packbits (width, src, &nout, packb);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
src += width;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2003-06-13 22:37:00 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
if (level2)
|
2003-06-13 22:37:00 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2003-06-13 22:37:00 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (data);
|
2014-10-27 01:54:42 +08:00
|
|
|
g_free (packb);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2013-05-14 16:54:00 +08:00
|
|
|
g_object_unref (buffer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
return FALSE;
|
2004-11-19 05:10:12 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#undef GET_GRAY_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_bw (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint ncols, nbsl, nwrite;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *cmap, *ct;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *scanline, *dst, mask;
|
|
|
|
guchar *hex_scanline;
|
|
|
|
gboolean level2 = (psvals.level > 1);
|
1999-01-04 06:41:12 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
cmap = gimp_image_get_colormap (image, &ncols);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
|
|
|
format = gimp_drawable_get_format (drawable);
|
2014-10-27 01:54:42 +08:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 22:13:19 +08:00
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 22:13:19 +08:00
|
|
|
src = data = g_new (guchar, tile_height * width * bpp);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
nbsl = (width + 7) / 8;
|
|
|
|
|
|
|
|
scanline = g_new (guchar, nbsl + 1);
|
2003-07-03 21:26:06 +08:00
|
|
|
hex_scanline = g_new (guchar, (nbsl + 1) * 2);
|
1999-01-04 06:41:12 +08:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, 1, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
1999-01-04 06:41:12 +08:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop }\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-23 06:26:20 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"currentfile /ASCII85Decode filter /RunLengthDecode filter\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = g_new (guchar, ((nbsl+1) * 105) / 100 + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "image\n"))
|
|
|
|
goto fail;
|
1999-01-04 06:41:12 +08:00
|
|
|
|
|
|
|
#define GET_BW_TILE(begin) \
|
2014-10-27 01:54:42 +08:00
|
|
|
{ gint scan_lines; \
|
1999-01-04 06:41:12 +08:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 22:13:19 +08:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1999-01-04 06:41:12 +08:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_BW_TILE (data); /* Get more data */
|
|
|
|
|
2000-01-23 06:26:20 +08:00
|
|
|
dst = scanline;
|
2000-01-26 01:46:56 +08:00
|
|
|
memset (dst, 0, nbsl);
|
|
|
|
mask = 0x80;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
/* Build a bitmap for a scanline */
|
|
|
|
for (j = 0; j < width; j++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
ct = cmap + *(src++)*3;
|
|
|
|
if (ct[0] || ct[1] || ct[2])
|
|
|
|
*dst |= mask;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (mask == 0x01)
|
|
|
|
{
|
|
|
|
mask = 0x80; dst++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
/* Convert to hexstring */
|
|
|
|
for (j = 0; j < nbsl; j++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
hex_scanline[j * 2] = (guchar) hex[scanline[j] >> 4];
|
|
|
|
hex_scanline[j * 2 + 1] = (guchar) hex[scanline[j] & 0x0f];
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
/* Write out hexstring */
|
|
|
|
j = nbsl * 2;
|
|
|
|
dst = hex_scanline;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
while (j > 0)
|
|
|
|
{
|
|
|
|
nwrite = (j > 78) ? 78 : j;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! g_output_stream_write_all (output,
|
|
|
|
dst, nwrite, NULL,
|
|
|
|
NULL, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
j -= nwrite;
|
|
|
|
dst += nwrite;
|
|
|
|
}
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
gint nout;
|
2000-03-11 01:27:25 +08:00
|
|
|
|
|
|
|
compress_packbits (nbsl, scanline, &nout, packb);
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2003-06-13 22:37:00 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1999-01-04 06:41:12 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
if (level2)
|
2003-06-13 22:37:00 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2003-06-13 22:37:00 +08:00
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
1999-01-04 06:41:12 +08:00
|
|
|
|
|
|
|
g_free (hex_scanline);
|
|
|
|
g_free (scanline);
|
|
|
|
g_free (data);
|
2014-10-27 01:54:42 +08:00
|
|
|
g_free (packb);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (hex_scanline);
|
|
|
|
g_free (scanline);
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
1999-01-04 06:41:12 +08:00
|
|
|
|
2013-05-14 22:13:19 +08:00
|
|
|
g_object_unref (buffer);
|
1999-01-04 06:41:12 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
return FALSE;
|
2004-11-19 05:10:12 +08:00
|
|
|
|
1999-01-04 06:41:12 +08:00
|
|
|
#undef GET_BW_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_index (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error)
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
|
|
|
gint bpp;
|
|
|
|
gint height, width, i, j;
|
|
|
|
gint ncols, bw;
|
|
|
|
gint tile_height;
|
|
|
|
guchar *cmap, *cmap_start;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *plane = NULL;
|
|
|
|
gchar coltab[256 * 6], *ct;
|
|
|
|
gboolean level2 = (psvals.level > 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
cmap = cmap_start = gimp_image_get_colormap (image, &ncols);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
ct = coltab;
|
1999-01-04 06:41:12 +08:00
|
|
|
bw = 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
for (j = 0; j < 256; j++)
|
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
if (j >= ncols)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2008-12-04 00:07:32 +08:00
|
|
|
memset (ct, 0, 6);
|
2006-05-08 20:23:32 +08:00
|
|
|
ct += 6;
|
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
bw &= ((cmap[0] == 0) && (cmap[1] == 0) && (cmap[2] == 0)) ||
|
|
|
|
((cmap[0] == 255) && (cmap[1] == 255) && (cmap[2] == 255));
|
|
|
|
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
|
|
|
*(ct++) = (guchar) hex[(*cmap) >> 4];
|
|
|
|
*(ct++) = (guchar) hex[(*(cmap++)) & 0x0f];
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
if (bw)
|
2019-08-19 21:46:53 +08:00
|
|
|
return save_bw (output, image, drawable, error);
|
1999-01-04 06:41:12 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
|
|
|
format = gimp_drawable_get_format (drawable);
|
2014-10-27 01:54:42 +08:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 22:13:19 +08:00
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1999-01-04 06:41:12 +08:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2014-10-27 01:54:42 +08:00
|
|
|
src = data = (guchar *) g_malloc (tile_height * width * bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, 3 * 8, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop } false 3\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-23 06:26:20 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Strings to hold RGB-samples per scanline\n"
|
|
|
|
"/rstr %d string def\n"
|
|
|
|
"/gstr %d string def\n"
|
|
|
|
"/bstr %d string def\n",
|
|
|
|
width, width, width))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
rstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
gstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
bstr readstring pop}\n"
|
|
|
|
"true 3\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = (guchar *) g_malloc ((width * 105) / 100 + 2);
|
|
|
|
plane = (guchar *) g_malloc (width);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "colorimage\n"))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#define GET_INDEX_TILE(begin) \
|
2014-10-27 01:54:42 +08:00
|
|
|
{ gint scan_lines; \
|
1997-11-25 06:05:25 +08:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 22:13:19 +08:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-25 06:05:25 +08:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
2000-01-23 06:26:20 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_INDEX_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! g_output_stream_write_all (output,
|
|
|
|
coltab + (*(src++)) * 6, 6, NULL,
|
|
|
|
NULL, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j + 1) % 13) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
gint rgb;
|
2000-03-11 01:27:25 +08:00
|
|
|
|
|
|
|
for (rgb = 0; rgb < 3; rgb++)
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
guchar *src_ptr = src;
|
|
|
|
guchar *plane_ptr = plane;
|
|
|
|
gint nout;
|
|
|
|
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
*(plane_ptr++) = cmap_start[3 * *(src_ptr++) + rgb];
|
|
|
|
|
|
|
|
compress_packbits (width, plane, &nout, packb);
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
src += width;
|
|
|
|
}
|
2003-06-13 22:37:00 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
g_free (data);
|
2014-10-27 01:54:42 +08:00
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
fail:
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2013-05-14 22:13:19 +08:00
|
|
|
g_object_unref (buffer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
return FALSE;
|
2004-11-19 05:10:12 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#undef GET_INDEX_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
save_rgb (GOutputStream *output,
|
2019-08-19 21:46:53 +08:00
|
|
|
GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
2014-10-27 01:54:42 +08:00
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
GeglBuffer *buffer = NULL;
|
|
|
|
const Babl *format;
|
|
|
|
gint bpp;
|
|
|
|
gint height, width, tile_height;
|
|
|
|
gint i, j;
|
|
|
|
guchar *data, *src;
|
|
|
|
guchar *packb = NULL;
|
|
|
|
guchar *plane = NULL;
|
|
|
|
gboolean level2 = (psvals.level > 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-08-19 21:46:53 +08:00
|
|
|
buffer = gimp_drawable_get_buffer (drawable);
|
2013-05-14 16:54:00 +08:00
|
|
|
format = babl_format ("R'G'B' u8");
|
2014-10-27 01:54:42 +08:00
|
|
|
bpp = babl_format_get_bytes_per_pixel (format);
|
|
|
|
width = gegl_buffer_get_width (buffer);
|
2013-05-14 16:54:00 +08:00
|
|
|
height = gegl_buffer_get_height (buffer);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
|
|
|
|
/* allocate a buffer for retrieving information from the pixel region */
|
2013-05-14 16:54:00 +08:00
|
|
|
src = data = g_new (guchar, tile_height * width * bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set up transformation in PostScript */
|
2019-08-19 21:46:53 +08:00
|
|
|
if (! save_ps_setup (output, drawable, width, height, 3 * 8, error))
|
2014-10-27 01:54:42 +08:00
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Write read image procedure */
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! level2)
|
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"{ currentfile scanline readhexstring pop } false 3\n"))
|
|
|
|
goto fail;
|
|
|
|
}
|
2000-01-23 06:26:20 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
if (! print (output, error,
|
|
|
|
"%% Strings to hold RGB-samples per scanline\n"
|
|
|
|
"/rstr %d string def\n"
|
|
|
|
"/gstr %d string def\n"
|
|
|
|
"/bstr %d string def\n",
|
|
|
|
width, width, width))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error,
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
rstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
gstr readstring pop}\n"
|
|
|
|
"{currentfile /ASCII85Decode filter /RunLengthDecode filter\
|
|
|
|
bstr readstring pop}\n"
|
|
|
|
"true 3\n"))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Allocate buffer for packbits data. Worst case: Less than 1% increase */
|
|
|
|
packb = g_new (guchar, (width * 105) / 100 + 2);
|
|
|
|
plane = g_new (guchar, width);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! ps_begin_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "colorimage\n"))
|
|
|
|
goto fail;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#define GET_RGB_TILE(begin) \
|
2014-10-27 01:54:42 +08:00
|
|
|
{ gint scan_lines; \
|
1997-11-25 06:05:25 +08:00
|
|
|
scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
|
2013-05-14 16:54:00 +08:00
|
|
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, scan_lines), \
|
|
|
|
1.0, format, begin, \
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); \
|
1997-11-25 06:05:25 +08:00
|
|
|
src = begin; }
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if ((i % tile_height) == 0)
|
|
|
|
GET_RGB_TILE (data); /* Get more data */
|
|
|
|
|
|
|
|
if (! level2)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Red */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Green */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*src) >> 4])) /* Blue */
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "%c",
|
|
|
|
hex[(*(src++)) & 0x0f]))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (((j+1) % 13) == 0)
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
if (! print (output, error, "\n"))
|
|
|
|
goto fail;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2014-10-27 01:54:42 +08:00
|
|
|
{
|
|
|
|
gint rgb;
|
2000-03-11 01:27:25 +08:00
|
|
|
|
|
|
|
for (rgb = 0; rgb < 3; rgb++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2014-10-27 01:54:42 +08:00
|
|
|
guchar *src_ptr = src + rgb;
|
|
|
|
guchar *plane_ptr = plane;
|
|
|
|
gint nout;
|
|
|
|
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
*(plane_ptr++) = *src_ptr;
|
|
|
|
src_ptr += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
compress_packbits (width, plane, &nout, packb);
|
|
|
|
|
|
|
|
ascii85_init ();
|
|
|
|
|
|
|
|
if (! ascii85_nout (output, nout, packb, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Write EOD of RunLengthDecode filter */
|
|
|
|
if (! ascii85_out (output, 128, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! ascii85_done (output, error))
|
|
|
|
goto fail;
|
2000-03-11 01:27:25 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
src += 3 * width;
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
2003-06-13 22:37:00 +08:00
|
|
|
|
|
|
|
if ((i % 20) == 0)
|
2014-10-27 01:54:42 +08:00
|
|
|
gimp_progress_update ((gdouble) i / (gdouble) height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2014-10-27 01:54:42 +08:00
|
|
|
|
2011-04-11 01:05:08 +08:00
|
|
|
gimp_progress_update (1.0);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
if (! ps_end_data (output, error))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (! print (output, error, "showpage\n"))
|
|
|
|
goto fail;
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2007-05-29 23:29:37 +08:00
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2013-05-14 16:54:00 +08:00
|
|
|
g_object_unref (buffer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-11-19 05:10:12 +08:00
|
|
|
return TRUE;
|
2014-10-27 01:54:42 +08:00
|
|
|
|
|
|
|
fail:
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
g_free (packb);
|
|
|
|
g_free (plane);
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#undef GET_RGB_TILE
|
|
|
|
}
|
|
|
|
|
2014-10-27 01:54:42 +08:00
|
|
|
static gboolean
|
|
|
|
print (GOutputStream *output,
|
|
|
|
GError **error,
|
|
|
|
const gchar *format,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
va_start (args, format);
|
|
|
|
success = g_output_stream_vprintf (output, NULL, NULL,
|
|
|
|
error, format, args);
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Load interface functions */
|
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
static gint32
|
2019-09-12 03:48:34 +08:00
|
|
|
count_ps_pages (GFile *file)
|
2005-08-15 16:48:45 +08:00
|
|
|
{
|
2007-05-29 23:29:37 +08:00
|
|
|
FILE *psfile;
|
|
|
|
gchar *extension;
|
|
|
|
gchar buf[1024];
|
2005-08-15 16:48:45 +08:00
|
|
|
gint32 num_pages = 0;
|
|
|
|
gint32 showpage_count = 0;
|
|
|
|
|
2021-10-02 00:56:12 +08:00
|
|
|
extension = strrchr (g_file_peek_path (file), '.');
|
2007-05-29 23:29:37 +08:00
|
|
|
if (extension)
|
|
|
|
{
|
|
|
|
extension = g_ascii_strdown (extension + 1, -1);
|
|
|
|
|
|
|
|
if (strcmp (extension, "eps") == 0)
|
|
|
|
{
|
|
|
|
g_free (extension);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (extension);
|
|
|
|
}
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2021-10-02 00:56:12 +08:00
|
|
|
psfile = g_fopen (g_file_peek_path (file), "r");
|
2019-09-12 03:48:34 +08:00
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
if (psfile == NULL)
|
|
|
|
{
|
|
|
|
g_message (_("Could not open '%s' for reading: %s"),
|
2019-09-12 03:48:34 +08:00
|
|
|
gimp_file_get_utf8_name (file), g_strerror (errno));
|
2005-08-15 16:48:45 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (num_pages == 0 && !feof (psfile))
|
|
|
|
{
|
2007-05-29 23:29:37 +08:00
|
|
|
fgets (buf, sizeof (buf), psfile);
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2007-05-29 23:29:37 +08:00
|
|
|
if (strncmp (buf + 2, "Pages:", 6) == 0)
|
|
|
|
sscanf (buf + strlen ("%%Pages:"), "%d", &num_pages);
|
|
|
|
else if (strncmp (buf, "showpage", 8) == 0)
|
2005-08-15 16:48:45 +08:00
|
|
|
showpage_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (feof (psfile) && num_pages < 1 && showpage_count > 0)
|
|
|
|
num_pages = showpage_count;
|
|
|
|
|
|
|
|
fclose (psfile);
|
|
|
|
|
|
|
|
return num_pages;
|
|
|
|
}
|
|
|
|
|
2004-05-20 01:53:21 +08:00
|
|
|
static gboolean
|
2019-09-12 03:48:34 +08:00
|
|
|
load_dialog (GFile *file)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *main_vbox;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *vbox;
|
2018-05-09 05:06:26 +08:00
|
|
|
GtkWidget *grid;
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *spinbutton;
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
GtkWidget *entry = NULL;
|
|
|
|
GtkWidget *target = NULL;
|
|
|
|
GtkWidget *toggle;
|
|
|
|
GtkWidget *selector = NULL;
|
|
|
|
gint32 page_count;
|
|
|
|
gchar *range = NULL;
|
|
|
|
gboolean run;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2019-09-12 03:48:34 +08:00
|
|
|
page_count = count_ps_pages (file);
|
2005-08-15 16:48:45 +08:00
|
|
|
|
2019-09-21 01:39:00 +08:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2011-04-09 02:31:34 +08:00
|
|
|
dialog = gimp_dialog_new (_("Import from PostScript"), PLUG_IN_ROLE,
|
2003-11-06 23:27:05 +08:00
|
|
|
NULL, 0,
|
2006-05-08 20:23:32 +08:00
|
|
|
gimp_standard_help_func, LOAD_PS_PROC,
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2017-02-12 23:18:24 +08:00
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("_Import"), GTK_RESPONSE_OK,
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2018-05-10 23:04:37 +08:00
|
|
|
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
2005-08-15 16:48:45 +08:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
2005-02-09 04:40:33 +08:00
|
|
|
|
2007-05-15 15:12:15 +08:00
|
|
|
gimp_window_set_transient (GTK_WINDOW (dialog));
|
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
|
2009-07-16 00:57:12 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
|
|
main_vbox, TRUE, TRUE, 0);
|
2000-01-08 23:23:28 +08:00
|
|
|
gtk_widget_show (main_vbox);
|
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
if (page_count > 1)
|
|
|
|
{
|
|
|
|
selector = gimp_page_selector_new ();
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), selector, TRUE, TRUE, 0);
|
|
|
|
gimp_page_selector_set_n_pages (GIMP_PAGE_SELECTOR (selector),
|
2006-05-08 20:23:32 +08:00
|
|
|
page_count);
|
2005-08-15 16:48:45 +08:00
|
|
|
gimp_page_selector_set_target (GIMP_PAGE_SELECTOR (selector),
|
2006-05-08 20:23:32 +08:00
|
|
|
ps_pagemode);
|
2005-10-28 22:57:32 +08:00
|
|
|
|
2005-08-15 16:48:45 +08:00
|
|
|
gtk_widget_show (selector);
|
2005-10-28 22:57:32 +08:00
|
|
|
|
|
|
|
g_signal_connect_swapped (selector, "activate",
|
|
|
|
G_CALLBACK (gtk_window_activate_default),
|
|
|
|
dialog);
|
2005-08-15 16:48:45 +08:00
|
|
|
}
|
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
|
|
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
|
2000-01-08 23:23:28 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
/* Rendering */
|
2004-05-20 01:53:21 +08:00
|
|
|
frame = gimp_frame_new (_("Rendering"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
|
|
|
|
/* Resolution/Width/Height/Pages labels */
|
2018-05-09 05:06:26 +08:00
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (grid);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
adj = gtk_adjustment_new (plvals.resolution,
|
|
|
|
MIN_RESOLUTION, MAX_RESOLUTION,
|
|
|
|
1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (adj, 1.0, 0);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 0,
|
|
|
|
_("Resolution:"), 0.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2007-05-15 15:12:15 +08:00
|
|
|
|
2007-03-01 20:48:00 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
|
|
|
G_CALLBACK (resolution_change_callback),
|
|
|
|
&plvals.resolution);
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
|
|
|
&plvals.resolution);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
adj = gtk_adjustment_new (plvals.width,
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE,
|
|
|
|
1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
ps_width_spinbutton = gimp_spin_button_new (adj, 1.0, 0);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 1,
|
|
|
|
_("_Width:"), 0.0, 0.5,
|
|
|
|
ps_width_spinbutton, 1);
|
2014-06-23 05:01:31 +08:00
|
|
|
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
|
|
|
&plvals.width);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
adj = gtk_adjustment_new (plvals.height,
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE,
|
|
|
|
1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
ps_height_spinbutton = gimp_spin_button_new (adj, 1.0, 0);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 2,
|
|
|
|
_("_Height:"), 0.0, 0.5,
|
|
|
|
ps_height_spinbutton, 1);
|
2014-06-23 05:01:31 +08:00
|
|
|
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
|
|
|
&plvals.height);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2017-12-14 03:35:41 +08:00
|
|
|
if (page_count == 0)
|
2005-08-15 16:48:45 +08:00
|
|
|
{
|
|
|
|
entry = gtk_entry_new ();
|
|
|
|
gtk_widget_set_size_request (entry, 80, -1);
|
|
|
|
gtk_entry_set_text (GTK_ENTRY (entry), plvals.pages);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 3,
|
|
|
|
_("Pages:"), 0.0, 0.5,
|
|
|
|
entry, 1);
|
2005-08-15 16:48:45 +08:00
|
|
|
|
|
|
|
g_signal_connect (entry, "changed",
|
|
|
|
G_CALLBACK (load_pages_entry_callback),
|
|
|
|
NULL);
|
|
|
|
gimp_help_set_help_data (GTK_WIDGET (entry),
|
|
|
|
_("Pages to load (e.g.: 1-4 or 1,3,5-7)"), NULL);
|
|
|
|
|
2011-03-17 21:31:39 +08:00
|
|
|
target = gtk_combo_box_text_new ();
|
|
|
|
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (target),
|
|
|
|
GIMP_PAGE_SELECTOR_TARGET_LAYERS,
|
|
|
|
_("Layers"));
|
|
|
|
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (target),
|
|
|
|
GIMP_PAGE_SELECTOR_TARGET_IMAGES,
|
|
|
|
_("Images"));
|
2005-08-15 16:48:45 +08:00
|
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (target), (int) ps_pagemode);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 4,
|
|
|
|
_("Open as"), 0.0, 0.5,
|
|
|
|
target, 1);
|
2005-08-15 16:48:45 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-08 23:23:28 +08:00
|
|
|
toggle = gtk_check_button_new_with_label (_("Try Bounding Box"));
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), plvals.use_bbox);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&plvals.use_bbox);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (vbox);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2013-06-07 05:26:16 +08:00
|
|
|
/* Coloring */
|
2003-11-15 02:05:39 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Coloring"),
|
2006-05-08 20:23:32 +08:00
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
2020-01-15 20:51:55 +08:00
|
|
|
&plvals.pnm_type, NULL, plvals.pnm_type,
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
_("B/W"), 4, NULL,
|
|
|
|
_("Gray"), 5, NULL,
|
|
|
|
_("Color"), 6, NULL,
|
|
|
|
_("Automatic"), 7, NULL,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
|
|
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
|
2000-01-08 23:23:28 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
2004-06-22 03:15:08 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Text antialiasing"),
|
2006-05-08 20:23:32 +08:00
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
2020-01-15 20:51:55 +08:00
|
|
|
&plvals.textalpha, NULL, plvals.textalpha,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2011-11-17 06:13:03 +08:00
|
|
|
C_("antialiasing", "None"), 1, NULL,
|
|
|
|
_("Weak"), 2, NULL,
|
|
|
|
_("Strong"), 4, NULL,
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2004-06-22 03:15:08 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Graphic antialiasing"),
|
2006-05-08 20:23:32 +08:00
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
2020-01-15 20:51:55 +08:00
|
|
|
&plvals.graphicsalpha, NULL, plvals.graphicsalpha,
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2011-11-17 06:13:03 +08:00
|
|
|
C_("antialiasing", "None"), 1, NULL,
|
|
|
|
_("Weak"), 2, NULL,
|
|
|
|
_("Strong"), 4, NULL,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
|
|
|
gtk_widget_show (dialog);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-12 02:11:56 +08:00
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-10-28 22:57:32 +08:00
|
|
|
if (selector)
|
2005-08-15 16:48:45 +08:00
|
|
|
{
|
|
|
|
range = gimp_page_selector_get_selected_range (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
|
|
|
|
if (strlen (range) < 1)
|
|
|
|
{
|
|
|
|
gimp_page_selector_select_all (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
range = gimp_page_selector_get_selected_range (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
}
|
|
|
|
|
2019-08-15 05:52:38 +08:00
|
|
|
g_strlcpy (plvals.pages, range, sizeof (plvals.pages));
|
2005-08-15 16:48:45 +08:00
|
|
|
|
|
|
|
ps_pagemode = gimp_page_selector_get_target (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
}
|
2017-12-14 03:35:41 +08:00
|
|
|
else if (page_count == 0)
|
2005-08-15 16:48:45 +08:00
|
|
|
{
|
|
|
|
ps_pagemode = gtk_combo_box_get_active (GTK_COMBO_BOX (target));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-15 05:52:38 +08:00
|
|
|
g_strlcpy (plvals.pages, "1", sizeof (plvals.pages));
|
2005-08-15 16:48:45 +08:00
|
|
|
ps_pagemode = GIMP_PAGE_SELECTOR_TARGET_IMAGES;
|
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
return run;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
static void
|
2000-01-26 01:46:56 +08:00
|
|
|
load_pages_entry_callback (GtkWidget *widget,
|
2006-05-08 20:23:32 +08:00
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2019-08-15 05:52:38 +08:00
|
|
|
g_strlcpy (plvals.pages, gtk_entry_get_text (GTK_ENTRY (widget)),
|
|
|
|
sizeof (plvals.pages));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Save interface functions */
|
|
|
|
|
2004-05-20 01:53:21 +08:00
|
|
|
static gboolean
|
1997-11-25 06:05:25 +08:00
|
|
|
save_dialog (void)
|
|
|
|
{
|
|
|
|
SaveDialogVals *vals;
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *toggle;
|
|
|
|
GtkWidget *frame, *uframe;
|
|
|
|
GtkWidget *hbox, *vbox;
|
|
|
|
GtkWidget *main_vbox[2];
|
2018-05-09 05:06:26 +08:00
|
|
|
GtkWidget *grid;
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *spinbutton;
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
gint j;
|
|
|
|
gboolean run;
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2000-07-31 06:48:35 +08:00
|
|
|
vals = g_new (SaveDialogVals, 1);
|
2000-01-26 01:46:56 +08:00
|
|
|
vals->level = (psvals.level > 1);
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2009-07-21 20:10:29 +08:00
|
|
|
dialog = gimp_export_dialog_new (_("PostScript"), PLUG_IN_BINARY, SAVE_PS_PROC);
|
2005-09-10 02:38:00 +08:00
|
|
|
|
1997-12-26 15:08:20 +08:00
|
|
|
/* Main hbox */
|
2011-09-30 18:17:53 +08:00
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
|
2009-07-21 20:10:29 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)),
|
2009-07-16 00:57:12 +08:00
|
|
|
hbox, FALSE, FALSE, 0);
|
1997-12-26 15:08:20 +08:00
|
|
|
main_vbox[0] = main_vbox[1] = NULL;
|
|
|
|
|
2001-12-06 10:28:58 +08:00
|
|
|
for (j = 0; j < G_N_ELEMENTS (main_vbox); j++)
|
2000-01-08 23:23:28 +08:00
|
|
|
{
|
2011-09-30 18:17:53 +08:00
|
|
|
main_vbox[j] = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), main_vbox[j], FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show (main_vbox[j]);
|
2000-01-08 23:23:28 +08:00
|
|
|
}
|
1997-12-26 15:08:20 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Image Size */
|
2004-05-20 01:53:21 +08:00
|
|
|
frame = gimp_frame_new (_("Image Size"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox[0]), frame, FALSE, TRUE, 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
|
|
|
|
/* Width/Height/X-/Y-offset labels */
|
2018-05-09 05:06:26 +08:00
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (grid);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
vals->adjustment[0] = gtk_adjustment_new (psvals.width,
|
|
|
|
1e-5, GIMP_MAX_IMAGE_SIZE, 1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (vals->adjustment[0], 1.0, 2);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 0,
|
|
|
|
_("_Width:"), 0.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (vals->adjustment[0], "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_double_adjustment_update),
|
|
|
|
&psvals.width);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
vals->adjustment[1] = gtk_adjustment_new (psvals.height,
|
|
|
|
1e-5, GIMP_MAX_IMAGE_SIZE, 1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (vals->adjustment[1], 1.0, 2);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 1,
|
|
|
|
_("_Height:"), 0.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (vals->adjustment[1], "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_double_adjustment_update),
|
|
|
|
&psvals.height);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
vals->adjustment[2] = gtk_adjustment_new (psvals.x_offset,
|
|
|
|
0.0, GIMP_MAX_IMAGE_SIZE, 1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (vals->adjustment[2], 1.0, 2);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 2,
|
|
|
|
_("_X offset:"), 0.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (vals->adjustment[2], "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_double_adjustment_update),
|
|
|
|
&psvals.x_offset);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
vals->adjustment[3] = gtk_adjustment_new (psvals.y_offset,
|
|
|
|
0.0, GIMP_MAX_IMAGE_SIZE, 1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (vals->adjustment[3], 1.0, 2);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 3,
|
|
|
|
_("_Y offset:"), 0.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (vals->adjustment[3], "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_double_adjustment_update),
|
|
|
|
&psvals.y_offset);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-06-22 03:15:08 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("_Keep aspect ratio"));
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.keep_ratio);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2001-12-31 08:21:10 +08:00
|
|
|
gimp_help_set_help_data (toggle,
|
2006-08-29 21:32:22 +08:00
|
|
|
_("When toggled, the resulting image will be "
|
|
|
|
"scaled to fit into the given size without "
|
|
|
|
"changing the aspect ratio."),
|
2006-05-08 20:23:32 +08:00
|
|
|
"#keep_aspect_ratio"),
|
2001-12-31 08:21:10 +08:00
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&psvals.keep_ratio);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Unit */
|
2003-11-15 02:05:39 +08:00
|
|
|
uframe = gimp_int_radio_group_new (TRUE, _("Unit"),
|
2006-05-08 20:23:32 +08:00
|
|
|
G_CALLBACK (save_unit_toggle_update),
|
2020-01-15 20:51:55 +08:00
|
|
|
vals, NULL, psvals.unit_mm,
|
2001-12-31 08:21:10 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
_("_Inch"), FALSE, NULL,
|
|
|
|
_("_Millimeter"), TRUE, NULL,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2001-12-31 08:21:10 +08:00
|
|
|
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox[0]), uframe, TRUE, TRUE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (uframe);
|
|
|
|
|
|
|
|
gtk_widget_show (vbox);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
|
|
|
/* Rotation */
|
2003-11-15 02:05:39 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Rotation"),
|
2006-05-08 20:23:32 +08:00
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
2020-01-15 20:51:55 +08:00
|
|
|
&psvals.rotate, NULL, psvals.rotate,
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
"_0", 0, NULL,
|
|
|
|
"_90", 90, NULL,
|
|
|
|
"_180", 180, NULL,
|
|
|
|
"_270", 270, NULL,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-05-08 20:23:32 +08:00
|
|
|
NULL);
|
2001-12-31 08:21:10 +08:00
|
|
|
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox[1]), frame, TRUE, TRUE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
1997-12-26 15:08:20 +08:00
|
|
|
/* Format */
|
2004-05-20 01:53:21 +08:00
|
|
|
frame = gimp_frame_new (_("Output"));
|
1997-12-26 15:08:20 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox[1]), frame, TRUE, TRUE, 0);
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
1997-12-26 15:08:20 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
|
2004-06-22 03:15:08 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("_PostScript level 2"));
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
2000-01-23 06:26:20 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), vals->level);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&vals->level);
|
|
|
|
|
2003-01-19 22:40:56 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("_Encapsulated PostScript"));
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.eps);
|
1997-12-26 15:08:20 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&psvals.eps);
|
|
|
|
|
2003-01-19 22:40:56 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("P_review"));
|
2004-05-20 01:53:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), psvals.preview);
|
1997-12-26 15:08:20 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&psvals.preview);
|
|
|
|
|
1997-12-26 15:08:20 +08:00
|
|
|
/* Preview size label/entry */
|
2018-05-09 05:06:26 +08:00
|
|
|
grid = gtk_grid_new ();
|
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (grid);
|
1997-12-26 15:08:20 +08:00
|
|
|
|
2011-05-11 17:41:26 +08:00
|
|
|
g_object_bind_property (toggle, "active",
|
2018-05-09 05:06:26 +08:00
|
|
|
grid, "sensitive",
|
2011-05-11 17:41:26 +08:00
|
|
|
G_BINDING_SYNC_CREATE);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2018-06-25 00:15:16 +08:00
|
|
|
adj = gtk_adjustment_new (psvals.preview_size,
|
|
|
|
0, 1024, 1, 10, 0);
|
2019-03-09 20:25:19 +08:00
|
|
|
spinbutton = gimp_spin_button_new (adj, 1.0, 0);
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
2018-05-09 05:06:26 +08:00
|
|
|
gimp_grid_attach_aligned (GTK_GRID (grid), 0, 0,
|
|
|
|
_("Preview _size:"), 1.0, 0.5,
|
|
|
|
spinbutton, 1);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_widget_show (spinbutton);
|
1997-12-26 15:08:20 +08:00
|
|
|
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2001-12-31 08:21:10 +08:00
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
|
|
|
&psvals.preview_size);
|
|
|
|
|
1997-12-26 15:08:20 +08:00
|
|
|
gtk_widget_show (vbox);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
|
|
|
gtk_widget_show (hbox);
|
2000-01-26 01:46:56 +08:00
|
|
|
gtk_widget_show (dialog);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-12 02:11:56 +08:00
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-03-11 01:27:25 +08:00
|
|
|
psvals.level = (vals->level) ? 2 : 1;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (vals);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
return run;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
static void
|
2000-01-26 01:46:56 +08:00
|
|
|
save_unit_toggle_update (GtkWidget *widget,
|
2006-05-08 20:23:32 +08:00
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2008-06-29 02:40:23 +08:00
|
|
|
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
|
2000-01-26 01:46:56 +08:00
|
|
|
{
|
2007-05-29 23:29:37 +08:00
|
|
|
SaveDialogVals *vals = (SaveDialogVals *) data;
|
|
|
|
gdouble factor;
|
|
|
|
gdouble value;
|
|
|
|
gint unit_mm;
|
|
|
|
gint i;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-31 08:21:10 +08:00
|
|
|
unit_mm = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
|
|
"gimp-item-data"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
psvals.unit_mm = unit_mm;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
if (unit_mm)
|
2006-05-08 20:23:32 +08:00
|
|
|
factor = 25.4;
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
2006-05-08 20:23:32 +08:00
|
|
|
factor = 1.0 / 25.4;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
for (i = 0; i < 4; i++)
|
2006-05-08 20:23:32 +08:00
|
|
|
{
|
2014-06-23 05:01:31 +08:00
|
|
|
value = gtk_adjustment_get_value (vals->adjustment[i]) * factor;
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2014-06-23 05:01:31 +08:00
|
|
|
gtk_adjustment_set_value (vals->adjustment[i], value);
|
2006-05-08 20:23:32 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
2007-03-01 20:48:00 +08:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
resolution_change_callback (GtkAdjustment *adjustment,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2007-05-29 23:29:37 +08:00
|
|
|
guint *old_resolution = (guint *) data;
|
|
|
|
gdouble ratio;
|
2007-03-01 20:48:00 +08:00
|
|
|
|
|
|
|
if (*old_resolution)
|
2009-10-10 20:46:05 +08:00
|
|
|
ratio = (gdouble) gtk_adjustment_get_value (adjustment) / *old_resolution;
|
2007-03-01 20:48:00 +08:00
|
|
|
else
|
2007-05-29 23:29:37 +08:00
|
|
|
ratio = 1.0;
|
|
|
|
|
2007-03-01 20:48:00 +08:00
|
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (ps_width_spinbutton),
|
2008-06-29 02:40:23 +08:00
|
|
|
gtk_spin_button_get_value (GTK_SPIN_BUTTON (ps_width_spinbutton)) * ratio);
|
2007-03-01 20:48:00 +08:00
|
|
|
|
|
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (ps_height_spinbutton),
|
2008-06-29 02:40:23 +08:00
|
|
|
gtk_spin_button_get_value (GTK_SPIN_BUTTON (ps_height_spinbutton)) * ratio);
|
2007-05-15 15:12:15 +08:00
|
|
|
|
2007-03-01 20:48:00 +08:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|