gimp r27419 - in trunk: . app app/actions app/menus app/text app/tools app/widgets menus
- From: mitch svn gnome org
- To: svn-commits-list gnome org
- Subject: gimp r27419 - in trunk: . app app/actions app/menus app/text app/tools app/widgets menus
- Date: Sun, 26 Oct 2008 17:39:55 +0000 (UTC)
Author: mitch
Date: Sun Oct 26 17:39:55 2008
New Revision: 27419
URL: http://svn.gnome.org/viewvc/gimp?rev=27419&view=rev
Log:
2008-10-26 Michael Natterer <mitch gimp org>
Merge on-canvas GSoC project:
* configure.in: check for pangocairo.
* app/Makefile.am
* app/text/Makefile.am: add its CFLAGS and LIBS.
* app/text/gimptext-bitmap.[ch]
* app/text/gimptext-private.h
* app/text/gimptext-vectors.[ch]
* app/text/gimptextlayer.c
* app/text/gimptextlayout-render.c
* app/text/gimptextlayout.c: port to pangocairo.
* menus/Makefile.am
* menus/text-tool-menu.xml
* app/menus/menus.c
* app/actions/Makefile.am
* app/actions/actions.c
* app/actions/text-tool-actions.[ch]
* app/actions/text-tool-commands.[ch]: add a context menu for the
text tool similar to GtkEntry's context menu.
* app/tools/gimprectangletool.[ch]: add "narrow-mode" property.
* app/tools/gimptextoptions.[ch]
* app/widgets/gimptexteditor.[ch]: take a text buffer for the
standalone text editor window instead of creating one internally.
* app/tools/gimptexttool.[ch]: all the new wonderful on-canvas
text editing logic. Wheee!
Added:
trunk/app/actions/text-tool-actions.c
trunk/app/actions/text-tool-actions.h
trunk/app/actions/text-tool-commands.c
trunk/app/actions/text-tool-commands.h
trunk/menus/text-tool-menu.xml
Modified:
trunk/ChangeLog
trunk/app/Makefile.am
trunk/app/actions/Makefile.am
trunk/app/actions/actions.c
trunk/app/menus/menus.c
trunk/app/text/Makefile.am
trunk/app/text/gimptext-bitmap.c
trunk/app/text/gimptext-bitmap.h
trunk/app/text/gimptext-private.h
trunk/app/text/gimptext-vectors.c
trunk/app/text/gimptext-vectors.h
trunk/app/text/gimptextlayer.c
trunk/app/text/gimptextlayout-render.c
trunk/app/text/gimptextlayout.c
trunk/app/tools/gimprectangletool.c
trunk/app/tools/gimprectangletool.h
trunk/app/tools/gimptextoptions.c
trunk/app/tools/gimptextoptions.h
trunk/app/tools/gimptexttool.c
trunk/app/tools/gimptexttool.h
trunk/app/widgets/gimptexteditor.c
trunk/app/widgets/gimptexteditor.h
trunk/configure.in
trunk/menus/Makefile.am
Modified: trunk/app/Makefile.am
==============================================================================
--- trunk/app/Makefile.am (original)
+++ trunk/app/Makefile.am Sun Oct 26 17:39:55 2008
@@ -90,6 +90,7 @@
-I$(top_srcdir) \
$(GTK_CFLAGS) \
$(PANGOFT2_CFLAGS) \
+ $(PANGOCAIRO_CFLAGS) \
$(DBUS_GLIB_CFLAGS) \
$(GEGL_CFLAGS) \
-I$(includedir)
@@ -137,6 +138,7 @@
$(libgimpbase) \
$(GTK_LIBS) \
$(PANGOFT2_LIBS) \
+ $(PANGOCAIRO_LIBS) \
$(FONTCONFIG_LIBS) \
$(FREETYPE_LIBS) \
$(DBUS_GLIB_LIBS) \
@@ -181,6 +183,7 @@
$(GDK_PIXBUF_LIBS) \
$(CAIRO_LIBS) \
$(PANGOFT2_LIBS) \
+ $(PANGOCAIRO_LIBS) \
$(FONTCONFIG_LIBS) \
$(FREETYPE_LIBS) \
$(GEGL_LIBS) \
Modified: trunk/app/actions/Makefile.am
==============================================================================
--- trunk/app/actions/Makefile.am (original)
+++ trunk/app/actions/Makefile.am Sun Oct 26 17:39:55 2008
@@ -149,6 +149,10 @@
text-editor-actions.h \
text-editor-commands.c \
text-editor-commands.h \
+ text-tool-actions.c \
+ text-tool-actions.h \
+ text-tool-commands.c \
+ text-tool-commands.h \
tool-options-actions.c \
tool-options-actions.h \
tool-options-commands.c \
Modified: trunk/app/actions/actions.c
==============================================================================
--- trunk/app/actions/actions.c (original)
+++ trunk/app/actions/actions.c Sun Oct 26 17:39:55 2008
@@ -81,6 +81,7 @@
#include "select-actions.h"
#include "templates-actions.h"
#include "text-editor-actions.h"
+#include "text-tool-actions.h"
#include "tool-options-actions.h"
#include "tools-actions.h"
#include "vectors-actions.h"
@@ -195,6 +196,9 @@
{ "templates", N_("Templates"), GIMP_STOCK_TEMPLATE,
templates_actions_setup,
templates_actions_update },
+ { "text-tool", N_("Text Tool"), GTK_STOCK_EDIT,
+ text_tool_actions_setup,
+ text_tool_actions_update },
{ "text-editor", N_("Text Editor"), GTK_STOCK_EDIT,
text_editor_actions_setup,
text_editor_actions_update },
Added: trunk/app/actions/text-tool-actions.c
==============================================================================
--- (empty file)
+++ trunk/app/actions/text-tool-actions.c Sun Oct 26 17:39:55 2008
@@ -0,0 +1,172 @@
+/* GIMP - The GNU 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimptexteditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+
+#include "tools/gimptool.h"
+#include "tools/gimptexttool.h"
+
+#include "text-tool-actions.h"
+#include "text-tool-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry text_tool_actions[] =
+{
+ { "text-tool-popup", NULL,
+ N_("Text Tool Popup"), NULL, NULL, NULL,
+ NULL },
+
+ { "text-tool-cut", GTK_STOCK_CUT,
+ N_("Cut"), NULL, NULL,
+ G_CALLBACK (text_tool_cut_cmd_callback),
+ NULL },
+
+ { "text-tool-copy", GTK_STOCK_COPY,
+ N_("Copy"), NULL, NULL,
+ G_CALLBACK (text_tool_copy_cmd_callback),
+ NULL },
+
+ { "text-tool-paste", GTK_STOCK_PASTE,
+ N_("Paste"), NULL, NULL,
+ G_CALLBACK (text_tool_paste_cmd_callback),
+ NULL },
+
+ { "text-tool-delete", GTK_STOCK_DELETE,
+ N_("Delete selected"), NULL, NULL,
+ G_CALLBACK (text_tool_delete_cmd_callback),
+ NULL },
+
+ { "text-tool-load", GTK_STOCK_OPEN,
+ N_("Open"), NULL,
+ N_("Load text from file"),
+ G_CALLBACK (text_tool_load_cmd_callback),
+ NULL },
+
+ { "text-tool-clear", GTK_STOCK_CLEAR,
+ N_("Clear"), "",
+ N_("Clear all text"),
+ G_CALLBACK (text_tool_clear_cmd_callback),
+ NULL },
+
+ { "text-tool-path-from-text", GIMP_STOCK_PATH,
+ N_("Path from Text"), "",
+ N_("Create a path from the outlines of the current text"),
+ G_CALLBACK (text_tool_path_from_text_callback),
+ NULL },
+
+ { "text-tool-input-methods", NULL,
+ N_("Input Methods"), NULL, NULL, NULL,
+ NULL }
+};
+
+static const GimpRadioActionEntry text_tool_direction_actions[] =
+{
+ { "text-tool-direction-ltr", GIMP_STOCK_TEXT_DIR_LTR,
+ N_("LTR"), "",
+ N_("From left to right"),
+ GIMP_TEXT_DIRECTION_LTR,
+ NULL },
+
+ { "text-tool-direction-rtl", GIMP_STOCK_TEXT_DIR_RTL,
+ N_("RTL"), "",
+ N_("From right to left"),
+ GIMP_TEXT_DIRECTION_RTL,
+ NULL }
+};
+
+
+void
+text_tool_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group,
+ text_tool_actions,
+ G_N_ELEMENTS (text_tool_actions));
+
+ gimp_action_group_add_radio_actions (group,
+ text_tool_direction_actions,
+ G_N_ELEMENTS (text_tool_direction_actions),
+ NULL,
+ GIMP_TEXT_DIRECTION_LTR,
+ G_CALLBACK (text_tool_direction_cmd_callback));
+}
+
+/*
+ * The following code is written on the assumption that this is for a context
+ * menu, activated by right-clicking in a text layer. Therefore, the tool
+ * must have a display. If for any reason the code is adapted to a different
+ * situation, some existence testing will need to be added.
+ */
+void
+text_tool_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GimpImage *image = GIMP_TOOL (text_tool)->display->image;
+ GimpLayer *layer;
+ GtkClipboard *clipboard;
+ gboolean text_layer = FALSE;
+ gboolean text_sel = FALSE; /* some text is selected */
+ gboolean clip = FALSE; /* clipboard has text available */
+
+ layer = gimp_image_get_active_layer (image);
+
+ if (layer)
+ text_layer = gimp_drawable_is_text_layer (GIMP_DRAWABLE (layer));
+
+ text_sel = gimp_text_tool_get_has_text_selection (text_tool);
+
+ /*
+ * see whether there is text available for pasting
+ */
+ clipboard = gtk_widget_get_clipboard (GIMP_TOOL (text_tool)->display->shell,
+ GDK_SELECTION_PRIMARY);
+ clip = gtk_clipboard_wait_is_text_available (clipboard);
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("text-tool-cut", text_sel);
+ SET_SENSITIVE ("text-tool-copy", text_sel);
+ SET_SENSITIVE ("text-tool-paste", clip);
+ SET_SENSITIVE ("text-tool-delete", text_sel);
+ SET_SENSITIVE ("text-tool-clear", text_layer);
+ SET_SENSITIVE ("text-tool-load", image);
+ SET_SENSITIVE ("text-tool-path-from-text", text_layer);
+}
Added: trunk/app/actions/text-tool-actions.h
==============================================================================
--- (empty file)
+++ trunk/app/actions/text-tool-actions.h Sun Oct 26 17:39:55 2008
@@ -0,0 +1,28 @@
+/* GIMP - The GNU 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TEXT_TOOL_ACTIONS_H__
+#define __TEXT_TOOL_ACTIONS_H__
+
+
+void text_tool_actions_setup (GimpActionGroup *group);
+void text_tool_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TEXT_TOOL_ACTIONS_H__ */
Added: trunk/app/actions/text-tool-commands.c
==============================================================================
--- (empty file)
+++ trunk/app/actions/text-tool-commands.c Sun Oct 26 17:39:55 2008
@@ -0,0 +1,206 @@
+/* GIMP - The GNU 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimptexteditor.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpuimanager.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "tools/gimptexttool.h"
+
+#include "text-tool-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void text_tool_load_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextEditor *editor);
+
+
+/* public functions */
+
+void
+text_tool_cut_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_clipboard_cut (text_tool);
+}
+
+void
+text_tool_copy_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_clipboard_copy (text_tool, TRUE);
+}
+
+void
+text_tool_paste_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_clipboard_paste (text_tool, TRUE);
+}
+
+void
+text_tool_delete_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ if (gtk_text_buffer_get_has_selection (text_tool->text_buffer))
+ gimp_text_tool_delete_text (text_tool);
+}
+
+void
+text_tool_load_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+ GtkFileChooser *chooser;
+
+ if (editor->file_dialog)
+ {
+ gtk_window_present (GTK_WINDOW (editor->file_dialog));
+ return;
+ }
+
+ editor->file_dialog =
+ gtk_file_chooser_dialog_new (_("Open Text File (UTF-8)"),
+ GTK_WINDOW (editor),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+
+ NULL);
+
+ chooser = GTK_FILE_CHOOSER (editor->file_dialog);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (editor->file_dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_object_add_weak_pointer (G_OBJECT (chooser),
+ (gpointer) &editor->file_dialog);
+
+ gtk_window_set_role (GTK_WINDOW (chooser), "gimp-text-load-file");
+ gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_MOUSE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (text_tool_load_response),
+ editor);
+ g_signal_connect (chooser, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+
+ gtk_widget_show (GTK_WIDGET (chooser));
+}
+
+void
+text_tool_clear_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_bounds (text_tool->text_buffer, &start, &end);
+ gtk_text_buffer_select_range (text_tool->text_buffer, &start, &end);
+ gimp_text_tool_delete_text (text_tool);
+}
+
+void
+text_tool_path_from_text_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_create_vectors (text_tool);
+}
+
+void
+text_tool_direction_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+ gint value;
+
+ value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+
+ /*
+ gimp_text_tool_set_direction (editor, (GimpTextDirection) value);
+ */
+}
+
+
+/* private functions */
+
+static void
+text_tool_load_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextEditor *editor)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GtkTextBuffer *buffer;
+ gchar *filename;
+ GError *error = NULL;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ if (! gimp_text_buffer_load (buffer, filename, &error))
+ {
+ gimp_message (editor->ui_manager->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ _("Could not open '%s' for reading: %s"),
+ gimp_filename_to_utf8 (filename),
+ error->message);
+ g_clear_error (&error);
+ g_free (filename);
+ return;
+ }
+
+ g_free (filename);
+ }
+
+ gtk_widget_destroy (dialog);
+}
Added: trunk/app/actions/text-tool-commands.h
==============================================================================
--- (empty file)
+++ trunk/app/actions/text-tool-commands.h Sun Oct 26 17:39:55 2008
@@ -0,0 +1,42 @@
+/* GIMP - The GNU 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
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TEXT_TOOL_COMMANDS_H__
+#define __TEXT_TOOL_COMMANDS_H__
+
+
+void text_tool_cut_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_copy_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_paste_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_delete_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_load_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_clear_cmd_callback (GtkAction *action,
+ gpointer data);
+void text_tool_path_from_text_callback (GtkAction *action,
+ gpointer data);
+void text_tool_direction_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data);
+
+
+#endif /* __TEXT_TOOL_COMMANDS_H__ */
Modified: trunk/app/menus/menus.c
==============================================================================
--- trunk/app/menus/menus.c (original)
+++ trunk/app/menus/menus.c Sun Oct 26 17:39:55 2008
@@ -340,6 +340,14 @@
NULL,
NULL);
+ gimp_menu_factory_manager_register (global_menu_factory, "<TextTool>",
+ "text-tool",
+ NULL,
+ "/text-tool-popup",
+ "text-tool-menu.xml",
+ NULL,
+ NULL);
+
gimp_menu_factory_manager_register (global_menu_factory, "<CursorInfo>",
"cursor-info",
NULL,
Modified: trunk/app/text/Makefile.am
==============================================================================
--- trunk/app/text/Makefile.am (original)
+++ trunk/app/text/Makefile.am Sun Oct 26 17:39:55 2008
@@ -10,6 +10,7 @@
-I$(top_srcdir)/app \
$(GEGL_CFLAGS) \
$(PANGOFT2_CFLAGS) \
+ $(PANGOCAIRO_CFLAGS) \
$(GDK_PIXBUF_CFLAGS) \
-I$(includedir)
Modified: trunk/app/text/gimptext-bitmap.c
==============================================================================
--- trunk/app/text/gimptext-bitmap.c (original)
+++ trunk/app/text/gimptext-bitmap.c Sun Oct 26 17:39:55 2008
@@ -24,7 +24,8 @@
#include <glib-object.h>
#define PANGO_ENABLE_ENGINE
-#include <pango/pangoft2.h>
+#include <cairo.h>
+#include <pango/pangocairo.h>
#include "text-types.h"
@@ -38,102 +39,33 @@
void
-gimp_text_render_bitmap (PangoFont *font,
- PangoGlyph glyph,
- FT_Int32 flags,
- FT_Matrix *trafo,
- gint x,
- gint y,
- FT_Bitmap *bitmap)
+gimp_text_render_bitmap (PangoFont *font,
+ PangoGlyph glyph,
+ cairo_font_options_t *options,
+ cairo_matrix_t *trafo,
+ gint x,
+ gint y,
+ cairo_t *cr)
{
- FT_Face face;
- gint y_start, y_limit, x_start, x_limit;
- gint ix, iy;
- const guchar *src;
- guchar *dest;
-
- face = pango_fc_font_lock_face (PANGO_FC_FONT (font));
-
- FT_Set_Transform (face, trafo, NULL);
-
- FT_Load_Glyph (face, (FT_UInt) glyph, flags);
- FT_Render_Glyph (face->glyph,
- (flags & FT_LOAD_TARGET_MONO ?
- ft_render_mode_mono : ft_render_mode_normal));
+
+ cairo_scaled_font_t *cfont;
+ cairo_glyph_t cglyph;
+
+ cfont = pango_cairo_font_get_scaled_font ((PangoCairoFont *) font);
x = PANGO_PIXELS (x);
y = PANGO_PIXELS (y);
- x_start = MAX (0, - (x + face->glyph->bitmap_left));
- x_limit = MIN (face->glyph->bitmap.width,
- bitmap->width - (x + face->glyph->bitmap_left));
-
- y_start = MAX (0, - (y - face->glyph->bitmap_top));
- y_limit = MIN (face->glyph->bitmap.rows,
- bitmap->rows - (y - face->glyph->bitmap_top));
-
- src = face->glyph->bitmap.buffer + y_start * face->glyph->bitmap.pitch;
-
- dest = bitmap->buffer +
- (y_start + y - face->glyph->bitmap_top) * bitmap->pitch +
- x_start + x + face->glyph->bitmap_left;
-
- switch (face->glyph->bitmap.pixel_mode)
- {
- case ft_pixel_mode_grays:
- src += x_start;
- for (iy = y_start; iy < y_limit; iy++)
- {
- const guchar *s = src;
- guchar *d = dest;
-
- for (ix = x_start; ix < x_limit; ix++)
- {
- switch (*s)
- {
- case 0:
- break;
- case 0xff:
- *d = 0xff;
- default:
- *d = MIN ((gushort) *d + (const gushort) *s, 0xff);
- break;
- }
-
- s++;
- d++;
- }
-
- dest += bitmap->pitch;
- src += face->glyph->bitmap.pitch;
- }
- break;
-
- case ft_pixel_mode_mono:
- src += x_start / 8;
- for (iy = y_start; iy < y_limit; iy++)
- {
- const guchar *s = src;
- guchar *d = dest;
-
- for (ix = x_start; ix < x_limit; ix++)
- {
- if ((*s) & (1 << (7 - (ix % 8))))
- *d |= 0xff;
-
- if ((ix % 8) == 7)
- s++;
- d++;
- }
-
- dest += bitmap->pitch;
- src += face->glyph->bitmap.pitch;
- }
- break;
-
- default:
- break;
- }
+ cglyph.x = x;
+ cglyph.y = y;
+ cglyph.index = glyph;
+
+ cairo_set_scaled_font (cr, cfont);
+ cairo_set_font_options (cr, options);
+
+ cairo_transform (cr, trafo);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
- pango_fc_font_unlock_face (PANGO_FC_FONT (font));
+ cairo_show_glyphs (cr, &cglyph, 1);
}
Modified: trunk/app/text/gimptext-bitmap.h
==============================================================================
--- trunk/app/text/gimptext-bitmap.h (original)
+++ trunk/app/text/gimptext-bitmap.h Sun Oct 26 17:39:55 2008
@@ -23,13 +23,13 @@
#define __GIMP_TEXT_BITMAP_H__
-void gimp_text_render_bitmap (PangoFont *font,
- PangoGlyph glyph,
- FT_Int32 flags,
- FT_Matrix *trafo,
- gint x,
- gint y,
- FT_Bitmap *bitmap);
+void gimp_text_render_bitmap (PangoFont *font,
+ PangoGlyph glyph,
+ cairo_font_options_t *options,
+ cairo_matrix_t *trafo,
+ gint x,
+ gint y,
+ cairo_t *cr);
#endif /* __GIMP_TEXT_BITMAP_H__ */
Modified: trunk/app/text/gimptext-private.h
==============================================================================
--- trunk/app/text/gimptext-private.h (original)
+++ trunk/app/text/gimptext-private.h Sun Oct 26 17:39:55 2008
@@ -22,8 +22,9 @@
#ifndef __GIMP_TEXT_LAYOUT_PRIVATE_H__
#define __GIMP_TEXT_LAYOUT_PRIVATE_H__
+
/* The purpose of this extra header file is to hide any Pango or
- * FreeType types from the rest of the gimp core.
+ * Cairo types from the rest of the gimp core.
*/
@@ -44,13 +45,13 @@
};
-typedef void (* GimpTextRenderFunc) (PangoFont *font,
- PangoGlyph glyph,
- FT_Int32 load_flags,
- FT_Matrix *tranform,
- gint x,
- gint y,
- gpointer render_data);
+typedef void (* GimpTextRenderFunc) (PangoFont *font,
+ PangoGlyph glyph,
+ cairo_font_options_t *options,
+ cairo_matrix_t *tranform,
+ gint x,
+ gint y,
+ gpointer render_data);
#endif /* __GIMP_TEXT_LAYOUT_PRIVATE_H__ */
Modified: trunk/app/text/gimptext-vectors.c
==============================================================================
--- trunk/app/text/gimptext-vectors.c (original)
+++ trunk/app/text/gimptext-vectors.c Sun Oct 26 17:39:55 2008
@@ -1,7 +1,7 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
- * GimpText
+ * GimpText-vectors
* Copyright (C) 2003 Sven Neumann <sven gimp org>
*
* This program is free software; you can redistribute it and/or modify
@@ -24,11 +24,9 @@
#include <gegl.h>
#define PANGO_ENABLE_ENGINE
-#include <pango/pangoft2.h>
+#include <cairo.h>
+#include <pango/pangocairo.h>
-#include <ft2build.h>
-#include FT_GLYPH_H
-#include FT_OUTLINE_H
#include "text-types.h"
@@ -62,13 +60,13 @@
};
-static void gimp_text_render_vectors (PangoFont *font,
- PangoGlyph glyph,
- FT_Int32 flags,
- FT_Matrix *matrix,
- gint x,
- gint y,
- RenderContext *context);
+static void gimp_text_render_vectors (PangoFont *font,
+ PangoGlyph glyph,
+ cairo_font_options_t *options,
+ cairo_matrix_t *cmatrix,
+ gint x,
+ gint y,
+ RenderContext *context);
GimpVectors *
@@ -108,11 +106,12 @@
static inline void
gimp_text_vector_coords (RenderContext *context,
- const FT_Vector *vector,
+ const double x,
+ const double y,
GimpCoords *coords)
{
- coords->x = context->offset_x + (gdouble) vector->x / 64.0;
- coords->y = context->offset_y - (gdouble) vector->y / 64.0;
+ coords->x = context->offset_x + (gdouble) x;
+ coords->y = context->offset_y + (gdouble) y;
coords->pressure = GIMP_COORDS_DEFAULT_PRESSURE;
coords->xtilt = GIMP_COORDS_DEFAULT_TILT;
coords->ytilt = GIMP_COORDS_DEFAULT_TILT;
@@ -120,17 +119,17 @@
}
static gint
-moveto (const FT_Vector *to,
- gpointer data)
+moveto (RenderContext *context,
+ const double x,
+ const double y)
{
- RenderContext *context = data;
GimpCoords start;
#if GIMP_TEXT_DEBUG
- g_printerr ("moveto %f, %f\n", to->x / 64.0, to->y / 64.0);
+ g_printerr ("moveto %f, %f\n", x, y);
#endif
- gimp_text_vector_coords (context, to, &start);
+ gimp_text_vector_coords (context, x, y, &start);
if (context->stroke)
gimp_stroke_close (context->stroke);
@@ -144,20 +143,20 @@
}
static gint
-lineto (const FT_Vector *to,
- gpointer data)
+lineto (RenderContext *context,
+ const double x,
+ const double y)
{
- RenderContext *context = data;
GimpCoords end;
#if GIMP_TEXT_DEBUG
- g_printerr ("lineto %f, %f\n", to->x / 64.0, to->y / 64.0);
+ g_printerr ("lineto %f, %f\n", x, y);
#endif
if (! context->stroke)
return 0;
- gimp_text_vector_coords (context, to, &end);
+ gimp_text_vector_coords (context, x, y, &end);
gimp_bezier_stroke_lineto (context->stroke, &end);
@@ -165,96 +164,131 @@
}
static gint
-conicto (const FT_Vector *ftcontrol,
- const FT_Vector *to,
- gpointer data)
+cubicto (RenderContext *context,
+ const double x1,
+ const double y1,
+ const double x2,
+ const double y2,
+ const double x3,
+ const double y3)
{
- RenderContext *context = data;
- GimpCoords control;
+ GimpCoords control1;
+ GimpCoords control2;
GimpCoords end;
#if GIMP_TEXT_DEBUG
- g_printerr ("conicto %f, %f\n", to->x / 64.0, to->y / 64.0);
+ g_printerr ("cubicto %f, %f\n", x3, y3);
#endif
if (! context->stroke)
return 0;
- gimp_text_vector_coords (context, ftcontrol, &control);
- gimp_text_vector_coords (context, to, &end);
+ gimp_text_vector_coords (context, x1, y1, &control1);
+ gimp_text_vector_coords (context, x2, y2, &control2);
+ gimp_text_vector_coords (context, x3, y3, &end);
- gimp_bezier_stroke_conicto (context->stroke, &control, &end);
+ gimp_bezier_stroke_cubicto (context->stroke, &control1, &control2, &end);
return 0;
}
static gint
-cubicto (const FT_Vector *ftcontrol1,
- const FT_Vector *ftcontrol2,
- const FT_Vector *to,
- gpointer data)
+closepath (RenderContext *context)
{
- RenderContext *context = data;
- GimpCoords control1;
- GimpCoords control2;
- GimpCoords end;
-
#if GIMP_TEXT_DEBUG
- g_printerr ("cubicto %f, %f\n", to->x / 64.0, to->y / 64.0);
+ g_printerr ("moveto\n");
#endif
- if (! context->stroke)
+ if (!context->stroke)
return 0;
- gimp_text_vector_coords (context, ftcontrol1, &control1);
- gimp_text_vector_coords (context, ftcontrol2, &control2);
- gimp_text_vector_coords (context, to, &end);
+ gimp_stroke_close (context->stroke);
- gimp_bezier_stroke_cubicto (context->stroke, &control1, &control2, &end);
+ context->stroke = NULL;
return 0;
}
static void
-gimp_text_render_vectors (PangoFont *font,
- PangoGlyph pango_glyph,
- FT_Int32 flags,
- FT_Matrix *trafo,
- gint x,
- gint y,
- RenderContext *context)
+gimp_text_render_vectors (PangoFont *font,
+ PangoGlyph pango_glyph,
+ cairo_font_options_t *options,
+ cairo_matrix_t *matrix,
+ gint x,
+ gint y,
+ RenderContext *context)
{
- const FT_Outline_Funcs outline_funcs =
- {
- moveto,
- lineto,
- conicto,
- cubicto,
- 0,
- 0
- };
-
- FT_Face face;
- FT_Glyph glyph;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ cairo_path_t *cpath;
+ cairo_scaled_font_t *cfont;
+ cairo_glyph_t cglyph;
+ gint i;
- face = pango_fc_font_lock_face (PANGO_FC_FONT (font));
+ context->offset_x = (gdouble) x / PANGO_SCALE;
+ context->offset_y = (gdouble) y / PANGO_SCALE;
- FT_Load_Glyph (face, (FT_UInt) pango_glyph, flags);
+ cglyph.x = 0;
+ cglyph.y = 0;
+ cglyph.index = pango_glyph;
- FT_Get_Glyph (face->glyph, &glyph);
+ /* A cairo_t needs an image surface to function, so "surface" is created
+ * temporarily for this purpose. Nothing is drawn to "surface", but it is
+ * still needed to be connected to "cr" for "cr" to execute
+ * cr_glyph_path(). The size of surface is therefore irrelevant.
+ */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
+ cr = cairo_create (surface);
- if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
- {
- FT_OutlineGlyph outline_glyph = (FT_OutlineGlyph) glyph;
+ cfont = pango_cairo_font_get_scaled_font ((PangoCairoFont *) font);
+
+ cairo_set_scaled_font (cr, cfont);
+
+ cairo_set_font_options (cr, options);
- context->offset_x = (gdouble) x / PANGO_SCALE;
- context->offset_y = (gdouble) y / PANGO_SCALE;
+ cairo_transform (cr, matrix);
+
+ cairo_glyph_path (cr, &cglyph, 1);
+
+ cpath = cairo_copy_path (cr);
+
+ for (i = 0; i < cpath->num_data; i += cpath->data[i].header.length)
+ {
+ cairo_path_data_t *data = &cpath->data[i];
- FT_Outline_Decompose (&outline_glyph->outline, &outline_funcs, context);
+ /* if the drawing operation is the final moveto of the glyph,
+ * break to avoid creating an empty point. This is because cairo
+ * always adds a moveto after each closepath.
+ */
+ if (i + data->header.length >= cpath->num_data)
+ break;
+
+ switch (data->header.type)
+ {
+ case CAIRO_PATH_MOVE_TO:
+ moveto (context, data[1].point.x, data[1].point.y);
+ break;
+
+ case CAIRO_PATH_LINE_TO:
+ lineto (context, data[1].point.x, data[1].point.y);
+ break;
+
+ case CAIRO_PATH_CURVE_TO:
+ cubicto (context,
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ break;
+
+ case CAIRO_PATH_CLOSE_PATH:
+ closepath (context);
+ break;
+ }
}
- FT_Done_Glyph (glyph);
+ cairo_path_destroy (cpath);
- pango_fc_font_unlock_face (PANGO_FC_FONT (font));
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
}
Modified: trunk/app/text/gimptext-vectors.h
==============================================================================
--- trunk/app/text/gimptext-vectors.h (original)
+++ trunk/app/text/gimptext-vectors.h Sun Oct 26 17:39:55 2008
@@ -1,7 +1,7 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
- * GimpText
+ * GimpText-vectors
* Copyright (C) 2003 Sven Neumann <sven gimp org>
*
* This program is free software; you can redistribute it and/or modify
Modified: trunk/app/text/gimptextlayer.c
==============================================================================
--- trunk/app/text/gimptextlayer.c (original)
+++ trunk/app/text/gimptextlayer.c Sun Oct 26 17:39:55 2008
@@ -24,7 +24,7 @@
#include <string.h>
#include <gegl.h>
-#include <pango/pangoft2.h>
+#include <pango/pangocairo.h>
#include "libgimpconfig/gimpconfig.h"
@@ -61,6 +61,7 @@
PROP_MODIFIED
};
+
static void gimp_text_layer_finalize (GObject *object);
static void gimp_text_layer_get_property (GObject *object,
guint property_id,
@@ -151,6 +152,7 @@
"auto-rename", NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
+
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_MODIFIED,
"modified", NULL,
FALSE,
@@ -194,6 +196,7 @@
case PROP_MODIFIED:
g_value_set_boolean (value, text_layer->modified);
break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -216,6 +219,7 @@
case PROP_MODIFIED:
text_layer->modified = g_value_get_boolean (value);
break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -579,6 +583,7 @@
layer->text->text : _("Empty Text Layer"));
gimp_text_layer_render_layout (layer, layout);
+
g_object_unref (layout);
g_object_thaw_notify (G_OBJECT (drawable));
@@ -590,42 +595,47 @@
gimp_text_layer_render_layout (GimpTextLayer *layer,
GimpTextLayout *layout)
{
- GimpDrawable *drawable = GIMP_DRAWABLE (layer);
- GimpItem *item = GIMP_ITEM (layer);
- TileManager *mask;
- FT_Bitmap bitmap;
- PixelRegion textPR;
- PixelRegion maskPR;
- gint i;
+ GimpDrawable *drawable = GIMP_DRAWABLE (layer);
+ GimpItem *item = GIMP_ITEM (layer);
+ TileManager *mask;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ PixelRegion textPR;
+ PixelRegion maskPR;
+ gint i;
+ gint width, height;
gimp_drawable_fill (drawable, &layer->text->color, NULL);
- bitmap.width = gimp_item_width (item);
- bitmap.rows = gimp_item_height (item);
- bitmap.pitch = bitmap.width;
- if (bitmap.pitch & 3)
- bitmap.pitch += 4 - (bitmap.pitch & 3);
- bitmap.buffer = g_malloc0 (bitmap.rows * bitmap.pitch);
+ width = gimp_item_width (item);
+ height = gimp_item_height (item);
+
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
+ width, height);
+
+ cr = cairo_create (surface);
gimp_text_layout_render (layout,
(GimpTextRenderFunc) gimp_text_render_bitmap,
- &bitmap);
+ cr);
- mask = tile_manager_new (bitmap.width, bitmap.rows, 1);
- pixel_region_init (&maskPR, mask, 0, 0, bitmap.width, bitmap.rows, TRUE);
+ mask = tile_manager_new ( width, height, 1);
+ pixel_region_init (&maskPR, mask, 0, 0, width, height, TRUE);
- for (i = 0; i < bitmap.rows; i++)
+ for (i = 0; i < height; i++)
pixel_region_set_row (&maskPR,
- 0, i, bitmap.width,
- bitmap.buffer + i * bitmap.pitch);
+ 0, i, width,
+ cairo_image_surface_get_data (surface) + i * cairo_image_surface_get_stride (surface));
- g_free (bitmap.buffer);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
pixel_region_init (&textPR, gimp_drawable_get_tiles (drawable),
- 0, 0, bitmap.width, bitmap.rows, TRUE);
+ 0, 0, width, height, TRUE);
pixel_region_init (&maskPR, mask,
- 0, 0, bitmap.width, bitmap.rows, FALSE);
+ 0, 0, width, height, FALSE);
apply_mask_to_region (&textPR, &maskPR, OPAQUE_OPACITY);
Modified: trunk/app/text/gimptextlayout-render.c
==============================================================================
--- trunk/app/text/gimptextlayout-render.c (original)
+++ trunk/app/text/gimptextlayout-render.c Sun Oct 26 17:39:55 2008
@@ -24,7 +24,8 @@
#include "config.h"
#include <glib-object.h>
-#include <pango/pangoft2.h>
+#include <cairo.h>
+#include <pango/pangocairo.h>
#include <pango/pango-font.h>
#include "text-types.h"
@@ -61,9 +62,10 @@
gint x,
gint y,
gpointer render_data);
-static FT_Int32 gimp_text_layout_render_flags (GimpTextLayout *layout);
-static void gimp_text_layout_render_trafo (GimpTextLayout *layout,
- FT_Matrix *trafo);
+static cairo_font_options_t *
+ gimp_text_layout_render_flags (GimpTextLayout *layout);
+static void gimp_text_layout_render_trafo (GimpTextLayout *layout,
+ cairo_matrix_t *trafo);
@@ -164,12 +166,13 @@
gint y,
gpointer render_data)
{
- PangoGlyphInfo *gi;
- FT_Int32 flags;
- FT_Matrix trafo;
- FT_Vector pos;
- gint i;
- gint x_position = 0;
+ PangoGlyphInfo *gi;
+ cairo_font_options_t *flags;
+ cairo_matrix_t trafo;
+ double pos_x;
+ double pos_y;
+ gint i;
+ gint x_position = 0;
flags = gimp_text_layout_render_flags (layout);
gimp_text_layout_render_trafo (layout, &trafo);
@@ -178,13 +181,14 @@
{
if (gi->glyph != PANGO_GLYPH_EMPTY)
{
- pos.x = x + x_position + gi->geometry.x_offset;
- pos.y = y + gi->geometry.y_offset;
- FT_Vector_Transform (&pos, &trafo);
+ pos_x = x + x_position + gi->geometry.x_offset;
+ pos_y = y + gi->geometry.y_offset;
+
+ cairo_matrix_transform_point (&trafo, &pos_x, &pos_y);
render_func (font, gi->glyph, flags, &trafo,
- pos.x, pos.y,
+ pos_x, pos_y,
render_data);
}
@@ -192,34 +196,39 @@
}
}
-static FT_Int32
+static cairo_font_options_t *
gimp_text_layout_render_flags (GimpTextLayout *layout)
{
- GimpText *text = layout->text;
- gint flags;
+ GimpText *text = layout->text;
+ cairo_font_options_t *flags;
+
+ flags = cairo_font_options_create ();
if (text->antialias)
- flags = FT_LOAD_NO_BITMAP;
+ cairo_font_options_set_antialias (flags, CAIRO_ANTIALIAS_DEFAULT);
else
- flags = FT_LOAD_TARGET_MONO;
-
- if (!text->hinting)
- flags |= FT_LOAD_NO_HINTING;
-
+ cairo_font_options_set_antialias (flags, CAIRO_ANTIALIAS_NONE);
+/*
+ * commented because there's no real autohint support in cairo like there is in ft2
if (text->autohint)
- flags |= FT_LOAD_FORCE_AUTOHINT;
+ cairo_font_options_set_hint_style (flags, CAIRO_HINT_STYLE_DEFAULT);
+*/
+ if (!text->hinting)
+ cairo_font_options_set_hint_style (flags, CAIRO_HINT_STYLE_NONE);
return flags;
}
static void
gimp_text_layout_render_trafo (GimpTextLayout *layout,
- FT_Matrix *trafo)
+ cairo_matrix_t *trafo)
{
GimpText *text = layout->text;
- trafo->xx = text->transformation.coeff[0][0] * 65536.0 / layout->yres * layout->xres;
- trafo->xy = text->transformation.coeff[0][1] * 65536.0;
- trafo->yx = text->transformation.coeff[1][0] * 65536.0 / layout->yres * layout->xres;
- trafo->yy = text->transformation.coeff[1][1] * 65536.0;
+ trafo->xx = text->transformation.coeff[0][0] * 1.0 / layout->yres * layout->xres;
+ trafo->xy = text->transformation.coeff[0][1] * 1.0;
+ trafo->yx = text->transformation.coeff[1][0] * 1.0 / layout->yres * layout->xres;
+ trafo->yy = text->transformation.coeff[1][1] * 1.0;
+ trafo->x0 = 0;
+ trafo->y0 = 0;
}
Modified: trunk/app/text/gimptextlayout.c
==============================================================================
--- trunk/app/text/gimptextlayout.c (original)
+++ trunk/app/text/gimptextlayout.c Sun Oct 26 17:39:55 2008
@@ -22,7 +22,8 @@
#include "config.h"
#include <gegl.h>
-#include <pango/pangoft2.h>
+#include <cairo.h>
+#include <pango/pangocairo.h>
#include "text-types.h"
@@ -36,19 +37,19 @@
#include "gimptextlayout.h"
-static void gimp_text_layout_finalize (GObject *object);
+static void gimp_text_layout_finalize (GObject *object);
-static void gimp_text_layout_position (GimpTextLayout *layout);
+static void gimp_text_layout_position (GimpTextLayout *layout);
static PangoContext * gimp_text_get_pango_context (GimpText *text,
gdouble xres,
gdouble yres);
-static gint gimp_text_layout_pixel_size (Gimp *gimp,
+static gint gimp_text_layout_pixel_size (Gimp *gimp,
gdouble value,
GimpUnit unit,
gdouble res);
-static gint gimp_text_layout_point_size (Gimp *gimp,
+static gint gimp_text_layout_point_size (Gimp *gimp,
gdouble value,
GimpUnit unit,
gdouble res);
@@ -302,49 +303,21 @@
#endif
}
-
-static void
-gimp_text_ft2_subst_func (FcPattern *pattern,
- gpointer data)
-{
- GimpText *text = GIMP_TEXT (data);
-
- FcPatternAddBool (pattern, FC_HINTING, text->hinting);
- FcPatternAddBool (pattern, FC_AUTOHINT, text->autohint);
- FcPatternAddBool (pattern, FC_ANTIALIAS, text->antialias);
-}
-
static PangoContext *
gimp_text_get_pango_context (GimpText *text,
gdouble xres,
gdouble yres)
{
- PangoContext *context;
- PangoFT2FontMap *fontmap;
+ PangoContext *context;
+ PangoCairoFontMap *fontmap;
- fontmap = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
+ fontmap = PANGO_CAIRO_FONT_MAP (pango_cairo_font_map_new ());
- pango_ft2_font_map_set_resolution (fontmap, xres, yres);
+ pango_cairo_font_map_set_resolution (fontmap, xres);
- pango_ft2_font_map_set_default_substitute (fontmap,
- gimp_text_ft2_subst_func,
- g_object_ref (text),
- (GDestroyNotify) g_object_unref);
-
- context = pango_ft2_font_map_create_context (fontmap);
+ context = pango_cairo_font_map_create_context (fontmap);
g_object_unref (fontmap);
- /* Workaround for bug #143542 (PangoFT2Fontmap leak),
- * see also bug #148997 (Text layer rendering leaks font file descriptor):
- *
- * Calling pango_ft2_font_map_substitute_changed() causes the
- * font_map cache to be flushed, thereby removing the circular
- * reference that causes the leak.
- */
- g_object_weak_ref (G_OBJECT (context),
- (GWeakNotify) pango_ft2_font_map_substitute_changed,
- fontmap);
-
if (text->language)
pango_context_set_language (context,
pango_language_from_string (text->language));
Modified: trunk/app/tools/gimprectangletool.c
==============================================================================
--- trunk/app/tools/gimprectangletool.c (original)
+++ trunk/app/tools/gimprectangletool.c Sun Oct 26 17:39:55 2008
@@ -414,6 +414,11 @@
GIMP_TYPE_RECTANGLE_PRECISION,
GIMP_RECTANGLE_PRECISION_INT,
GIMP_PARAM_READWRITE));
+ g_object_interface_install_property (iface,
+ g_param_spec_boolean ("narrow-mode",
+ NULL, NULL,
+ FALSE,
+ GIMP_PARAM_READWRITE));
iface->execute = NULL;
iface->cancel = NULL;
@@ -497,6 +502,9 @@
g_object_class_override_property (klass,
GIMP_RECTANGLE_TOOL_PROP_PRECISION,
"precision");
+ g_object_class_override_property (klass,
+ GIMP_RECTANGLE_TOOL_PROP_NARROW_MODE,
+ "narrow-mode");
}
void
@@ -718,6 +726,9 @@
case GIMP_RECTANGLE_TOOL_PROP_PRECISION:
private->precision = g_value_get_enum (value);
break;
+ case GIMP_RECTANGLE_TOOL_PROP_NARROW_MODE:
+ private->narrow_mode = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -758,6 +769,9 @@
case GIMP_RECTANGLE_TOOL_PROP_PRECISION:
g_value_set_enum (value, private->precision);
break;
+ case GIMP_RECTANGLE_TOOL_PROP_NARROW_MODE:
+ g_value_set_boolean (value, private->narrow_mode);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Modified: trunk/app/tools/gimprectangletool.h
==============================================================================
--- trunk/app/tools/gimprectangletool.h (original)
+++ trunk/app/tools/gimprectangletool.h Sun Oct 26 17:39:55 2008
@@ -29,7 +29,8 @@
GIMP_RECTANGLE_TOOL_PROP_Y2,
GIMP_RECTANGLE_TOOL_PROP_CONSTRAINT,
GIMP_RECTANGLE_TOOL_PROP_PRECISION,
- GIMP_RECTANGLE_TOOL_PROP_LAST = GIMP_RECTANGLE_TOOL_PROP_PRECISION
+ GIMP_RECTANGLE_TOOL_PROP_NARROW_MODE,
+ GIMP_RECTANGLE_TOOL_PROP_LAST = GIMP_RECTANGLE_TOOL_PROP_NARROW_MODE
} GimpRectangleToolProp;
Modified: trunk/app/tools/gimptextoptions.c
==============================================================================
--- trunk/app/tools/gimptextoptions.c (original)
+++ trunk/app/tools/gimptextoptions.c Sun Oct 26 17:39:55 2008
@@ -62,6 +62,7 @@
PROP_INDENTATION,
PROP_LINE_SPACING,
PROP_LETTER_SPACING,
+ PROP_USE_EDITOR,
PROP_FONT_VIEW_TYPE,
PROP_FONT_VIEW_SIZE
@@ -173,6 +174,14 @@
GIMP_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_DEFAULTS);
+ GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_USE_EDITOR,
+ "use-editor",
+ N_("Use an external editor window for text "
+ "entry, instead of direct-on-canvas "
+ "editing"),
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
+
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_FONT_VIEW_TYPE,
"font-view-type", NULL,
GIMP_TYPE_VIEW_TYPE,
@@ -192,7 +201,6 @@
gimp_text_options_init (GimpTextOptions *options)
{
options->size_entry = NULL;
- options->to_vectors_button = NULL;
options->along_vectors_button = NULL;
}
@@ -240,6 +248,10 @@
g_value_set_double (value, options->letter_spacing);
break;
+ case PROP_USE_EDITOR:
+ g_value_set_boolean (value, options->use_editor);
+ break;
+
case PROP_FONT_VIEW_TYPE:
g_value_set_enum (value, options->font_view_type);
break;
@@ -298,6 +310,10 @@
options->letter_spacing = g_value_get_double (value);
break;
+ case PROP_USE_EDITOR:
+ options->use_editor = g_value_get_boolean (value);
+ break;
+
case PROP_FONT_VIEW_TYPE:
options->font_view_type = g_value_get_enum (value);
break;
@@ -458,6 +474,10 @@
gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
gtk_widget_show (vbox);
+ button = gimp_prop_check_button_new (config, "use-editor", _("Use editor"));
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
button = gimp_prop_check_button_new (config, "hinting", _("Hinting"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
@@ -516,14 +536,6 @@
gimp_table_attach_stock (GTK_TABLE (table), row++,
GIMP_STOCK_LETTER_SPACING, spinbutton, 1, TRUE);
- /* Create a path from the current text */
- button = gtk_button_new_with_label (_("Path from Text"));
- gtk_box_pack_end (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
- gtk_widget_set_sensitive (button, FALSE);
- gtk_widget_show (button);
-
- options->to_vectors_button = button;
-
button = gtk_button_new_with_label (_("Text along Path"));
gtk_box_pack_end (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
@@ -573,7 +585,8 @@
gimp_text_options_editor_new (GtkWindow *parent,
GimpTextOptions *options,
GimpMenuFactory *menu_factory,
- const gchar *title)
+ const gchar *title,
+ GtkTextBuffer *text_buffer)
{
GtkWidget *editor;
const gchar *font_name;
@@ -582,7 +595,7 @@
g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
g_return_val_if_fail (title != NULL, NULL);
- editor = gimp_text_editor_new (title, parent, menu_factory);
+ editor = gimp_text_editor_new (title, parent, menu_factory, text_buffer);
font_name = gimp_context_get_font_name (GIMP_CONTEXT (options));
Modified: trunk/app/tools/gimptextoptions.h
==============================================================================
--- trunk/app/tools/gimptextoptions.h (original)
+++ trunk/app/tools/gimptextoptions.h Sun Oct 26 17:39:55 2008
@@ -53,9 +53,10 @@
GimpViewType font_view_type;
GimpViewSize font_view_size;
+ gboolean use_editor;
+
/* options gui */
GtkWidget *size_entry;
- GtkWidget *to_vectors_button;
GtkWidget *along_vectors_button;
};
@@ -70,7 +71,8 @@
GtkWidget * gimp_text_options_editor_new (GtkWindow *parent,
GimpTextOptions *options,
GimpMenuFactory *menu_factory,
- const gchar *title);
+ const gchar *title,
+ GtkTextBuffer *text_buffer);
#endif /* __GIMP_TEXT_OPTIONS_H__ */
Modified: trunk/app/tools/gimptexttool.c
==============================================================================
--- trunk/app/tools/gimptexttool.c (original)
+++ trunk/app/tools/gimptexttool.c Sun Oct 26 17:39:55 2008
@@ -28,6 +28,7 @@
#include <gegl.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
@@ -47,16 +48,21 @@
#include "text/gimptext.h"
#include "text/gimptext-vectors.h"
#include "text/gimptextlayer.h"
+#include "text/gimptextlayout.h"
#include "text/gimptextundo.h"
+#include "text/gimptext-private.h"
#include "vectors/gimpvectors-warp.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmenufactory.h"
#include "widgets/gimptexteditor.h"
#include "widgets/gimpviewabledialog.h"
+#include "display/gimpcanvas.h"
#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
#include "gimpeditselectiontool.h"
#include "gimprectangletool.h"
@@ -95,10 +101,23 @@
GdkModifierType state,
GimpButtonReleaseType release_type,
GimpDisplay *display);
+static void gimp_text_tool_motion (GimpTool *tool,
+ GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplay *display);
+static gboolean gimp_text_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display);
static void gimp_text_tool_cursor_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
GimpDisplay *display);
+static GimpUIManager * gimp_text_tool_get_popup(GimpTool *tool,
+ GimpCoords *coords,
+ GdkModifierType state,
+ GimpDisplay *display,
+ const gchar **ui_path);
static void gimp_text_tool_connect (GimpTextTool *text_tool,
GimpTextLayer *layer,
@@ -115,16 +134,15 @@
static gboolean gimp_text_tool_idle_apply (GimpTextTool *text_tool);
static void gimp_text_tool_apply (GimpTextTool *text_tool);
-static void gimp_text_tool_create_vectors (GimpTextTool *text_tool);
static void gimp_text_tool_create_vectors_warped
(GimpTextTool *text_tool);
static void gimp_text_tool_create_layer (GimpTextTool *text_tool,
GimpText *text);
+static void gimp_text_tool_canvas_editor (GimpTextTool *text_tool);
+static gchar *gimp_text_tool_canvas_editor_get_text (GimpTextTool *text_tool);
+
static void gimp_text_tool_editor (GimpTextTool *text_tool);
-static void gimp_text_tool_editor_update (GimpTextTool *text_tool);
-static void gimp_text_tool_text_changed (GimpTextEditor *editor,
- GimpTextTool *text_tool);
static void gimp_text_tool_layer_changed (GimpImage *image,
GimpTextTool *text_tool);
@@ -139,6 +157,36 @@
void gimp_rectangle_tool_frame_item(GimpRectangleTool *rect_tool,
GimpItem *item);
+static void gimp_text_tool_draw (GimpDrawTool *draw_tool);
+static void gimp_text_tool_draw_preedit_lines (GimpDrawTool *draw_tool);
+static void gimp_text_tool_draw_text_selection (GimpDrawTool *draw_tool);
+
+static void gimp_text_tool_update_layout (GimpTextTool *text_tool);
+static void gimp_text_tool_update_proxy (GimpTextTool *text_tool);
+
+static void gimp_text_tool_reset_im_context (GimpTextTool *text_tool);
+static void gimp_text_tool_enter_text (GimpTextTool *text_tool,
+ const gchar *str);
+static void gimp_text_tool_text_buffer_changed (GtkTextBuffer *text_buffer,
+ GimpTextTool *text_tool);
+static void gimp_text_tool_text_buffer_mark_set (GtkTextBuffer *text_buffer,
+ GtkTextIter *location,
+ GtkTextMark *mark,
+ GimpTextTool *text_tool);
+static void gimp_text_tool_use_editor_notify (GimpTextOptions *options,
+ GParamSpec *pspec,
+ GimpTextTool *text_tool);
+
+/* IM Context Callbacks
+ */
+static void gimp_text_tool_commit_cb (GtkIMContext *context,
+ const gchar *str,
+ GimpTextTool *text_tool);
+
+static void gimp_text_tool_preedit_changed_cb (GtkIMContext *context,
+ GimpTextTool *text_tool);
+
+
G_DEFINE_TYPE_WITH_CODE (GimpTextTool, gimp_text_tool,
GIMP_TYPE_DRAW_TOOL,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_TOOL,
@@ -183,20 +231,21 @@
tool_class->control = gimp_text_tool_control;
tool_class->button_press = gimp_text_tool_button_press;
- tool_class->motion = gimp_rectangle_tool_motion;
+ tool_class->motion = gimp_text_tool_motion;
tool_class->button_release = gimp_text_tool_button_release;
- tool_class->key_press = gimp_edit_selection_tool_key_press;
+ tool_class->key_press = gimp_text_tool_key_press;
tool_class->oper_update = gimp_rectangle_tool_oper_update;
tool_class->cursor_update = gimp_text_tool_cursor_update;
+ tool_class->get_popup = gimp_text_tool_get_popup;
- draw_tool_class->draw = gimp_rectangle_tool_draw;
+ draw_tool_class->draw = gimp_text_tool_draw;
}
static void
gimp_text_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface)
{
- iface->execute = NULL;
- iface->cancel = NULL;
+ iface->execute = NULL;
+ iface->cancel = NULL;
iface->rectangle_change_complete = gimp_text_tool_rectangle_change_complete;
}
@@ -212,12 +261,35 @@
text_tool->text = NULL;
text_tool->layer = NULL;
text_tool->image = NULL;
+ text_tool->layout = NULL;
+
+ text_tool->text_buffer = gtk_text_buffer_new (NULL);
+ gtk_text_buffer_set_text (text_tool->text_buffer, "", -1);
+
+ g_signal_connect (text_tool->text_buffer, "changed",
+ G_CALLBACK (gimp_text_tool_text_buffer_changed),
+ text_tool);
+ g_signal_connect (text_tool->text_buffer, "mark-set",
+ G_CALLBACK (gimp_text_tool_text_buffer_mark_set),
+ text_tool);
+
+ text_tool->im_context = gtk_im_multicontext_new ();
- gimp_tool_control_set_scroll_lock (tool->control, TRUE);
- gimp_tool_control_set_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_TEXT);
- gimp_tool_control_set_action_object_1 (tool->control,
- "context/context-font-select-set");
+ text_tool->preedit_string = NULL;
+
+ g_signal_connect (text_tool->im_context, "commit",
+ G_CALLBACK (gimp_text_tool_commit_cb),
+ text_tool);
+ g_signal_connect (text_tool->im_context, "preedit_changed",
+ G_CALLBACK (gimp_text_tool_preedit_changed_cb),
+ text_tool);
+
+ gimp_tool_control_set_scroll_lock (tool->control, TRUE);
+ gimp_tool_control_set_wants_all_key_events (tool->control, TRUE);
+ gimp_tool_control_set_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_TEXT);
+ gimp_tool_control_set_action_object_1 (tool->control,
+ "context/context-font-select-set");
text_tool->handle_rectangle_change_complete = TRUE;
}
@@ -246,6 +318,14 @@
G_CALLBACK (gimp_text_tool_proxy_notify),
text_tool, 0);
+ g_signal_connect_object (options, "notify::use-editor",
+ G_CALLBACK (gimp_text_tool_use_editor_notify),
+ text_tool, 0);
+
+ g_object_set (options,
+ "highlight", FALSE,
+ NULL);
+
return object;
}
@@ -253,9 +333,16 @@
gimp_text_tool_dispose (GObject *object)
{
GimpTextTool *text_tool = GIMP_TEXT_TOOL (object);
+ GimpTool *tool = GIMP_TOOL (object);
gimp_text_tool_set_drawable (text_tool, NULL, FALSE);
+ if (text_tool->editor)
+ {
+ gtk_widget_destroy (text_tool->editor);
+ text_tool->editor = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -270,6 +357,24 @@
text_tool->proxy = NULL;
}
+ if (text_tool->layout)
+ {
+ g_object_unref (text_tool->layout);
+ text_tool->layout = NULL;
+ }
+
+ if (text_tool->text_buffer)
+ {
+ g_object_unref (text_tool->text_buffer);
+ text_tool->text_buffer = NULL;
+ }
+
+ if (text_tool->im_context)
+ {
+ g_object_unref (text_tool->im_context);
+ text_tool->im_context = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -308,35 +413,64 @@
GimpDrawable *drawable;
GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
GimpRectangleTool *rect_tool = GIMP_RECTANGLE_TOOL (tool);
+ gint cx, cy;
+ gint x1, y1;
+ gint x2, y2;
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
-
- /* FIXME: this should certainly be done elsewhere */
- g_object_set (options,
- "highlight", FALSE,
- NULL);
+ g_signal_handlers_block_by_func (text_tool->text_buffer,
+ G_CALLBACK (gimp_text_tool_text_buffer_mark_set),
+ text_tool);
text_tool->x1 = coords->x;
text_tool->y1 = coords->y;
- gimp_rectangle_tool_button_press (tool, coords, time, state, display);
+ g_object_get (rect_tool,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ cx = coords->x;
+ cy = coords->y;
+
+ if (x1 <= cx && x2 >= cx && y1 <= cy && y2 >= cy)
+ {
+ text_tool->text_cursor_changing = TRUE;
+
+ gimp_rectangle_tool_set_function (rect_tool, GIMP_RECTANGLE_TOOL_DEAD);
+ gimp_tool_control_activate (tool->control);
+ }
+ else
+ {
+ text_tool->text_cursor_changing = FALSE;
+
+ gimp_rectangle_tool_button_press (tool, coords, time, state, display);
+ }
- gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
- /* bail out now if the rectangle is narrow and the button
- press is outside the layer */
+ /* bail out now if the rectangle is narrow and the button press is
+ * outside the layer
+ */
if (text_tool->layer &&
- gimp_rectangle_tool_get_function (rect_tool) != GIMP_RECTANGLE_TOOL_CREATING)
+ gimp_rectangle_tool_get_function (rect_tool) !=
+ GIMP_RECTANGLE_TOOL_CREATING)
{
GimpItem *item = GIMP_ITEM (text_tool->layer);
gdouble x = coords->x - item->offset_x;
gdouble y = coords->y - item->offset_y;
if (x < 0 || x > item->width || y < 0 || y > item->height)
- return;
+ {
+ gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+ return;
+ }
}
+ gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+
drawable = gimp_image_get_active_drawable (display->image);
gimp_text_tool_set_drawable (text_tool, drawable, FALSE);
@@ -356,10 +490,46 @@
/* did the user click on a text layer? */
if (gimp_text_tool_set_drawable (text_tool, drawable, TRUE))
{
- /* on second click, open the text editor */
+ /*enable keyboard-handling for the text*/
+
+ gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
+
if (text && text_tool->text == text)
- gimp_text_tool_editor (text_tool);
+ {
+ gimp_text_tool_canvas_editor (text_tool);
+ gtk_text_buffer_set_text (text_tool->text_buffer,
+ text_tool->text->text, -1);
+ gimp_text_tool_update_layout (text_tool);
+ }
+
+ if (text_tool->layout)
+ {
+ GtkTextIter cursor, start, end;
+ gint offset;
+ gint trailing;
+ gchar *string;
+
+ gtk_text_buffer_get_bounds (text_tool->text_buffer,
+ &start, &end);
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &end, TRUE);
+ pango_layout_xy_to_index (text_tool->layout->layout,
+ x * PANGO_SCALE, y * PANGO_SCALE,
+ &offset, &trailing);
+ offset = g_utf8_pointer_to_offset (string,
+ (string + offset));
+ offset += trailing;
+
+ g_free (string);
+
+ gtk_text_buffer_get_iter_at_offset (text_tool->text_buffer,
+ &cursor, offset);
+ gtk_text_buffer_place_cursor (text_tool->text_buffer,
+ &cursor);
+ }
+
+ gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
return;
}
}
@@ -367,8 +537,22 @@
/* create a new text layer */
text_tool->text_box_fixed = FALSE;
+
+ if (text_tool->text)
+ {
+ g_object_unref (text_tool->text);
+ text_tool->text = NULL;
+ }
+
+ gtk_text_buffer_set_text (text_tool->text_buffer, "", -1);
gimp_text_tool_connect (text_tool, NULL, NULL);
- gimp_text_tool_editor (text_tool);
+ gimp_text_tool_canvas_editor (text_tool);
+
+/* if (text_tool->text) */
+/* gtk_text_buffer_set_text (text_tool->text_buffer, */
+/* text_tool->text->text, -1); */
+/* else */
+/* gtk_text_buffer_set_text (text_tool->text_buffer, "", -1); */
}
#define MIN_LAYER_WIDTH 20
@@ -400,13 +584,17 @@
GimpText *text = text_tool->text;
gint x1, y1, x2, y2;
- g_object_get (rect_tool,
+ g_object_get (text_tool,
"x1", &x1,
"y1", &y1,
"x2", &x2,
"y2", &y2,
NULL);
+ if (gtk_text_buffer_get_has_selection (text_tool->text_buffer))
+ gimp_text_tool_clipboard_copy (text_tool, FALSE);
+ text_tool->text_cursor_changing = FALSE;
+
if (text && text_tool->text == text)
{
if (gimp_rectangle_tool_rectangle_is_new (rect_tool))
@@ -418,11 +606,45 @@
gimp_rectangle_tool_frame_item (rect_tool,
GIMP_ITEM (text_tool->layer));
text_tool->handle_rectangle_change_complete = TRUE;
+
+ g_signal_handlers_unblock_by_func (text_tool->text_buffer,
+ G_CALLBACK (gimp_text_tool_text_buffer_mark_set),
+ text_tool);
+
return;
}
else
{
/* user has modified shape of an existing text layer */
+ gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
+ if (text_tool->layout && text_tool->text_cursor_changing)
+ {
+ GimpItem *item = GIMP_ITEM (text_tool->layer);
+ gdouble x = coords->x - item->offset_x;
+ gdouble y = coords->y - item->offset_y;
+ GtkTextIter cursor, start, end;
+ gint offset, trailing;
+ gchar *string;
+
+ gtk_text_buffer_get_bounds (text_tool->text_buffer, &start, &end);
+
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &end, TRUE);
+
+ pango_layout_xy_to_index (text_tool->layout->layout,
+ x * PANGO_SCALE, y * PANGO_SCALE,
+ &offset, &trailing);
+
+ offset = g_utf8_pointer_to_offset (string, (string + offset));
+ offset += trailing;
+
+ g_free (string);
+
+ gtk_text_buffer_get_iter_at_offset (text_tool->text_buffer, &cursor, offset);
+ gtk_text_buffer_move_mark_by_name (text_tool->text_buffer,
+ "selection_bound", &cursor);
+ }
+ gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
}
else if (y2 - y1 < MIN_LAYER_WIDTH)
@@ -444,6 +666,171 @@
gimp_rectangle_tool_button_release (tool, coords, time, state,
release_type, display);
text_tool->handle_rectangle_change_complete = TRUE;
+
+ g_signal_handlers_unblock_by_func (text_tool->text_buffer,
+ G_CALLBACK (gimp_text_tool_text_buffer_mark_set),
+ text_tool);
+}
+
+void
+gimp_text_tool_motion (GimpTool *tool,
+ GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplay *display)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
+ gdouble snapped_x;
+ gdouble snapped_y;
+ gint snap_x, snap_y;
+
+ if (text_tool->text_cursor_changing)
+ {
+ if (text_tool->layout)
+ {
+ GimpItem *item = GIMP_ITEM (text_tool->layer);
+ gdouble x = coords->x - item->offset_x;
+ gdouble y = coords->y - item->offset_y;
+ GtkTextIter cursor;
+ GtkTextIter start, end;
+ GtkTextIter old_selection_bound;
+ GtkTextMark *selection_mark;
+ gint offset, trailing;
+ gint old_cursor_offset;
+ gchar *string;
+
+ gtk_text_buffer_get_bounds (text_tool->text_buffer, &start, &end);
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &end, TRUE);
+
+ pango_layout_xy_to_index (text_tool->layout->layout, x * PANGO_SCALE,
+ y * PANGO_SCALE, &offset, &trailing);
+
+ offset = g_utf8_pointer_to_offset (string, (string + offset));
+ offset += trailing;
+
+ g_free (string);
+
+ selection_mark = gtk_text_buffer_get_selection_bound (text_tool->text_buffer);
+
+ gtk_text_buffer_get_iter_at_mark (text_tool->text_buffer,
+ &old_selection_bound,
+ selection_mark);
+
+ old_cursor_offset = gtk_text_iter_get_offset (&old_selection_bound);
+
+ if (offset == old_cursor_offset)
+ return;
+
+ gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
+ gtk_text_buffer_get_iter_at_offset (text_tool->text_buffer,
+ &cursor, offset);
+ gtk_text_buffer_move_mark_by_name (text_tool->text_buffer,
+ "selection_bound", &cursor);
+ gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+ }
+ }
+ else
+ {
+ gimp_rectangle_tool_motion (tool, coords, time, state, display);
+ }
+}
+
+static gboolean
+gimp_text_tool_key_press (GimpTool *tool,
+ GdkEventKey *kevent,
+ GimpDisplay *display)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
+ GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
+ GtkTextMark *insert;
+ GtkTextMark *selection_bound;
+ GtkTextIter cursor, selection;
+ GtkTextIter *sel_start;
+ gboolean retval = TRUE;
+
+ if (gtk_im_context_filter_keypress (text_tool->im_context, kevent))
+ {
+ text_tool->needs_im_reset = TRUE;
+
+ return TRUE;
+ }
+
+ insert = gtk_text_buffer_get_insert (text_tool->text_buffer);
+ selection_bound = gtk_text_buffer_get_selection_bound (text_tool->text_buffer);
+
+ gtk_text_buffer_get_iter_at_mark (text_tool->text_buffer,
+ &cursor, insert);
+ gtk_text_buffer_get_iter_at_mark (text_tool->text_buffer,
+ &selection, selection_bound);
+
+ if (kevent->state & GDK_SHIFT_MASK)
+ sel_start = &cursor;
+ else
+ sel_start = &selection;
+
+ switch (kevent->keyval)
+ {
+ case GDK_Return:
+ case GDK_KP_Enter:
+ case GDK_ISO_Enter:
+ gimp_draw_tool_pause (draw_tool);
+ gtk_text_buffer_delete_selection (text_tool->text_buffer, TRUE, TRUE);
+ gimp_text_tool_enter_text (text_tool, "\n");
+ gimp_text_tool_reset_im_context (text_tool);
+ gimp_text_tool_update_layout (text_tool);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ case GDK_BackSpace:
+ gimp_draw_tool_pause (draw_tool);
+ gimp_text_tool_delete_text (text_tool);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ case GDK_Right:
+ case GDK_KP_Right:
+ gimp_draw_tool_pause (draw_tool);
+ gtk_text_iter_forward_cursor_position (&selection);
+ gtk_text_buffer_select_range (text_tool->text_buffer, sel_start,
+ &selection);
+ gimp_text_tool_reset_im_context (text_tool);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ case GDK_Left:
+ case GDK_KP_Left:
+ gimp_draw_tool_pause (draw_tool);
+ gtk_text_iter_backward_cursor_position (&selection);
+ gtk_text_buffer_select_range (text_tool->text_buffer, sel_start,
+ &selection);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ case GDK_Home:
+ case GDK_KP_Home:
+ gimp_draw_tool_pause (draw_tool);
+ gtk_text_iter_set_line (&selection, gtk_text_iter_get_line (&selection));
+ gtk_text_buffer_select_range (text_tool->text_buffer, sel_start,
+ &selection);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ case GDK_End:
+ case GDK_KP_End:
+ gimp_draw_tool_pause (draw_tool);
+ gtk_text_iter_set_line (&selection, gtk_text_iter_get_line (&selection));
+ gtk_text_iter_forward_to_line_end (&selection);
+ gtk_text_buffer_select_range (text_tool->text_buffer, sel_start,
+ &selection);
+ gimp_draw_tool_resume (draw_tool);
+ break;
+
+ default:
+ retval = FALSE;
+ }
+
+ return retval;
}
static void
@@ -452,13 +839,96 @@
GdkModifierType state,
GimpDisplay *display)
{
- /* FIXME: should do something fancy here... */
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
+
+ if (tool->display == display)
+ {
+ gint x, y;
+ gint x1, y1;
+ gint x2, y2;
+
+ x = coords->x;
+ y = coords->y;
- gimp_rectangle_tool_cursor_update (tool, coords, state, display);
+ g_object_get (G_OBJECT (tool),
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ if (x1 <= x && x2 >= x && y1 <= y && y2 >= y)
+ {
+ GimpCursorType cursor = GDK_XTERM;
+
+ gimp_tool_control_set_cursor (tool->control, cursor);
+ }
+ else
+ {
+ gimp_rectangle_tool_cursor_update (tool, coords, state, display);
+ }
+ }
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
+static GimpUIManager *
+gimp_text_tool_get_popup (GimpTool *tool,
+ GimpCoords *coords,
+ GdkModifierType state,
+ GimpDisplay *display,
+ const gchar **ui_path)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
+ gint cx, cy;
+ gint x1, y1, x2, y2;
+
+ if (! text_tool->ui_manager)
+ {
+ GimpDialogFactory *dialog_factory;
+ GtkWidget *im_menu;
+ GtkWidget *im_menuitem;
+
+ dialog_factory = gimp_dialog_factory_from_name ("toplevel");
+
+ text_tool->ui_manager =
+ gimp_menu_factory_manager_new (dialog_factory->menu_factory,
+ "<TextTool>",
+ text_tool, FALSE);
+
+ im_menuitem = gtk_ui_manager_get_widget (GTK_UI_MANAGER (text_tool->ui_manager),
+ "/text-tool-popup/text-tool-input-methods");
+
+ im_menu = gtk_menu_new ();
+
+ gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_tool->im_context),
+ GTK_MENU_SHELL (im_menu));
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (im_menuitem), im_menu);
+ gtk_widget_show (im_menuitem);
+ }
+
+ g_object_get (text_tool,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ cx = coords->x;
+ cy = coords->y;
+
+ if (x1 > cx || x2 < cx || y1 > cy || y2 < cy)
+ {
+ return NULL;
+ }
+
+ gimp_ui_manager_update (text_tool->ui_manager, text_tool);
+
+ *ui_path = "/text-tool-popup";
+
+ return text_tool->ui_manager;
+}
+
static void
gimp_text_tool_connect (GimpTextTool *text_tool,
GimpTextLayer *layer,
@@ -468,9 +938,6 @@
g_return_if_fail (text == NULL || (layer != NULL && layer->text == text));
- if (! text && text_tool->editor)
- gtk_widget_destroy (text_tool->editor);
-
if (text_tool->text != text)
{
GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (tool);
@@ -484,14 +951,6 @@
if (text_tool->pending)
gimp_text_tool_apply (text_tool);
- if (options->to_vectors_button)
- {
- gtk_widget_set_sensitive (options->to_vectors_button, FALSE);
- g_signal_handlers_disconnect_by_func (options->to_vectors_button,
- gimp_text_tool_create_vectors,
- text_tool);
- }
-
if (options->along_vectors_button)
{
gtk_widget_set_sensitive (options->along_vectors_button,
@@ -521,14 +980,6 @@
G_CALLBACK (gimp_text_tool_text_notify),
text_tool);
- if (options->to_vectors_button)
- {
- g_signal_connect_swapped (options->to_vectors_button, "clicked",
- G_CALLBACK (gimp_text_tool_create_vectors),
- text_tool);
- gtk_widget_set_sensitive (options->to_vectors_button, TRUE);
- }
-
if (options->along_vectors_button)
{
g_signal_connect_swapped (options->along_vectors_button, "clicked",
@@ -536,9 +987,6 @@
text_tool);
gtk_widget_set_sensitive (options->along_vectors_button, TRUE);
}
-
- if (text_tool->editor)
- gimp_text_tool_editor_update (text_tool);
}
}
@@ -562,6 +1010,23 @@
}
static void
+gimp_text_tool_use_editor_notify (GimpTextOptions *options,
+ GParamSpec *pspec,
+ GimpTextTool *text_tool)
+{
+ if (options->use_editor)
+ {
+ if (text_tool->text && text_tool->text_buffer)
+ gimp_text_tool_editor (text_tool);
+ }
+ else
+ {
+ if (text_tool->editor)
+ gtk_widget_destroy (text_tool->editor);
+ }
+}
+
+static void
gimp_text_tool_layer_notify (GimpTextLayer *layer,
GParamSpec *pspec,
GimpTextTool *text_tool)
@@ -620,9 +1085,6 @@
g_value_unset (&value);
}
- if (text_tool->editor && strcmp (pspec->name, "text") == 0)
- gimp_text_tool_editor_update (text_tool);
-
/* we need to redraw the rectangle if it is visible and the shape of
the layer has changed, because of an undo for example. */
if (strcmp (pspec->name, "box-width") == 0 ||
@@ -636,6 +1098,27 @@
GIMP_ITEM (text_tool->layer));
text_tool->handle_rectangle_change_complete = TRUE;
}
+
+ /* if the text has changed, (probably because of an undo), we put
+ * the new text into the text buffer
+ */
+ if (strcmp (pspec->name, "text") == 0)
+ {
+ g_signal_handlers_block_by_func (text_tool->proxy,
+ gimp_text_tool_text_buffer_changed,
+ text_tool);
+
+ gtk_text_buffer_set_text (text_tool->text_buffer, text->text, -1);
+
+ g_signal_handlers_unblock_by_func (text_tool->proxy,
+ gimp_text_tool_text_buffer_changed,
+ text_tool);
+
+ /* force change of cursor and selection display */
+ gimp_text_tool_update_layout (text_tool);
+/* gimp_text_tool_update_proxy (text_tool); */
+ return;
+ }
}
static gboolean
@@ -784,9 +1267,10 @@
}
gimp_image_flush (image);
+ gimp_text_tool_update_layout (text_tool);
}
-static void
+void
gimp_text_tool_create_vectors (GimpTextTool *text_tool)
{
GimpVectors *vectors;
@@ -853,10 +1337,11 @@
{
gchar *str;
- str = gimp_text_editor_get_text (GIMP_TEXT_EDITOR (text_tool->editor));
+ str = gimp_text_tool_canvas_editor_get_text (text_tool);
g_object_set (text_tool->proxy,
"text", str,
+ "box-mode", GIMP_TEXT_BOX_DYNAMIC,
NULL);
g_free (str);
@@ -933,6 +1418,23 @@
}
static void
+gimp_text_tool_canvas_editor (GimpTextTool *text_tool)
+{
+ GimpTool *tool = GIMP_TOOL (text_tool);
+ GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
+
+ gtk_im_context_set_client_window (text_tool->im_context,
+ GIMP_DISPLAY_SHELL (tool->display->shell)->canvas->window);
+
+ gtk_im_context_focus_in (text_tool->im_context);
+
+ gimp_text_tool_update_layout (text_tool);
+
+ if (options->use_editor)
+ gimp_text_tool_editor (text_tool);
+}
+
+static void
gimp_text_tool_editor (GimpTextTool *text_tool)
{
GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
@@ -952,7 +1454,8 @@
text_tool->editor = gimp_text_options_editor_new (parent, options,
dialog_factory->menu_factory,
- _("GIMP Text Editor"));
+ _("GIMP Text Editor"),
+ text_tool->text_buffer);
g_object_add_weak_pointer (G_OBJECT (text_tool->editor),
(gpointer) &text_tool->editor);
@@ -961,60 +1464,55 @@
"gimp-text-tool-dialog",
text_tool->editor);
- if (text_tool->text)
- gimp_text_editor_set_text (GIMP_TEXT_EDITOR (text_tool->editor),
- text_tool->text->text, -1);
-
- g_signal_connect_object (text_tool->editor, "text-changed",
- G_CALLBACK (gimp_text_tool_text_changed),
- text_tool, 0);
-
gtk_widget_show (text_tool->editor);
}
-static void
-gimp_text_tool_editor_update (GimpTextTool *text_tool)
-{
- gchar *str = NULL;
-
- if (! text_tool->editor)
- return;
-
- if (text_tool->text)
- g_object_get (text_tool->text, "text", &str, NULL);
-
- g_signal_handlers_block_by_func (text_tool->editor,
- gimp_text_tool_text_changed, text_tool);
-
- gimp_text_editor_set_text (GIMP_TEXT_EDITOR (text_tool->editor),
- str, str ? -1 : 0);
-
- g_signal_handlers_unblock_by_func (text_tool->editor,
- gimp_text_tool_text_changed, text_tool);
-
- g_free (str);
-}
-
-static void
-gimp_text_tool_text_changed (GimpTextEditor *editor,
- GimpTextTool *text_tool)
+static gchar *
+gimp_text_tool_canvas_editor_get_text (GimpTextTool *text_tool)
{
- if (text_tool->text)
+ if (text_tool->text_buffer)
{
- gchar *text;
+ GtkTextIter start, end;
+ GtkTextIter selstart, selend;
+ gchar *string;
+ gchar *fb;
+ gchar *lb;
+
+ gtk_text_buffer_get_bounds (text_tool->text_buffer, &start, &end);
+ gtk_text_buffer_get_selection_bounds (text_tool->text_buffer,
+ &selstart, &selend);
+
+ fb = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &selstart, TRUE);
+ lb = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &selstart, &end, TRUE);
- text = gimp_text_editor_get_text (GIMP_TEXT_EDITOR (text_tool->editor));
+ if (text_tool->preedit_string)
+ {
+ if (fb == NULL)
+ {
+ string = g_strconcat (text_tool->preedit_string, lb, NULL);
+ }
+ else
+ {
+ string = g_strconcat (fb, text_tool->preedit_string, lb, NULL);
+ }
+ }
+ else
+ {
+ string = g_strconcat (fb, lb, NULL);
+ }
- g_object_set (text_tool->proxy, "text", text, NULL);
+ g_free (fb);
+ g_free (lb);
- g_free (text);
- }
- else
- {
- gimp_text_tool_create_layer (text_tool, NULL);
+ return string;
}
+
+ return NULL;
}
+
#define RESPONSE_NEW 1
static void
@@ -1041,7 +1539,7 @@
if (text_tool->proxy)
g_object_notify (G_OBJECT (text_tool->proxy), "text");
- gimp_text_tool_editor (text_tool);
+ gimp_text_tool_canvas_editor (text_tool);
break;
default:
@@ -1268,7 +1766,7 @@
{
tool->drawable = GIMP_DRAWABLE (layer);
- gimp_text_tool_editor (text_tool);
+ gimp_text_tool_canvas_editor (text_tool);
}
}
}
@@ -1276,14 +1774,14 @@
static gboolean
gimp_text_tool_rectangle_change_complete (GimpRectangleTool *rect_tool)
{
- GimpTextTool *text_tool = GIMP_TEXT_TOOL (rect_tool);
- GimpText *text = text_tool->text;
- GimpImage *image = text_tool->image;
- GimpItem *item ;
- gint x1, y1, x2, y2;
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (rect_tool);
if (text_tool->handle_rectangle_change_complete)
{
+ GimpText *text = text_tool->text;
+ GimpItem *item;
+ gint x1, y1, x2, y2;
+
g_object_get (rect_tool,
"x1", &x1,
"y1", &y1,
@@ -1293,7 +1791,7 @@
text_tool->text_box_fixed = TRUE;
- if (! text)
+ if (! text || ! text->text || (text->text[0] == 0))
{
/*
* we can't set properties for the text layer, because
@@ -1310,15 +1808,17 @@
"box-height", (gdouble) (y2 - y1),
NULL);
- gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TEXT,
- _("Reshape Text Layer"));
+ gimp_image_undo_group_start (text_tool->image, GIMP_UNDO_GROUP_TEXT,
+ _("Reshape Text Layer"));
+
item = GIMP_ITEM (text_tool->layer);
gimp_item_translate (item,
x1 - item->offset_x,
y1 - item->offset_y,
TRUE);
gimp_text_tool_apply (text_tool);
- gimp_image_undo_group_end (image);
+
+ gimp_image_undo_group_end (text_tool->image);
}
return TRUE;
@@ -1343,7 +1843,7 @@
gimp_rectangle_tool_frame_item (GimpRectangleTool *rect_tool,
GimpItem *item)
{
- GimpDisplay *display = GIMP_TOOL (rect_tool)->display;
+ GimpDisplay *display = GIMP_TOOL (rect_tool)->display;
gint offset_x;
gint offset_y;
gint width;
@@ -1371,8 +1871,7 @@
"y2", offset_y + height,
NULL);
- /*
- * kludge to force handle sizes to update. This call may be
+ /* kludge to force handle sizes to update. This call may be
* harmful if this function is ever moved out of the text tool code.
*/
gimp_rectangle_tool_set_constraint (rect_tool,
@@ -1381,3 +1880,443 @@
gimp_draw_tool_resume (GIMP_DRAW_TOOL (rect_tool));
}
+static void
+gimp_text_tool_draw_preedit_lines (GimpDrawTool *draw_tool)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (draw_tool);
+ PangoLayout *layout;
+ PangoLayoutIter *line_iter;
+ GtkTextIter cursor, start;
+ gint i;
+ gint min, max;
+ gchar *string;
+
+ gtk_text_buffer_get_selection_bounds (text_tool->text_buffer, &cursor, NULL);
+ gtk_text_buffer_get_start_iter (text_tool->text_buffer, &start);
+
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &cursor, FALSE);
+ min = strlen (string);
+ g_free (string);
+
+ max = min + text_tool->preedit_len;
+
+ layout = text_tool->layout->layout;
+ line_iter = pango_layout_get_iter (layout);
+ i = 0;
+
+ do
+ {
+ gint firstline, lastline;
+ gint first_x, last_x;
+
+ pango_layout_index_to_line_x (layout, min, 0, &firstline, &first_x);
+ pango_layout_index_to_line_x (layout, max, 0, &lastline, &last_x);
+
+ if (i >= firstline && i <= lastline)
+ {
+ PangoRectangle crect;
+
+ pango_layout_iter_get_line_extents (line_iter, NULL, &crect);
+ pango_extents_to_pixels (&crect, NULL);
+
+ gimp_draw_tool_draw_line (draw_tool,
+ crect.x, crect.y + crect.height,
+ crect.x + crect.width,
+ crect.y + crect.height,
+ TRUE);
+ if (i == firstline)
+ {
+ PangoRectangle crect2 = crect;
+
+ crect2.width = PANGO_PIXELS (first_x) - crect.x;
+ crect2.x = crect.x;
+
+ gimp_draw_tool_draw_line (draw_tool,
+ crect2.x, crect2.y + crect2.height,
+ crect2.width,
+ crect2.y + crect2.height,
+ TRUE);
+ }
+ if (i == lastline)
+ {
+ PangoRectangle crect2 = crect;
+
+ crect2.width = crect.x + crect.width - PANGO_PIXELS (last_x);
+ crect2.x = PANGO_PIXELS (last_x);
+
+ gimp_draw_tool_draw_line (draw_tool,
+ crect2.x, crect2.y + crect2.height,
+ crect2.x + crect2.width,
+ crect2.y + crect2.height,
+ TRUE);
+ }
+ }
+
+ i++;
+ }
+ while (pango_layout_iter_next_line (line_iter));
+
+ pango_layout_iter_free (line_iter);
+}
+
+static void
+gimp_text_tool_draw_text_selection (GimpDrawTool *draw_tool)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (draw_tool);
+ PangoLayout *layout;
+ PangoLayoutIter *line_iter;
+ GtkTextIter start;
+ GtkTextIter sel_start, sel_end;
+ gint i;
+ gint min, max;
+ gchar *string;
+
+ gtk_text_buffer_get_selection_bounds (text_tool->text_buffer,
+ &sel_start, &sel_end);
+ gtk_text_buffer_get_start_iter (text_tool->text_buffer, &start);
+
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &sel_start, FALSE);
+ min = strlen (string);
+ g_free (string);
+
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &sel_end, FALSE);
+ max = strlen (string);
+ g_free (string);
+
+ layout = text_tool->layout->layout;
+ line_iter = pango_layout_get_iter (layout);
+ i = 0;
+
+ /* Invert the selected letters by inverting all
+ * lines containing selected letters, then
+ * invert the unselected letters on these lines
+ * a second time to make them look normal*/
+ do
+ {
+ gint firstline, lastline;
+ gint first_x, last_x;
+
+ pango_layout_index_to_line_x (layout, min, 0, &firstline, &first_x);
+ pango_layout_index_to_line_x (layout, max, 0, &lastline, &last_x);
+
+ if (i >= firstline && i <= lastline)
+ {
+ PangoRectangle crect;
+
+ pango_layout_iter_get_line_extents (line_iter, NULL, &crect);
+ pango_extents_to_pixels (&crect, NULL);
+
+ gimp_draw_tool_draw_rectangle (draw_tool, TRUE,
+ crect.x, crect.y,
+ crect.width, crect.height,
+ TRUE);
+ if (i == firstline)
+ {
+ /* Twice invert all letters before the selection,
+ * making them look normal
+ */
+ PangoRectangle crect2 = crect;
+
+ crect2.width = PANGO_PIXELS (first_x) - crect.x;
+ crect2.x = crect.x;
+
+ gimp_draw_tool_draw_rectangle (draw_tool, TRUE,
+ crect2.x, crect2.y,
+ crect2.width, crect2.height,
+ TRUE);
+ }
+ if (i == lastline)
+ {
+ /* Twice invert all letters after the selection,
+ * making them look normal
+ */
+ PangoRectangle crect2 = crect;
+
+ crect2.width = crect.x + crect.width - PANGO_PIXELS (last_x);
+ crect2.x = PANGO_PIXELS (last_x);
+
+ gimp_draw_tool_draw_rectangle (draw_tool, TRUE,
+ crect2.x, crect2.y,
+ crect2.width, crect2.height,
+ TRUE);
+ }
+ }
+ i++;
+ }
+ while (pango_layout_iter_next_line (line_iter));
+ pango_layout_iter_free (line_iter);
+}
+
+static void
+gimp_text_tool_draw (GimpDrawTool *draw_tool)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (draw_tool);
+ GimpTool *tool = GIMP_TOOL (draw_tool);
+ GimpDisplayShell *shell;
+ GdkRectangle cliprect;
+ gint width, height;
+ gint x1, x2, y1, y2;
+ GtkTextIter start;
+
+ g_object_set (text_tool,
+ "narrow-mode", TRUE,
+ NULL);
+
+ gimp_rectangle_tool_draw (draw_tool);
+
+ if (!text_tool->layer) return;
+ if (!text_tool->layer->text) return;
+
+ /* There will be no layout if the function is called from the wrong place */
+ if (! text_tool->layout)
+ gimp_text_tool_update_layout (text_tool);
+
+ g_object_get (text_tool,
+ "x1", &x1,
+ "y1", &y1,
+ "x2", &x2,
+ "y2", &y2,
+ NULL);
+
+ /* Turn on clipping for text-cursor and selections */
+ cliprect.x = x1;
+ cliprect.width = x2 - x1;
+ cliprect.y = y1;
+ cliprect.height = y2 - y1;
+ gimp_canvas_set_clip_rect (GIMP_CANVAS (GIMP_DISPLAY_SHELL (tool->display->shell)->canvas),
+ GIMP_CANVAS_STYLE_XOR, &cliprect);
+
+ gtk_text_buffer_get_start_iter (text_tool->text_buffer, &start);
+
+ if (! gtk_text_buffer_get_has_selection (text_tool->text_buffer))
+ {
+ /* If the text buffer has no selection, draw the text cursor */
+
+ gint cursorx;
+ GtkTextIter cursor;
+ PangoRectangle crect;
+ gchar *string;
+
+ gtk_text_buffer_get_iter_at_mark (text_tool->text_buffer, &cursor,
+ gtk_text_buffer_get_insert (text_tool->text_buffer));
+
+ string = gtk_text_buffer_get_text (text_tool->text_buffer,
+ &start, &cursor, FALSE);
+
+ /* Using strlen to get the byte index, not the character offset*/
+ cursorx = strlen (string);
+
+ /* TODO: make cursor position itself
+ * even inside preedits!*/
+ if (text_tool->preedit_len > 0)
+ cursorx += text_tool->preedit_len;
+
+ g_free (string);
+
+ pango_layout_index_to_pos (text_tool->layout->layout, cursorx, &crect);
+
+ crect.x = PANGO_PIXELS (crect.x);
+ crect.y = PANGO_PIXELS (crect.y);
+ crect.height = PANGO_PIXELS (crect.height);
+
+ gimp_draw_tool_draw_rectangle (draw_tool, TRUE,
+ crect.x, crect.y,
+ 4, crect.height,
+ TRUE);
+
+ if (text_tool->preedit_string && text_tool->preedit_len > 0)
+ gimp_text_tool_draw_preedit_lines (draw_tool);
+ }
+ else
+ {
+ /* If the text buffer has a selection, highlight the
+ * selected letters*/
+
+ gimp_text_tool_draw_text_selection (draw_tool);
+ }
+
+ /* Turn off clipping when done */
+ shell = GIMP_DISPLAY_SHELL (tool->display->shell);
+ gimp_canvas_set_clip_rect (GIMP_CANVAS (shell->canvas),
+ GIMP_CANVAS_STYLE_XOR, NULL);
+}
+
+static void
+gimp_text_tool_commit_cb (GtkIMContext *context,
+ const gchar *str,
+ GimpTextTool *text_tool)
+{
+ gimp_text_tool_enter_text (text_tool, str);
+}
+
+static void
+gimp_text_tool_reset_im_context (GimpTextTool *text_tool)
+{
+ if (text_tool->needs_im_reset)
+ {
+ text_tool->needs_im_reset = FALSE;
+ gtk_im_context_reset (text_tool->im_context);
+ }
+}
+
+static void
+gimp_text_tool_preedit_changed_cb (GtkIMContext *context,
+ GimpTextTool *text_tool)
+{
+ if (text_tool->preedit_string)
+ g_free (text_tool->preedit_string);
+
+ gtk_im_context_get_preedit_string (context,
+ &text_tool->preedit_string, NULL,
+ &text_tool->preedit_cursor);
+
+ text_tool->preedit_len = strlen (text_tool->preedit_string);
+
+ gimp_text_tool_update_proxy (text_tool);
+}
+
+static void
+gimp_text_tool_update_proxy (GimpTextTool *text_tool)
+{
+ if (text_tool->text)
+ {
+ gchar *string;
+
+ string = gimp_text_tool_canvas_editor_get_text (text_tool);
+
+ g_object_set (text_tool->proxy, "text",
+ string, NULL);
+
+ g_free (string);
+ }
+ else
+ {
+ gimp_text_tool_create_layer (text_tool, NULL);
+ }
+}
+
+void
+gimp_text_tool_delete_text (GimpTextTool *text_tool)
+{
+ GtkTextIter cursor, start, end;
+
+ gtk_text_buffer_get_iter_at_mark (text_tool->text_buffer,
+ &cursor,
+ gtk_text_buffer_get_insert (text_tool->text_buffer));
+
+ if (gtk_text_buffer_get_has_selection (text_tool->text_buffer))
+ {
+ gtk_text_buffer_delete_selection (text_tool->text_buffer, TRUE, TRUE);
+ }
+ else
+ {
+ gtk_text_buffer_backspace (text_tool->text_buffer, &cursor, TRUE, TRUE);
+ }
+}
+
+static void
+gimp_text_tool_enter_text (GimpTextTool *text_tool,
+ const gchar *str)
+{
+ if (gtk_text_buffer_get_has_selection (text_tool->text_buffer))
+ {
+ gtk_text_buffer_delete_selection (text_tool->text_buffer, TRUE, TRUE);
+ }
+
+ gtk_text_buffer_insert_at_cursor (text_tool->text_buffer, str, -1);
+}
+
+static void
+gimp_text_tool_text_buffer_changed (GtkTextBuffer *text_buffer,
+ GimpTextTool *text_tool)
+{
+ gimp_text_tool_update_proxy (text_tool);
+}
+
+static void
+gimp_text_tool_text_buffer_mark_set (GtkTextBuffer *text_buffer,
+ GtkTextIter *iter,
+ GtkTextMark *mark,
+ GimpTextTool *text_tool)
+{
+ gimp_text_tool_update_layout (text_tool);
+/* gimp_text_tool_update_proxy (text_tool); */
+}
+
+static void
+gimp_text_tool_update_layout (GimpTextTool *text_tool)
+{
+ GimpItem *item;
+ GimpImage *image;
+
+ if (! text_tool->text)
+ {
+ gimp_text_tool_update_proxy (text_tool);
+ return;
+ }
+
+ if (text_tool->layout)
+ g_object_unref (text_tool->layout);
+
+ item = GIMP_ITEM (text_tool->layer);
+ image = gimp_item_get_image (item);
+
+ text_tool->layout = gimp_text_layout_new (text_tool->layer->text, image);
+}
+
+gboolean
+gimp_text_tool_get_has_text_selection (GimpTextTool *text_tool)
+{
+ if (text_tool->text_buffer)
+ return gtk_text_buffer_get_has_selection (text_tool->text_buffer);
+ else
+ return FALSE;
+}
+
+void
+gimp_text_tool_clipboard_cut (GimpTextTool *text_tool)
+{
+ GimpTool *tool = GIMP_TOOL (text_tool);
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_widget_get_clipboard (tool->display->shell,
+ GDK_SELECTION_CLIPBOARD);
+ gtk_text_buffer_cut_clipboard (text_tool->text_buffer, clipboard, TRUE);
+}
+
+void
+gimp_text_tool_clipboard_copy (GimpTextTool *text_tool,
+ gboolean use_clipboard)
+{
+ GimpTool *tool = GIMP_TOOL (text_tool);
+ GtkClipboard *clipboard;
+
+ if (use_clipboard)
+ clipboard = gtk_widget_get_clipboard (tool->display->shell,
+ GDK_SELECTION_CLIPBOARD);
+ else
+ clipboard = gtk_widget_get_clipboard (tool->display->shell,
+ GDK_SELECTION_PRIMARY);
+
+ gtk_text_buffer_copy_clipboard (text_tool->text_buffer, clipboard);
+}
+
+void
+gimp_text_tool_clipboard_paste (GimpTextTool *text_tool,
+ gboolean use_clipboard)
+{
+ GimpTool *tool = GIMP_TOOL (text_tool);
+ GtkClipboard *clipboard;
+
+ if (use_clipboard)
+ clipboard = gtk_widget_get_clipboard (tool->display->shell,
+ GDK_SELECTION_CLIPBOARD);
+ else
+ clipboard = gtk_widget_get_clipboard (tool->display->shell,
+ GDK_SELECTION_PRIMARY);
+
+ gtk_text_buffer_paste_clipboard (text_tool->text_buffer, clipboard, NULL, TRUE);
+}
Modified: trunk/app/tools/gimptexttool.h
==============================================================================
--- trunk/app/tools/gimptexttool.h (original)
+++ trunk/app/tools/gimptexttool.h Sun Oct 26 17:39:55 2008
@@ -37,24 +37,37 @@
struct _GimpTextTool
{
- GimpDrawTool parent_instance;
+ GimpDrawTool parent_instance;
- GimpText *proxy;
- GList *pending;
- guint idle_id;
+ GimpText *proxy;
+ GList *pending;
+ guint idle_id;
- gint x1, y1;
- gint x2, y2;
+ gint x1, y1;
+ gint x2, y2;
- GimpText *text;
- GimpTextLayer *layer;
- GimpImage *image;
+ GtkTextBuffer *text_buffer;
- GtkWidget *editor;
- GtkWidget *confirm_dialog;
+ GimpText *text;
+ GimpTextLayer *layer;
+ GimpImage *image;
- gboolean handle_rectangle_change_complete;
- gboolean text_box_fixed;
+ GtkWidget *editor;
+ GtkWidget *confirm_dialog;
+ GimpUIManager *ui_manager;
+ GtkIMContext *im_context;
+
+ gboolean needs_im_reset;
+
+ gchar *preedit_string;
+ gint preedit_len;
+ gint preedit_cursor;
+
+ gboolean handle_rectangle_change_complete;
+ gboolean text_box_fixed;
+ gboolean text_cursor_changing;
+
+ GimpTextLayout *layout;
};
struct _GimpTextToolClass
@@ -63,13 +76,23 @@
};
-void gimp_text_tool_register (GimpToolRegisterCallback callback,
- gpointer data);
+void gimp_text_tool_register (GimpToolRegisterCallback callback,
+ gpointer data);
+
+GType gimp_text_tool_get_type (void) G_GNUC_CONST;
+
+void gimp_text_tool_set_layer (GimpTextTool *text_tool,
+ GimpLayer *layer);
-GType gimp_text_tool_get_type (void) G_GNUC_CONST;
+void gimp_text_tool_delete_text (GimpTextTool *text_tool);
+void gimp_text_tool_clipboard_cut (GimpTextTool *text_tool);
+void gimp_text_tool_clipboard_copy (GimpTextTool *text_tool,
+ gboolean use_clipboard);
+void gimp_text_tool_clipboard_paste (GimpTextTool *text_tool,
+ gboolean use_clipboard);
-void gimp_text_tool_set_layer (GimpTextTool *text_tool,
- GimpLayer *layer);
+gboolean gimp_text_tool_get_has_text_selection (GimpTextTool *text_tool);
+void gimp_text_tool_create_vectors (GimpTextTool *text_tool);
#endif /* __GIMP_TEXT_TOOL_H__ */
Modified: trunk/app/widgets/gimptexteditor.c
==============================================================================
--- trunk/app/widgets/gimptexteditor.c (original)
+++ trunk/app/widgets/gimptexteditor.c Sun Oct 26 17:39:55 2008
@@ -129,10 +129,10 @@
GtkWidget *
gimp_text_editor_new (const gchar *title,
GtkWindow *parent,
- GimpMenuFactory *menu_factory)
+ GimpMenuFactory *menu_factory,
+ GtkTextBuffer *text_buffer)
{
GimpTextEditor *editor;
- GtkTextBuffer *buffer;
GtkWidget *toolbar;
GtkWidget *scrolled_window;
@@ -155,6 +155,10 @@
G_CALLBACK (gtk_widget_destroy),
NULL);
+ g_signal_connect_object (text_buffer, "changed",
+ G_CALLBACK (gimp_text_editor_text_changed),
+ editor, 0);
+
editor->ui_manager = gimp_menu_factory_manager_new (menu_factory,
"<TextEditor>",
editor, FALSE);
@@ -206,18 +210,12 @@
scrolled_window, TRUE, TRUE, 0);
gtk_widget_show (scrolled_window);
- editor->view = gtk_text_view_new ();
+ editor->view = gtk_text_view_new_with_buffer (text_buffer);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (editor->view),
GTK_WRAP_WORD_CHAR);
gtk_container_add (GTK_CONTAINER (scrolled_window), editor->view);
gtk_widget_show (editor->view);
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
-
- g_signal_connect (buffer, "changed",
- G_CALLBACK (gimp_text_editor_text_changed),
- editor);
-
switch (editor->base_dir)
{
case GIMP_TEXT_DIRECTION_LTR:
Modified: trunk/app/widgets/gimptexteditor.h
==============================================================================
--- trunk/app/widgets/gimptexteditor.h (original)
+++ trunk/app/widgets/gimptexteditor.h Sun Oct 26 17:39:55 2008
@@ -56,7 +56,8 @@
GType gimp_text_editor_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_text_editor_new (const gchar *title,
GtkWindow *parent,
- GimpMenuFactory *menu_factory);
+ GimpMenuFactory *menu_factory,
+ GtkTextBuffer *text_buffer);
void gimp_text_editor_set_text (GimpTextEditor *editor,
const gchar *text,
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Sun Oct 26 17:39:55 2008
@@ -45,6 +45,7 @@
m4_define([glib_required_version], [2.16.1])
m4_define([gtk_required_version], [2.12.5])
m4_define([gdk_pixbuf_required_version], [gtk_required_version])
+m4_define([pangocairo_required_version], [1.20.1])
m4_define([pangoft2_required_version], [1.18.0])
m4_define([fontconfig_required_version], [2.2.0])
m4_define([cairo_required_version], [1.4.10])
@@ -496,6 +497,14 @@
PKG_CHECK_MODULES(CAIRO, cairo >= cairo_required_version)
+PKG_CHECK_MODULES(PANGOCAIRO, pangocairo >= pangocairo_required_version, :,
+ AC_MSG_ERROR([Test for PangoCairo failed.
+*** We require Pango with the optional support for Cairo compiled in.
+*** See the file 'INSTALL' for more help.]))
+
+CFLAGS=$gimp_save_CFLAGS
+CFLAGS="$PANGOCAIRO_CFLAGS $CFLAGS"
+
PKG_CHECK_MODULES(FONTCONFIG, fontconfig >= fontconfig_required_version)
PKG_CHECK_MODULES(PANGOFT2, pangoft2 >= pangoft2_required_version, :,
@@ -536,6 +545,7 @@
*** the same as the result here.])
fi
+
AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no)
if test "x$FREETYPE_CONFIG" != "xno" ; then
AC_MSG_CHECKING([for freetype libraries])
Modified: trunk/menus/Makefile.am
==============================================================================
--- trunk/menus/Makefile.am (original)
+++ trunk/menus/Makefile.am Sun Oct 26 17:39:55 2008
@@ -31,6 +31,7 @@
selection-menu.xml \
templates-menu.xml \
text-editor-toolbar.xml \
+ text-tool-menu.xml \
tool-options-menu.xml \
tools-menu.xml \
undo-menu.xml \
Added: trunk/menus/text-tool-menu.xml
==============================================================================
--- (empty file)
+++ trunk/menus/text-tool-menu.xml Sun Oct 26 17:39:55 2008
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE ui SYSTEM "gtkuimanager.dtd">
+
+<ui>
+ <popup action="text-tool-popup">
+ <menuitem action="text-tool-cut" />
+ <menuitem action="text-tool-copy" />
+ <menuitem action="text-tool-paste" />
+ <menuitem action="text-tool-delete" />
+ <separator />
+ <menuitem action="text-tool-load" />
+ <menuitem action="text-tool-clear" />
+ <separator />
+ <menuitem action="text-tool-path-from-text" />
+ <separator />
+ <menuitem action="text-tool-direction-ltr" />
+ <menuitem action="text-tool-direction-rtl" />
+ <separator />
+ <menu action="text-tool-input-methods">
+ </menu>
+ </popup>
+</ui>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]