Commit ee414d9e authored by Michael Natterer's avatar Michael Natterer Committed by Michael Natterer

Merge on-canvas GSoC project:

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!


svn path=/trunk/; revision=27419
parent b8d8f147
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!
2008-10-26 Sven Neumann <sven@gimp.org>
* app/tools/gimptool.c (gimp_tool_get_popup)
......
......@@ -90,6 +90,7 @@ INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
$(PANGOFT2_CFLAGS) \
$(PANGOCAIRO_CFLAGS) \
$(DBUS_GLIB_CFLAGS) \
$(GEGL_CFLAGS) \
-I$(includedir)
......@@ -137,6 +138,7 @@ gimp_2_7_LDADD = \
$(libgimpbase) \
$(GTK_LIBS) \
$(PANGOFT2_LIBS) \
$(PANGOCAIRO_LIBS) \
$(FONTCONFIG_LIBS) \
$(FREETYPE_LIBS) \
$(DBUS_GLIB_LIBS) \
......@@ -181,6 +183,7 @@ gimp_console_2_7_LDADD = \
$(GDK_PIXBUF_LIBS) \
$(CAIRO_LIBS) \
$(PANGOFT2_LIBS) \
$(PANGOCAIRO_LIBS) \
$(FONTCONFIG_LIBS) \
$(FREETYPE_LIBS) \
$(GEGL_LIBS) \
......
......@@ -149,6 +149,10 @@ libappactions_a_SOURCES = \
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 \
......
......@@ -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 @@ static GimpActionFactoryEntry action_groups[] =
{ "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 },
......
/* 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);
}
/* 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__ */
/* 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);
}
/* 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__ */
......@@ -340,6 +340,14 @@ menus_init (Gimp *gimp,
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,
......
......@@ -10,6 +10,7 @@ INCLUDES = \
-I$(top_srcdir)/app \
$(GEGL_CFLAGS) \
$(PANGOFT2_CFLAGS) \
$(PANGOCAIRO_CFLAGS) \
$(GDK_PIXBUF_CFLAGS) \
-I$(includedir)
......
......@@ -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));
cairo_scaled_font_t *cfont;
cairo_glyph_t cglyph;
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));
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;
}
pango_fc_font_unlock_face (PANGO_FC_FONT (font));
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);
cairo_show_glyphs (cr, &cglyph, 1);
}
......@@ -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__ */
......@@ -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.