1997-11-25 06:05:25 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* 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
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1999-05-05 06:18:13 +08:00
|
|
|
|
1998-04-29 16:47:24 +08:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
Win32 portability changes:
* config.h.win32, README.win32: Small changes.
* tools/pdbgen/pdb/*.pdb: Include <string.h>.
* app/*_cmds.c: Autogenerated files reflect above changes.
* libgimp/makefile.msc app/makefile.msc: Various updates,
including new object files. Gtk+ directory now should be called
gtk+ (not gtk-plus). Use win32-specific gdk subdir. Glib directory
now should be called just glib.
* libgimp/gimp.def: Updates.
* libgimp/gimpfeatures.h.win32: Made current with
gimpfeatures.h.in.
* libgimp/gimpfileselection.c: Define S_ISDIR and S_ISREG if
necessary.
* tools/pdbgen/pdb/fileops.pdb: Must have a
statement (even an empty one) after a label.
* app/fileops_cmds.c: Autogenerated file reflects above changes.
* app/crop.c: Include <string.h>.
* app/{app_procs,batch,fileops,datafiles,errorconsole,general,
plug_in,temp_buf,tile_swap}.c: Test NATIVE_WIN32, not
_MSC_VER. (NATIVE_WIN32 means we are using the Microsoft C
runtime, even if we might be compiling with gcc.)
* app/fileops.c: Don't include <process.h> here.
* app/fileops.h: Do include <process.h> here.
* app/gimpparasite.c: Include config.h, guard inclusion of
<unistd.h>. (Is the inclusion of unistd.h in source files all over
the place really necessary?)
* app/ink.c: MSC doesn't handle conversion from unsigned __int64
to double, so cast to signed.
* app/lut_funcs.c: Include config.h, and define rint() if necessary.
* app/pixel_processor.c: Include config.h without "..", like in
all the other places. Include <string.h>
* app/text_tool.c: Guard the "POINTS" identifier that clashes with
<windows.h>, sigh.
1999-05-05 05:32:17 +08:00
|
|
|
#include <gdk/gdk.h>
|
2000-01-19 07:12:26 +08:00
|
|
|
|
|
|
|
#ifndef GDK_WINDOWING_WIN32
|
2000-01-16 02:06:15 +08:00
|
|
|
#include <gdk/gdkx.h>
|
2000-01-19 07:12:26 +08:00
|
|
|
#endif
|
1999-05-05 06:18:13 +08:00
|
|
|
|
|
|
|
#include <gdk/gdkprivate.h>
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "appenv.h"
|
|
|
|
#include "drawable.h"
|
|
|
|
#include "edit_selection.h"
|
|
|
|
#include "errors.h"
|
|
|
|
#include "floating_sel.h"
|
|
|
|
#include "gimage_mask.h"
|
2000-01-14 20:41:00 +08:00
|
|
|
#include "gimpui.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "global_edit.h"
|
1998-03-15 00:24:56 +08:00
|
|
|
#include "procedural_db.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "selection.h"
|
|
|
|
#include "text_tool.h"
|
|
|
|
#include "tools.h"
|
|
|
|
#include "undo.h"
|
|
|
|
|
1998-01-22 15:02:57 +08:00
|
|
|
#include "tile_manager_pvt.h"
|
|
|
|
#include "drawable_pvt.h"
|
|
|
|
|
2000-02-01 07:59:05 +08:00
|
|
|
#include "config.h"
|
1999-05-10 00:38:05 +08:00
|
|
|
#include "libgimp/gimplimits.h"
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
#define FOUNDRY 0
|
|
|
|
#define FAMILY 1
|
|
|
|
#define WEIGHT 2
|
|
|
|
#define SLANT 3
|
|
|
|
#define SET_WIDTH 4
|
|
|
|
#define PIXEL_SIZE 6
|
|
|
|
#define POINT_SIZE 7
|
1999-04-25 23:53:30 +08:00
|
|
|
#define XRESOLUTION 8
|
|
|
|
#define YRESOLUTION 9
|
1999-04-09 06:25:54 +08:00
|
|
|
#define SPACING 10
|
|
|
|
#define REGISTRY 12
|
|
|
|
#define ENCODING 13
|
|
|
|
|
|
|
|
/* the text tool structures */
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
typedef struct _TextTool TextTool;
|
1999-12-18 00:37:50 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
struct _TextTool
|
|
|
|
{
|
1999-12-18 00:37:50 +08:00
|
|
|
gint click_x;
|
|
|
|
gint click_y;
|
1999-05-10 01:39:07 +08:00
|
|
|
void *gdisp_ptr;
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
typedef struct _TextOptions TextOptions;
|
1999-12-18 00:37:50 +08:00
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
struct _TextOptions
|
|
|
|
{
|
1999-04-13 01:55:06 +08:00
|
|
|
ToolOptions tool_options;
|
1999-04-09 06:25:54 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
gboolean antialias;
|
|
|
|
gboolean antialias_d;
|
1999-04-13 01:55:06 +08:00
|
|
|
GtkWidget *antialias_w;
|
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
gint border;
|
|
|
|
gint border_d;
|
1999-04-13 01:55:06 +08:00
|
|
|
GtkObject *border_w;
|
1999-04-19 02:55:49 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
gboolean use_dyntext;
|
|
|
|
gboolean use_dyntext_d;
|
1999-04-19 02:55:49 +08:00
|
|
|
GtkWidget *use_dyntext_w;
|
1999-04-09 06:25:54 +08:00
|
|
|
};
|
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
|
|
|
|
/* the text tool options */
|
1999-04-09 06:25:54 +08:00
|
|
|
static TextOptions *text_options = NULL;
|
|
|
|
|
|
|
|
/* local variables */
|
1999-05-10 01:39:07 +08:00
|
|
|
static TextTool *the_text_tool = NULL;
|
|
|
|
static GtkWidget *text_tool_shell = NULL;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-06-22 06:12:07 +08:00
|
|
|
static void text_button_press (Tool *, GdkEventButton *, gpointer);
|
|
|
|
static void text_button_release (Tool *, GdkEventButton *, gpointer);
|
|
|
|
static void text_cursor_update (Tool *, GdkEventMotion *, gpointer);
|
|
|
|
static void text_control (Tool *, ToolAction, gpointer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
static void text_dialog_create (void);
|
|
|
|
static void text_dialog_ok_callback (GtkWidget *, gpointer);
|
|
|
|
static void text_dialog_cancel_callback (GtkWidget *, gpointer);
|
|
|
|
static gint text_dialog_delete_callback (GtkWidget *, GdkEvent *, gpointer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-06-22 06:12:07 +08:00
|
|
|
static void text_init_render (TextTool *);
|
1999-12-18 00:37:50 +08:00
|
|
|
static void text_gdk_image_to_region (GdkImage *, gint, PixelRegion *);
|
|
|
|
static void text_size_multiply (gchar **fontname, gint);
|
|
|
|
static void text_set_resolution (gchar **fontname, gdouble, gdouble);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-06-22 06:12:07 +08:00
|
|
|
Layer * text_render (GImage *, GimpDrawable *,
|
1999-12-18 00:37:50 +08:00
|
|
|
gint, gint, gchar *, gchar *, gint, gint);
|
1999-04-09 06:25:54 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
/* functions */
|
1999-04-09 06:25:54 +08:00
|
|
|
|
|
|
|
static void
|
1999-04-13 01:55:06 +08:00
|
|
|
text_options_reset (void)
|
1999-04-09 06:25:54 +08:00
|
|
|
{
|
|
|
|
TextOptions *options = text_options;
|
|
|
|
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w),
|
|
|
|
options->antialias_d);
|
|
|
|
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->border_w),
|
|
|
|
options->border_d);
|
1999-04-19 02:55:49 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_dyntext_w),
|
|
|
|
options->use_dyntext_d);
|
1999-04-09 06:25:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static TextOptions *
|
1999-04-13 01:55:06 +08:00
|
|
|
text_options_new (void)
|
1999-04-09 06:25:54 +08:00
|
|
|
{
|
|
|
|
TextOptions *options;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *spinbutton;
|
1999-04-19 02:55:49 +08:00
|
|
|
GtkWidget *sep;
|
1999-04-13 01:55:06 +08:00
|
|
|
|
|
|
|
/* the new text tool options structure */
|
2000-01-14 20:41:00 +08:00
|
|
|
options = g_new (TextOptions, 1);
|
1999-04-13 01:55:06 +08:00
|
|
|
tool_options_init ((ToolOptions *) options,
|
2000-02-01 05:27:00 +08:00
|
|
|
_("Text Tool"),
|
1999-04-13 01:55:06 +08:00
|
|
|
text_options_reset);
|
1999-04-19 02:55:49 +08:00
|
|
|
options->antialias = options->antialias_d = TRUE;
|
|
|
|
options->border = options->border_d = 0;
|
|
|
|
options->use_dyntext = options->use_dyntext_d = FALSE;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
/* the main vbox */
|
1999-04-13 01:55:06 +08:00
|
|
|
vbox = options->tool_options.main_vbox;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
/* antialias toggle */
|
1999-04-09 06:25:54 +08:00
|
|
|
options->antialias_w =
|
|
|
|
gtk_check_button_new_with_label (_("Antialiasing"));
|
|
|
|
gtk_signal_connect (GTK_OBJECT (options->antialias_w), "toggled",
|
2000-01-14 20:41:00 +08:00
|
|
|
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
1999-04-09 06:25:54 +08:00
|
|
|
&options->antialias);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w),
|
|
|
|
options->antialias_d);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), options->antialias_w,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (options->antialias_w);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
/* the border spinbutton */
|
1999-04-22 22:34:00 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
1999-04-13 01:55:06 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
label = gtk_label_new (_("Border:"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
1999-04-19 02:55:49 +08:00
|
|
|
gtk_widget_show (label);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
options->border_w =
|
|
|
|
gtk_adjustment_new (options->border_d, 0.0, 32767.0, 1.0, 50.0, 0.0);
|
1999-10-23 03:45:05 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (options->border_w), "value_changed",
|
2000-01-14 20:41:00 +08:00
|
|
|
GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
|
1999-04-19 02:55:49 +08:00
|
|
|
&options->border);
|
1999-04-09 06:25:54 +08:00
|
|
|
spinbutton =
|
|
|
|
gtk_spin_button_new (GTK_ADJUSTMENT (options->border_w), 1.0, 0.0);
|
|
|
|
gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton),
|
|
|
|
GTK_SHADOW_NONE);
|
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
|
|
|
|
gtk_widget_set_usize (spinbutton, 75, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (spinbutton);
|
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
gtk_widget_show (hbox);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-19 02:55:49 +08:00
|
|
|
sep = gtk_hseparator_new ();
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), sep, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (sep);
|
|
|
|
|
1999-05-19 01:33:39 +08:00
|
|
|
/* the dynamic text toggle */
|
1999-04-19 02:55:49 +08:00
|
|
|
options->use_dyntext_w =
|
|
|
|
gtk_check_button_new_with_label (_("Use Dynamic Text"));
|
|
|
|
gtk_signal_connect (GTK_OBJECT (options->use_dyntext_w), "toggled",
|
2000-01-14 20:41:00 +08:00
|
|
|
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
1999-04-19 02:55:49 +08:00
|
|
|
&options->use_dyntext);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_dyntext_w),
|
|
|
|
options->use_dyntext_d);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), options->use_dyntext_w,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (options->use_dyntext_w);
|
|
|
|
|
|
|
|
/* let the toggle callback set the sensitive states */
|
|
|
|
gtk_widget_set_sensitive (options->antialias_w, ! options->use_dyntext_d);
|
|
|
|
gtk_widget_set_sensitive (spinbutton, ! options->use_dyntext_d);
|
|
|
|
gtk_widget_set_sensitive (label, ! options->use_dyntext_d);
|
|
|
|
gtk_object_set_data (GTK_OBJECT (options->use_dyntext_w), "inverse_sensitive",
|
|
|
|
spinbutton);
|
|
|
|
gtk_object_set_data (GTK_OBJECT (spinbutton), "inverse_sensitive", label);
|
2000-02-24 08:51:00 +08:00
|
|
|
gtk_object_set_data (GTK_OBJECT (label), "inverse_sensitive",
|
|
|
|
options->antialias_w);
|
1999-04-19 02:55:49 +08:00
|
|
|
|
1999-04-09 06:25:54 +08:00
|
|
|
return options;
|
1998-10-07 16:59:11 +08:00
|
|
|
}
|
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
Tool*
|
1999-12-18 00:37:50 +08:00
|
|
|
tools_new_text (void)
|
1999-04-13 01:55:06 +08:00
|
|
|
{
|
1999-05-10 01:39:07 +08:00
|
|
|
Tool * tool;
|
1999-04-13 01:55:06 +08:00
|
|
|
|
|
|
|
/* The tool options */
|
|
|
|
if (! text_options)
|
|
|
|
{
|
|
|
|
text_options = text_options_new ();
|
|
|
|
tools_register (TEXT, (ToolOptions *) text_options);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the new text tool structure */
|
1999-07-03 01:40:10 +08:00
|
|
|
tool = tools_new_tool (TEXT);
|
|
|
|
the_text_tool = g_new (TextTool, 1);
|
1999-04-13 01:55:06 +08:00
|
|
|
|
1999-07-03 01:40:10 +08:00
|
|
|
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
1999-04-13 01:55:06 +08:00
|
|
|
|
1999-07-03 01:40:10 +08:00
|
|
|
tool->private = (void *) the_text_tool;
|
1999-06-26 19:16:47 +08:00
|
|
|
|
1999-07-03 01:40:10 +08:00
|
|
|
tool->button_press_func = text_button_press;
|
1999-04-13 01:55:06 +08:00
|
|
|
tool->button_release_func = text_button_release;
|
1999-07-03 01:40:10 +08:00
|
|
|
tool->cursor_update_func = text_cursor_update;
|
|
|
|
tool->control_func = text_control;
|
1999-06-22 06:12:07 +08:00
|
|
|
|
1999-04-13 01:55:06 +08:00
|
|
|
return tool;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tools_free_text (Tool *tool)
|
|
|
|
{
|
|
|
|
g_free (tool->private);
|
1999-05-19 01:33:39 +08:00
|
|
|
the_text_tool = NULL;
|
1999-05-10 01:39:07 +08:00
|
|
|
|
2000-03-29 07:02:05 +08:00
|
|
|
if (text_tool_shell)
|
|
|
|
gimp_dialog_hide (text_tool_shell);
|
1999-04-13 01:55:06 +08:00
|
|
|
}
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-19 02:55:49 +08:00
|
|
|
static void
|
1999-04-25 23:53:30 +08:00
|
|
|
text_call_gdyntext (GDisplay *gdisp)
|
1999-04-19 02:55:49 +08:00
|
|
|
{
|
|
|
|
ProcRecord *proc_rec;
|
|
|
|
Argument *args;
|
|
|
|
|
|
|
|
/* find the gDynText PDB record */
|
|
|
|
if ((proc_rec = procedural_db_lookup ("plug_in_dynamic_text")) == NULL)
|
|
|
|
{
|
1999-12-28 22:09:20 +08:00
|
|
|
g_message ("text_call_gdyntext: gDynText procedure lookup failed");
|
1999-04-19 02:55:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* plug-in arguments as if called by <Image>/Filters/... */
|
|
|
|
args = g_new (Argument, 3);
|
|
|
|
args[0].arg_type = PDB_INT32;
|
|
|
|
args[0].value.pdb_int = RUN_INTERACTIVE;
|
|
|
|
args[1].arg_type = PDB_IMAGE;
|
|
|
|
args[1].value.pdb_int = (gint32) pdb_image_to_id (gdisp->gimage);
|
|
|
|
args[2].arg_type = PDB_DRAWABLE;
|
1999-04-25 23:53:30 +08:00
|
|
|
args[2].value.pdb_int = (gint32) gimage_active_drawable (gdisp->gimage)->ID;
|
1999-04-19 02:55:49 +08:00
|
|
|
|
|
|
|
plug_in_run (proc_rec, args, 3, FALSE, TRUE, gdisp->ID);
|
|
|
|
|
|
|
|
g_free (args);
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
|
|
|
text_button_press (Tool *tool,
|
|
|
|
GdkEventButton *bevent,
|
|
|
|
gpointer gdisp_ptr)
|
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
|
|
|
Layer *layer;
|
|
|
|
TextTool *text_tool;
|
|
|
|
|
|
|
|
gdisp = gdisp_ptr;
|
1999-04-19 02:55:49 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
text_tool = tool->private;
|
|
|
|
text_tool->gdisp_ptr = gdisp_ptr;
|
|
|
|
|
|
|
|
tool->state = ACTIVE;
|
|
|
|
tool->gdisp_ptr = gdisp_ptr;
|
|
|
|
|
|
|
|
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
|
|
|
|
&text_tool->click_x, &text_tool->click_y,
|
|
|
|
TRUE, 0);
|
|
|
|
|
1999-04-19 02:55:49 +08:00
|
|
|
if ((layer = gimage_pick_correlate_layer (gdisp->gimage,
|
|
|
|
text_tool->click_x,
|
|
|
|
text_tool->click_y)))
|
1997-11-25 06:05:25 +08:00
|
|
|
/* If there is a floating selection, and this aint it, use the move tool */
|
|
|
|
if (layer_is_floating_sel (layer))
|
|
|
|
{
|
|
|
|
init_edit_selection (tool, gdisp_ptr, bevent, LayerTranslate);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-04-19 02:55:49 +08:00
|
|
|
if (text_options->use_dyntext)
|
|
|
|
{
|
1999-04-25 23:53:30 +08:00
|
|
|
text_call_gdyntext (gdisp);
|
1999-04-19 02:55:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-05-10 01:39:07 +08:00
|
|
|
if (! text_tool_shell)
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_create ();
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-10 01:39:07 +08:00
|
|
|
if (!GTK_WIDGET_VISIBLE (text_tool_shell))
|
|
|
|
gtk_widget_show (text_tool_shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
text_button_release (Tool *tool,
|
|
|
|
GdkEventButton *bevent,
|
|
|
|
gpointer gdisp_ptr)
|
|
|
|
{
|
|
|
|
tool->state = INACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
text_cursor_update (Tool *tool,
|
|
|
|
GdkEventMotion *mevent,
|
|
|
|
gpointer gdisp_ptr)
|
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
|
|
|
Layer *layer;
|
1999-12-18 00:37:50 +08:00
|
|
|
gint x, y;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
|
|
|
|
|
|
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, FALSE, FALSE);
|
|
|
|
|
|
|
|
if ((layer = gimage_pick_correlate_layer (gdisp->gimage, x, y)))
|
|
|
|
/* if there is a floating selection, and this aint it... */
|
|
|
|
if (layer_is_floating_sel (layer))
|
|
|
|
{
|
|
|
|
gdisplay_install_tool_cursor (gdisp, GDK_FLEUR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gdisplay_install_tool_cursor (gdisp, GDK_XTERM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-06-22 06:12:07 +08:00
|
|
|
text_control (Tool *tool,
|
|
|
|
ToolAction action,
|
|
|
|
gpointer gdisp_ptr)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
switch (action)
|
|
|
|
{
|
1999-06-22 06:12:07 +08:00
|
|
|
case PAUSE:
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
1999-06-22 06:12:07 +08:00
|
|
|
|
|
|
|
case RESUME:
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
1999-06-22 06:12:07 +08:00
|
|
|
|
|
|
|
case HALT:
|
2000-03-29 07:02:05 +08:00
|
|
|
if (text_tool_shell)
|
|
|
|
gimp_dialog_hide (text_tool_shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
1999-06-22 06:12:07 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_create (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-04-09 06:25:54 +08:00
|
|
|
/* Create the shell */
|
1999-05-10 01:39:07 +08:00
|
|
|
text_tool_shell = gtk_font_selection_dialog_new (_("Text Tool"));
|
|
|
|
gtk_window_set_wmclass (GTK_WINDOW (text_tool_shell), "text_tool", "Gimp");
|
1999-12-18 00:37:50 +08:00
|
|
|
gtk_window_set_policy (GTK_WINDOW (text_tool_shell), FALSE, TRUE, FALSE);
|
|
|
|
gtk_window_set_position (GTK_WINDOW (text_tool_shell), GTK_WIN_POS_MOUSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* handle the wm close signal */
|
1999-05-10 01:39:07 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (text_tool_shell), "delete_event",
|
1999-12-18 00:37:50 +08:00
|
|
|
GTK_SIGNAL_FUNC (text_dialog_delete_callback),
|
1999-05-10 01:39:07 +08:00
|
|
|
NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
/* ok and cancel buttons */
|
|
|
|
gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG
|
1999-12-18 00:37:50 +08:00
|
|
|
(text_tool_shell)->ok_button), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC (text_dialog_ok_callback),
|
1999-05-10 01:39:07 +08:00
|
|
|
NULL);
|
1999-04-19 02:55:49 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG
|
1999-12-18 00:37:50 +08:00
|
|
|
(text_tool_shell)->cancel_button), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC (text_dialog_cancel_callback),
|
1999-05-10 01:39:07 +08:00
|
|
|
NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Show the shell */
|
1999-05-10 01:39:07 +08:00
|
|
|
gtk_widget_show (text_tool_shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_ok_callback (GtkWidget *widget,
|
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-03-29 07:02:05 +08:00
|
|
|
gimp_dialog_hide (text_tool_shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-10 01:39:07 +08:00
|
|
|
if (the_text_tool)
|
|
|
|
text_init_render (the_text_tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_delete_callback (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_cancel_callback (widget, data);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-03-13 06:01:43 +08:00
|
|
|
return TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_dialog_cancel_callback (GtkWidget *widget,
|
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-03-29 07:02:05 +08:00
|
|
|
gimp_dialog_hide (text_tool_shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-10-07 16:59:11 +08:00
|
|
|
text_init_render (TextTool *text_tool)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-10-07 16:59:11 +08:00
|
|
|
GDisplay *gdisp;
|
1999-12-18 00:37:50 +08:00
|
|
|
gchar *fontname;
|
|
|
|
gchar *text;
|
|
|
|
gboolean antialias = text_options->antialias;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-10 01:39:07 +08:00
|
|
|
fontname = gtk_font_selection_dialog_get_font_name
|
|
|
|
(GTK_FONT_SELECTION_DIALOG (text_tool_shell));
|
1998-10-07 16:59:11 +08:00
|
|
|
if (!fontname)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
gdisp = (GDisplay *) text_tool->gdisp_ptr;
|
1998-02-22 18:45:12 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
/* override the user's antialias setting if this is an indexed image */
|
|
|
|
if (gimage_base_type (gdisp->gimage) == INDEXED)
|
|
|
|
antialias = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
/* If we're anti-aliasing, request a larger font than user specified.
|
|
|
|
* This will probably produce a font which isn't available if fonts
|
|
|
|
* are not scalable on this particular X server. TODO: Ideally, should
|
|
|
|
* grey out anti-alias on these kinds of servers. */
|
|
|
|
if (antialias)
|
1999-12-18 00:37:50 +08:00
|
|
|
text_size_multiply (&fontname, SUPERSAMPLE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-04-25 23:53:30 +08:00
|
|
|
/* If the text size is specified in points, it's size will be scaled
|
|
|
|
* correctly according to the image's resolution.
|
|
|
|
* FIXME: this currently can't be activated for the PDB, as the text has
|
|
|
|
* to be rendered in the size "text_get_extents" returns.
|
1999-05-10 00:38:05 +08:00
|
|
|
* TODO: add resolution parameters to "text_get_extents"
|
1999-04-25 23:53:30 +08:00
|
|
|
*/
|
|
|
|
text_set_resolution (&fontname,
|
|
|
|
gdisp->gimage->xresolution,
|
|
|
|
gdisp->gimage->yresolution);
|
|
|
|
|
1999-05-10 01:39:07 +08:00
|
|
|
text = gtk_font_selection_dialog_get_preview_text
|
|
|
|
(GTK_FONT_SELECTION_DIALOG (text_tool_shell));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
/* strdup it since the render function strtok()s the text */
|
1999-12-18 00:37:50 +08:00
|
|
|
text = g_strdup (text);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
text_render (gdisp->gimage, gimage_active_drawable (gdisp->gimage),
|
|
|
|
text_tool->click_x, text_tool->click_y,
|
1999-04-09 06:25:54 +08:00
|
|
|
fontname, text, text_options->border, antialias);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
gdisplays_flush ();
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
g_free (fontname);
|
|
|
|
g_free (text);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
text_gdk_image_to_region (GdkImage *image,
|
|
|
|
int scale,
|
|
|
|
PixelRegion *textPR)
|
|
|
|
{
|
1999-02-21 07:20:54 +08:00
|
|
|
GdkColor black;
|
1999-12-18 00:37:50 +08:00
|
|
|
gint black_pixel;
|
|
|
|
gint pixel;
|
|
|
|
gint value;
|
|
|
|
gint scalex, scaley;
|
|
|
|
gint scale2;
|
|
|
|
gint x, y;
|
|
|
|
gint i, j;
|
|
|
|
guchar * data;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
scale2 = scale * scale;
|
1999-06-15 06:18:02 +08:00
|
|
|
/* GDK_WINDOWING is defined only with GTk+ 1.3 */
|
1999-10-03 08:43:05 +08:00
|
|
|
#ifndef GDK_WINDOWING_WIN32
|
1999-02-21 07:20:54 +08:00
|
|
|
black.red = black.green = black.blue = 0;
|
|
|
|
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
|
|
|
|
black_pixel = black.pixel;
|
1999-03-07 20:56:03 +08:00
|
|
|
#else
|
|
|
|
black_pixel = 0;
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
data = textPR->data;
|
|
|
|
|
|
|
|
for (y = 0, scaley = 0; y < textPR->h; y++, scaley += scale)
|
|
|
|
{
|
|
|
|
for (x = 0, scalex = 0; x < textPR->w; x++, scalex += scale)
|
|
|
|
{
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
for (i = scaley; i < scaley + scale; i++)
|
|
|
|
for (j = scalex; j < scalex + scale; j++)
|
|
|
|
{
|
|
|
|
pixel = gdk_image_get_pixel (image, j, i);
|
|
|
|
if (pixel == black_pixel)
|
1998-04-24 10:18:52 +08:00
|
|
|
value ++;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* store the alpha value in the data */
|
1999-12-18 00:37:50 +08:00
|
|
|
*data++= (guchar) ((value * 255) / scale2);
|
1998-04-24 10:18:52 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-04-10 12:54:34 +08:00
|
|
|
GimpLayer *
|
1999-12-18 00:37:50 +08:00
|
|
|
text_render (GimpImage *gimage,
|
1998-01-22 15:02:57 +08:00
|
|
|
GimpDrawable *drawable,
|
1999-12-18 00:37:50 +08:00
|
|
|
int text_x,
|
|
|
|
int text_y,
|
|
|
|
char *fontname,
|
|
|
|
char *text,
|
|
|
|
int border,
|
|
|
|
int antialias)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GdkFont *font;
|
|
|
|
GdkPixmap *pixmap;
|
|
|
|
GdkImage *image;
|
|
|
|
GdkGC *gc;
|
|
|
|
GdkColor black, white;
|
|
|
|
Layer *layer;
|
|
|
|
TileManager *mask, *newmask;
|
|
|
|
PixelRegion textPR, maskPR;
|
1999-12-18 00:37:50 +08:00
|
|
|
gint layer_type;
|
|
|
|
guchar color[MAX_CHANNELS];
|
|
|
|
gchar *str;
|
|
|
|
gint nstrs;
|
|
|
|
gint crop;
|
|
|
|
gint line_width, line_height;
|
|
|
|
gint pixmap_width, pixmap_height;
|
|
|
|
gint text_width, text_height;
|
|
|
|
gint width, height;
|
|
|
|
gint x, y, k;
|
1997-11-25 06:05:25 +08:00
|
|
|
void * pr;
|
2000-01-19 07:12:26 +08:00
|
|
|
#ifndef GDK_WINDOWING_WIN32
|
2000-01-16 02:06:15 +08:00
|
|
|
XFontStruct *xfs;
|
2000-01-19 07:12:26 +08:00
|
|
|
#endif
|
2000-01-16 02:06:15 +08:00
|
|
|
char *fname;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* determine the layer type */
|
1998-04-24 10:18:52 +08:00
|
|
|
if (drawable)
|
1998-01-22 15:02:57 +08:00
|
|
|
layer_type = drawable_type_with_alpha (drawable);
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
|
|
|
layer_type = gimage_base_type_with_alpha (gimage);
|
|
|
|
|
|
|
|
/* scale the text based on the antialiasing amount */
|
|
|
|
if (antialias)
|
|
|
|
antialias = SUPERSAMPLE;
|
|
|
|
else
|
1999-12-18 00:37:50 +08:00
|
|
|
antialias = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-01-04 08:43:51 +08:00
|
|
|
/* Dont crop the text if border is negative */
|
|
|
|
crop = (border >= 0);
|
|
|
|
if (!crop) border = 0;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* load the font in */
|
1998-04-29 16:47:24 +08:00
|
|
|
gdk_error_warnings = 0;
|
|
|
|
gdk_error_code = 0;
|
2000-01-19 07:12:26 +08:00
|
|
|
#ifndef GDK_WINDOWING_WIN32
|
1997-11-25 06:05:25 +08:00
|
|
|
font = gdk_font_load (fontname);
|
2000-02-24 07:42:25 +08:00
|
|
|
if (!font)
|
|
|
|
{
|
2000-03-16 18:03:01 +08:00
|
|
|
g_message (_("Font '%s' not found."), fontname);
|
2000-02-24 07:42:25 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2000-01-16 02:06:15 +08:00
|
|
|
xfs = GDK_FONT_XFONT(font);
|
|
|
|
if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0) {
|
|
|
|
gdk_font_unref(font);
|
|
|
|
fname = g_strdup_printf("%s,*", fontname);
|
|
|
|
font = gdk_fontset_load (fname);
|
|
|
|
g_free(fname);
|
|
|
|
}
|
2000-01-19 07:12:26 +08:00
|
|
|
#else
|
|
|
|
/* Just use gdk_fontset_load all the time. IMHO it could be like
|
|
|
|
* this on all platforms?
|
|
|
|
*/
|
|
|
|
font = gdk_fontset_load (fontname);
|
|
|
|
#endif
|
1998-04-29 16:47:24 +08:00
|
|
|
gdk_error_warnings = 1;
|
|
|
|
if (!font || (gdk_error_code == -1))
|
1999-12-18 00:37:50 +08:00
|
|
|
{
|
|
|
|
g_message (_("Font '%s' not found.%s"),
|
|
|
|
fontname,
|
|
|
|
antialias ?
|
|
|
|
_("\nIf you don't have scalable fonts, "
|
|
|
|
"try turning off antialiasing in the tool options.") : "");
|
1998-10-07 16:59:11 +08:00
|
|
|
return NULL;
|
1999-12-18 00:37:50 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* determine the bounding box of the text */
|
|
|
|
width = -1;
|
|
|
|
height = 0;
|
|
|
|
line_height = font->ascent + font->descent;
|
|
|
|
|
|
|
|
nstrs = 0;
|
|
|
|
str = strtok (text, "\n");
|
|
|
|
while (str)
|
|
|
|
{
|
|
|
|
nstrs += 1;
|
|
|
|
|
|
|
|
/* gdk_string_measure will give the correct width of the
|
|
|
|
* string. However, we'll add a little "fudge" factor just
|
|
|
|
* to be sure.
|
|
|
|
*/
|
|
|
|
line_width = gdk_string_measure (font, str) + 5;
|
|
|
|
if (line_width > width)
|
|
|
|
width = line_width;
|
|
|
|
height += line_height;
|
|
|
|
|
|
|
|
str = strtok (NULL, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We limit the largest pixmap we create to approximately 200x200.
|
|
|
|
* This is approximate since it depends on the amount of antialiasing.
|
|
|
|
* Basically, we want the width and height to be divisible by the antialiasing
|
|
|
|
* amount. (Which lies in the range 1-10).
|
|
|
|
* This avoids problems on some X-servers (Xinside) which have problems
|
|
|
|
* with large pixmaps. (Specifically pixmaps which are larger - width
|
|
|
|
* or height - than the screen).
|
|
|
|
*/
|
|
|
|
pixmap_width = TILE_WIDTH * antialias;
|
|
|
|
pixmap_height = TILE_HEIGHT * antialias;
|
|
|
|
|
|
|
|
/* determine the actual text size based on the amount of antialiasing */
|
|
|
|
text_width = width / antialias;
|
|
|
|
text_height = height / antialias;
|
|
|
|
|
|
|
|
/* create the pixmap of depth 1 */
|
|
|
|
pixmap = gdk_pixmap_new (NULL, pixmap_width, pixmap_height, 1);
|
|
|
|
|
|
|
|
/* create the gc */
|
|
|
|
gc = gdk_gc_new (pixmap);
|
|
|
|
gdk_gc_set_font (gc, font);
|
|
|
|
|
|
|
|
/* get black and white pixels for this gdisplay */
|
1999-02-21 07:20:54 +08:00
|
|
|
black.red = black.green = black.blue = 0;
|
|
|
|
white.red = white.green = white.blue = 65535;
|
1999-10-03 08:43:05 +08:00
|
|
|
#ifndef GDK_WINDOWING_WIN32
|
1999-03-07 20:56:03 +08:00
|
|
|
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
|
1999-02-21 07:20:54 +08:00
|
|
|
gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, FALSE, TRUE);
|
1999-03-07 20:56:03 +08:00
|
|
|
#else
|
|
|
|
black.pixel = 0;
|
|
|
|
white.pixel = 1;
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Render the text into the pixmap.
|
|
|
|
* Since the pixmap may not fully bound the text (because we limit its size)
|
|
|
|
* we must tile it around the texts actual bounding box.
|
|
|
|
*/
|
|
|
|
mask = tile_manager_new (text_width, text_height, 1);
|
|
|
|
pixel_region_init (&maskPR, mask, 0, 0, text_width, text_height, TRUE);
|
|
|
|
|
|
|
|
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
|
|
|
|
{
|
|
|
|
/* erase the pixmap */
|
|
|
|
gdk_gc_set_foreground (gc, &white);
|
|
|
|
gdk_draw_rectangle (pixmap, gc, 1, 0, 0, pixmap_width, pixmap_height);
|
|
|
|
gdk_gc_set_foreground (gc, &black);
|
|
|
|
|
|
|
|
/* adjust the x and y values */
|
|
|
|
x = -maskPR.x * antialias;
|
|
|
|
y = font->ascent - maskPR.y * antialias;
|
|
|
|
str = text;
|
|
|
|
|
|
|
|
for (k = 0; k < nstrs; k++)
|
|
|
|
{
|
|
|
|
gdk_draw_string (pixmap, font, gc, x, y, str);
|
|
|
|
str += strlen (str) + 1;
|
|
|
|
y += line_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create the GdkImage */
|
|
|
|
image = gdk_image_get (pixmap, 0, 0, pixmap_width, pixmap_height);
|
|
|
|
|
|
|
|
if (!image)
|
new ui for the "Layer Offset" dialog.
1999-07-22 Michael Natterer <mitschel@cs.tu-berlin.de>
* app/channel_ops.[ch]: new ui for the "Layer Offset" dialog.
* app/channels_dialog.c
* app/layers_dialog.c: major code cleanup: Folded some callbacks
into common ones, "widget" instead of "w", indentation, ...
* app/commands.c
* app/interface.[ch]
* app/global_edit.c: the query boxes must be shown by the caller
now. There's no need to split up the string for the message box
manually as the Gtk 1.2 label widget handles newlines corectly.
Added the "edge_lock" toggle to the "Shrink Selection" dialog.
Nicer spacings for the query and message boxes.
* app/ink.c: tried to grab the pointer in the blob preview but
failed. Left the code there as a reminder (commented out).
* app/menus.c: reordered <Image>/Select.
I was bored and grep-ed the sources for ancient or deprecated stuff:
* app/about_dialog.[ch]
* app/actionarea.[ch]
* app/app_procs.c
* app/brush_edit.c
* app/brush_select.c
* app/color_select.c
* app/convert.c
* app/devices.c
* app/gdisplay.c
* app/gdisplay_ops.c
* app/histogram_tool.[ch]
* app/info_window.c
* app/install.c
* app/ops_buttons.c
* app/palette.c
* app/palette_select.c
* app/paths_dialog.c
* app/pattern_select.c
* app/resize.c
* app/scale_toolc.c
* app/text_tool.c:
s/container_border_width/container_set_border_width/g,
s/sprintf/g_snprintf/g, replaced some constant string lengths with
strlen(x).
* app/bezier_select.c
* app/blend.c
* app/boundary.c
* app/errors.[ch]
* app/free_select.c
* app/gimpbrushlist.c
* app/gimprc.c
* app/iscissors.c
* app/main.c
* app/patterns.[ch]
* app/text_tool.c: namespace fanaticism: prefixed all gimp error
functions with "gimp_" and formated the messages more uniformly.
* app/gradient.c
* app/gradient_select.c: same stuff as above for the ui
code. There are still some sub-dialogs which need cleanup.
Did some cleanup in most of these files: prototypes, removed tons
of #include's, i18n fixes, s/w/widget/ as above, indentation, ...
1999-07-23 00:21:10 +08:00
|
|
|
gimp_fatal_error ("text_render(): Sanity check failed: could not get gdk image");
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (image->depth != 1)
|
new ui for the "Layer Offset" dialog.
1999-07-22 Michael Natterer <mitschel@cs.tu-berlin.de>
* app/channel_ops.[ch]: new ui for the "Layer Offset" dialog.
* app/channels_dialog.c
* app/layers_dialog.c: major code cleanup: Folded some callbacks
into common ones, "widget" instead of "w", indentation, ...
* app/commands.c
* app/interface.[ch]
* app/global_edit.c: the query boxes must be shown by the caller
now. There's no need to split up the string for the message box
manually as the Gtk 1.2 label widget handles newlines corectly.
Added the "edge_lock" toggle to the "Shrink Selection" dialog.
Nicer spacings for the query and message boxes.
* app/ink.c: tried to grab the pointer in the blob preview but
failed. Left the code there as a reminder (commented out).
* app/menus.c: reordered <Image>/Select.
I was bored and grep-ed the sources for ancient or deprecated stuff:
* app/about_dialog.[ch]
* app/actionarea.[ch]
* app/app_procs.c
* app/brush_edit.c
* app/brush_select.c
* app/color_select.c
* app/convert.c
* app/devices.c
* app/gdisplay.c
* app/gdisplay_ops.c
* app/histogram_tool.[ch]
* app/info_window.c
* app/install.c
* app/ops_buttons.c
* app/palette.c
* app/palette_select.c
* app/paths_dialog.c
* app/pattern_select.c
* app/resize.c
* app/scale_toolc.c
* app/text_tool.c:
s/container_border_width/container_set_border_width/g,
s/sprintf/g_snprintf/g, replaced some constant string lengths with
strlen(x).
* app/bezier_select.c
* app/blend.c
* app/boundary.c
* app/errors.[ch]
* app/free_select.c
* app/gimpbrushlist.c
* app/gimprc.c
* app/iscissors.c
* app/main.c
* app/patterns.[ch]
* app/text_tool.c: namespace fanaticism: prefixed all gimp error
functions with "gimp_" and formated the messages more uniformly.
* app/gradient.c
* app/gradient_select.c: same stuff as above for the ui
code. There are still some sub-dialogs which need cleanup.
Did some cleanup in most of these files: prototypes, removed tons
of #include's, i18n fixes, s/w/widget/ as above, indentation, ...
1999-07-23 00:21:10 +08:00
|
|
|
gimp_fatal_error ("text_render(): Sanity check failed: image should have 1 bit per pixel");
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* convert the GdkImage bitmap to a region */
|
|
|
|
text_gdk_image_to_region (image, antialias, &maskPR);
|
|
|
|
|
|
|
|
/* free the image */
|
|
|
|
gdk_image_destroy (image);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Crop the mask buffer */
|
1998-01-04 08:43:51 +08:00
|
|
|
newmask = crop ? crop_buffer (mask, border) : mask;
|
1997-11-25 06:05:25 +08:00
|
|
|
if (newmask != mask)
|
|
|
|
tile_manager_destroy (mask);
|
|
|
|
|
|
|
|
if (newmask &&
|
1998-08-16 03:17:36 +08:00
|
|
|
(layer = layer_new (gimage, newmask->width,
|
|
|
|
newmask->height, layer_type,
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
_("Text Layer"), OPAQUE_OPACITY, NORMAL_MODE)))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* color the layer buffer */
|
1998-01-22 15:02:57 +08:00
|
|
|
gimage_get_foreground (gimage, drawable, color);
|
1999-12-18 00:37:50 +08:00
|
|
|
color[GIMP_DRAWABLE (layer)->bytes - 1] = OPAQUE_OPACITY;
|
|
|
|
pixel_region_init (&textPR, GIMP_DRAWABLE (layer)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (layer)->width,
|
|
|
|
GIMP_DRAWABLE (layer)->height, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
color_region (&textPR, color);
|
|
|
|
|
|
|
|
/* apply the text mask */
|
1999-12-18 00:37:50 +08:00
|
|
|
pixel_region_init (&textPR, GIMP_DRAWABLE (layer)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (layer)->width,
|
|
|
|
GIMP_DRAWABLE (layer)->height, TRUE);
|
|
|
|
pixel_region_init (&maskPR, newmask,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (layer)->width,
|
|
|
|
GIMP_DRAWABLE (layer)->height, FALSE);
|
1998-01-25 09:24:46 +08:00
|
|
|
apply_mask_to_region (&textPR, &maskPR, OPAQUE_OPACITY);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Start a group undo */
|
1999-11-04 06:34:32 +08:00
|
|
|
undo_push_group_start (gimage, TEXT_UNDO);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set the layer offsets */
|
1999-12-18 00:37:50 +08:00
|
|
|
GIMP_DRAWABLE (layer)->offset_x = text_x;
|
|
|
|
GIMP_DRAWABLE (layer)->offset_y = text_y;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* If there is a selection mask clear it--
|
|
|
|
* this might not always be desired, but in general,
|
|
|
|
* it seems like the correct behavior.
|
|
|
|
*/
|
|
|
|
if (! gimage_mask_is_empty (gimage))
|
|
|
|
channel_clear (gimage_get_mask (gimage));
|
|
|
|
|
|
|
|
/* If the drawable id is invalid, create a new layer */
|
1998-01-22 15:02:57 +08:00
|
|
|
if (drawable == NULL)
|
1997-11-25 06:05:25 +08:00
|
|
|
gimage_add_layer (gimage, layer, -1);
|
|
|
|
/* Otherwise, instantiate the text as the new floating selection */
|
|
|
|
else
|
1998-01-22 15:02:57 +08:00
|
|
|
floating_sel_attach (layer, drawable);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* end the group undo */
|
|
|
|
undo_push_group_end (gimage);
|
|
|
|
|
|
|
|
tile_manager_destroy (newmask);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (newmask)
|
1998-05-12 08:12:47 +08:00
|
|
|
{
|
1999-12-28 18:30:50 +08:00
|
|
|
g_message ("text_render: could not allocate image");
|
1998-05-12 08:12:47 +08:00
|
|
|
tile_manager_destroy (newmask);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
layer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free the pixmap */
|
1997-12-18 14:30:11 +08:00
|
|
|
gdk_pixmap_unref (pixmap);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* free the gc */
|
|
|
|
gdk_gc_destroy (gc);
|
|
|
|
|
|
|
|
/* free the font */
|
1997-12-18 14:30:11 +08:00
|
|
|
gdk_font_unref (font);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
1999-04-10 12:54:34 +08:00
|
|
|
int
|
1997-11-25 06:05:25 +08:00
|
|
|
text_get_extents (char *fontname,
|
|
|
|
char *text,
|
|
|
|
int *width,
|
|
|
|
int *height,
|
|
|
|
int *ascent,
|
|
|
|
int *descent)
|
|
|
|
{
|
|
|
|
GdkFont *font;
|
1999-12-18 00:37:50 +08:00
|
|
|
gchar *str;
|
|
|
|
gint nstrs;
|
|
|
|
gint line_width, line_height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* load the font in */
|
1998-04-29 16:47:24 +08:00
|
|
|
gdk_error_warnings = 0;
|
|
|
|
gdk_error_code = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
font = gdk_font_load (fontname);
|
1998-04-29 16:47:24 +08:00
|
|
|
gdk_error_warnings = 1;
|
|
|
|
if (!font || (gdk_error_code == -1))
|
1997-11-25 06:05:25 +08:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* determine the bounding box of the text */
|
|
|
|
*width = -1;
|
|
|
|
*height = 0;
|
|
|
|
*ascent = font->ascent;
|
|
|
|
*descent = font->descent;
|
|
|
|
line_height = *ascent + *descent;
|
|
|
|
|
|
|
|
nstrs = 0;
|
|
|
|
str = strtok (text, "\n");
|
|
|
|
while (str)
|
|
|
|
{
|
|
|
|
nstrs += 1;
|
|
|
|
|
|
|
|
/* gdk_string_measure will give the correct width of the
|
|
|
|
* string. However, we'll add a little "fudge" factor just
|
|
|
|
* to be sure.
|
|
|
|
*/
|
|
|
|
line_width = gdk_string_measure (font, str) + 5;
|
|
|
|
if (line_width > *width)
|
|
|
|
*width = line_width;
|
|
|
|
*height += line_height;
|
|
|
|
|
|
|
|
str = strtok (NULL, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*width < 0)
|
|
|
|
return FALSE;
|
|
|
|
else
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_field_edges (gchar *fontname,
|
|
|
|
gint field_num,
|
|
|
|
/* RETURNS: */
|
|
|
|
gchar **start,
|
|
|
|
gchar **end)
|
1998-10-07 16:59:11 +08:00
|
|
|
{
|
1999-12-18 00:37:50 +08:00
|
|
|
gchar *t1, *t2;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
t1 = fontname;
|
|
|
|
|
|
|
|
while (*t1 && (field_num >= 0))
|
|
|
|
if (*t1++ == '-')
|
|
|
|
field_num--;
|
|
|
|
|
|
|
|
t2 = t1;
|
|
|
|
while (*t2 && (*t2 != '-'))
|
|
|
|
t2++;
|
|
|
|
|
|
|
|
*start = t1;
|
|
|
|
*end = t2;
|
|
|
|
}
|
|
|
|
|
1999-04-25 23:53:30 +08:00
|
|
|
/* convert sizes back to text */
|
|
|
|
#define TO_TXT(x) \
|
new ui for the "Layer Offset" dialog.
1999-07-22 Michael Natterer <mitschel@cs.tu-berlin.de>
* app/channel_ops.[ch]: new ui for the "Layer Offset" dialog.
* app/channels_dialog.c
* app/layers_dialog.c: major code cleanup: Folded some callbacks
into common ones, "widget" instead of "w", indentation, ...
* app/commands.c
* app/interface.[ch]
* app/global_edit.c: the query boxes must be shown by the caller
now. There's no need to split up the string for the message box
manually as the Gtk 1.2 label widget handles newlines corectly.
Added the "edge_lock" toggle to the "Shrink Selection" dialog.
Nicer spacings for the query and message boxes.
* app/ink.c: tried to grab the pointer in the blob preview but
failed. Left the code there as a reminder (commented out).
* app/menus.c: reordered <Image>/Select.
I was bored and grep-ed the sources for ancient or deprecated stuff:
* app/about_dialog.[ch]
* app/actionarea.[ch]
* app/app_procs.c
* app/brush_edit.c
* app/brush_select.c
* app/color_select.c
* app/convert.c
* app/devices.c
* app/gdisplay.c
* app/gdisplay_ops.c
* app/histogram_tool.[ch]
* app/info_window.c
* app/install.c
* app/ops_buttons.c
* app/palette.c
* app/palette_select.c
* app/paths_dialog.c
* app/pattern_select.c
* app/resize.c
* app/scale_toolc.c
* app/text_tool.c:
s/container_border_width/container_set_border_width/g,
s/sprintf/g_snprintf/g, replaced some constant string lengths with
strlen(x).
* app/bezier_select.c
* app/blend.c
* app/boundary.c
* app/errors.[ch]
* app/free_select.c
* app/gimpbrushlist.c
* app/gimprc.c
* app/iscissors.c
* app/main.c
* app/patterns.[ch]
* app/text_tool.c: namespace fanaticism: prefixed all gimp error
functions with "gimp_" and formated the messages more uniformly.
* app/gradient.c
* app/gradient_select.c: same stuff as above for the ui
code. There are still some sub-dialogs which need cleanup.
Did some cleanup in most of these files: prototypes, removed tons
of #include's, i18n fixes, s/w/widget/ as above, indentation, ...
1999-07-23 00:21:10 +08:00
|
|
|
{ \
|
|
|
|
if (x >= 0) \
|
|
|
|
g_snprintf (new_ ## x, sizeof (new_ ## x), "%d", x); \
|
|
|
|
else \
|
|
|
|
g_snprintf (new_ ## x, sizeof (new_ ## x), "*"); \
|
1999-04-25 23:53:30 +08:00
|
|
|
}
|
|
|
|
|
1998-10-07 16:59:11 +08:00
|
|
|
/* Multiply the point and pixel sizes in *fontname by "mul", which
|
|
|
|
* must be positive. If either point or pixel sizes are "*" then they
|
|
|
|
* are left untouched. The memory *fontname is g_free()d, and
|
1999-05-05 01:20:05 +08:00
|
|
|
* *fontname is replaced by a fresh allocation of the correct size.
|
|
|
|
*/
|
1998-10-07 16:59:11 +08:00
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_size_multiply (gchar **fontname,
|
|
|
|
gint mul)
|
1998-10-07 16:59:11 +08:00
|
|
|
{
|
1999-12-18 00:37:50 +08:00
|
|
|
gchar *pixel_str;
|
|
|
|
gchar *point_str;
|
|
|
|
gchar *newfont;
|
|
|
|
gchar *end;
|
|
|
|
gint pixel = -1;
|
|
|
|
gint point = -1;
|
|
|
|
gchar new_pixel[16];
|
|
|
|
gchar new_point[16];
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
/* slice the font spec around the size fields */
|
1999-12-18 00:37:50 +08:00
|
|
|
text_field_edges (*fontname, PIXEL_SIZE, &pixel_str, &end);
|
|
|
|
text_field_edges (*fontname, POINT_SIZE, &point_str, &end);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-04-10 12:54:34 +08:00
|
|
|
*(pixel_str - 1) = 0;
|
|
|
|
*(point_str - 1) = 0;
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
if (*pixel_str != '*')
|
1999-12-18 00:37:50 +08:00
|
|
|
pixel = atoi (pixel_str);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
if (*point_str != '*')
|
1999-12-18 00:37:50 +08:00
|
|
|
point = atoi (point_str);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
pixel *= mul;
|
|
|
|
point *= mul;
|
|
|
|
|
|
|
|
/* convert the pixel and point sizes back to text */
|
1999-12-18 00:37:50 +08:00
|
|
|
TO_TXT (pixel);
|
|
|
|
TO_TXT (point);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
newfont = g_strdup_printf ("%s-%s-%s%s", *fontname, new_pixel, new_point, end);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
1999-12-18 00:37:50 +08:00
|
|
|
g_free (*fontname);
|
1998-10-07 16:59:11 +08:00
|
|
|
|
|
|
|
*fontname = newfont;
|
|
|
|
}
|
1999-04-25 23:53:30 +08:00
|
|
|
|
|
|
|
static void
|
1999-12-18 00:37:50 +08:00
|
|
|
text_set_resolution (gchar **fontname,
|
|
|
|
gdouble xresolution,
|
|
|
|
gdouble yresolution)
|
1999-04-25 23:53:30 +08:00
|
|
|
{
|
1999-12-18 00:37:50 +08:00
|
|
|
gchar *size_str;
|
|
|
|
gchar *xres_str;
|
|
|
|
gchar *yres_str;
|
|
|
|
gchar *newfont;
|
|
|
|
gchar *end;
|
|
|
|
gchar new_size[16];
|
|
|
|
gchar new_xres[16];
|
|
|
|
gchar new_yres[16];
|
|
|
|
gdouble points;
|
|
|
|
|
|
|
|
gint size;
|
|
|
|
gint xres;
|
|
|
|
gint yres;
|
1999-04-25 23:53:30 +08:00
|
|
|
|
1999-05-05 01:20:05 +08:00
|
|
|
/* get the point size string */
|
1999-05-10 00:38:05 +08:00
|
|
|
text_field_edges (*fontname, POINT_SIZE, &size_str, &end);
|
1999-05-05 01:20:05 +08:00
|
|
|
|
|
|
|
/* don't set the resolution if the point size is unspecified */
|
1999-05-10 00:38:05 +08:00
|
|
|
if (xresolution < GIMP_MIN_RESOLUTION ||
|
|
|
|
yresolution < GIMP_MIN_RESOLUTION ||
|
|
|
|
*size_str == '*')
|
1999-05-05 01:20:05 +08:00
|
|
|
return;
|
|
|
|
|
1999-05-10 00:38:05 +08:00
|
|
|
points = atof (size_str);
|
|
|
|
|
|
|
|
/* X allows only integer resolution values, so we do some
|
|
|
|
* ugly calculations (starting with yres because the size of
|
|
|
|
* a font is it's height)
|
|
|
|
*/
|
|
|
|
if (yresolution < 1.0)
|
|
|
|
{
|
|
|
|
points /= (1.0 / yresolution);
|
|
|
|
xresolution *= (1.0 / yresolution);
|
|
|
|
yresolution = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* res may be != (int) res
|
|
|
|
* (important only for very small resolutions)
|
|
|
|
*/
|
|
|
|
points *= yresolution / (double) (int) yresolution;
|
|
|
|
xresolution /= yresolution / (double) (int) yresolution;
|
|
|
|
|
|
|
|
/* finally, if xres became invalid by the above calculations */
|
2000-01-26 07:06:12 +08:00
|
|
|
xresolution = CLAMP (xresolution, 1.0, GIMP_MAX_RESOLUTION);
|
1999-05-10 00:38:05 +08:00
|
|
|
|
1999-04-25 23:53:30 +08:00
|
|
|
/* slice the font spec around the resolution fields */
|
|
|
|
text_field_edges (*fontname, XRESOLUTION, &xres_str, &end);
|
|
|
|
text_field_edges (*fontname, YRESOLUTION, &yres_str, &end);
|
|
|
|
|
1999-05-10 00:38:05 +08:00
|
|
|
*(size_str - 1) = 0;
|
1999-04-25 23:53:30 +08:00
|
|
|
*(xres_str - 1) = 0;
|
|
|
|
*(yres_str - 1) = 0;
|
|
|
|
|
|
|
|
/* convert the resolutions to text */
|
1999-12-18 00:37:50 +08:00
|
|
|
size = (gint) points;
|
|
|
|
xres = (gint) xresolution;
|
|
|
|
yres = (gint) yresolution;
|
1999-05-10 00:38:05 +08:00
|
|
|
|
|
|
|
TO_TXT (size);
|
1999-04-25 23:53:30 +08:00
|
|
|
TO_TXT (xres);
|
|
|
|
TO_TXT (yres);
|
|
|
|
|
1999-05-10 00:38:05 +08:00
|
|
|
newfont = g_strdup_printf ("%s-%s-%s-%s%s",
|
|
|
|
*fontname, new_size, new_xres, new_yres, end);
|
1999-04-25 23:53:30 +08:00
|
|
|
|
|
|
|
g_free (*fontname);
|
|
|
|
|
|
|
|
*fontname = newfont;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef TO_TXT
|