1999-08-22 19:02:52 +00:00
/* Plug-in to save .gpb (GIMP Pixmap Brush) files.
Overhaul of pixmap brushes and pipes: No separate pixmap pipe
brush tool any longer. The paintbrush, airbrush and pencil
tools, which already knew how to handle the single-pixmap
brushes now also handle the pipes as well.
* app/pixmapbrush.{h,c}
* app/gimpbrushpixmap.{h,c}: Removed these files.
* app/Makefile.am
* app/makefile.{cygwin,msc}: Remove from here, too.
* app/gimpbrushpipe.{h,c}: Total overhaul.
* app/paint_core.h
* app/apptypes.h: Some more types moved to apptypes.h
* app/context_manager.c
* app/tool_options.c
* app/tools.c
* app/toolsF.h: Remove PIXMAPBRUSH tool.
* app/gimpbrush.h: New method: select_brush. Used to change the
brush in paint_core, for pipe brushes.
* app/gimpbrush.c: Add gimp_brush_select_brush, which is dummy for
the normal brushes (returns the same brush).
* app/paint_core.c: Call the brush's select_brush method to get a
potential new brush before calling the paint_func.
* app/gimpbrushlist.c: Various changes related to the pixmap and
pipe overhaul.
* app/airbrush.c
* app/pencil.c: Reorder code a bit in the tool motion function to
avoid executing unnecessary code in the case of a pixmap brush.
Other changes in the same commit:
* app/install.c: Make quote_spaces extern.
* app/appenv.h: Declare it.
* libgimp/gimpui.def: Add missing entry points.
* libgimp/makefile.{cygwin,msc}: Add missing objects to gimpui.
1999-08-26 00:54:30 +00:00
* The format for pixmap brushes might well change , and this will have to
* be updated .
1999-08-22 19:02:52 +00:00
*
* Copyright ( C ) 1999 Tor Lillqvist
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( 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
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
1999-08-24 05:30:14 +00:00
/* set to the level of debugging output you want, 0 for none */
# define GPB_DEBUG 0
# define IFDBG(level) if (GPB_DEBUG >= level)
1999-08-22 19:02:52 +00:00
# include "config.h"
# include <stdio.h>
# include <string.h>
1999-08-24 05:30:14 +00:00
# include <stdlib.h>
1999-08-22 19:02:52 +00:00
# include <gtk/gtk.h>
2000-01-06 22:26:10 +00:00
1999-08-22 19:02:52 +00:00
# include <libgimp/gimp.h>
1999-10-08 20:09:04 +00:00
# include <libgimp/gimpui.h>
1999-09-02 00:01:41 +00:00
# include <libgimp/parasiteio.h>
2000-01-06 22:26:10 +00:00
1999-12-25 21:49:51 +00:00
# include "libgimp/stdplugins-intl.h"
1999-08-22 19:02:52 +00:00
# include "app/brush_header.h"
# include "app/pattern_header.h"
1999-08-24 05:30:14 +00:00
# define DUMMY_PATTERN_NAME "x"
1999-08-22 19:02:52 +00:00
1999-08-24 05:30:14 +00:00
# define MAXDESCLEN 256
1999-08-22 19:02:52 +00:00
1999-08-24 05:30:14 +00:00
/* Parameters applicable each time we save a gpb or gih, saved
* in the main gimp application between invocations of this plug - in .
*/
2000-01-15 15:32:28 +00:00
static struct
{
1999-08-24 05:30:14 +00:00
/* Use by both gpb and gih: */
guint spacing ;
guchar description [ MAXDESCLEN + 1 ] ;
} info =
/* Initialize to this, change if non-interactive later */
{
1999-08-22 19:02:52 +00:00
10 ,
" GIMP Pixmap Brush "
} ;
1999-08-24 05:30:14 +00:00
static gint run_flag = 0 ;
static gint num_layers_with_alpha ;
1999-09-02 00:01:41 +00:00
static PixPipeParams gihparms ;
typedef struct
{
GOrientation orientation ;
gint32 image ;
gint32 toplayer ;
gint nguides ;
gint32 * guides ;
gint * value ;
GtkWidget * count_label ; /* Corresponding count adjustment, */
gint * count ; /* cols or rows */
gint * other_count ; /* And the other one */
GtkObject * ncells ;
GtkObject * rank0 ;
GtkWidget * warning_label ;
} SizeAdjustmentData ;
1999-10-08 20:09:04 +00:00
/* static gint32 *vguides, *hguides; */
/* static gint nvguides = 0, nhguides = 0; */
1999-08-22 19:02:52 +00:00
/* Declare some local functions.
*/
1999-10-08 20:09:04 +00:00
static void query ( void ) ;
2000-01-15 15:32:28 +00:00
static void run ( gchar * name ,
gint nparams ,
1999-10-08 20:09:04 +00:00
GParam * param ,
2000-01-15 15:32:28 +00:00
gint * nreturn_vals ,
1999-10-08 20:09:04 +00:00
GParam * * return_vals ) ;
static void init_gtk ( void ) ;
1999-08-22 19:02:52 +00:00
GPlugInInfo PLUG_IN_INFO =
{
2000-01-15 15:32:28 +00:00
NULL , /* init_proc */
NULL , /* quit_proc */
query , /* query_proc */
run , /* run_proc */
1999-08-22 19:02:52 +00:00
} ;
MAIN ( )
static void
2000-01-15 15:32:28 +00:00
query ( void )
1999-08-22 19:02:52 +00:00
{
1999-08-24 05:30:14 +00:00
static GParamDef gpb_save_args [ ] =
1999-08-22 19:02:52 +00:00
{
1999-10-08 20:09:04 +00:00
{ PARAM_INT32 , " run_mode " , " Interactive, non-interactive " } ,
{ PARAM_IMAGE , " image " , " Input image " } ,
{ PARAM_DRAWABLE , " drawable " , " Drawable to save " } ,
{ PARAM_STRING , " filename " , " The name of the file to save the brush in " } ,
{ PARAM_STRING , " raw_filename " , " The name of the file to save the brush in " } ,
{ PARAM_INT32 , " spacing " , " Spacing of the brush " } ,
{ PARAM_STRING , " description " , " Short description of the brush " } ,
1999-08-22 19:02:52 +00:00
} ;
2000-01-25 17:46:56 +00:00
static gint ngpb_save_args = ( sizeof ( gpb_save_args ) /
sizeof ( gpb_save_args [ 0 ] ) ) ;
1999-08-24 05:30:14 +00:00
static GParamDef gih_save_args [ ] =
{
1999-10-08 20:09:04 +00:00
{ PARAM_INT32 , " run_mode " , " Interactive, non-interactive " } ,
{ PARAM_IMAGE , " image " , " Input image " } ,
{ PARAM_DRAWABLE , " drawable " , " Drawable to save " } ,
{ PARAM_STRING , " filename " , " The name of the file to save the brush pipe in " } ,
{ PARAM_STRING , " raw_filename " , " The name of the file to save the brush pipe in " } ,
{ PARAM_INT32 , " spacing " , " Spacing of the brush " } ,
{ PARAM_STRING , " description " , " Short description of the brush pipe " } ,
1999-08-24 05:30:14 +00:00
} ;
2000-01-25 17:46:56 +00:00
static gint ngih_save_args = ( sizeof ( gih_save_args ) /
sizeof ( gih_save_args [ 0 ] ) ) ;
1999-08-22 19:02:52 +00:00
1999-12-25 21:49:51 +00:00
INIT_I18N ( ) ;
1999-08-22 19:02:52 +00:00
gimp_install_procedure ( " file_gpb_save " ,
1999-12-25 21:49:51 +00:00
_ ( " saves images in GIMP pixmap brush format " ) ,
_ ( " This plug-in saves a layer of an image in the GIMP pixmap brush format. The image must have an alpha channel. " ) ,
1999-08-22 19:02:52 +00:00
" Tor Lillqvist " ,
" Tor Lillqvist " ,
" 1999 " ,
" <Save>/GPB " ,
" RGBA " ,
PROC_PLUG_IN ,
1999-08-24 05:30:14 +00:00
ngpb_save_args , 0 ,
gpb_save_args , NULL ) ;
1999-08-22 19:02:52 +00:00
2000-01-25 17:46:56 +00:00
gimp_register_save_handler ( " file_gpb_save " ,
" gpb " ,
" " ) ;
1999-08-24 05:30:14 +00:00
gimp_install_procedure ( " file_gih_save " ,
1999-12-25 21:49:51 +00:00
_ ( " saves images in GIMP pixmap brush pipe format " ) ,
_ ( " This plug-in saves an image in the GIMP pixmap brush pipe format. The image must have an alpha channel. The image can be multi-layered, and additionally the layers can be divided into a rectangular array of brushes. " ) ,
1999-08-24 05:30:14 +00:00
" Tor Lillqvist " ,
" Tor Lillqvist " ,
" 1999 " ,
" <Save>/GIH " ,
" RGBA " ,
PROC_PLUG_IN ,
ngih_save_args , 0 ,
gih_save_args , NULL ) ;
2000-01-25 17:46:56 +00:00
gimp_register_save_handler ( " file_gih_save " ,
" gih " ,
" " ) ;
1999-08-24 05:30:14 +00:00
}
1999-10-08 20:09:04 +00:00
static void
2000-01-15 15:32:28 +00:00
init_gtk ( void )
1999-10-08 20:09:04 +00:00
{
gchar * * argv ;
2000-01-25 17:46:56 +00:00
gint argc ;
argc = 1 ;
argv = g_new ( gchar * , 1 ) ;
argv [ 0 ] = g_strdup ( " gpb " ) ;
1999-10-08 20:09:04 +00:00
gtk_init ( & argc , & argv ) ;
gtk_rc_parse ( gimp_gtkrc ( ) ) ;
}
1999-09-02 00:01:41 +00:00
static void
size_adjustment_callback ( GtkWidget * widget ,
gpointer data )
{
/* Unfortunately this doesn't work, sigh. The guides don't show up unless
* you manually force a redraw of the image .
*/
int i ;
int size ;
int newn ;
SizeAdjustmentData * adj = ( SizeAdjustmentData * ) data ;
char buf [ 10 ] ;
for ( i = 0 ; i < adj - > nguides ; i + + )
gimp_image_delete_guide ( adj - > image , adj - > guides [ i ] ) ;
g_free ( adj - > guides ) ;
adj - > guides = NULL ;
gimp_displays_flush ( ) ;
* ( adj - > value ) = GTK_ADJUSTMENT ( widget ) - > value ;
if ( adj - > orientation = = ORIENTATION_VERTICAL )
{
size = gimp_image_width ( adj - > image ) ;
newn = size / * ( adj - > value ) ;
adj - > nguides = newn - 1 ;
adj - > guides = g_new ( gint32 , adj - > nguides ) ;
for ( i = 0 ; i < adj - > nguides ; i + + )
adj - > guides [ i ] = gimp_image_add_vguide ( adj - > image ,
* ( adj - > value ) * ( i + 1 ) ) ;
}
else
{
size = gimp_image_height ( adj - > image ) ;
newn = size / * ( adj - > value ) ;
adj - > nguides = newn - 1 ;
adj - > guides = g_new ( gint32 , adj - > nguides ) ;
for ( i = 0 ; i < adj - > nguides ; i + + )
adj - > guides [ i ] = gimp_image_add_hguide ( adj - > image ,
* ( adj - > value ) * ( i + 1 ) ) ;
}
gimp_displays_flush ( ) ;
sprintf ( buf , " %2d " , newn ) ;
gtk_label_set_text ( GTK_LABEL ( adj - > count_label ) , buf ) ;
* ( adj - > count ) = newn ;
if ( newn * * ( adj - > value ) ! = size )
gtk_widget_show ( GTK_WIDGET ( adj - > warning_label ) ) ;
else
gtk_widget_hide ( GTK_WIDGET ( adj - > warning_label ) ) ;
if ( adj - > ncells ! = NULL )
gtk_adjustment_set_value ( GTK_ADJUSTMENT ( adj - > ncells ) ,
* ( adj - > other_count ) * * ( adj - > count ) ) ;
if ( adj - > rank0 ! = NULL )
gtk_adjustment_set_value ( GTK_ADJUSTMENT ( adj - > rank0 ) ,
* ( adj - > other_count ) * * ( adj - > count ) ) ;
}
1999-08-22 19:02:52 +00:00
static void
1999-08-24 05:30:14 +00:00
entry_callback ( GtkWidget * widget ,
gpointer data )
1999-08-22 19:02:52 +00:00
{
1999-08-24 05:30:14 +00:00
if ( data = = info . description )
{
strncpy ( info . description , gtk_entry_get_text ( GTK_ENTRY ( widget ) ) , MAXDESCLEN ) ;
info . description [ MAXDESCLEN ] = 0 ;
}
1999-08-22 19:02:52 +00:00
}
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
static void
cb_callback ( GtkWidget * widget ,
gpointer data )
{
* ( ( char * * ) data ) = gtk_entry_get_text ( GTK_ENTRY ( widget ) ) ;
}
1999-08-22 19:02:52 +00:00
static void
ok_callback ( GtkWidget * widget ,
gpointer data )
{
1999-10-20 01:01:00 +00:00
int i ;
for ( i = 0 ; i < PIXPIPE_MAXDIM ; i + + )
gihparms . selection [ i ] = g_strdup ( gihparms . selection [ i ] ) ;
1999-08-22 19:02:52 +00:00
run_flag = 1 ;
gtk_widget_destroy ( GTK_WIDGET ( data ) ) ;
}
1999-08-24 05:30:14 +00:00
static void
common_save_dialog ( GtkWidget * dlg ,
GtkWidget * table )
1999-08-22 19:02:52 +00:00
{
1999-08-24 05:30:14 +00:00
GtkObject * adjustment ;
GtkWidget * spinbutton ;
1999-08-22 19:02:52 +00:00
GtkWidget * entry ;
2000-01-06 22:26:10 +00:00
gimp_dialog_create_action_area ( GTK_DIALOG ( dlg ) ,
_ ( " OK " ) , ok_callback ,
NULL , NULL , NULL , TRUE , FALSE ,
_ ( " Cancel " ) , gtk_widget_destroy ,
NULL , 1 , NULL , FALSE , TRUE ,
NULL ) ;
1999-08-22 19:02:52 +00:00
1999-08-24 05:30:14 +00:00
/*
* Spacing : __
*/
2000-01-25 17:46:56 +00:00
spinbutton = gimp_spin_button_new ( & adjustment , info . spacing ,
1 , 1000 , 1 , 10 , 10 , 1 , 0 ) ;
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 0 ,
_ ( " Spacing (Percent): " ) , 1.0 , 0.5 ,
spinbutton , TRUE ) ;
1999-08-24 05:30:14 +00:00
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-25 17:46:56 +00:00
GTK_SIGNAL_FUNC ( gimp_int_adjustment_update ) ,
2000-01-15 15:32:28 +00:00
& info . spacing ) ;
1999-08-24 05:30:14 +00:00
/*
* Description : ___________
*/
1999-08-22 19:02:52 +00:00
entry = gtk_entry_new ( ) ;
gtk_widget_set_usize ( entry , 200 , 0 ) ;
gtk_entry_set_text ( GTK_ENTRY ( entry ) , info . description ) ;
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 1 ,
_ ( " Description: " ) , 1.0 , 0.5 ,
entry , FALSE ) ;
1999-08-22 19:02:52 +00:00
gtk_signal_connect ( GTK_OBJECT ( entry ) , " changed " ,
2000-01-15 15:32:28 +00:00
GTK_SIGNAL_FUNC ( entry_callback ) ,
info . description ) ;
1999-08-24 05:30:14 +00:00
}
static gint
2000-01-06 22:26:10 +00:00
gpb_save_dialog ( void )
1999-08-24 05:30:14 +00:00
{
GtkWidget * dlg ;
GtkWidget * table ;
2000-01-06 22:26:10 +00:00
dlg = gimp_dialog_new ( _ ( " Save as Pixmap Brush " ) , " gpb " ,
gimp_plugin_help_func , " filters/gpb.html " ,
GTK_WIN_POS_MOUSE ,
FALSE , TRUE , FALSE ,
NULL ) ;
1999-08-24 05:30:14 +00:00
gtk_signal_connect ( GTK_OBJECT ( dlg ) , " destroy " ,
2000-01-06 22:26:10 +00:00
GTK_SIGNAL_FUNC ( gtk_main_quit ) ,
NULL ) ;
1999-08-24 05:30:14 +00:00
/* The main table */
2000-01-15 15:32:28 +00:00
table = gtk_table_new ( 2 , 2 , FALSE ) ;
2000-01-25 17:46:56 +00:00
gtk_table_set_row_spacings ( GTK_TABLE ( table ) , 4 ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( table ) , 4 ) ;
2000-01-15 15:32:28 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( table ) , 6 ) ;
1999-08-24 05:30:14 +00:00
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dlg ) - > vbox ) , table , TRUE , TRUE , 0 ) ;
gtk_widget_show ( table ) ;
common_save_dialog ( dlg , table ) ;
1999-08-22 19:02:52 +00:00
gtk_widget_show ( dlg ) ;
gtk_main ( ) ;
gdk_flush ( ) ;
return run_flag ;
}
1999-08-24 05:30:14 +00:00
static gint
1999-09-02 00:01:41 +00:00
gih_save_dialog ( gint32 image_ID )
1999-08-24 05:30:14 +00:00
{
GtkWidget * dlg ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
GtkWidget * table , * dimtable ;
1999-08-24 05:30:14 +00:00
GtkWidget * label ;
GtkObject * adjustment ;
GtkWidget * spinbutton ;
GtkWidget * box ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
GtkWidget * cb ;
GList * cbitems = NULL ;
1999-08-24 05:30:14 +00:00
gint i ;
gchar buffer [ 100 ] ;
1999-09-02 00:01:41 +00:00
SizeAdjustmentData cellw_adjust , cellh_adjust ;
gint32 * layer_ID ;
gint32 nlayers ;
1999-08-24 05:30:14 +00:00
/* Setup default values */
if ( gihparms . rows > = 1 & & gihparms . cols > = 1 )
gihparms . ncells = num_layers_with_alpha * gihparms . rows * gihparms . cols ;
else
1999-09-02 00:01:41 +00:00
gihparms . ncells = num_layers_with_alpha ;
if ( gihparms . cellwidth = = 1 & & gihparms . cellheight = = 1 )
{
gihparms . cellwidth = gimp_image_width ( image_ID ) / gihparms . cols ;
gihparms . cellheight = gimp_image_height ( image_ID ) / gihparms . rows ;
}
1999-08-24 05:30:14 +00:00
2000-01-06 22:26:10 +00:00
dlg = gimp_dialog_new ( _ ( " Save as Pixmap Brush Pipe " ) , " gpb " ,
gimp_plugin_help_func , " filters/gpb.html " ,
GTK_WIN_POS_MOUSE ,
FALSE , TRUE , FALSE ,
NULL ) ;
1999-08-24 05:30:14 +00:00
gtk_signal_connect ( GTK_OBJECT ( dlg ) , " destroy " ,
2000-01-06 22:26:10 +00:00
GTK_SIGNAL_FUNC ( gtk_main_quit ) ,
NULL ) ;
1999-08-24 05:30:14 +00:00
/* The main table */
2000-01-25 17:46:56 +00:00
table = gtk_table_new ( 8 , 2 , FALSE ) ;
gtk_table_set_row_spacings ( GTK_TABLE ( table ) , 4 ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( table ) , 4 ) ;
gtk_container_set_border_width ( GTK_CONTAINER ( table ) , 6 ) ;
1999-08-24 05:30:14 +00:00
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dlg ) - > vbox ) , table , TRUE , TRUE , 0 ) ;
gtk_widget_show ( table ) ;
common_save_dialog ( dlg , table ) ;
1999-09-02 00:01:41 +00:00
/*
* Cell size : __ x __ pixels
*/
2000-01-15 15:32:28 +00:00
box = gtk_hbox_new ( FALSE , 4 ) ;
spinbutton = gimp_spin_button_new ( & adjustment ,
gihparms . cellwidth ,
2 , gimp_image_width ( image_ID ) , 1 , 1 , 1 ,
1 , 0 ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , spinbutton , FALSE , FALSE , 0 ) ;
layer_ID = gimp_image_get_layers ( image_ID , & nlayers ) ;
cellw_adjust . orientation = ORIENTATION_VERTICAL ;
cellw_adjust . image = image_ID ;
cellw_adjust . toplayer = layer_ID [ nlayers - 1 ] ;
cellw_adjust . nguides = 0 ;
cellw_adjust . guides = NULL ;
cellw_adjust . value = & gihparms . cellwidth ;
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-15 15:32:28 +00:00
GTK_SIGNAL_FUNC ( size_adjustment_callback ) ,
1999-09-02 00:01:41 +00:00
& cellw_adjust ) ;
gtk_widget_show ( spinbutton ) ;
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( " x " ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
gtk_widget_show ( label ) ;
2000-01-15 15:32:28 +00:00
spinbutton = gimp_spin_button_new ( & adjustment ,
gihparms . cellheight ,
gimp_image_height ( image_ID ) , 1 , 1 , 1 , 1 ,
1 , 0 ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , spinbutton , FALSE , FALSE , 0 ) ;
cellh_adjust . orientation = ORIENTATION_HORIZONTAL ;
cellh_adjust . image = image_ID ;
cellh_adjust . toplayer = layer_ID [ nlayers - 1 ] ;
cellh_adjust . nguides = 0 ;
cellh_adjust . guides = NULL ;
cellh_adjust . value = & gihparms . cellheight ;
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-15 15:32:28 +00:00
GTK_SIGNAL_FUNC ( size_adjustment_callback ) ,
1999-09-02 00:01:41 +00:00
& cellh_adjust ) ;
gtk_widget_show ( spinbutton ) ;
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( _ ( " Pixels " ) ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
gtk_widget_show ( label ) ;
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 2 ,
_ ( " Cell Size: " ) , 1.0 , 0.5 ,
box , FALSE ) ;
1999-09-02 00:01:41 +00:00
g_free ( layer_ID ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
/*
* Number of cells : ___
*/
2000-01-15 15:32:28 +00:00
spinbutton = gimp_spin_button_new ( & adjustment ,
gihparms . ncells , 1 , 1000 , 1 , 10 , 10 ,
1 , 0 ) ;
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 3 ,
_ ( " Number of Cells: " ) , 1.0 , 0.5 ,
spinbutton , TRUE ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-25 17:46:56 +00:00
GTK_SIGNAL_FUNC ( gimp_int_adjustment_update ) ,
2000-01-15 15:32:28 +00:00
& gihparms . ncells ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
1999-09-02 00:01:41 +00:00
if ( gihparms . dim = = 1 )
cellw_adjust . ncells = cellh_adjust . ncells = adjustment ;
else
cellw_adjust . ncells = cellh_adjust . ncells = NULL ;
1999-08-24 05:30:14 +00:00
/*
* Display as : __ rows x __ cols
*/
box = gtk_hbox_new ( FALSE , 0 ) ;
2000-01-15 15:32:28 +00:00
g_snprintf ( buffer , sizeof ( buffer ) , " %2d " , gihparms . rows ) ;
1999-09-02 00:01:41 +00:00
label = gtk_label_new ( buffer ) ;
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
cellh_adjust . count_label = label ;
cellh_adjust . count = & gihparms . rows ;
cellh_adjust . other_count = & gihparms . cols ;
gtk_widget_show ( label ) ;
1999-08-24 05:30:14 +00:00
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( _ ( " Rows of " ) ) ;
1999-08-24 05:30:14 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
gtk_widget_show ( label ) ;
2000-01-15 15:32:28 +00:00
g_snprintf ( buffer , sizeof ( buffer ) , " %2d " , gihparms . cols ) ;
1999-09-02 00:01:41 +00:00
label = gtk_label_new ( buffer ) ;
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
cellw_adjust . count_label = label ;
cellw_adjust . count = & gihparms . cols ;
cellw_adjust . other_count = & gihparms . rows ;
gtk_widget_show ( label ) ;
1999-08-24 05:30:14 +00:00
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( _ ( " Columns on each Layer " ) ) ;
1999-08-24 05:30:14 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
gtk_widget_show ( label ) ;
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( _ ( " (Width Mismatch!) " ) ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
cellw_adjust . warning_label = label ;
2000-01-15 15:32:28 +00:00
label = gtk_label_new ( _ ( " (Height Mismatch!) " ) ) ;
1999-09-02 00:01:41 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , label , FALSE , FALSE , 0 ) ;
cellh_adjust . warning_label = label ;
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 4 ,
_ ( " Display as: " ) , 1.0 , 0.5 ,
box , FALSE ) ;
1999-08-24 05:30:14 +00:00
/*
* Dimension : ___
*/
2000-01-25 17:46:56 +00:00
spinbutton = gimp_spin_button_new ( & adjustment , gihparms . dim ,
1 , 5 , 1 , 1 , 1 , 1 , 0 ) ;
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 5 ,
_ ( " Dimension: " ) , 1.0 , 0.5 ,
spinbutton , TRUE ) ;
1999-08-24 05:30:14 +00:00
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-25 17:46:56 +00:00
GTK_SIGNAL_FUNC ( gimp_int_adjustment_update ) ,
& gihparms . dim ) ;
1999-08-24 05:30:14 +00:00
/*
* Ranks : __ __ __ __ __
*/
2000-01-15 15:32:28 +00:00
dimtable = gtk_table_new ( 1 , PIXPIPE_MAXDIM , FALSE ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( dimtable ) , 4 ) ;
1999-09-02 00:01:41 +00:00
for ( i = 0 ; i < PIXPIPE_MAXDIM ; i + + )
1999-08-24 05:30:14 +00:00
{
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
box = gtk_hbox_new ( FALSE , 0 ) ;
gtk_table_attach ( GTK_TABLE ( dimtable ) , box , i , i + 1 , 0 , 1 ,
2000-01-15 15:32:28 +00:00
GTK_EXPAND | GTK_FILL , GTK_EXPAND | GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( box ) ;
spinbutton = gimp_spin_button_new ( & adjustment ,
gihparms . rank [ i ] , 0 , 100 , 1 , 1 , 1 ,
1 , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( box ) , spinbutton , FALSE , TRUE , 0 ) ;
1999-08-24 05:30:14 +00:00
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
2000-01-25 17:46:56 +00:00
GTK_SIGNAL_FUNC ( gimp_int_adjustment_update ) ,
2000-01-15 15:32:28 +00:00
& gihparms . rank [ i ] ) ;
1999-08-24 05:30:14 +00:00
gtk_widget_show ( spinbutton ) ;
1999-09-02 00:01:41 +00:00
if ( i = = 0 )
1999-10-08 20:09:04 +00:00
{
if ( gihparms . dim = = 1 )
cellw_adjust . rank0 = cellh_adjust . rank0 = adjustment ;
else
cellw_adjust . rank0 = cellh_adjust . rank0 = NULL ;
}
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
}
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 6 ,
_ ( " Ranks: " ) , 1.0 , 0.5 ,
dimtable , FALSE ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
/*
* Selection : ______ ______ ______ ______ ______
*/
cbitems = g_list_append ( cbitems , " incremental " ) ;
cbitems = g_list_append ( cbitems , " angular " ) ;
cbitems = g_list_append ( cbitems , " random " ) ;
cbitems = g_list_append ( cbitems , " velocity " ) ;
cbitems = g_list_append ( cbitems , " pressure " ) ;
cbitems = g_list_append ( cbitems , " xtilt " ) ;
cbitems = g_list_append ( cbitems , " ytilt " ) ;
2000-01-25 17:46:56 +00:00
box = gtk_hbox_new ( TRUE , 4 ) ;
1999-09-02 00:01:41 +00:00
for ( i = 0 ; i < PIXPIPE_MAXDIM ; i + + )
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
{
cb = gtk_combo_new ( ) ;
gtk_combo_set_popdown_strings ( GTK_COMBO ( cb ) , cbitems ) ;
if ( gihparms . selection [ i ] )
2000-01-15 15:32:28 +00:00
gtk_entry_set_text ( GTK_ENTRY ( GTK_COMBO ( cb ) - > entry )
, gihparms . selection [ i ] ) ;
1999-08-31 16:49:46 +00:00
else
gtk_entry_set_text ( GTK_ENTRY ( GTK_COMBO ( cb ) - > entry ) , " random " ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
gtk_entry_set_editable ( GTK_ENTRY ( GTK_COMBO ( cb ) - > entry ) , FALSE ) ;
2000-01-15 15:32:28 +00:00
gtk_box_pack_start ( GTK_BOX ( box ) , cb , FALSE , TRUE , 0 ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
gtk_signal_connect ( GTK_OBJECT ( GTK_COMBO ( cb ) - > entry ) , " changed " ,
2000-01-15 15:32:28 +00:00
GTK_SIGNAL_FUNC ( cb_callback ) ,
& gihparms . selection [ i ] ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
gtk_widget_show ( cb ) ;
1999-08-24 05:30:14 +00:00
}
2000-01-25 17:46:56 +00:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 7 ,
_ ( " Selection: " ) , 1.0 , 0.5 ,
box , FALSE ) ;
2000-01-15 15:32:28 +00:00
1999-08-24 05:30:14 +00:00
gtk_widget_show ( dlg ) ;
gtk_main ( ) ;
gdk_flush ( ) ;
1999-09-02 00:01:41 +00:00
for ( i = 0 ; i < cellw_adjust . nguides ; i + + )
gimp_image_delete_guide ( image_ID , cellw_adjust . guides [ i ] ) ;
for ( i = 0 ; i < cellh_adjust . nguides ; i + + )
gimp_image_delete_guide ( image_ID , cellh_adjust . guides [ i ] ) ;
1999-08-24 05:30:14 +00:00
if ( run_flag )
{
/* Fix up bogus values */
gihparms . ncells =
MIN ( gihparms . ncells ,
num_layers_with_alpha * gihparms . rows * gihparms . cols ) ;
}
return run_flag ;
}
1999-08-22 19:02:52 +00:00
static gboolean
try_fwrite ( gpointer buffer ,
guint size ,
guint nitems ,
FILE * file )
{
if ( fwrite ( buffer , size , nitems , file ) < nitems )
{
1999-12-28 20:04:19 +00:00
g_message ( " GPB: write error " ) ;
1999-08-22 19:02:52 +00:00
fclose ( file ) ;
return FALSE ;
}
return TRUE ;
}
static gboolean
1999-08-24 05:30:14 +00:00
save_one_gpb ( FILE * file ,
GPixelRgn * pixel_rgn ,
int index ,
int total )
1999-08-22 19:02:52 +00:00
{
BrushHeader brushheader ;
PatternHeader patternheader ;
1999-08-24 05:30:14 +00:00
guint y , x ;
guchar * buffer ;
guint width , height ;
width = pixel_rgn - > w ;
height = pixel_rgn - > h ;
brushheader . header_size = g_htonl ( sizeof ( brushheader ) + strlen ( info . description ) + 1 ) ;
brushheader . version = g_htonl ( 2 ) ;
brushheader . width = g_htonl ( width ) ;
brushheader . height = g_htonl ( height ) ;
brushheader . bytes = g_htonl ( 1 ) ;
brushheader . magic_number = g_htonl ( GBRUSH_MAGIC ) ;
brushheader . spacing = g_htonl ( info . spacing ) ;
if ( ! try_fwrite ( & brushheader , sizeof ( brushheader ) , 1 , file ) )
return FALSE ;
if ( ! try_fwrite ( info . description , strlen ( info . description ) + 1 , 1 , file ) )
return FALSE ;
IFDBG ( 3 ) g_message ( " saving gpb %d of %d: %dx%d, offset %d,%d stride %d drawable %d " ,
index + 1 , total ,
width , height , pixel_rgn - > x , pixel_rgn - > y ,
pixel_rgn - > rowstride , pixel_rgn - > drawable - > id ) ;
buffer = g_malloc ( width * pixel_rgn - > bpp ) ;
for ( y = 0 ; y < height ; y + + )
{
#if 0
/* No; the brushes don't have to be the same size, of course. */
if ( y > = pixel_rgn - > h )
{
if ( y = = pixel_rgn - > h )
memset ( buffer , 0 , width ) ;
if ( ! try_fwrite ( buffer , width , 1 , file ) )
{
g_free ( buffer ) ;
return FALSE ;
}
}
else
# endif
{
gimp_pixel_rgn_get_row ( pixel_rgn , buffer ,
0 + pixel_rgn - > x , y + pixel_rgn - > y ,
pixel_rgn - > w ) ;
for ( x = 0 ; x < pixel_rgn - > w ; x + + )
if ( ! try_fwrite ( buffer + x * pixel_rgn - > bpp + 3 , 1 , 1 , file ) )
{
g_free ( buffer ) ;
return FALSE ;
}
#if 0
if ( width > pixel_rgn - > w )
{
memset ( buffer , 0 , width - pixel_rgn - > w ) ;
if ( ! try_fwrite ( buffer , width - pixel_rgn - > w , 1 , file ) )
{
g_free ( buffer ) ;
return FALSE ;
}
}
# endif
}
if ( y % 10 = = 0 )
gimp_progress_update
( ( ( double ) index + 0.5 * y / pixel_rgn - > h ) / total ) ;
}
gimp_progress_update ( ( ( double ) index + 0.5 ) / total ) ;
patternheader . header_size = g_htonl ( sizeof ( patternheader ) + strlen ( DUMMY_PATTERN_NAME ) + 1 ) ;
patternheader . version = g_htonl ( 1 ) ;
patternheader . width = g_htonl ( width ) ;
patternheader . height = g_htonl ( height ) ;
patternheader . bytes = g_htonl ( 3 ) ;
patternheader . magic_number = g_htonl ( GPATTERN_MAGIC ) ;
if ( ! try_fwrite ( & patternheader , sizeof ( patternheader ) , 1 , file ) )
return FALSE ;
/* Pattern name is irrelevant */
if ( ! try_fwrite ( DUMMY_PATTERN_NAME , strlen ( DUMMY_PATTERN_NAME ) + 1 , 1 , file ) )
return FALSE ;
for ( y = 0 ; y < height ; y + + )
{
#if 0
if ( y > = pixel_rgn - > h )
{
if ( y = = pixel_rgn - > h )
memset ( buffer , 0 , width * 3 ) ;
if ( ! try_fwrite ( buffer , width * 3 , 1 , file ) )
{
g_free ( buffer ) ;
return FALSE ;
}
}
else
# endif
{
gimp_pixel_rgn_get_row ( pixel_rgn , buffer ,
0 + pixel_rgn - > x , y + pixel_rgn - > y , pixel_rgn - > w ) ;
for ( x = 0 ; x < pixel_rgn - > w ; x + + )
if ( ! try_fwrite ( buffer + x * pixel_rgn - > bpp , 3 , 1 , file ) )
return FALSE ;
#if 0
if ( width > pixel_rgn - > w )
{
memset ( buffer , 0 , ( width - pixel_rgn - > w ) * 3 ) ;
if ( ! try_fwrite ( buffer , ( width - pixel_rgn - > w ) * 3 , 1 , file ) )
{
g_free ( buffer ) ;
return FALSE ;
}
}
# endif
}
if ( y % 10 = = 0 )
gimp_progress_update
( ( ( double ) index + 0.5 + 0.5 * y / pixel_rgn - > h ) / total ) ;
}
g_free ( buffer ) ;
gimp_progress_update ( ( ( double ) index + 1.0 ) / total ) ;
return TRUE ;
}
static gboolean
gpb_save_image ( char * filename ,
gint32 image_ID ,
gint32 drawable_ID )
{
1999-08-22 19:02:52 +00:00
GDrawable * drawable ;
1999-08-24 05:30:14 +00:00
GPixelRgn pixel_rgn ;
1999-08-22 19:02:52 +00:00
FILE * file ;
gchar * temp ;
1999-10-08 20:09:04 +00:00
if ( ! ( gimp_drawable_has_alpha ( drawable_ID ) ) )
{
1999-12-28 20:04:19 +00:00
g_warning ( " drawable has no alpha channel -- aborting! \n " ) ;
1999-10-08 20:09:04 +00:00
return ( FALSE ) ;
}
1999-08-22 19:02:52 +00:00
drawable = gimp_drawable_get ( drawable_ID ) ;
gimp_tile_cache_size ( gimp_tile_height ( ) * drawable - > width * 4 ) ;
gimp_pixel_rgn_init ( & pixel_rgn , drawable , 0 , 0 , drawable - > width , drawable - > height , FALSE , FALSE ) ;
1999-12-25 21:49:51 +00:00
temp = g_strdup_printf ( _ ( " Saving %s: " ) , filename ) ;
1999-08-22 19:02:52 +00:00
gimp_progress_init ( temp ) ;
g_free ( temp ) ;
file = fopen ( filename , " wb " ) ;
if ( file = = NULL )
{
1999-12-28 20:04:19 +00:00
g_message ( " GPB: can't open \" %s \" " , filename ) ;
1999-08-22 19:02:52 +00:00
return FALSE ;
}
1999-08-24 05:30:14 +00:00
if ( ! save_one_gpb ( file , & pixel_rgn , 0 , 1 ) )
1999-08-22 19:02:52 +00:00
return FALSE ;
1999-08-24 05:30:14 +00:00
fclose ( file ) ;
return TRUE ;
}
static gboolean
gih_save_image ( char * filename ,
gint32 image_ID ,
1999-10-08 20:09:04 +00:00
gint32 orig_image_ID ,
1999-08-24 05:30:14 +00:00
gint32 drawable_ID )
{
GDrawable * drawable ;
GPixelRgn pixel_rgn ;
FILE * file ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
Parasite * pipe_parasite ;
1999-09-02 00:01:41 +00:00
gchar * msg , * parstring , * ncells ;
1999-08-24 05:30:14 +00:00
gint32 * layer_ID ;
gint nlayers , layer , row , col ;
gint imagew , imageh , offsetx , offsety ;
gint k , x , y , thisx , thisy , xnext , ynext , thisw , thish ;
imagew = gimp_image_width ( image_ID ) ;
imageh = gimp_image_height ( image_ID ) ;
gimp_tile_cache_size ( gimp_tile_height ( ) * imagew * 4 ) ;
1999-12-25 21:49:51 +00:00
msg = g_strdup_printf ( _ ( " Saving %s: " ) , filename ) ;
1999-08-24 05:30:14 +00:00
gimp_progress_init ( msg ) ;
g_free ( msg ) ;
file = fopen ( filename , " wb " ) ;
if ( file = = NULL )
{
1999-12-28 20:04:19 +00:00
g_message ( " GPB: can't open \" %s \" " , filename ) ;
1999-08-24 05:30:14 +00:00
return FALSE ;
}
1999-09-02 00:01:41 +00:00
parstring = pixpipeparams_build ( & gihparms ) ;
IFDBG ( 2 ) g_message ( " parameter string: %s " , parstring ) ;
1999-08-24 05:30:14 +00:00
ncells = g_strdup_printf ( " %d " , gihparms . ncells ) ;
if ( ! ( try_fwrite ( info . description , strlen ( info . description ) , 1 , file )
& & try_fwrite ( " \n " , 1 , 1 , file )
& & try_fwrite ( ncells , strlen ( ncells ) , 1 , file )
1999-09-02 00:01:41 +00:00
& & try_fwrite ( parstring , strlen ( parstring ) , 1 , file )
1999-08-24 05:30:14 +00:00
& & try_fwrite ( " \n " , 1 , 1 , file ) ) )
1999-08-22 19:02:52 +00:00
{
1999-09-02 00:01:41 +00:00
g_free ( parstring ) ;
1999-08-24 05:30:14 +00:00
g_free ( ncells ) ;
return FALSE ;
1999-08-22 19:02:52 +00:00
}
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
pipe_parasite = parasite_new ( " gimp-brush-pipe-parameters " ,
PARASITE_PERSISTENT ,
1999-09-02 00:01:41 +00:00
strlen ( parstring ) + 1 , parstring ) ;
1999-10-17 00:07:55 +00:00
gimp_image_parasite_attach ( orig_image_ID , pipe_parasite ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
parasite_free ( pipe_parasite ) ;
1999-09-02 00:01:41 +00:00
g_free ( parstring ) ;
1999-08-24 05:30:14 +00:00
g_free ( ncells ) ;
layer_ID = gimp_image_get_layers ( image_ID , & nlayers ) ;
k = 0 ;
for ( layer = 0 ; layer < nlayers ; layer + + )
{
if ( ! gimp_drawable_has_alpha ( layer_ID [ layer ] ) )
continue ;
drawable = gimp_drawable_get ( layer_ID [ layer ] ) ;
gimp_drawable_offsets ( layer_ID [ layer ] , & offsetx , & offsety ) ;
1999-08-22 19:02:52 +00:00
1999-08-24 05:30:14 +00:00
for ( row = 0 ; row < gihparms . rows ; row + + )
{
y = ( row * imageh ) / gihparms . rows ;
ynext = ( ( row + 1 ) * imageh / gihparms . rows ) ;
/* Assume layer is offset to positive direction in x and y.
* That ' s reasonable , as otherwise all of the layer
* won ' t be visible .
* thisy and thisx are in the drawable ' s coordinate space .
*/
thisy = MAX ( 0 , y - offsety ) ;
thish = ( ynext - offsety ) - thisy ;
thish = MIN ( thish , drawable - > height - thisy ) ;
for ( col = 0 ; col < gihparms . cols ; col + + )
{
x = ( col * imagew / gihparms . cols ) ;
xnext = ( ( col + 1 ) * imagew / gihparms . cols ) ;
thisx = MAX ( 0 , x - offsetx ) ;
thisw = ( xnext - offsetx ) - thisx ;
thisw = MIN ( thisw , drawable - > width - thisx ) ;
IFDBG ( 3 ) g_message ( " gimp_pixel_rgn_init %d %d %d %d " ,
thisx , thisy , thisw , thish ) ;
gimp_pixel_rgn_init ( & pixel_rgn , drawable , thisx , thisy ,
thisw , thish , FALSE , FALSE ) ;
if ( ! save_one_gpb ( file , & pixel_rgn , k , gihparms . ncells ) )
return FALSE ;
k + + ;
}
}
}
1999-08-22 19:02:52 +00:00
gimp_progress_update ( 1.0 ) ;
fclose ( file ) ;
return TRUE ;
}
static void
run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals )
{
static GParam values [ 1 ] ;
2000-01-25 17:46:56 +00:00
GRunModeType run_mode ;
GStatusType status = STATUS_SUCCESS ;
Parasite * pipe_parasite ;
gint32 image_ID ;
gint32 orig_image_ID ;
gint32 drawable_ID ;
gint32 * layer_ID ;
gint nlayers , layer ;
gchar * layer_name ;
1999-10-08 20:09:04 +00:00
GimpExportReturnType export = EXPORT_CANCEL ;
1999-08-22 19:02:52 +00:00
run_mode = param [ 0 ] . data . d_int32 ;
2000-01-25 17:46:56 +00:00
* return_vals = values ;
1999-08-22 19:02:52 +00:00
* nreturn_vals = 1 ;
2000-01-25 17:46:56 +00:00
values [ 0 ] . type = PARAM_STATUS ;
values [ 0 ] . data . d_status = STATUS_EXECUTION_ERROR ;
1999-08-22 19:02:52 +00:00
2000-01-15 15:32:28 +00:00
if ( run_mode = = RUN_INTERACTIVE )
{
INIT_I18N_UI ( ) ;
}
else
{
INIT_I18N ( ) ;
}
2000-01-01 07:35:13 +00:00
1999-08-22 19:02:52 +00:00
if ( strcmp ( name , " file_gpb_save " ) = = 0 )
{
1999-10-08 20:09:04 +00:00
image_ID = param [ 1 ] . data . d_int32 ;
drawable_ID = param [ 2 ] . data . d_int32 ;
/* eventually export the image */
switch ( run_mode )
{
case RUN_INTERACTIVE :
case RUN_WITH_LAST_VALS :
init_gtk ( ) ;
export = gimp_export_image ( & image_ID , & drawable_ID , " GPB " ,
2000-01-25 17:46:56 +00:00
( CAN_HANDLE_RGB |
CAN_HANDLE_ALPHA |
1999-10-09 00:11:50 +00:00
NEEDS_ALPHA ) ) ;
1999-10-08 20:09:04 +00:00
if ( export = = EXPORT_CANCEL )
{
2000-01-25 17:46:56 +00:00
values [ 0 ] . data . d_status = STATUS_CANCEL ;
1999-10-08 20:09:04 +00:00
return ;
}
break ;
default :
break ;
}
switch ( run_mode )
{
case RUN_INTERACTIVE :
/* Possibly retrieve data */
gimp_get_data ( " file_gpb_save " , & info ) ;
if ( ! gpb_save_dialog ( ) )
2000-01-25 17:46:56 +00:00
status = STATUS_CANCEL ;
1999-10-08 20:09:04 +00:00
break ;
case RUN_NONINTERACTIVE : /* FIXME - need a real RUN_NONINTERACTIVE */
if ( nparams ! = 7 )
2000-01-25 17:46:56 +00:00
{
status = STATUS_CALLING_ERROR ;
}
else
1999-10-08 20:09:04 +00:00
{
info . spacing = param [ 5 ] . data . d_int32 ;
strncpy ( info . description , param [ 6 ] . data . d_string , MAXDESCLEN ) ;
info . description [ MAXDESCLEN ] = 0 ;
}
break ;
2000-01-25 17:46:56 +00:00
1999-10-08 20:09:04 +00:00
case RUN_WITH_LAST_VALS :
gimp_get_data ( " file_gpb_save " , & info ) ;
break ;
}
2000-01-25 17:46:56 +00:00
if ( status = = STATUS_SUCCESS )
1999-08-22 20:08:15 +00:00
{
2000-01-25 17:46:56 +00:00
if ( gpb_save_image ( param [ 3 ] . data . d_string , image_ID , drawable_ID ) )
{
gimp_set_data ( " file_gpb_save " , & info , sizeof ( info ) ) ;
}
else
{
status = STATUS_EXECUTION_ERROR ;
}
1999-08-22 20:08:15 +00:00
}
1999-08-22 19:02:52 +00:00
}
1999-08-24 05:30:14 +00:00
else if ( strcmp ( name , " file_gih_save " ) = = 0 )
{
1999-10-08 20:09:04 +00:00
image_ID = orig_image_ID = param [ 1 ] . data . d_int32 ;
drawable_ID = param [ 2 ] . data . d_int32 ;
/* eventually export the image */
switch ( run_mode )
{
case RUN_INTERACTIVE :
case RUN_WITH_LAST_VALS :
init_gtk ( ) ;
export = gimp_export_image ( & image_ID , & drawable_ID , " GIH " ,
2000-01-25 17:46:56 +00:00
( CAN_HANDLE_RGB |
CAN_HANDLE_ALPHA |
CAN_HANDLE_LAYERS |
NEEDS_ALPHA ) ) ;
1999-10-08 20:09:04 +00:00
if ( export = = EXPORT_CANCEL )
{
2000-01-25 17:46:56 +00:00
values [ 0 ] . data . d_status = STATUS_CANCEL ;
1999-10-08 20:09:04 +00:00
return ;
}
break ;
default :
break ;
}
1999-08-24 05:30:14 +00:00
layer_ID = gimp_image_get_layers ( image_ID , & nlayers ) ;
num_layers_with_alpha = 0 ;
for ( layer = 0 ; layer < nlayers ; layer + + )
{
if ( ! gimp_drawable_has_alpha ( layer_ID [ layer ] ) )
{
layer_name = gimp_layer_get_name ( layer_ID [ layer ] ) ;
2000-01-25 17:46:56 +00:00
g_message ( _ ( " Layer %s doesn't have an alpha channel, skipped " ) ,
1999-08-24 05:30:14 +00:00
layer_name ) ;
g_free ( layer_name ) ;
}
num_layers_with_alpha + + ;
}
2000-01-25 17:46:56 +00:00
1999-08-24 05:30:14 +00:00
IFDBG ( 2 ) g_message ( " nlayers:%d num_layers_with_alpha:%d " ,
nlayers , num_layers_with_alpha ) ;
switch ( run_mode )
{
case RUN_INTERACTIVE :
/* Possibly retrieve data */
gimp_get_data ( " file_gih_save " , & info ) ;
2000-01-25 17:46:56 +00:00
pipe_parasite =
gimp_image_parasite_find ( orig_image_ID ,
" gimp-brush-pipe-parameters " ) ;
1999-09-02 00:01:41 +00:00
pixpipeparams_init ( & gihparms ) ;
1999-08-24 05:30:14 +00:00
if ( pipe_parasite )
1999-09-02 00:01:41 +00:00
pixpipeparams_parse ( pipe_parasite - > data , & gihparms ) ;
Implement the selection of brush based on cursor direction, pressure,
1999-08-28 Tor Lillqvist <tml@iki.fi>
* app/gimpbrushpipe.c: Implement the selection of brush based on
cursor direction, pressure, tilt, or a random value. (Hmm, forgot
velocity, later.) (In addition to just incrementally stepping.)
Read the brush pipe parameters from the gih file's second line.
There is no way to tune the parameters in the GIMP, they must
currently be set when saving the gih file (in the gpb plug-in).
* app/gimpbrushpipe.h
* app/gimpbrushpipeP.h: Move the PipeSelectModes enum to the
"private" header. Add a stride array to GimpBrushPipe to make
indexing easier.
* plug-ins/common/gpb.c: Add selection mode fields to the dialog.
Attach the pipe parameters entered as a parasite, too.
* docs/parasites.txt
* plug-ins/common/psp.c: Use "placement", not "spacing" (which
means another thing).
1999-08-28 01:14:42 +00:00
1999-09-02 00:01:41 +00:00
if ( ! gih_save_dialog ( image_ID ) )
2000-01-25 17:46:56 +00:00
status = STATUS_CANCEL ;
1999-08-24 05:30:14 +00:00
break ;
case RUN_NONINTERACTIVE : /* FIXME - need a real RUN_NONINTERACTIVE */
if ( nparams ! = 7 )
2000-01-25 17:46:56 +00:00
{
status = STATUS_CALLING_ERROR ;
}
else
1999-08-24 05:30:14 +00:00
{
info . spacing = param [ 5 ] . data . d_int32 ;
strncpy ( info . description , param [ 6 ] . data . d_string , MAXDESCLEN ) ;
info . description [ MAXDESCLEN ] = 0 ;
}
break ;
case RUN_WITH_LAST_VALS :
gimp_get_data ( " file_gih_save " , & info ) ;
2000-01-25 17:46:56 +00:00
pipe_parasite =
gimp_image_parasite_find ( orig_image_ID ,
" gimp-brush-pipe-parameters " ) ;
1999-10-06 06:36:46 +00:00
pixpipeparams_init ( & gihparms ) ;
if ( pipe_parasite )
pixpipeparams_parse ( pipe_parasite - > data , & gihparms ) ;
1999-08-24 05:30:14 +00:00
break ;
}
2000-01-25 17:46:56 +00:00
if ( status = = STATUS_SUCCESS )
1999-08-24 05:30:14 +00:00
{
2000-01-25 17:46:56 +00:00
if ( gih_save_image ( param [ 3 ] . data . d_string ,
image_ID , orig_image_ID , drawable_ID ) )
{
gimp_set_data ( " file_gih_save " , & info , sizeof ( info ) ) ;
}
else
{
status = STATUS_EXECUTION_ERROR ;
}
1999-08-24 05:30:14 +00:00
}
}
2000-01-15 15:32:28 +00:00
2000-01-25 17:46:56 +00:00
if ( export = = EXPORT_EXPORT )
gimp_image_delete ( image_ID ) ;
1999-08-22 19:02:52 +00:00
values [ 0 ] . data . d_status = status ;
}