summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2013-03-03 22:17:21 +0000
committerJabiertxo Arraiza Zenotz <jtx@jtx.marker.es>2013-03-03 22:17:21 +0000
commitf5f95da9b90081aadaf4f939a5fd8512ecd941b7 (patch)
tree9be295ce3ab7727c41a1fe00ce00317b8d9ebc8c /src
parentBSpline refactor (diff)
parentUpdate from branch (diff)
downloadinkscape-f5f95da9b90081aadaf4f939a5fd8512ecd941b7.tar.gz
inkscape-f5f95da9b90081aadaf4f939a5fd8512ecd941b7.zip
Spiro refactor
(bzr r11950.1.42)
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/device-manager.cpp1
-rw-r--r--src/extension/CMakeLists.txt2
-rw-r--r--src/extension/implementation/script.cpp2
-rw-r--r--src/extension/implementation/script.h3
-rw-r--r--src/extension/system.cpp1
-rw-r--r--src/ink-comboboxentry-action.cpp226
-rw-r--r--src/ink-comboboxentry-action.h18
-rw-r--r--src/inkscape.cpp2
-rw-r--r--src/interface.cpp114
-rw-r--r--src/libnrtype/font-lister.cpp737
-rw-r--r--src/libnrtype/font-lister.h221
-rw-r--r--src/livarot/PathCutting.cpp2
-rw-r--r--src/live_effects/lpe-bspline.cpp72
-rw-r--r--src/pen-context.cpp527
-rw-r--r--src/shortcuts.cpp68
-rw-r--r--src/shortcuts.h5
-rw-r--r--src/splivarot.cpp5
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp3
-rw-r--r--src/ui/dialog/floating-behavior.cpp1
-rw-r--r--src/ui/dialog/font-substitution.cpp2
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp3
-rw-r--r--src/ui/dialog/layers.cpp1
-rw-r--r--src/ui/dialog/swatches.cpp1
-rw-r--r--src/ui/widget/dock-item.cpp1
-rw-r--r--src/widgets/desktop-widget.cpp4
-rw-r--r--src/widgets/font-selector.cpp9
-rw-r--r--src/widgets/icon.cpp1
-rw-r--r--src/widgets/text-toolbar.cpp484
30 files changed, 1652 insertions, 868 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 65baec21b..a899c7b35 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,6 +37,7 @@ noinst_LIBRARIES = \
all_libs = \
$(noinst_LIBRARIES) \
$(INKSCAPE_LIBS) \
+ $(EXIF_LIBS) \
$(GNOME_VFS_LIBS) \
$(XFT_LIBS) \
$(FREETYPE_LIBS) \
@@ -66,6 +67,7 @@ EXTRA_DIST =
INCLUDES = \
$(PERL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(EXIF_CFLAGS) \
$(FREETYPE_CFLAGS) \
$(GNOME_PRINT_CFLAGS) \
$(GNOME_VFS_CFLAGS) \
diff --git a/src/device-manager.cpp b/src/device-manager.cpp
index a9394a5f6..a07231805 100644
--- a/src/device-manager.cpp
+++ b/src/device-manager.cpp
@@ -14,6 +14,7 @@
#include "device-manager.h"
#include "preferences.h"
#include <gtk/gtk.h>
+#include <glibmm/regex.h>
#define noDEBUG_VERBOSE 1
diff --git a/src/extension/CMakeLists.txt b/src/extension/CMakeLists.txt
index b5634f42f..fa4fdd740 100644
--- a/src/extension/CMakeLists.txt
+++ b/src/extension/CMakeLists.txt
@@ -36,6 +36,7 @@ set(extension_SRC
internal/cairo-render-context.cpp
internal/cairo-renderer.cpp
internal/cairo-renderer-pdf-out.cpp
+ internal/cdr-input.cpp
internal/emf-win32-inout.cpp
internal/emf-win32-print.cpp
internal/gdkpixbuf-input.cpp
@@ -100,6 +101,7 @@ set(extension_SRC
internal/cairo-render-context.h
internal/cairo-renderer-pdf-out.h
internal/cairo-renderer.h
+ internal/cdr-input.h
internal/clear-n_.h
internal/emf-win32-inout.h
internal/emf-win32-print.h
diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp
index 4af778e04..fa46569e2 100644
--- a/src/extension/implementation/script.cpp
+++ b/src/extension/implementation/script.cpp
@@ -23,6 +23,8 @@
#include <gtkmm/main.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/textview.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/convert.h>
#include <unistd.h>
#include <errno.h>
diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h
index f52683623..270c361af 100644
--- a/src/extension/implementation/script.h
+++ b/src/extension/implementation/script.h
@@ -15,6 +15,9 @@
#include "implementation.h"
#include <gtkmm/enums.h>
+#include <glibmm/main.h>
+#include <glibmm/spawn.h>
+#include <glibmm/fileutils.h>
namespace Inkscape {
namespace XML {
diff --git a/src/extension/system.cpp b/src/extension/system.cpp
index a9ca5c456..56cc6d1af 100644
--- a/src/extension/system.cpp
+++ b/src/extension/system.cpp
@@ -22,6 +22,7 @@
#include <interface.h>
#include <unistd.h>
+#include <glibmm/miscutils.h>
#include "system.h"
#include "preferences.h"
diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp
index fd146926f..320472347 100644
--- a/src/ink-comboboxentry-action.cpp
+++ b/src/ink-comboboxentry-action.cpp
@@ -303,11 +303,18 @@ ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass)
static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action)
{
action->active = -1;
- action->text = NULL;
+ action->text = strdup("");
action->entry_completion = NULL;
action->indicator = NULL;
action->popup = false;
+ action->info = NULL;
+ action->info_cb = NULL;
+ action->info_cb_id = 0;
+ action->info_cb_blocked = false;
action->warning = NULL;
+ action->warning_cb = NULL;
+ action->warning_cb_id = 0;
+ action->warning_cb_blocked = false;
action->altx_name = NULL;
action->focusWidget = NULL;
}
@@ -370,7 +377,8 @@ GtkWidget* create_tool_item( GtkAction* action )
ink_comboboxentry_action->combobox = GTK_COMBO_BOX (comboBoxEntry);
- gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active );
+ //gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active );
+ gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), 0 );
g_signal_connect( G_OBJECT(comboBoxEntry), "changed", G_CALLBACK(combo_box_changed_cb), action );
@@ -432,7 +440,6 @@ GtkWidget* create_tool_item( GtkAction* action )
// Add signal for GtkEntry to check if finished typing.
g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action );
g_signal_connect( G_OBJECT(child), "key-press-event", G_CALLBACK(keypress_cb), action );
-
}
gtk_activatable_set_related_action( GTK_ACTIVATABLE (item), GTK_ACTION( action ) );
@@ -476,66 +483,141 @@ gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* actio
return text;
}
-gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* ink_comboboxentry_action, const gchar* text ) {
+/*
+ * For the font-family list we need to handle two cases:
+ * Text is in list store:
+ * In this case we use row number as the font-family list can have duplicate
+ * entries, one in the document font part and one in the system font part. In
+ * order that scrolling through the list works properly we must distinguish
+ * between the two.
+ * Text is not in the list store (i.e. default font-family is not on system):
+ * In this case we have a row number of -1, and the text must be set by hand.
+ */
+gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* action, const gchar* text, int row ) {
- g_free( ink_comboboxentry_action->text );
- ink_comboboxentry_action->text = g_strdup( text );
+ if( strcmp( action->text, text ) != 0 ) {
+ g_free( action->text );
+ action->text = g_strdup( text );
+ }
// Get active row or -1 if none
- ink_comboboxentry_action->active = get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+ if( row < 0 ) {
+ row = get_active_row_from_text( action, action->text );
+ }
+ action->active = row;
// Set active row, check that combobox has been created.
- if( ink_comboboxentry_action->combobox ) {
- gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox ), ink_comboboxentry_action->active );
+ if( action->combobox ) {
+ gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox ), action->active );
}
// Fiddle with entry
- if( ink_comboboxentry_action->entry ) {
+ if( action->entry ) {
// Explicitly set text in GtkEntry box (won't be set if text not in list).
- gtk_entry_set_text( ink_comboboxentry_action->entry, text );
+ gtk_entry_set_text( action->entry, text );
// Show or hide warning -- this might be better moved to text-toolbox.cpp
- bool clear = true;
+ if( action->info_cb_id != 0 &&
+ !action->info_cb_blocked ) {
+ g_signal_handler_block (G_OBJECT(action->entry),
+ action->info_cb_id );
+ action->info_cb_blocked = true;
+ }
+ if( action->warning_cb_id != 0 &&
+ !action->warning_cb_blocked ) {
+ g_signal_handler_block (G_OBJECT(action->entry),
+ action->warning_cb_id );
+ action->warning_cb_blocked = true;
+ }
- if( ink_comboboxentry_action->warning != NULL ) {
- Glib::ustring missing = check_comma_separated_text( ink_comboboxentry_action );
+ bool set = false;
+ if( action->warning != NULL ) {
+ Glib::ustring missing = check_comma_separated_text( action );
if( !missing.empty() ) {
- GtkStockItem item;
- gboolean isStock = gtk_stock_lookup( GTK_STOCK_DIALOG_WARNING, &item );
- if (isStock) {
- gtk_entry_set_icon_from_stock( ink_comboboxentry_action->entry,
+ GtkStockItem item;
+ gboolean isStock = gtk_stock_lookup( GTK_STOCK_DIALOG_WARNING, &item );
+ if (isStock) {
+ gtk_entry_set_icon_from_stock( action->entry,
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_DIALOG_WARNING );
+ } else {
+ gtk_entry_set_icon_from_icon_name( action->entry,
GTK_ENTRY_ICON_SECONDARY,
GTK_STOCK_DIALOG_WARNING );
- } else {
- gtk_entry_set_icon_from_icon_name( ink_comboboxentry_action->entry,
- GTK_ENTRY_ICON_SECONDARY,
- GTK_STOCK_DIALOG_WARNING );
+ }
+ // Can't add tooltip until icon set
+ Glib::ustring warning = action->warning;
+ warning += ": ";
+ warning += missing;
+ gtk_entry_set_icon_tooltip_text( action->entry,
+ GTK_ENTRY_ICON_SECONDARY,
+ warning.c_str() );
+
+ if( action->warning_cb ) {
+
+ // Add callback if we haven't already
+ if( action->warning_cb_id == 0 ) {
+ action->warning_cb_id =
+ g_signal_connect( G_OBJECT(action->entry),
+ "icon-press",
+ G_CALLBACK(action->warning_cb),
+ action);
}
- // Can't add tooltip until icon set
- Glib::ustring warning = ink_comboboxentry_action->warning;
- warning += ": ";
- warning += missing;
- gtk_entry_set_icon_tooltip_text( ink_comboboxentry_action->entry,
- GTK_ENTRY_ICON_SECONDARY,
- warning.c_str() );
- clear = false;
+ // Unblock signal
+ if( action->warning_cb_blocked ) {
+ g_signal_handler_unblock (G_OBJECT(action->entry),
+ action->warning_cb_id );
+ action->warning_cb_blocked = false;
+ }
+ }
+ set = true;
}
}
- if( clear ) {
- gtk_entry_set_icon_from_icon_name( GTK_ENTRY(ink_comboboxentry_action->entry),
+ if( !set && action->info != NULL ) {
+ gtk_entry_set_icon_from_icon_name( GTK_ENTRY(action->entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_SELECT_ALL );
+ gtk_entry_set_icon_from_stock( GTK_ENTRY(action->entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_SELECT_ALL );
+ gtk_entry_set_icon_tooltip_text( action->entry,
+ GTK_ENTRY_ICON_SECONDARY,
+ action->info );
+
+ if( action->info_cb ) {
+ // Add callback if we haven't already
+ if( action->info_cb_id == 0 ) {
+ action->info_cb_id =
+ g_signal_connect( G_OBJECT(action->entry),
+ "icon-press",
+ G_CALLBACK(action->info_cb),
+ action);
+ }
+ // Unblock signal
+ if( action->info_cb_blocked ) {
+ g_signal_handler_unblock (G_OBJECT(action->entry),
+ action->info_cb_id );
+ action->info_cb_blocked = false;
+ }
+ }
+ set = true;
+ }
+
+ if( !set ) {
+ gtk_entry_set_icon_from_icon_name( GTK_ENTRY(action->entry),
GTK_ENTRY_ICON_SECONDARY,
NULL );
- gtk_entry_set_icon_from_stock( GTK_ENTRY(ink_comboboxentry_action->entry),
+ gtk_entry_set_icon_from_stock( GTK_ENTRY(action->entry),
GTK_ENTRY_ICON_SECONDARY,
NULL );
}
}
// Return if active text in list
- gboolean found = ( ink_comboboxentry_action->active != -1 );
+ gboolean found = ( action->active != -1 );
return found;
}
@@ -611,6 +693,24 @@ void ink_comboboxentry_action_set_tooltip( Ink_ComboBoxEntry_Action* action,
}
+void ink_comboboxentry_action_set_info( Ink_ComboBoxEntry_Action* action, const gchar* info ) {
+
+ g_free( action->info );
+ action->info = g_strdup( info );
+
+ // Widget may not have been created....
+ if( action->entry ) {
+ gtk_entry_set_icon_tooltip_text( GTK_ENTRY(action->entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ action->info );
+ }
+}
+
+void ink_comboboxentry_action_set_info_cb( Ink_ComboBoxEntry_Action* action, gpointer info_cb ) {
+
+ action->info_cb = info_cb;
+}
+
void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, const gchar* warning ) {
g_free( action->warning );
@@ -624,6 +724,11 @@ void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action,
}
}
+void ink_comboboxentry_action_set_warning_cb( Ink_ComboBoxEntry_Action* action, gpointer warning_cb ) {
+
+ action->warning_cb = warning_cb;
+}
+
void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* action, const gchar* altx_name ) {
g_free( action->altx_name );
@@ -728,22 +833,27 @@ static void combo_box_changed_cb( GtkComboBox* widget, gpointer data ) {
// We only react here if an item is selected.
// Get action
- Ink_ComboBoxEntry_Action *act = INK_COMBOBOXENTRY_ACTION( data );
+ Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data );
// Check if item selected:
gint newActive = gtk_combo_box_get_active(widget);
- if( newActive >= 0 ) {
+ if( newActive >= 0 && newActive != action->active ) {
- if( newActive != act->active ) {
- act->active = newActive;
- g_free( act->text );
- GtkWidget *entry = gtk_bin_get_child (GTK_BIN (widget));
- act->text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+ action->active = newActive;
- // Now let the world know
- g_signal_emit( G_OBJECT(act), signals[CHANGED], 0 );
+ GtkTreeIter iter;
+ if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX( action->combobox ), &iter ) ) {
+ gchar* text = 0;
+ gtk_tree_model_get( action->model, &iter, 0, &text, -1 );
+ gtk_entry_set_text( action->entry, text );
+
+ g_free( action->text );
+ action->text = text;
}
+
+ // Now let the world know
+ g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 );
}
}
@@ -752,29 +862,29 @@ static void entry_activate_cb( GtkEntry* widget, gpointer data ) {
// Get text from entry box.. check if it matches a menu entry.
// Get action
- Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data );
+ Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data );
// Get text
- g_free( ink_comboboxentry_action->text );
- ink_comboboxentry_action->text = g_strdup( gtk_entry_get_text( widget ) );
+ g_free( action->text );
+ action->text = g_strdup( gtk_entry_get_text( widget ) );
// Get row
- ink_comboboxentry_action->active =
- get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+ action->active =
+ get_active_row_from_text( action, action->text );
// Set active row
- gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
+ gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox), action->active );
// Now let the world know
- g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 );
+ g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 );
}
static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel* model, GtkTreeIter* iter, gpointer data )
{
// Get action
- Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data );
- GtkEntry *entry = ink_comboboxentry_action->entry;
+ Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data );
+ GtkEntry *entry = action->entry;
if( entry) {
gchar *family = 0;
@@ -784,18 +894,18 @@ static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel*
gtk_entry_set_text (GTK_ENTRY (entry), family );
// Set text in GtkAction
- g_free( ink_comboboxentry_action->text );
- ink_comboboxentry_action->text = family;
+ g_free( action->text );
+ action->text = family;
// Get row
- ink_comboboxentry_action->active =
- get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+ action->active =
+ get_active_row_from_text( action, action->text );
// Set active row
- gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
+ gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox), action->active );
// Now let the world know
- g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 );
+ g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 );
return true;
}
diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h
index f0dc0ee7e..a66f0790e 100644
--- a/src/ink-comboboxentry-action.h
+++ b/src/ink-comboboxentry-action.h
@@ -58,7 +58,14 @@ struct _Ink_ComboBoxEntry_Action {
gint entry_width;// Width of GtkEntry in characters.
gint extra_width;// Extra Width of GtkComboBox.. to widen drop-down list in list mode.
gboolean popup; // Do we pop-up an entry-completion dialog?
- gchar *warning; // Text for warning that entry isn't in list.
+ gchar *info; // Text for tooltip info about entry.
+ gpointer info_cb; // Callback for clicking info icon.
+ gint info_cb_id;
+ gboolean info_cb_blocked;
+ gchar *warning; // Text for tooltip warning that entry isn't in list.
+ gpointer warning_cb; // Callback for clicking warning icon.
+ gint warning_cb_id;
+ gboolean warning_cb_blocked;
gchar *altx_name; // Target for Alt-X keyboard shortcut.
GtkWidget *focusWidget;
};
@@ -84,7 +91,7 @@ GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action*
GtkComboBox *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action );
gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* action );
-gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* action, const gchar* text );
+gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* action, const gchar* text, int row=-1 );
void ink_comboboxentry_action_set_entry_width( Ink_ComboBoxEntry_Action* action, gint entry_width );
void ink_comboboxentry_action_set_extra_width( Ink_ComboBoxEntry_Action* action, gint extra_width );
@@ -92,8 +99,11 @@ void ink_comboboxentry_action_set_extra_width( Ink_ComboBoxEntry_Action* act
void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action );
void ink_comboboxentry_action_popup_disable( Ink_ComboBoxEntry_Action* action );
-void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, const gchar* warning );
-void ink_comboboxentry_action_set_tooltip( Ink_ComboBoxEntry_Action* action, const gchar* tooltip );
+void ink_comboboxentry_action_set_info( Ink_ComboBoxEntry_Action* action, const gchar* info );
+void ink_comboboxentry_action_set_info_cb( Ink_ComboBoxEntry_Action* action, gpointer info_cb );
+void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, const gchar* warning_cb );
+void ink_comboboxentry_action_set_warning_cb(Ink_ComboBoxEntry_Action* action, gpointer warning );
+void ink_comboboxentry_action_set_tooltip( Ink_ComboBoxEntry_Action* action, const gchar* tooltip );
void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* action, const gchar* altx_name );
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index fc823f8b7..449220357 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -37,6 +37,8 @@
#include <glib/gstdio.h>
#include <glib.h>
#include <glibmm/i18n.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/convert.h>
#include <gtkmm/messagedialog.h>
#include <gtk/gtk.h>
#include <signal.h>
diff --git a/src/interface.cpp b/src/interface.cpp
index 823119953..284368bff 100644
--- a/src/interface.cpp
+++ b/src/interface.cpp
@@ -458,47 +458,21 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb
item = gtk_separator_menu_item_new();
} else {
- unsigned int shortcut;
action = verb->get_action(view);
if (!action) return NULL;
- shortcut = sp_shortcut_get_primary(verb);
- if (shortcut!=GDK_KEY_VoidSymbol) {
- gchar* c = sp_shortcut_get_label(shortcut);
-#if GTK_CHECK_VERSION(3,0,0)
- GtkWidget *const hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
- gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
-#else
- GtkWidget *const hb = gtk_hbox_new(FALSE, 16);
-#endif
- GtkWidget *const name_lbl = gtk_label_new("");
- gtk_label_set_markup_with_mnemonic(GTK_LABEL(name_lbl), action->name);
- gtk_misc_set_alignment(reinterpret_cast<GtkMisc *>(name_lbl), 0.0, 0.5);
- gtk_box_pack_start(reinterpret_cast<GtkBox *>(hb), name_lbl, TRUE, TRUE, 0);
- GtkWidget *const accel_lbl = gtk_label_new(c);
- gtk_misc_set_alignment(reinterpret_cast<GtkMisc *>(accel_lbl), 1.0, 0.5);
- gtk_box_pack_end(reinterpret_cast<GtkBox *>(hb), accel_lbl, FALSE, FALSE, 0);
- gtk_widget_show_all(hb);
- if (radio) {
- item = gtk_radio_menu_item_new (group);
- } else {
- item = gtk_image_menu_item_new();
- }
- gtk_container_add(reinterpret_cast<GtkContainer *>(item), hb);
- g_free(c);
+ if (radio) {
+ item = gtk_radio_menu_item_new_with_mnemonic(group, action->name);
} else {
- if (radio) {
- item = gtk_radio_menu_item_new (group);
- } else {
- item = gtk_image_menu_item_new ();
- }
- GtkWidget *const name_lbl = gtk_label_new("");
- gtk_label_set_markup_with_mnemonic(GTK_LABEL(name_lbl), action->name);
- gtk_misc_set_alignment(reinterpret_cast<GtkMisc *>(name_lbl), 0.0, 0.5);
- gtk_container_add(reinterpret_cast<GtkContainer *>(item), name_lbl);
+ item = gtk_image_menu_item_new_with_mnemonic(action->name);
}
+ GtkAccelGroup *accel_group = sp_shortcut_get_accel_group();
+ gtk_menu_set_accel_group(menu, accel_group);
+
+ sp_shortcut_add_accelerator(item, sp_shortcut_get_primary(verb));
+
action->signal_set_sensitive.connect(
sigc::bind<0>(
sigc::ptr_fun(&gtk_widget_set_sensitive),
@@ -698,45 +672,16 @@ sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *
{
unsigned int shortcut = (verb) ? sp_shortcut_get_primary(verb) : 0;
SPAction *action = (verb) ? verb->get_action(view) : 0;
- GtkWidget *item = gtk_check_menu_item_new();
-
-
- if (verb && shortcut!=GDK_KEY_VoidSymbol) {
- gchar* c = sp_shortcut_get_label(shortcut);
-
-#if GTK_CHECK_VERSION(3,0,0)
- GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
- gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
-#else
- GtkWidget *hb = gtk_hbox_new(FALSE, 16);
-#endif
+ GtkWidget *item = gtk_check_menu_item_new_with_mnemonic(action ? action->name : label);
- {
- GtkWidget *l = gtk_label_new_with_mnemonic(action ? action->name : label);
- gtk_misc_set_alignment((GtkMisc *) l, 0.0, 0.5);
- gtk_box_pack_start((GtkBox *) hb, l, TRUE, TRUE, 0);
- }
-
- {
- GtkWidget *l = gtk_label_new(c);
- gtk_misc_set_alignment((GtkMisc *) l, 1.0, 0.5);
- gtk_box_pack_end((GtkBox *) hb, l, FALSE, FALSE, 0);
- }
-
- gtk_widget_show_all(hb);
-
- gtk_container_add((GtkContainer *) item, hb);
- g_free(c);
- } else {
- GtkWidget *l = gtk_label_new_with_mnemonic(action ? action->name : label);
- gtk_misc_set_alignment((GtkMisc *) l, 0.0, 0.5);
- gtk_container_add((GtkContainer *) item, l);
- }
#if 0
if (!action->sensitive) {
gtk_widget_set_sensitive(item, FALSE);
}
#endif
+
+ sp_shortcut_add_accelerator(item, shortcut);
+
gtk_widget_show(item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
@@ -1726,40 +1671,13 @@ void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)//
append(*item);
} else {
action = verb->get_action(view);
- if (!action)
- {
+ if (!action) {
return;
}
- Gtk::ImageMenuItem *item = NULL;
- unsigned int shortcut = sp_shortcut_get_primary(verb);
- if (shortcut!=GDK_KEY_VoidSymbol) {
- gchar* c = sp_shortcut_get_label(shortcut);
- Gtk::HBox *const hb = manage(new Gtk::HBox (FALSE, 16));
- Gtk::Label *const name_lbl = manage(new Gtk::Label(action->name, true));
- name_lbl->set_alignment(0.0, 0.5);
- hb->pack_start(*name_lbl, TRUE, TRUE, 0);
- Gtk::Label *const accel_lbl = manage(new Gtk::Label(c));
- accel_lbl->set_alignment(1.0, 0.5);
- hb->pack_end(*accel_lbl, FALSE, FALSE, 0);
- hb->show_all();
- // if (radio) {
- // item = gtk_radio_menu_item_new (group);
- // } else {
- item = new Gtk::ImageMenuItem();
- // }
- item->add(*hb);
- g_free(c);
- } else {
- // if (radio) {
- // item = gtk_radio_menu_item_new (group);
- // } else {
- item = manage(new Gtk::ImageMenuItem());
- // }
- Gtk::Label *const name_lbl = manage(new Gtk::Label(action->name, true));
- name_lbl->set_alignment(0.0, 0.5);
- item->add(*name_lbl);
- }
+ Gtk::ImageMenuItem *item = manage(new Gtk::ImageMenuItem(action->name, true));
+
+ sp_shortcut_add_accelerator(GTK_WIDGET(item->gobj()), sp_shortcut_get_primary(verb));
action->signal_set_sensitive.connect(sigc::mem_fun(*this, &ContextMenu::set_sensitive));
action->signal_set_name.connect(sigc::mem_fun(*item, &ContextMenu::set_name));
diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp
index 04859185c..5e67c5991 100644
--- a/src/libnrtype/font-lister.cpp
+++ b/src/libnrtype/font-lister.cpp
@@ -10,15 +10,19 @@
#include <glibmm.h>
#include <gtkmm/treemodel.h>
#include <gtkmm/liststore.h>
-
#include "font-lister.h"
#include "FontFactory.h"
+#include "desktop.h"
+#include "desktop-style.h"
+#include "document.h"
+#include "inkscape.h"
+#include "preferences.h"
#include "sp-object.h"
#include "sp-root.h"
-#include "document.h"
#include "xml/repr.h"
-#include "preferences.h"
+
+//#define DEBUG_FONT
namespace Inkscape
{
@@ -29,7 +33,7 @@ namespace Inkscape
FamilyToStylesMap familyStyleMap;
font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
-
+
// Grab the family names into a list and then sort them
std::list<Glib::ustring> familyList;
for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
@@ -47,7 +51,8 @@ namespace Inkscape
if (!familyName.empty()) {
Gtk::TreeModel::iterator treeModelIter = font_list_store->append();
- (*treeModelIter)[FontList.font] = reinterpret_cast<const char*>(g_strdup(familyName.c_str()));
+ //(*treeModelIter)[FontList.family] = reinterpret_cast<const char*>(g_strdup(familyName.c_str()));
+ (*treeModelIter)[FontList.family] = familyName;
// Now go through the styles
GList *styles = NULL;
@@ -62,7 +67,22 @@ namespace Inkscape
(*treeModelIter)[FontList.onSystem] = true;
}
}
+ current_family_row = 0;
+ current_family = "sans-serif";
+ current_style = "Normal";
+ current_fontspec = "sans-serif"; // Empty style -> Normal
+ current_fontspec_system = "Sans";
+
+ /* Create default styles for use when font-family is unknown on system. */
+ default_styles = g_list_append( NULL, g_strdup("Normal") );
+ default_styles = g_list_append( default_styles, g_strdup("Italic") );
+ default_styles = g_list_append( default_styles, g_strdup("Bold") );
+ default_styles = g_list_append( default_styles, g_strdup("Bold Italic") );
+
font_list_store->thaw_notify();
+
+ style_list_store = Gtk::ListStore::create (FontStyleList);
+ style_list_store_trial = Gtk::ListStore::create (FontStyleList);
}
// Example of how to use "foreach_iter"
@@ -70,7 +90,7 @@ namespace Inkscape
// FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) {
// Gtk::TreeModel::Row row = *iter;
// if( !row[FontList.onSystem] ) {
- // std::cout << " Not on system: " << row[FontList.font] << std::endl;
+ // std::cout << " Not on system: " << row[FontList.family] << std::endl;
// return false;
// }
// return true;
@@ -87,28 +107,31 @@ namespace Inkscape
font_list_store->freeze_notify();
+ /* Find if current row is in document or system part of list */
+ gboolean row_is_system = false;
+ if( current_family_row > -1 ) {
+ Gtk::TreePath path;
+ path.push_back( current_family_row );
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
+ if( iter ) {
+ row_is_system = (*iter)[FontList.onSystem];
+ // std::cout << " In: row: " << current_family_row << " " << (*iter)[FontList.family] << std::endl;
+ }
+ }
+
/* Clear all old document font-family entries */
Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
while( iter != font_list_store->children().end() ) {
Gtk::TreeModel::Row row = *iter;
if( !row[FontList.onSystem] ) {
- // std::cout << " Not on system: " << row[FontList.font] << std::endl;
+ // std::cout << " Not on system: " << row[FontList.family] << std::endl;
iter = font_list_store->erase( iter );
} else {
- // std::cout << " First on system: " << row[FontList.font] << std::endl;
+ // std::cout << " First on system: " << row[FontList.family] << std::endl;
break;
}
}
- /* Create default styles for use when font-family is unknown on system. */
- static GList *default_styles = NULL;
- if( default_styles == NULL ) {
- default_styles = g_list_append( default_styles, g_strdup("Normal") );
- default_styles = g_list_append( default_styles, g_strdup("Italic") );
- default_styles = g_list_append( default_styles, g_strdup("Bold") );
- default_styles = g_list_append( default_styles, g_strdup("Bold Italic") );
- }
-
/* Get "font-family"s used in document. */
std::list<Glib::ustring> fontfamilies;
update_font_list_recursive( r, &fontfamilies );
@@ -120,7 +143,7 @@ namespace Inkscape
/* Insert separator */
if( !fontfamilies.empty() ) {
Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
- (*treeModelIter)[FontList.font] = "#";
+ (*treeModelIter)[FontList.family] = "#";
(*treeModelIter)[FontList.onSystem] = false;
}
@@ -137,7 +160,7 @@ namespace Inkscape
Gtk::TreeModel::iterator iter2 = font_list_store->get_iter( "0" );
while( iter2 != font_list_store->children().end() ) {
Gtk::TreeModel::Row row = *iter2;
- if( row[FontList.onSystem] && tokens[0].compare( row[FontList.font] ) == 0 ) {
+ if( row[FontList.onSystem] && tokens[0].compare( row[FontList.family] ) == 0 ) {
styles = row[FontList.styles];
break;
}
@@ -146,11 +169,37 @@ namespace Inkscape
}
Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend();
- (*treeModelIter)[FontList.font] = reinterpret_cast<const char*>(g_strdup((*i).c_str()));
+ (*treeModelIter)[FontList.family] = reinterpret_cast<const char*>(g_strdup((*i).c_str()));
(*treeModelIter)[FontList.styles] = styles;
(*treeModelIter)[FontList.onSystem] = false;
}
+ /* Now we do a song and dance to find the correct row as the row corresponding
+ * to the current_family may have changed. We can't simply search for the
+ * family name in the list since it can occur twice, once in the document
+ * font family part and once in the system font family part. Above we determined
+ * which part it is in.
+ */
+ if( current_family_row > -1 ) {
+ int start = 0;
+ if( row_is_system ) start = fontfamilies.size();
+ int length = font_list_store->children().size();
+ for( int i = 0; i < length; ++i ) {
+ int row = i + start;
+ if( row >= length ) row -= length;
+ Gtk::TreePath path;
+ path.push_back( row );
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
+ if( iter ) {
+ if( current_family.compare( (*iter)[FontList.family] ) == 0 ) {
+ current_family_row = row;
+ break;
+ }
+ }
+ }
+ }
+ // std::cout << " Out: row: " << current_family_row << " " << current_family << std::endl;
+
font_list_store->thaw_notify();
}
@@ -191,7 +240,578 @@ namespace Inkscape
}
}
- Gtk::TreePath
+ Glib::ustring
+ FontLister::canonize_fontspec( Glib::ustring fontspec ) {
+
+ // Pass fontspec to and back from Pango to get a the fontspec in
+ // canonical form. -inkscape-font-specification relies on the
+ // Pango constructed fontspec not changing form. If it does,
+ // this is the place to fix it.
+ PangoFontDescription *descr = pango_font_description_from_string( fontspec.c_str() );
+ gchar* canonized = pango_font_description_to_string ( descr );
+ Glib::ustring Canonized = canonized;
+ g_free( canonized );
+ pango_font_description_free( descr );
+
+ // Pango canonized strings remove space after comma between family names. Put it back.
+ size_t i = 0;
+ while( (i = Canonized.find(",", i)) != std::string::npos) {
+ Canonized.replace(i, 1, ", ");
+ i += 2;
+ }
+
+ return Canonized;
+ }
+
+ Glib::ustring
+ FontLister::system_fontspec( Glib::ustring fontspec ) {
+
+ // Find what Pango thinks is the closest match.
+ Glib::ustring out = fontspec;
+
+ PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
+ font_instance *res = (font_factory::Default())->Face(descr);
+ if (res->pFont) {
+ PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont);
+ out = sp_font_description_get_family(nFaceDesc);
+ }
+ pango_font_description_free(descr);
+
+ return out;
+ }
+
+ std::pair<Glib::ustring, Glib::ustring>
+ FontLister::ui_from_fontspec( Glib::ustring fontspec ) {
+
+ PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str());
+ const gchar* family = pango_font_description_get_family(descr);
+ Glib::ustring Family = family;
+
+ // Pango canonized strings remove space after comma between family names. Put it back.
+ size_t i = 0;
+ while( (i = Family.find(",", i)) != std::string::npos) {
+ Family.replace(i, 1, ", ");
+ i += 2;
+ }
+
+ pango_font_description_unset_fields(descr, PANGO_FONT_MASK_FAMILY);
+ gchar* style = pango_font_description_to_string( descr );
+ Glib::ustring Style = style;
+ pango_font_description_free(descr);
+ g_free( style );
+
+ return std::make_pair( Family, Style );
+ }
+
+ std::pair<Glib::ustring, Glib::ustring>
+ FontLister::selection_update () {
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::selection_update: entrance" << std::endl;
+#endif
+ // Get fontspec from a selection, preferences, or thin air.
+ Glib::ustring fontspec;
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+
+ // Directly from stored font specification.
+ int result =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ //std::cout << " Attempting selected style" << std::endl;
+ if( result != QUERY_STYLE_NOTHING && query->text->font_specification.set ) {
+ fontspec = query->text->font_specification.value;
+ //std::cout << " fontspec from query :" << fontspec << ":" << std::endl;
+ }
+
+ // From style
+ if( fontspec.empty() ) {
+ //std::cout << " Attempting desktop style" << std::endl;
+ int rfamily = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ int rstyle = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+
+ // Must have text in selection
+ if( rfamily != QUERY_STYLE_NOTHING && rstyle != QUERY_STYLE_NOTHING ) {
+ fontspec = fontspec_from_style( query );
+ }
+ //std::cout << " fontspec from style :" << fontspec << ":" << std::endl;
+ }
+
+ // From preferences
+ if( fontspec.empty() ) {
+ //std::cout << " Attempting preferences" << std::endl;
+ sp_style_read_from_prefs(query, "/tools/text");
+ fontspec = fontspec_from_style( query );
+ //std::cout << " fontspec from prefs :" << fontspec << ":" << std::endl;
+ }
+ sp_style_unref(query);
+
+ // From thin air
+ if( fontspec.empty() ) {
+ //std::cout << " Attempting thin air" << std::endl;
+ fontspec = current_family + ", " + current_style;
+ //std::cout << " fontspec from thin air :" << fontspec << ":" << std::endl;
+ }
+
+ // Do we really need? Removes spaces between font-families.
+ //current_fontspec = canonize_fontspec( fontspec );
+ current_fontspec = fontspec; // Ignore for now
+
+ current_fontspec_system = system_fontspec( current_fontspec );
+
+ std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec( current_fontspec );
+ set_font_family( ui.first );
+
+#ifdef DEBUG_FONT
+ std::cout << " family_row: :" << current_family_row << ":" << std::endl;
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: :" << current_family << ":" << std::endl;
+ std::cout << " style: :" << current_style << ":" << std::endl;
+ std::cout << "FontLister::selection_update: exit" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return std::make_pair( current_family, current_style );
+ }
+
+
+ // TODO: use to determine font-selector best style
+ std::pair<Glib::ustring, Glib::ustring>
+ FontLister::new_font_family (Glib::ustring new_family, gboolean check_style ) {
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::new_font_family: " << new_family << std::endl;
+#endif
+
+ // No need to do anything if new family is same as old family.
+ if( new_family.compare( current_family ) == 0 ) {
+#ifdef DEBUG_FONT
+ std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return std::make_pair( current_family, current_style );
+ }
+
+ // We need to do two things:
+ // 1. Update style list for new family.
+ // 2. Select best valid style match to old style.
+
+ // For finding style list, use list of first family in font-family list.
+ GList* styles = NULL;
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
+ while( iter != font_list_store->children().end() ) {
+
+ Gtk::TreeModel::Row row = *iter;
+
+ if( new_family.compare( row[FontList.family] ) == 0 ) {
+ styles = row[FontList.styles];
+ break;
+ }
+ ++iter;
+ }
+
+ // Newly typed in font-family may not yet be in list... use default list.
+ // TODO: if font-family is list, check if first family in list is on system
+ // and set style accordingly.
+ if( styles == NULL ) {
+ styles = default_styles;
+ }
+
+ // Update style list.
+ // TODO: create a second "temporary" style_list_store for font_selector.
+ style_list_store->freeze_notify();
+ style_list_store->clear();
+
+ for (GList *l=styles; l; l = l->next) {
+ Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
+ (*treeModelIter)[FontStyleList.styles] = (char*)l->data;
+ }
+
+ style_list_store->thaw_notify();
+
+ // Find best match to the style from the old font-family to the
+ // styles available with the new font.
+ // TODO: Maybe check if an exact match exists before using Pango.
+ Glib::ustring best_style = current_style;
+ if( check_style ) {
+ //std::cout << " Trying to match: " << current_fontspec << std::endl;
+ PangoFontDescription *desc_old
+ = pango_font_description_from_string( current_fontspec.c_str() );
+ PangoFontDescription* desc_best = NULL;
+
+ for (GList *l=styles; l; l = l->next) {
+ Glib::ustring candidate = new_family + ", " + (char*)l->data;
+ PangoFontDescription* desc_candidate
+ = pango_font_description_from_string( candidate.c_str() );
+ //std::cout << " Testing: " << pango_font_description_to_string( desc_candidate ) << std::endl;
+ if( pango_font_description_better_match( desc_old, desc_best, desc_candidate ) ) {
+ pango_font_description_free( desc_best );
+ desc_best = desc_candidate;
+ //std::cout << " ... better: " << std::endl;
+ } else {
+ pango_font_description_free( desc_candidate );
+ //std::cout << " ... not better: " << std::endl;
+ }
+ }
+ if( desc_best ) {
+ pango_font_description_unset_fields( desc_best, PANGO_FONT_MASK_FAMILY );
+ best_style = pango_font_description_to_string( desc_best );
+ }
+
+ if( desc_old ) pango_font_description_free( desc_old );
+ if( desc_best ) pango_font_description_free( desc_best );
+ }
+
+#ifdef DEBUG_FONT
+ std::cout << "FontLister::new_font_family: exit: " << new_family << " " << best_style << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return std::make_pair( new_family, best_style );
+ }
+
+ std::pair<Glib::ustring, Glib::ustring>
+ FontLister::set_font_family (Glib::ustring new_family, gboolean check_style) {
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::set_font_family: " << new_family << std::endl;
+#endif
+
+ std::pair<Glib::ustring, Glib::ustring> ui = new_font_family( new_family, check_style );
+ current_family = ui.first;
+ current_style = ui.second;
+ current_fontspec = canonize_fontspec( current_family + ", " + current_style );
+ current_fontspec_system = system_fontspec( current_fontspec );
+
+#ifdef DEBUG_FONT
+ std::cout << " family_row: :" << current_family_row << ":" << std::endl;
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: :" << current_family << ":" << std::endl;
+ std::cout << " style: :" << current_style << ":" << std::endl;
+ std::cout << "FontLister::set_font_family: end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return ui;
+ }
+
+
+ std::pair<Glib::ustring, Glib::ustring>
+ FontLister::set_font_family (int row, gboolean check_style) {
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::set_font_family( row ): " << row << std::endl;
+#endif
+
+ current_family_row = row;
+ Gtk::TreePath path;
+ path.push_back( row );
+ Glib::ustring new_family = current_family;
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
+ if( iter ) {
+ new_family = (*iter)[FontList.family];
+ }
+
+ std::pair<Glib::ustring, Glib::ustring> ui = set_font_family( new_family, check_style );
+
+#ifdef DEBUG_FONT
+ std::cout << "FontLister::set_font_family( row ): end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return ui;
+ }
+
+
+ // void
+ // FontLister::new_font_style (Glib::ustring new_style) {
+ // // Is this needed? What do we do?
+ // }
+
+ void
+ FontLister::set_font_style (Glib::ustring new_style) {
+
+ // TODO: Validate input using Pango. If Pango doesn't recognize a style it will
+ // attach the "invalid" style to the font-family.
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister:set_font_style: " << new_style << std::endl;
+#endif
+
+ current_style = new_style;
+ current_fontspec = canonize_fontspec( current_family + ", " + current_style );
+ current_fontspec_system = system_fontspec( current_fontspec );
+
+#ifdef DEBUG_FONT
+ std::cout << " canonized: :" << current_fontspec << ":" << std::endl;
+ std::cout << " system: :" << current_fontspec_system << ":" << std::endl;
+ std::cout << " family: " << current_family << std::endl;
+ std::cout << " style: " << current_style << std::endl;
+ std::cout << "FontLister::set_font_style: end" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ }
+
+ // For use by font-selector where we already know that the style is valid
+ void
+ FontLister::set_font (Glib::ustring new_family, Glib::ustring new_style) {
+
+#ifdef DEBUG_FONT
+ std::cout << "FonLister::set_font: " << new_family << " " << new_style << std::endl;
+#endif
+ set_font_family( new_family, false );
+ set_font_style( new_style );
+ }
+
+ // We do this ourselves as we can't rely on FontFactory.
+ void
+ FontLister::set_css( SPCSSAttr *css ) {
+
+ //std::cout << "FontLister:set_css: " << std::endl;
+
+ sp_repr_css_set_property (css, "-inkscape-font-specification", current_fontspec.c_str() );
+ sp_repr_css_set_property (css, "font-family", current_family.c_str() ); //Canonized w/ spaces
+
+ PangoFontDescription *desc = pango_font_description_from_string( current_fontspec.c_str() );
+ PangoWeight weight = pango_font_description_get_weight( desc );
+ switch ( weight ) {
+ case PANGO_WEIGHT_THIN:
+ sp_repr_css_set_property (css, "font-weight", "100" );
+ break;
+ case PANGO_WEIGHT_ULTRALIGHT:
+ sp_repr_css_set_property (css, "font-weight", "200" );
+ break;
+ case PANGO_WEIGHT_LIGHT:
+ sp_repr_css_set_property (css, "font-weight", "300" );
+ break;
+ case PANGO_WEIGHT_BOOK:
+ sp_repr_css_set_property (css, "font-weight", "380" );
+ break;
+ case PANGO_WEIGHT_NORMAL:
+ sp_repr_css_set_property (css, "font-weight", "normal" );
+ break;
+ case PANGO_WEIGHT_MEDIUM:
+ sp_repr_css_set_property (css, "font-weight", "500" );
+ break;
+ case PANGO_WEIGHT_SEMIBOLD:
+ sp_repr_css_set_property (css, "font-weight", "600" );
+ break;
+ case PANGO_WEIGHT_BOLD:
+ sp_repr_css_set_property (css, "font-weight", "bold" );
+ break;
+ case PANGO_WEIGHT_ULTRABOLD:
+ sp_repr_css_set_property (css, "font-weight", "800" );
+ break;
+ case PANGO_WEIGHT_HEAVY:
+ sp_repr_css_set_property (css, "font-weight", "900" );
+ break;
+ case PANGO_WEIGHT_ULTRAHEAVY:
+ sp_repr_css_set_property (css, "font-weight", "1000" );
+ break;
+ }
+
+ PangoStyle style = pango_font_description_get_style( desc );
+ switch ( style ) {
+ case PANGO_STYLE_NORMAL:
+ sp_repr_css_set_property (css, "font-style", "normal" );
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ sp_repr_css_set_property (css, "font-style", "oblique" );
+ break;
+ case PANGO_STYLE_ITALIC:
+ sp_repr_css_set_property (css, "font-style", "italic" );
+ break;
+ }
+
+ PangoStretch stretch = pango_font_description_get_stretch( desc );
+ switch ( stretch ) {
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ sp_repr_css_set_property (css, "font-stretch", "ultra-condensed" );
+ break;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ sp_repr_css_set_property (css, "font-stretch", "extra-condensed" );
+ break;
+ case PANGO_STRETCH_CONDENSED:
+ sp_repr_css_set_property (css, "font-stretch", "condensed" );
+ break;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ sp_repr_css_set_property (css, "font-stretch", "semi-condensed" );
+ break;
+ case PANGO_STRETCH_NORMAL:
+ sp_repr_css_set_property (css, "font-stretch", "normal" );
+ break;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ sp_repr_css_set_property (css, "font-stretch", "semi-expanded" );
+ break;
+ case PANGO_STRETCH_EXPANDED:
+ sp_repr_css_set_property (css, "font-stretch", "expanded" );
+ break;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ sp_repr_css_set_property (css, "font-stretch", "extra-expanded" );
+ break;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ sp_repr_css_set_property (css, "font-stretch", "ultra-expanded" );
+ break;
+ }
+
+ PangoVariant variant = pango_font_description_get_variant( desc );
+ switch ( variant ) {
+ case PANGO_VARIANT_NORMAL:
+ sp_repr_css_set_property (css, "font-variant", "normal" );
+ break;
+ case PANGO_VARIANT_SMALL_CAPS:
+ sp_repr_css_set_property (css, "font-variant", "small-caps" );
+ break;
+ }
+ }
+
+ // We do this ourselves as we can't rely on FontFactory.
+ Glib::ustring
+ FontLister::fontspec_from_style (SPStyle* style) {
+
+ //std::cout << "FontLister:fontspec_from_style: " << std::endl;
+
+ Glib::ustring fontspec;
+ if (style) {
+
+ // First try to use the font specification if it is set
+ if (style->text->font_specification.set
+ && style->text->font_specification.value
+ && *style->text->font_specification.value) {
+
+ fontspec = style->text->font_specification.value;
+
+ } else {
+
+ fontspec = style->text->font_family.value;
+ fontspec += ",";
+
+ switch (style->font_weight.computed) {
+
+ case SP_CSS_FONT_WEIGHT_100:
+ fontspec += " 100";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_200:
+ fontspec += " 200";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_300:
+ fontspec += " 300";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_400:
+ case SP_CSS_FONT_WEIGHT_NORMAL:
+ //fontspec += " normal";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_500:
+ fontspec += " 500";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_600:
+ fontspec += " 600";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_700:
+ case SP_CSS_FONT_WEIGHT_BOLD:
+ fontspec += " bold";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_800:
+ fontspec += " 800";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_900:
+ fontspec += " 900";
+ break;
+
+ case SP_CSS_FONT_WEIGHT_LIGHTER:
+ case SP_CSS_FONT_WEIGHT_BOLDER:
+ default:
+ g_warning("Unrecognized font_weight.computed value");
+ break;
+ }
+
+ switch (style->font_style.computed) {
+ case SP_CSS_FONT_STYLE_ITALIC:
+ fontspec += " italic";
+ break;
+
+ case SP_CSS_FONT_STYLE_OBLIQUE:
+ fontspec += " oblique";
+ break;
+
+ case SP_CSS_FONT_STYLE_NORMAL:
+ default:
+ //fontspec += " normal";
+ break;
+ }
+
+ switch (style->font_stretch.computed) {
+
+ case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED:
+ fontspec += " extra_condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED:
+ fontspec += " extra_condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_CONDENSED:
+ case SP_CSS_FONT_STRETCH_NARROWER:
+ fontspec += " condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_CONDENSED:
+ fontspec += " semi_condensed";
+ break;
+
+ case SP_CSS_FONT_STRETCH_NORMAL:
+ //fontspec += " normal";
+ break;
+
+ case SP_CSS_FONT_STRETCH_SEMI_EXPANDED:
+ fontspec += " semi_expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXPANDED:
+ case SP_CSS_FONT_STRETCH_WIDER:
+ fontspec += " expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED:
+ fontspec += " extra_expanded";
+ break;
+
+ case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED:
+ fontspec += " ultra_expanded";
+ break;
+
+ default:
+ //fontspec += " normal";
+ break;
+ }
+
+ switch (style->font_variant.computed) {
+
+ case SP_CSS_FONT_VARIANT_SMALL_CAPS:
+ fontspec += "small-caps";
+ break;
+
+ default:
+ //fontspec += "normal";
+ break;
+ }
+ }
+ }
+ return canonize_fontspec( fontspec );
+ }
+
+
+ Gtk::TreeModel::Row
FontLister::get_row_for_font (Glib::ustring family)
{
Gtk::TreePath path;
@@ -201,8 +821,8 @@ namespace Inkscape
Gtk::TreeModel::Row row = *iter;
- if( family.compare( row[FontList.font] ) == 0 ) {
- return font_list_store->get_path( iter );
+ if( family.compare( row[FontList.family] ) == 0 ) {
+ return row;
}
++iter;
@@ -211,6 +831,65 @@ namespace Inkscape
throw FAMILY_NOT_FOUND;
}
+ Gtk::TreePath
+ FontLister::get_path_for_font (Glib::ustring family)
+ {
+ return font_list_store->get_path( get_row_for_font ( family ) );
+ }
+
+ /* Returns style string */
+ // TODO: Remove or turn into function to be used by new_font_family.
+ Glib::ustring
+ FontLister::get_best_style_match (Glib::ustring family, Glib::ustring target_style) {
+
+#ifdef DEBUG_FONT
+ std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
+ std::cout << "FontLister::get_best_style_match: " << family << " : " << target_style << std::endl;
+#endif
+
+ Glib::ustring font_string = family + " " + target_style;
+
+ Gtk::TreeModel::Row row;
+ try {
+ row = get_row_for_font( family );
+ } catch (...) {
+ //std::cout << " ERROR: can't find family: " << family << std::endl;
+ return (target_style);
+ }
+
+ PangoFontDescription* target = pango_font_description_from_string( font_string.c_str() );
+ PangoFontDescription* best = NULL;
+
+ //std::cout << " Target: " << pango_font_description_to_string( target ) << std::endl;
+
+ GList* styles = row[FontList.styles];
+ for (GList *l=styles; l; l = l->next) {
+ Glib::ustring font_string_test = family + " " + (char*)l->data;
+ PangoFontDescription* candidate = pango_font_description_from_string( font_string_test.c_str() );
+ // std::cout << " Testing: " << pango_font_description_to_string( candidate ) << std::endl;
+ if( pango_font_description_better_match( target, best, candidate ) ) {
+ best = candidate;
+ }
+ }
+
+ Glib::ustring best_style;
+ if( best ) {
+ //std::cout << " Best: " << pango_font_description_to_string( best ) << std::endl;
+ pango_font_description_unset_fields( best, PANGO_FONT_MASK_FAMILY );
+ best_style = pango_font_description_to_string( best );
+ } else {
+ //std::cout << " Failed: " << family << std::endl;
+ best_style = target_style;
+ }
+
+#ifdef DEBUG_FONT
+ std::cout << " Returning: " << best_style << std::endl;
+ std::cout << "FontLister::get_best_style_match: exit" << std::endl;
+ std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
+#endif
+ return best_style;
+ }
+
FontLister::~FontLister ()
{
};
@@ -220,6 +899,18 @@ namespace Inkscape
{
return font_list_store;
}
+
+ const Glib::RefPtr<Gtk::ListStore>
+ FontLister::get_style_list () const
+ {
+ return style_list_store;
+ }
+
+ const Glib::RefPtr<Gtk::ListStore>
+ FontLister::get_style_list_trial () const
+ {
+ return style_list_store_trial;
+ }
}
// Helper functions
diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h
index 751350407..aaa996247 100644
--- a/src/libnrtype/font-lister.h
+++ b/src/libnrtype/font-lister.h
@@ -25,12 +25,35 @@
class SPObject;
class SPDocument;
+class SPCSSAttr;
+struct SPStyle;
namespace Inkscape
{
/**
* This class enumerates fonts using libnrtype into reusable data stores and
- * allows for random access to the font list
+ * allows for random access to the font-family list and the font-style list.
+ * Setting the font-family updates the font-style list. "Style" in this case
+ * refers to everything but family and size (e.g. italic/oblique, weight).
+ *
+ * This class handles font-family lists and fonts that are not on the system,
+ * where there is not an entry in the fontInstanceMap.
+ *
+ * This class uses the idea of "font_spec". This is a plain text string as used by
+ * Pango. It is similar to the CSS font shorthand except that font-family comes
+ * first and in this class the font-size is not used.
+ *
+ * This class uses the FontFactory class to get a list of system fonts
+ * and to find best matches via Pango. The Pango interface is only setup
+ * to deal with fonts that are on the system so care must be taken. For
+ * example, best matches should only be done with the first font-family
+ * in a font-family list. If the first font-family is not on the system
+ * then a generic font-family should be used (sans-serif -> Sans).
+ *
+ * This class is used by the UI interface (text-toolbar, font-select, etc.).
+ *
+ * "Font" includes family and style. It should not be used when one
+ * means font-family.
*/
class FontLister
{
@@ -38,13 +61,14 @@ namespace Inkscape
enum Exceptions
{
- FAMILY_NOT_FOUND
+ FAMILY_NOT_FOUND,
+ STYLE_NOT_FOUND
};
virtual ~FontLister ();
- /** GtkTreeModelColumnRecord for the font list Gtk::ListStore
+ /** GtkTreeModelColumnRecord for the font-family list Gtk::ListStore
*/
class FontListClass
: public Gtk::TreeModelColumnRecord
@@ -52,10 +76,9 @@ namespace Inkscape
public:
/** Column containing the family name
*/
- Gtk::TreeModelColumn<Glib::ustring> font;
+ Gtk::TreeModelColumn<Glib::ustring> family;
- /** Column containing an std::vector<std::string> with style names
- * for the corresponding family
+ /** Column containing the styles for each family name.
*/
Gtk::TreeModelColumn<GList*> styles;
@@ -65,7 +88,7 @@ namespace Inkscape
FontListClass ()
{
- add (font);
+ add (family);
add (styles);
add (onSystem);
}
@@ -73,7 +96,24 @@ namespace Inkscape
FontListClass FontList;
- /** Returns the ListStore with the font names
+ class FontStyleListClass
+ : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ /** Column containing the styles
+ */
+ Gtk::TreeModelColumn<Glib::ustring> styles;
+
+ FontStyleListClass ()
+ {
+ add (styles);
+ }
+ };
+
+ FontStyleListClass FontStyleList;
+ FontStyleListClass FontStyleListTrial;
+
+ /** Returns the ListStore with the family names
*
* The return is const and the function is declared as const.
* The ListStore is ready to be used after class instantiation
@@ -82,6 +122,18 @@ namespace Inkscape
const Glib::RefPtr<Gtk::ListStore>
get_font_list () const;
+ /** Returns the ListStore with the styles
+ *
+ */
+ const Glib::RefPtr<Gtk::ListStore>
+ get_style_list () const;
+
+ /** Returns the ListStore with the styles - trial
+ *
+ */
+ const Glib::RefPtr<Gtk::ListStore>
+ get_style_list_trial () const;
+
/** Updates font list to include fonts in document
*
*/
@@ -96,13 +148,136 @@ namespace Inkscape
static Inkscape::FontLister*
get_instance ()
{
- static Inkscape::FontLister* instance = new Inkscape::FontLister();
+ static Inkscape::FontLister* instance = new Inkscape::FontLister();
return instance;
}
- Gtk::TreePath
+ /** Takes a hand written font spec and returns a Pango generated one in
+ * standard form.
+ */
+ Glib::ustring canonize_fontspec( Glib::ustring fontspec );
+
+ /** Find closest system font to given font.
+ */
+ Glib::ustring system_fontspec( Glib::ustring fontspec );
+
+ /** Gets font-family and style from fontspec.
+ * font-family and style returned.
+ */
+ std::pair<Glib::ustring, Glib::ustring>
+ ui_from_fontspec (Glib::ustring fontspec);
+
+ /** Sets font-family and style after a selection change.
+ * New font-family and style returned.
+ */
+ std::pair<Glib::ustring, Glib::ustring>
+ selection_update ();
+
+ /** Changes font-family, updating style list and attempting to find
+ * closest style to current_style style (if check_style is true).
+ * New font-family and style returned.
+ * Does NOT update current_family and current_style.
+ * (For potential use in font-selector which doesn't update until
+ * "Apply" button clicked.)
+ */
+ std::pair<Glib::ustring, Glib::ustring>
+ new_font_family (Glib::ustring family, gboolean check_style = true);
+
+ /** Sets font-family, updating style list and attempting
+ * to find closest style to old current_style.
+ * New font-family and style returned.
+ * Updates current_family and current_style.
+ * Calls new_font_family().
+ * (For use in text-toolbar where update is immediate.)
+ */
+ std::pair<Glib::ustring, Glib::ustring>
+ set_font_family (Glib::ustring family, gboolean check_style = true);
+
+ /** Sets font-family from row in list store.
+ * The row can be used to determine if we are in the
+ * document or system part of the font-family list.
+ * This is needed to handle scrolling through the
+ * font-family list correctly.
+ * Calls set_font_family().
+ */
+ std::pair<Glib::ustring, Glib::ustring>
+ set_font_family (int row, gboolean check_style = true);
+
+ Glib::ustring
+ get_font_family ()
+ {
+ return current_family;
+ }
+
+ int
+ get_font_family_row ()
+ {
+ return current_family_row;
+ }
+
+ /* Not Used */
+ void
+ new_font_style (Glib::ustring style);
+
+ /** Sets style. Does not validate style for family.
+ */
+ void
+ set_font_style (Glib::ustring style);
+
+ Glib::ustring
+ get_font_style ()
+ {
+ return current_style;
+ }
+
+ /** Sets both family and style. Does not attempt to find
+ * best match for style (assume that style is already valid
+ * for family).
+ */
+ void
+ set_font (Glib::ustring family, Glib::ustring style);
+
+ /** Sets both family and style. Does not attempt to find
+ * best match for style (assume that style is already valid
+ * for family).
+ */
+ void
+ new_font (Glib::ustring family, Glib::ustring style);
+
+ std::pair<Glib::ustring, Glib::ustring>
+ get_try_font () {
+ return ( std::make_pair( try_family, try_style ) );
+ }
+
+ Glib::ustring
+ fontspec_from_style (SPStyle* style);
+
+ /** Fill css using current_fontspec.
+ */
+ void
+ set_css( SPCSSAttr *css );
+
+ Gtk::TreeModel::Row
get_row_for_font (Glib::ustring family);
+ Gtk::TreePath
+ get_path_for_font (Glib::ustring family);
+
+ Gtk::TreeModel::Row
+ get_row_for_style (Glib::ustring style);
+
+ Gtk::TreePath
+ get_path_for_style (Glib::ustring style);
+
+ std::pair<Gtk::TreePath, Gtk::TreePath>
+ get_paths (Glib::ustring family, Glib::ustring style);
+
+ /** Return best style match for new font given style for old font.
+ */
+ Glib::ustring
+ get_best_style_match (Glib::ustring family, Glib::ustring style);
+
+ /* Not Used */
const NRNameList
get_name_list () const
{
@@ -116,7 +291,31 @@ namespace Inkscape
NRNameList families;
Glib::RefPtr<Gtk::ListStore> font_list_store;
+ Glib::RefPtr<Gtk::ListStore> style_list_store;
+ Glib::RefPtr<Gtk::ListStore> style_list_store_trial;
+ /** Info for currently selected font (what is shown in the UI).
+ * May include font-family lists and fonts not on system.
+ */
+ int current_family_row;
+ Glib::ustring current_family;
+ Glib::ustring current_style;
+ Glib::ustring current_fontspec;
+
+ /** fontspec of system font closest to current_fontspec.
+ * (What the system will use to display current_fontspec.)
+ */
+ Glib::ustring current_fontspec_system;
+
+ /** Info for proposed font (what is shown in the font-selection UI).
+ * May include font-family lists and fonts not on system.
+ */
+ Glib::ustring try_family;
+ Glib::ustring try_style;
+
+ /** If a font-family is not on system, this list of styles is used.
+ */
+ GList *default_styles;
};
}
@@ -125,7 +324,7 @@ namespace Inkscape
static gboolean font_lister_separator_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer /*data*/)
{
gchar* text = 0;
- gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0: FontList.font
+ gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0: FontList.family
return (text && strcmp(text,"#") == 0);
}
diff --git a/src/livarot/PathCutting.cpp b/src/livarot/PathCutting.cpp
index 9e6226ccc..848d8daa8 100644
--- a/src/livarot/PathCutting.cpp
+++ b/src/livarot/PathCutting.cpp
@@ -1126,6 +1126,8 @@ void Path::ConvertPositionsToForced(int nbPos, cut_position *poss)
}
}
}
+ if (descr_cmd[0]->getType() == descr_moveto)
+ descr_flags |= descr_doing_subpath; // see LP Bug 166302
qsort(poss, nbPos, sizeof(cut_position), CmpPosition);
diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp
index d046ad683..ed4791155 100644
--- a/src/live_effects/lpe-bspline.cpp
+++ b/src/live_effects/lpe-bspline.cpp
@@ -52,12 +52,6 @@ LPEBSpline::doEffect(SPCurve * curve)
//los puntos clave para los manejadores.
//Esto hace que la curva BSpline no pierda su condición aunque se trasladen
//dichos manejadores
- SPCurve * in = new SPCurve();
- in->moveto(curve_it1->initialPoint());
- in->lineto(curve_it1->finalPoint());
- SPCurve * out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
SPCurve *nCurve = new SPCurve();
Geom::Point startNode(0,0);
Geom::Point previousNode(0,0);
@@ -67,6 +61,9 @@ LPEBSpline::doEffect(SPCurve * curve)
Geom::Point nextPointAt1(0,0);
Geom::Point nextPointAt2(0,0);
Geom::Point nextPointAt3(0,0);
+ Geom::D2< Geom::SBasis > SBasisIn;
+ Geom::D2< Geom::SBasis > SBasisOut;
+ Geom::D2< Geom::SBasis > SBasisHelper;
Geom::CubicBezier const *cubic = NULL;
//Si la curva está cerrada calculamos el punto donde
//deveria estar el nodo BSpline de cierre/inicio de la curva
@@ -78,13 +75,12 @@ LPEBSpline::doEffect(SPCurve * curve)
if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
curve_endit = path_it->end_open();
}
- SPCurve * end = new SPCurve();
- end->moveto(curve_endit->initialPoint());
- end->lineto(curve_endit->finalPoint());
- Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis();
- Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis();
- end->reset();
- delete end;
+
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
+ SBasisIn = in->first_segment()->toSBasis();
+
SPCurve *lineHelper = new SPCurve();
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
if(cubic){
@@ -92,13 +88,23 @@ LPEBSpline::doEffect(SPCurve * curve)
}else{
lineHelper->moveto(in->first_segment()->initialPoint());
}
+ in->reset();
+ delete in;
+
+ SPCurve * end = new SPCurve();
+ end->moveto(curve_endit->initialPoint());
+ end->lineto(curve_endit->finalPoint());
+ Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis();
+ //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit);
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit);
if(cubic){
lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment())));
}else{
lineHelper->lineto(end->first_segment()->finalPoint());
}
- Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis();
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
lineHelper->reset();
delete lineHelper;
//Guardamos el principio de la curva
@@ -107,7 +113,12 @@ LPEBSpline::doEffect(SPCurve * curve)
node = startNode;
}else{
//Guardamos el principio de la curva
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
startNode = in->first_segment()->initialPoint();
+ in->reset();
+ delete in;
//Definimos el punto de inicio original de la curva resultante
node = startNode;
}
@@ -116,20 +127,28 @@ LPEBSpline::doEffect(SPCurve * curve)
{
//previousPointAt3 = pointAt3;
//Calculamos los puntos que dividirían en tres segmentos iguales el path recto de entrada y de salida
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
if(cubic){
- Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis();
+ SBasisIn = in->first_segment()->toSBasis();
pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()));
pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2],*in->first_segment()));
}else{
pointAt1 = in->first_segment()->initialPoint();
pointAt2 = in->first_segment()->finalPoint();
}
+ in->reset();
+ delete in;
//Y hacemos lo propio con el path de salida
//nextPointAt0 = curveOut.valueAt(0);
+ SPCurve * out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it2);
if(cubic){
- Geom::D2< Geom::SBasis > SBasisOut = out->first_segment()->toSBasis();
+ SBasisOut = out->first_segment()->toSBasis();
nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1],*out->first_segment()));
nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2],*out->first_segment()));;
nextPointAt3 = (*cubic)[3];
@@ -138,6 +157,8 @@ LPEBSpline::doEffect(SPCurve * curve)
nextPointAt2 = out->first_segment()->finalPoint();
nextPointAt3 = out->first_segment()->finalPoint();
}
+ out->reset();
+ delete out;
//La curva BSpline se forma calculando el centro del segmanto de unión
//de el punto situado en las 2/3 partes de el segmento de entrada
//con el punto situado en la posición 1/3 del segmento de salida
@@ -146,7 +167,7 @@ LPEBSpline::doEffect(SPCurve * curve)
SPCurve *lineHelper = new SPCurve();
lineHelper->moveto(pointAt2);
lineHelper->lineto(nextPointAt1);
- Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis();
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
lineHelper->reset();
delete lineHelper;
//almacenamos el punto del anterior bucle -o el de cierre- que nos hara de principio de curva
@@ -163,18 +184,6 @@ LPEBSpline::doEffect(SPCurve * curve)
//aumentamos los valores para el siguiente paso en el bucle
++curve_it1;
++curve_it2;
- in->reset();
- delete in;
- SPCurve * in = new SPCurve();
- in->moveto(curve_it1->initialPoint());
- in->lineto(curve_it1->finalPoint());
- out->reset();
- delete out;
- if(curve_it1 != curve_endit){
- SPCurve * out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
- }
}
//Aberiguamos la ultima parte de la curva correspondiente al último segmento
SPCurve *curveHelper = new SPCurve();
@@ -197,11 +206,6 @@ LPEBSpline::doEffect(SPCurve * curve)
curve->append(nCurve,false);
nCurve->reset();
delete nCurve;
- //Limpiamos
- in->reset();
- out->reset();
- delete in;
- delete out;
}
}
diff --git a/src/pen-context.cpp b/src/pen-context.cpp
index a505f8de7..0af9570c1 100644
--- a/src/pen-context.cpp
+++ b/src/pen-context.cpp
@@ -96,10 +96,15 @@ static void sp_pen_context_set_mode(SPPenContext *const pc, guint mode);
//Esta función cambia los colores rojo,verde y azul haciendolos transparentes o no en función de si se usa spiro
static void spiro_color(SPPenContext *const pc);
//Guarda el valor si se ha pulsado la tecla SHIFT al continuar una curva
-static bool saShift = false;
-
-//Preparamos la curva roja para que se muestre según esté pulsada la tecla SHIFT
-static void spiro(SPPenContext *const pc, bool Shift);
+static void spiro(SPPenContext *const pc,bool shift);
+static void spiroOn(SPPenContext *const pc);
+static void spiroOff(SPPenContext *const pc);
+static void spiroStartAnchor(SPPenContext *const pc,bool shift);
+static void spiroStartAnchorOn(SPPenContext *const pc);
+static void spiroStartAnchorOff(SPPenContext *const pc);
+static void spiroMotion(SPPenContext *const pc,bool shift);
+static void spiroEndAnchorOn(SPPenContext *const pc);
+static void spiroEndAnchorOff(SPPenContext *const pc);
//Unimos todas las curvas en juego y llamamos a la función doEffect.
static void spiro_build(SPPenContext *const pc);
//function spiro cloned from lpe-spiro.cpp
@@ -541,7 +546,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
//BSpline
if(anchor){
if(pc->spiro){
- spiro(pc,(bevent.state & GDK_SHIFT_MASK));
+ spiroStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK));
}
if(pc->bspline){
bsplineStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK));
@@ -794,7 +799,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons
//BSpline
if ( Geom::LInfty( event_w - pen_drag_origin_w ) > tolerance || mevent.time == 0) {
if(pc->spiro){
- spiro(pc,(mevent.state & GDK_SHIFT_MASK));
+ spiroMotion(pc,(mevent.state & GDK_SHIFT_MASK));
}
if(pc->bspline){
bsplineMotion(pc,(mevent.state & GDK_SHIFT_MASK));
@@ -848,7 +853,7 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con
//BSpline
if (anchor) {
if(pc->spiro){
- spiro(pc,(revent.state & GDK_SHIFT_MASK));
+ spiroStartAnchor(pc,(revent.state & GDK_SHIFT_MASK));
}
if(pc->bspline){
bsplineStartAnchor(pc,(revent.state & GDK_SHIFT_MASK));
@@ -1546,84 +1551,259 @@ static void spiro_color(SPPenContext *const pc)
}
-//Preparamos la curva roja para que se muestre según esté pulsada la tecla SHIFT
-static void spiro(SPPenContext *const pc, bool Shift)
+//Unimos todas las curvas en juego y llamamos a la función doEffect.
+
+static void spiro(SPPenContext *const pc, bool shift)
{
- if(Shift){
- if(!pc->red_curve->is_empty()){
- //Creamos un nodo CUSP
- pc->npoints = 5;
- pc->p[2] = pc->p[3];
- }
- //Continuamos la curva en modo CUSP
- //Guardamos el valor de inicio en cusp para que no se redibuje como SYMM
- if(pc->anchor_statusbar && pc->red_curve->is_empty()){
- saShift = true;
- }
- }else{
- //Symm nodo
+ if(!pc->anchor_statusbar)
+ shift?spiroOff(pc):spiroOn(pc);
+
+ spiro_build(pc);
+}
+
+static void spiroOn(SPPenContext *const pc){
+ if(!pc->red_curve->is_empty()){
using Geom::X;
using Geom::Y;
- Geom::CubicBezier const * cubic;
- if(pc->anchor_statusbar && pc->red_curve->is_empty()){
- saShift = false;
- }
- if(!pc->red_curve->is_empty()){
- //Damos valores a los puntos de la curva roja para que generen un nodo SYMM
- pc->npoints = 5;
- //Les damos valor
- pc->p[3] = pc->red_curve->first_segment()->finalPoint();
- pc->p[0] = pc->red_curve->first_segment()->initialPoint();
- pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]);
- pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]);
- pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1);
- pc->p[2] = Geom::Point(pc->p[2][X]+1,pc->p[2][Y]+1);
- pc->p[4] = pc->p[3] + (Geom::Point)( pc->p[3] - pc->p[2] );
+ pc->npoints = 5;
+ pc->p[0] = pc->red_curve->first_segment()->initialPoint();
+ pc->p[3] = pc->red_curve->first_segment()->finalPoint();
+ pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]);
+ pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625);
+ }
+}
+
+static void spiroOff(SPPenContext *const pc)
+{
+ if(!pc->red_curve->is_empty()){
+ pc->npoints = 5;
+ pc->p[0] = pc->red_curve->first_segment()->initialPoint();
+ pc->p[3] = pc->red_curve->first_segment()->finalPoint();
+ pc->p[2] = pc->p[3];
+ }
+}
+
+static void spiroStartAnchor(SPPenContext *const pc, bool shift)
+{
+ if(pc->sa->curve->is_empty())
+ return;
+
+ if(shift)
+ bsplineStartAnchorOff(pc);
+ else
+ bsplineStartAnchorOn(pc);
+}
+
+static void spiroStartAnchorOn(SPPenContext *const pc)
+{
+ using Geom::X;
+ using Geom::Y;
+ SPCurve *tmpCurve = new SPCurve();
+ tmpCurve = pc->sa->curve->copy();
+ if(pc->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ SPCurve *lastSeg = new SPCurve();
+ Geom::Point A = tmpCurve->last_segment()->initialPoint();
+ Geom::Point D = tmpCurve->last_segment()->finalPoint();
+ Geom::Point C = D + (1./3)*(A - D);
+ C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625);
+ if(cubic){
+ lastSeg->moveto(A);
+ lastSeg->curveto((*cubic)[1],C,D);
+ }else{
+ lastSeg->moveto(A);
+ lastSeg->curveto(A,C,D);
+ }
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (pc->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ pc->sa->curve->reset();
+ pc->sa->curve = tmpCurve;
+}
+
+static void spiroStartAnchorOff(SPPenContext *const pc)
+{
+ SPCurve *tmpCurve = new SPCurve();
+ tmpCurve = pc->sa->curve->copy();
+ if(pc->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ SPCurve *lastSeg = new SPCurve();
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (pc->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
}
+ pc->sa->curve->reset();
+ pc->sa->curve = tmpCurve;
+ }
- //Continuamos la curva en modo SPIRO
- if( saShift == false && pc->sa && !pc->sa->curve->is_empty() && !pc->ea && pc->green_curve->is_empty()){
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->sa->curve->last_segment());
- if (pc->sa->start) {
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->sa->curve->create_reverse()->last_segment() );
- }
- if(cubic){
- pc->p[1] = (pc->p[0] - (*cubic)[2]) + pc->p[0];
- }
+}
+
+static void spiroMotion(SPPenContext *const pc, bool shift){
+ using Geom::X;
+ using Geom::Y;
+ SPCurve *tmpCurve = new SPCurve();
+ if(shift)
+ pc->p[2] = pc->p[3];
+ else
+ pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]);
+ pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625);
+
+ if(pc->green_curve->is_empty() && !pc->sa){
+ pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]);
+ }else if(!pc->green_curve->is_empty()){
+ tmpCurve = pc->green_curve->copy();
+ }else{
+ tmpCurve = pc->sa->curve->copy();
+ if(pc->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ if(!tmpCurve->is_empty() && !pc->red_curve->is_empty()){
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ pc->p[1] = (*cubic)[3] + (Geom::Point)((*cubic)[3] - (*cubic)[2] );
+ }else{
+ pc->p[1] = pc->p[0];
}
+ }
- //Nos aseguramos que el primer nodo sea SYMM con el ultimo segmento de la curva verde
- if(!pc->green_curve->is_empty()){
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->green_curve->last_segment());
- if(cubic && (*cubic)[2] != (*cubic)[3]){
- pc->p[1] = (pc->p[0] - (*cubic)[2]) + pc->p[0];
- }
- //Damos valor original a la variable por si se necesita de nuevo
- saShift = false;
+ if(pc->anchor_statusbar && !pc->red_curve->is_empty()){
+ if(shift)
+ bsplineEndAnchorOff(pc);
+ else
+ bsplineEndAnchorOn(pc);
+ }
+
+ spiro_build(pc);
+}
+
+static void spiroEndAnchorOn(SPPenContext *const pc)
+{
+ using Geom::X;
+ using Geom::Y;
+ pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]);
+ pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625);
+ SPCurve *tmpCurve = new SPCurve();
+ SPCurve *lastSeg = new SPCurve();
+ Geom::Point C(0,0);
+ if(!pc->sa || pc->sa->curve->is_empty()){
+ tmpCurve = pc->green_curve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ C = tmpCurve->last_segment()->finalPoint() + + (Geom::Point)(tmpCurve->last_segment()->finalPoint() - pc->p[2]);
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],C,(*cubic)[3]);
+ }else{
+ lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
+ lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint());
}
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ tmpCurve = tmpCurve->create_reverse();
+ pc->green_curve->reset();
+ pc->green_curve = tmpCurve;
+ }else{
+ tmpCurve = pc->sa->curve->copy();
+ if(!pc->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ C = tmpCurve->last_segment()->finalPoint() + + (Geom::Point)(tmpCurve->last_segment()->finalPoint() - pc->p[2]);
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],C,(*cubic)[3]);
+ }else{
+ lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
+ lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint());
+ }
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (!pc->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
+ }
+ pc->sa->curve->reset();
+ pc->sa->curve = tmpCurve;
+ }
+}
- //Si cerramos sobre otra curva ponemos simetrico a esta el manejador del punto de cierre
- if(pc->anchor_statusbar && pc->sa && !Geom::are_near(pc->sa->dp, pc->red_curve->first_segment()->finalPoint())){
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->sa->curve->last_segment() );
- if (!pc->sa->start) {
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->sa->curve->create_reverse()->last_segment() );
- }
- if(cubic){
- pc->p[2] = (pc->p[3]-(*cubic)[2]) + pc->p[3];
+static void spiroEndAnchorOff(SPPenContext *const pc)
+{
+ pc->p[2] = pc->p[3];
+ SPCurve *tmpCurve = new SPCurve();
+ SPCurve *lastSeg = new SPCurve();
+ if(!pc->sa || pc->sa->curve->is_empty()){
+ tmpCurve = pc->green_curve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
}
+ tmpCurve = tmpCurve->create_reverse();
+ pc->green_curve->reset();
+ pc->green_curve = tmpCurve;
}
- //Lo mismpo pero cerrando sobre la curva inicial
- if(pc->anchor_statusbar && pc->green_anchor && pc->green_anchor->active){
- cubic = dynamic_cast<Geom::CubicBezier const *>( pc->green_curve->first_segment() );
- if(cubic){
- pc->p[2] = (pc->p[3]-(*cubic)[1]) + pc->p[3];
+ }else{
+ tmpCurve = pc->sa->curve->copy();
+ if(!pc->sa->start)
+ tmpCurve = tmpCurve->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(cubic){
+ lastSeg->moveto((*cubic)[0]);
+ lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( tmpCurve->get_segment_count() == 1){
+ tmpCurve = lastSeg;
+ }else{
+ //we eliminate the last segment
+ tmpCurve->backspace();
+ //and we add it again with the recreation
+ tmpCurve->append_continuous(lastSeg, 0.0625);
+ }
+ if (!pc->sa->start) {
+ tmpCurve = tmpCurve->create_reverse();
}
+ pc->sa->curve->reset();
+ pc->sa->curve = tmpCurve;
}
}
- spiro_build(pc);
}
-
//Unimos todas las curvas en juego y llamamos a la función doEffect.
static void spiro_build(SPPenContext *const pc)
{
@@ -2054,143 +2234,6 @@ static void bsplineEndAnchorOff(SPPenContext *const pc)
}
}
-/*
-//Unimos todas las curvas en juego y llamamos a la función doEffect.
-static void bspline(SPPenContext *const pc, bool Shift)
-{
- using Geom::X;
- using Geom::Y;
- Geom::CubicBezier const *cubic;
- if(Shift){
-
- //Continuamos la curva en modo CUSP
- //Guardamos el valor de inicio en cusp para que no se redibuje como SYMM
- if(pc->anchor_statusbar && pc->red_curve->is_empty()){
- SPCurve *previousCurve = new SPCurve();
- if(pc->sa && !pc->sa->curve->is_empty()){
- previousCurve = pc->sa->curve->copy();
- if (pc->sa->start) {
- previousCurve = previousCurve->create_reverse();
- }
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*previousCurve->last_segment());
- if(cubic){
- SPCurve *lastSeg = new SPCurve();
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- previousCurve->backspace();
- previousCurve->append_continuous(lastSeg, 0.0625);
- if (pc->sa->start) {
- previousCurve = previousCurve->create_reverse();
- }
- pc->sa->curve->reset();
- pc->sa->curve = previousCurve;
- }
- }
- }
-
- if(pc->anchor_statusbar && !pc->red_curve->is_empty()){
- // Step B - both start and end anchored to same curve
- if ( pc->sa && pc->ea
- && ( pc->sa->curve == pc->ea->curve )
- && ( ( pc->sa != pc->ea )
- || pc->sa->curve->is_closed() ) )
- {
- SPCurve * same = pc->sa->curve->copy();
- if (pc->sa->start) {
- same = same->create_reverse();
- }
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*same->last_segment());
- if(cubic){
- SPCurve *lastSeg = new SPCurve();
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- same->backspace();
- same->append_continuous(lastSeg, 0.0625);
- if (pc->sa->start) {
- same = same->create_reverse();
- }
- pc->sa->curve->reset();
- pc->sa->curve = same;
- }
- }
- // Step A - test, whether we ended on green anchor
- if ( pc->green_anchor && pc->green_anchor->active ) {
- // We hit green anchor, closing Green-Blue-Red
- SPCurve * green = pc->green_curve->copy()->create_reverse();
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*green->last_segment());
- if(cubic){
- SPCurve *lastSeg = new SPCurve();
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- green->backspace();
- green->append_continuous(lastSeg, 0.0625);
- green = green->create_reverse();
- pc->green_curve->reset();
- pc->green_curve = green;
- }
- }
- }
-
- if (!pc->red_curve->is_empty()){
- pc->npoints = 5;
- pc->p[0] = pc->red_curve->first_segment()->initialPoint();
- pc->p[3] = pc->red_curve->first_segment()->finalPoint();
- if(pc->green_curve->is_empty()){
- pc->p[1] = pc->p[0];
- }else{
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*pc->green_curve->last_segment());
- if(!cubic || ((*cubic)[2] == (*cubic)[3])){
- pc->p[1] = pc->p[0];
- pc->p[2] = pc->p[3];
- }else{
- pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]);
- pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1);
- pc->p[2] = pc->p[3];
- }
-
- }
- }
- }else{
- //NODO CUSP formado por nodo SMOOTH
- //solo mobemos el manejador del nodo final de cada segmento
- //Es suficiente para mostrar el nodo como CUSP
- //Usamos 5 puntos
- if(!pc->red_curve->is_empty()){
- pc->npoints = 5;
- pc->p[0] = pc->red_curve->first_segment()->initialPoint();
- pc->p[3] = pc->red_curve->first_segment()->finalPoint();
- if(pc->green_curve->is_empty()){
- if(!pc->sa || (pc->sa && pc->p[0] != pc->p[1])){
- pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]);
- pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1);
- }
- }else{
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*pc->green_curve->last_segment());
- if(!cubic || ((*cubic)[2] == (*cubic)[3]))
- pc->p[1] = pc->p[0];
- else{
- SPCurve * WPower = new SPCurve();
- Geom::D2< Geom::SBasis > SBasisWPower;
- WPower->moveto(pc->green_curve->last_segment()->finalPoint());
- WPower->lineto(pc->green_curve->last_segment()->initialPoint());
- float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment());
- WPower->reset();
- WPower->moveto(pc->red_curve->last_segment()->initialPoint());
- WPower->lineto(pc->red_curve->last_segment()->finalPoint());
- SBasisWPower = WPower->first_segment()->toSBasis();
- WPower->reset();
- pc->p[1] = SBasisWPower.valueAt(WP);
- pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1);
- }
- }
- pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]);
- pc->p[2] = Geom::Point(pc->p[2][X]+1,pc->p[2][Y]+1);
- }
- }
- bspline_build(pc);
-}
-
-/*/
//preparates the curves for its trasformation into BSline curves.
static void bspline_build(SPPenContext *const pc)
@@ -2267,12 +2310,6 @@ static void bspline_doEffect(SPCurve * curve)
//los puntos clave para los manejadores.
//Esto hace que la curva BSpline no pierda su condición aunque se trasladen
//dichos manejadores
- SPCurve * in = new SPCurve();
- in->moveto(curve_it1->initialPoint());
- in->lineto(curve_it1->finalPoint());
- SPCurve * out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
SPCurve *nCurve = new SPCurve();
Geom::Point startNode(0,0);
Geom::Point previousNode(0,0);
@@ -2282,6 +2319,9 @@ static void bspline_doEffect(SPCurve * curve)
Geom::Point nextPointAt1(0,0);
Geom::Point nextPointAt2(0,0);
Geom::Point nextPointAt3(0,0);
+ Geom::D2< Geom::SBasis > SBasisIn;
+ Geom::D2< Geom::SBasis > SBasisOut;
+ Geom::D2< Geom::SBasis > SBasisHelper;
Geom::CubicBezier const *cubic = NULL;
//Si la curva está cerrada calculamos el punto donde
//deveria estar el nodo BSpline de cierre/inicio de la curva
@@ -2293,13 +2333,12 @@ static void bspline_doEffect(SPCurve * curve)
if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
curve_endit = path_it->end_open();
}
- SPCurve * end = new SPCurve();
- end->moveto(curve_endit->initialPoint());
- end->lineto(curve_endit->finalPoint());
- Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis();
- Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis();
- end->reset();
- delete end;
+
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
+ SBasisIn = in->first_segment()->toSBasis();
+
SPCurve *lineHelper = new SPCurve();
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
if(cubic){
@@ -2307,13 +2346,23 @@ static void bspline_doEffect(SPCurve * curve)
}else{
lineHelper->moveto(in->first_segment()->initialPoint());
}
+ in->reset();
+ delete in;
+
+ SPCurve * end = new SPCurve();
+ end->moveto(curve_endit->initialPoint());
+ end->lineto(curve_endit->finalPoint());
+ Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis();
+ //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit);
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit);
if(cubic){
lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment())));
}else{
lineHelper->lineto(end->first_segment()->finalPoint());
}
- Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis();
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
lineHelper->reset();
delete lineHelper;
//Guardamos el principio de la curva
@@ -2322,7 +2371,12 @@ static void bspline_doEffect(SPCurve * curve)
node = startNode;
}else{
//Guardamos el principio de la curva
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
startNode = in->first_segment()->initialPoint();
+ in->reset();
+ delete in;
//Definimos el punto de inicio original de la curva resultante
node = startNode;
}
@@ -2331,20 +2385,28 @@ static void bspline_doEffect(SPCurve * curve)
{
//previousPointAt3 = pointAt3;
//Calculamos los puntos que dividirían en tres segmentos iguales el path recto de entrada y de salida
+ SPCurve * in = new SPCurve();
+ in->moveto(curve_it1->initialPoint());
+ in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
if(cubic){
- Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis();
+ SBasisIn = in->first_segment()->toSBasis();
pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()));
pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2],*in->first_segment()));
}else{
pointAt1 = in->first_segment()->initialPoint();
pointAt2 = in->first_segment()->finalPoint();
}
+ in->reset();
+ delete in;
//Y hacemos lo propio con el path de salida
//nextPointAt0 = curveOut.valueAt(0);
+ SPCurve * out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it2);
if(cubic){
- Geom::D2< Geom::SBasis > SBasisOut = out->first_segment()->toSBasis();
+ SBasisOut = out->first_segment()->toSBasis();
nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1],*out->first_segment()));
nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2],*out->first_segment()));;
nextPointAt3 = (*cubic)[3];
@@ -2353,6 +2415,8 @@ static void bspline_doEffect(SPCurve * curve)
nextPointAt2 = out->first_segment()->finalPoint();
nextPointAt3 = out->first_segment()->finalPoint();
}
+ out->reset();
+ delete out;
//La curva BSpline se forma calculando el centro del segmanto de unión
//de el punto situado en las 2/3 partes de el segmento de entrada
//con el punto situado en la posición 1/3 del segmento de salida
@@ -2361,7 +2425,7 @@ static void bspline_doEffect(SPCurve * curve)
SPCurve *lineHelper = new SPCurve();
lineHelper->moveto(pointAt2);
lineHelper->lineto(nextPointAt1);
- Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis();
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
lineHelper->reset();
delete lineHelper;
//almacenamos el punto del anterior bucle -o el de cierre- que nos hara de principio de curva
@@ -2378,18 +2442,6 @@ static void bspline_doEffect(SPCurve * curve)
//aumentamos los valores para el siguiente paso en el bucle
++curve_it1;
++curve_it2;
- in->reset();
- delete in;
- SPCurve * in = new SPCurve();
- in->moveto(curve_it1->initialPoint());
- in->lineto(curve_it1->finalPoint());
- out->reset();
- delete out;
- if(curve_it1 != curve_endit){
- SPCurve * out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
- }
}
//Aberiguamos la ultima parte de la curva correspondiente al último segmento
SPCurve *curveHelper = new SPCurve();
@@ -2412,11 +2464,6 @@ static void bspline_doEffect(SPCurve * curve)
curve->append(nCurve,false);
nCurve->reset();
delete nCurve;
- //Limpiamos
- in->reset();
- out->reset();
- delete in;
- delete out;
}
}
//BSpline end
diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp
index 5af75a9a5..755269edb 100644
--- a/src/shortcuts.cpp
+++ b/src/shortcuts.cpp
@@ -52,10 +52,12 @@ using Inkscape::IO::Resource::SYSTEM;
using Inkscape::IO::Resource::USER;
using Inkscape::IO::Resource::KEYS;
-
static void try_shortcuts_file(char const *filename);
static void read_shortcuts_file(char const *filename, bool const is_user_set=false);
+unsigned int sp_shortcut_get_key(unsigned int const shortcut);
+GdkModifierType sp_shortcut_get_modifiers(unsigned int const shortcut);
+
/* Returns true if action was performed */
bool
@@ -430,7 +432,7 @@ void sp_shortcut_delete_from_file(char const * /*action*/, unsigned int const sh
return;
}
- gchar *key = gdk_keyval_name (shortcut & (~SP_SHORTCUT_MODIFIER_MASK));
+ gchar *key = gdk_keyval_name (sp_shortcut_get_key(shortcut));
std::string modifiers = sp_shortcut_to_label(shortcut & (SP_SHORTCUT_MODIFIER_MASK));
if (!key) {
@@ -502,7 +504,7 @@ void sp_shortcut_add_to_file(char const *action, unsigned int const shortcut) {
}
}
- gchar *key = gdk_keyval_name (shortcut & (~SP_SHORTCUT_MODIFIER_MASK));
+ gchar *key = gdk_keyval_name (sp_shortcut_get_key(shortcut));
std::string modifiers = sp_shortcut_to_label(shortcut & (SP_SHORTCUT_MODIFIER_MASK));
if (!key) {
@@ -639,6 +641,58 @@ sp_shortcut_unset(unsigned int const shortcut)
}
}
+
+GtkAccelGroup *
+sp_shortcut_get_accel_group()
+{
+ static GtkAccelGroup *accel_group = NULL;
+
+ if (!accel_group) {
+ accel_group = gtk_accel_group_new ();
+ }
+
+ return accel_group;
+}
+
+/**
+ * Adds a gtk accelerator to a widget
+ * Used to display the keyboard shortcuts in the main menu items
+ */
+void
+sp_shortcut_add_accelerator(GtkWidget *item, unsigned int const shortcut)
+{
+ if (shortcut == GDK_KEY_VoidSymbol) {
+ return;
+ }
+
+ unsigned int accel_key = sp_shortcut_get_key(shortcut);
+ if (accel_key > 0) {
+ gtk_widget_add_accelerator (item,
+ "activate",
+ sp_shortcut_get_accel_group(),
+ accel_key,
+ sp_shortcut_get_modifiers(shortcut),
+ GTK_ACCEL_VISIBLE);
+ }
+}
+
+
+unsigned int
+sp_shortcut_get_key(unsigned int const shortcut)
+{
+ return (shortcut & (~SP_SHORTCUT_MODIFIER_MASK));
+}
+
+GdkModifierType
+sp_shortcut_get_modifiers(unsigned int const shortcut)
+{
+ return static_cast<GdkModifierType>(
+ ((shortcut & SP_SHORTCUT_SHIFT_MASK) ? GDK_SHIFT_MASK : 0) |
+ ((shortcut & SP_SHORTCUT_CONTROL_MASK) ? GDK_CONTROL_MASK : 0) |
+ ((shortcut & SP_SHORTCUT_ALT_MASK) ? GDK_MOD1_MASK : 0)
+ );
+}
+
/**
* Adds a keyboard shortcut for the given verb.
* (Removes any existing binding for the given shortcut, including appropriately
@@ -706,7 +760,6 @@ bool sp_shortcut_is_user_set(Inkscape::Verb *verb)
return result;
}
-
gchar *sp_shortcut_get_label(unsigned int shortcut)
{
// The comment below was copied from the function sp_ui_shortcut_string in interface.cpp (which was subsequently removed)
@@ -721,11 +774,8 @@ gchar *sp_shortcut_get_label(unsigned int shortcut)
gchar *result = 0;
if (shortcut != GDK_KEY_VoidSymbol) {
result = gtk_accelerator_get_label(
- shortcut & (~SP_SHORTCUT_MODIFIER_MASK), static_cast<GdkModifierType>(
- ((shortcut & SP_SHORTCUT_SHIFT_MASK) ? GDK_SHIFT_MASK : 0) |
- ((shortcut & SP_SHORTCUT_CONTROL_MASK) ? GDK_CONTROL_MASK : 0) |
- ((shortcut & SP_SHORTCUT_ALT_MASK) ? GDK_MOD1_MASK : 0)
- ));
+ sp_shortcut_get_key(shortcut),
+ sp_shortcut_get_modifiers(shortcut));
}
return result;
}
diff --git a/src/shortcuts.h b/src/shortcuts.h
index 118909bd3..c2a6f6cde 100644
--- a/src/shortcuts.h
+++ b/src/shortcuts.h
@@ -28,13 +28,14 @@ namespace Inkscape {
#define SP_SHORTCUT_ALT_MASK (1 << 26)
#define SP_SHORTCUT_MODIFIER_MASK (SP_SHORTCUT_SHIFT_MASK|SP_SHORTCUT_CONTROL_MASK|SP_SHORTCUT_ALT_MASK)
+
/* Returns true if action was performed */
bool sp_shortcut_invoke (unsigned int shortcut, Inkscape::UI::View::View *view);
void sp_shortcut_init();
Inkscape::Verb * sp_shortcut_get_verb (unsigned int shortcut);
unsigned int sp_shortcut_get_primary (Inkscape::Verb * verb); // Returns GDK_VoidSymbol if no shortcut is found.
-char* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free.
+gchar* sp_shortcut_get_label (unsigned int shortcut); // Returns the human readable form of the shortcut (or NULL), for example Shift+Ctrl+F. Free the returned string with g_free.
void sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary, bool const is_user_set=false);
void sp_shortcut_unset(unsigned int const shortcut);
void sp_shortcut_add_to_file(char const *action, unsigned int const shortcut);
@@ -48,6 +49,8 @@ void sp_shortcut_file_export();
bool sp_shortcut_file_import();
void sp_shortcut_file_import_do(char const *importname);
void sp_shortcut_file_export_do(char const *exportname);
+GtkAccelGroup *sp_shortcut_get_accel_group();
+void sp_shortcut_add_accelerator(GtkWidget *item, unsigned int const shortcut);
#endif
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 7cbd92eeb..8ce9a012b 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -307,7 +307,10 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
originaux[1]->ConvertWithBackData(1.0);
- originaux[1]->Fill(theShape, 1,false,false,false); //do not closeIfNeeded
+ if ((originaux[1]->pts.size() == 2) && originaux[1]->pts[0].isMoveTo && !originaux[1]->pts[1].isMoveTo)
+ originaux[1]->Fill(theShape, 1,false,true,false); // see LP Bug 177956
+ else
+ originaux[1]->Fill(theShape, 1,false,false,false); //do not closeIfNeeded
theShapeB->ConvertToShape(theShape, fill_justDont); // fill_justDont doesn't computes winding numbers
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 8fd8eb4e3..f3c3b8473 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -84,6 +84,7 @@ set(ui_SRC
widget/entry.cpp
widget/filter-effect-chooser.cpp
widget/frame.cpp
+ widget/gimpcolorwheel.c
widget/gimpspinscale.c
widget/imageicon.cpp
widget/imagetoggler.cpp
@@ -212,6 +213,7 @@ set(ui_SRC
widget/filter-effect-chooser.h
widget/frame.h
widget/gimpspinscale.h
+ widget/gimpcolorwheel.h
widget/imageicon.h
widget/imagetoggler.h
widget/labelled.h
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 50f30e8f4..7dc94c92f 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -1201,7 +1201,6 @@ void FilterEffectsDialog::FilterModifier::on_change_selection()
{
Inkscape::Selection *selection = sp_desktop_selection (SP_ACTIVE_DESKTOP);
update_selection(selection);
- update_filters();
}
void FilterEffectsDialog::FilterModifier::on_modified_selection( guint flags )
@@ -2668,7 +2667,7 @@ void FilterEffectsDialog::update_primitive_infobox()
break;
case(NR_FILTER_SPECULARLIGHTING):
_infobox_icon.set_from_icon_name("feSpecularLighting-icon", Gtk::ICON_SIZE_DIALOG);
- _infobox_desc.set_markup(_("The feDiffuseLighting and <b>feSpecularLighting</b> filter primitives create \"embossed\" shadings. The input's alpha channel is used to provide depth information: higher opacity areas are raised toward the viewer and lower opacity areas recede away from the viewer."));
+ _infobox_desc.set_markup(_("The <b>feDiffuseLighting</b> and <b>feSpecularLighting</b> filter primitives create \"embossed\" shadings. The input's alpha channel is used to provide depth information: higher opacity areas are raised toward the viewer and lower opacity areas recede away from the viewer."));
break;
case(NR_FILTER_TILE):
_infobox_icon.set_from_icon_name("feTile-icon", Gtk::ICON_SIZE_DIALOG);
diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp
index ba81c6d47..eab5f9d8f 100644
--- a/src/ui/dialog/floating-behavior.cpp
+++ b/src/ui/dialog/floating-behavior.cpp
@@ -12,6 +12,7 @@
#include <gtkmm/dialog.h>
#include <gtkmm/stock.h>
+#include <glibmm/main.h>
#include <gtk/gtk.h>
#include "floating-behavior.h"
diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp
index 07e73cec8..f0112f1d8 100644
--- a/src/ui/dialog/font-substitution.cpp
+++ b/src/ui/dialog/font-substitution.cpp
@@ -37,6 +37,8 @@
#include "libnrtype/FontFactory.h"
#include "libnrtype/font-instance.h"
+#include <glibmm/regex.h>
+
namespace Inkscape {
namespace UI {
namespace Dialog {
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 57f815730..c162681e7 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -18,6 +18,7 @@
#endif
#include <glibmm/i18n.h>
+#include <glibmm/miscutils.h>
#include "inkscape-preferences.h"
#include <gtkmm/main.h>
@@ -1288,7 +1289,7 @@ void InkscapePreferences::initPageBehavior()
_page_mask.add_group_header( _("Before applying"));
_mask_grouping_none.init( _("Do not group clipped/masked objects"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE, true, 0);
- _mask_grouping_separate.init( _("Enclose every clipped/masked object in its own group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_SEPARATE, false, &_mask_grouping_none);
+ _mask_grouping_separate.init( _("Put every clipped/masked object in its own group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_SEPARATE, false, &_mask_grouping_none);
_mask_grouping_all.init( _("Put all clipped/masked objects into one group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_ALL, false, &_mask_grouping_none);
_page_mask.add_line(true, "", _mask_grouping_none, "",
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index fdc33b2a6..dd147d00f 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -20,6 +20,7 @@
#include <gtkmm/separatormenuitem.h>
#include <glibmm/i18n.h>
+#include <glibmm/main.h>
#include "desktop.h"
#include "desktop-style.h"
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 43b88e5c6..71fee342a 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -23,6 +23,7 @@
#include <glibmm/i18n.h>
#include <glibmm/main.h>
+#include <glibmm/timer.h>
#include <gdkmm/pixbuf.h>
#include "color-item.h"
diff --git a/src/ui/widget/dock-item.cpp b/src/ui/widget/dock-item.cpp
index b9cc50845..8d960ddc3 100644
--- a/src/ui/widget/dock-item.cpp
+++ b/src/ui/widget/dock-item.cpp
@@ -18,6 +18,7 @@
#include <gtkmm/icontheme.h>
#include <gtkmm/stockitem.h>
+#include <glibmm/exceptionhandler.h>
namespace Inkscape {
namespace UI {
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 9e078cabb..2a816adf4 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -775,6 +775,10 @@ static void sp_desktop_widget_dispose(GObject *object)
{
SPDesktopWidget *dtw = SP_DESKTOP_WIDGET (object);
+ if (dtw == NULL) {
+ return;
+ }
+
UXManager::getInstance()->delTrack(dtw);
if (dtw->desktop) {
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp
index 013ad9e94..59fe25fa1 100644
--- a/src/widgets/font-selector.cpp
+++ b/src/widgets/font-selector.cpp
@@ -51,8 +51,6 @@ struct SPFontSelector
NRNameList families;
NRStyleList styles;
- int familyidx;
- int styleidx;
gfloat fontsize;
bool fontsize_dirty;
font_instance *font;
@@ -246,9 +244,7 @@ static void sp_font_selector_init(SPFontSelector *fsel)
gtk_widget_show_all (fsel->size);
- fsel->familyidx = 0;
- fsel->styleidx = 0;
- fsel->fontsize = 10.0;
+ fsel->fontsize = 18.0;
fsel->fontsize_dirty = false;
fsel->font = NULL;
}
@@ -290,8 +286,6 @@ static void sp_font_selector_family_select_row(GtkTreeSelection *selection,
path = gtk_tree_model_get_path (model, &iter);
gtk_tree_model_get (model, &iter, 1, &list, -1);
- fsel->familyidx = gtk_tree_path_get_indices (path)[0];
- fsel->styleidx = 0;
store = gtk_list_store_new (1, G_TYPE_STRING);
@@ -318,7 +312,6 @@ static void sp_font_selector_style_select_row (GtkTreeSelection *selection,
if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return;
path = gtk_tree_model_get_path (model, &iter);
- fsel->styleidx = gtk_tree_path_get_indices (path)[0];
if (!fsel->block_emit)
{
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index 8470e93db..7580d9602 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -24,6 +24,7 @@
#include <gtkmm/image.h>
#include <gdkmm/pixbuf.h>
#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
#include <2geom/transforms.h>
#include "path-prefix.h"
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index a01f950a6..cc6d02ea8 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -133,115 +133,7 @@ static void sp_print_fontstyle( SPStyle *query ) {
}
#endif
-/*
- * Fill the font style combobox with the available font styles for the selected font family
- * Set the selected style to that in font
- */
-static void sp_text_fontstyle_populate(GObject *tbl, font_instance *font=NULL)
-{
-
- Ink_ComboBoxEntry_Action* act = INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
- GtkTreeModel *model = ink_comboboxentry_action_get_model( act );
- gchar *current_font = ink_comboboxentry_action_get_active_text( act );
- if (!current_font) {
- return;
- }
-
- // If font list, take only first font in list
- gchar** tokens = g_strsplit( current_font, ",", 0 );
- g_strstrip( tokens[0] );
- current_font = tokens[0];
-
- // Get an iter to the selected font from the model data
- // We cant get it from the combo, cause it might not have been created yet
- gboolean found = false;
- GtkTreeIter iter;
- gboolean valid = gtk_tree_model_get_iter_first( model, &iter );
- while ( valid ) {
-
- // Get text from list entry
- gchar* text = NULL;
- gtk_tree_model_get( model, &iter, 0, &text, -1 ); // Column 0
-
- // Check for match
- if ( text && (strcmp( current_font, text ) == 0) ) {
- found = true;
- break;
- }
- valid = gtk_tree_model_iter_next( model, &iter );
- }
-
- g_strfreev( tokens );
-
- Ink_ComboBoxEntry_Action* fontStyleAction = INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontStyleAction" ) );
-
- gchar *current_style = ink_comboboxentry_action_get_active_text( fontStyleAction );
-
- GtkListStore *store = GTK_LIST_STORE( ink_comboboxentry_action_get_model( fontStyleAction ) );
- gtk_list_store_clear ( store );
-
- // Get the list of styles from the selected font.
- GList *list = NULL;
-
- if (found) {
-
- // Use precompiled list if font-family on system.
- gtk_tree_model_get (model, &iter, 1, &list, -1);
-
- } else {
-
- // Use generic list if font-family not on system.
- static GList *glist = NULL;
- if( glist == NULL ) {
- glist = g_list_append (glist, (void*)"Normal");
- glist = g_list_append (glist, (void*)"Italic");
- glist = g_list_append (glist, (void*)"Bold");
- glist = g_list_append (glist, (void*)"Bold Italic");
- }
- list = glist;
- }
-
- for (GList *l=list; l; l = l->next)
- {
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, (char*)l->data, -1);
- }
-
- // Select the style in the combo that best matches font
- if (font && list) {
-
- unsigned int index = sp_font_selector_get_best_style(font, list);
-
- Ink_ComboBoxEntry_Action* fontStyleAction =
- INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontStyleAction" ) );
- model = ink_comboboxentry_action_get_model( fontStyleAction );
- GtkTreePath *path_c = gtk_tree_path_new ();
- gtk_tree_path_append_index (path_c, index);
- gtk_tree_model_get_iter(model, &iter, path_c);
- gchar *name;
- gtk_tree_model_get (model, &iter, 0, &name, -1);
- ink_comboboxentry_action_set_active_text( fontStyleAction, name );
-
- } else if (current_style) {
- ink_comboboxentry_action_set_active_text( fontStyleAction, current_style );
- }
-}
-
// Font family
-//
-// In most cases we should just be able to set the new family name
-// but there may be cases where a font family doesn't follow the
-// standard naming pattern. To handle those cases, we do a song and
-// dance to use Pango to find the best match. To do that we start
-// with the old "fontSpec" (which is the returned string from
-// pango_font_description_to_string() with the size unset). This
-// has the form "[family-list] [style-options]" where the
-// family-list is a comma separated list of font-family names
-// (optionally terminated by a comma). An example would be
-// "DejaVu Sans, Sans Bold". Only a "fontSpec" containing a
-// single font-family will work with Pango's best match routine.
-// If we can't obtain a good "fontSpec", we then resort to blindly
-// changing the font-family.
static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
{
#ifdef DEBUG_TEXT
@@ -252,156 +144,45 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb
// quit if run by the _changed callbacks
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
- return;
- }
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
-
- gchar *family = ink_comboboxentry_action_get_active_text( act );
-#ifdef DEBUG_TEXT
- std::cout << " New family: " << family << std::endl;
-#endif
-
- // First try to get the old font spec from the stored value
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
-
- Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
-#ifdef DEBUG_TEXT
- std::cout << " fontSpec from query :" << fontSpec << ":" << std::endl;
-#endif
-
- // If that didn't work, try to get font spec from style
- if (fontSpec.empty()) {
-
- // Must query all to fill font-family, font-style, font-weight, font-specification
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
-
- // Construct a new font specification if it does not yet exist
- font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
- if( fontFromStyle ) {
- fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
- fontFromStyle->Unref();
- }
-
-#ifdef DEBUG_TEXT
- std::cout << " fontSpec empty, try from style" << std::endl;
- std::cout << " from style :" << fontSpec << ":" << std::endl;
- sp_print_font( query );
-#endif
-
- }
-
- // And if that didn't work use default. DO WE REALLY WANT TO DO THIS?
- if ( fontSpec.empty() ) {
-
- sp_style_read_from_prefs(query, "/tools/text");
-
- // Construct a new font specification if it does not yet exist
- font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
- if ( fontFromStyle ) {
- fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
- fontFromStyle->Unref();
- }
-
#ifdef DEBUG_TEXT
- std::cout << " fontSpec empty, trying from prefs" << std::endl;
- std::cout << " from prefs :" << fontSpec << ":" << std::endl;
- sp_print_font( query );
+ std::cout << "sp_text_fontfamily_value_changed: frozen... return" << std::endl;
+ std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n" << std::endl;
#endif
+ return;
}
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- // Now we have a font specification, replace family.
- Glib::ustring newFontSpec = "";
- SPCSSAttr *css = sp_repr_css_attr_new ();
-
- if (!fontSpec.empty()) newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
-
-#ifdef DEBUG_TEXT
- std::cout << " New FontSpec from ReplaceFontSpecificationFamily :" << newFontSpec << ":" << std::endl;
-#endif
-
- if (!fontSpec.empty() && !newFontSpec.empty() ) {
-
- if (fontSpec != newFontSpec) {
-
- font_instance *font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
-
- if (font) {
- sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
-
- // Set all the these just in case they were altered when finding the best
- // match for the new family and old style... Unnecessary?
-
- gchar c[256];
-
- font->Family(c, 256);
-
- sp_repr_css_set_property (css, "font-family", c);
-
- font->Attribute( "weight", c, 256);
- sp_repr_css_set_property (css, "font-weight", c);
-
- font->Attribute("style", c, 256);
- sp_repr_css_set_property (css, "font-style", c);
-
- font->Attribute("stretch", c, 256);
- sp_repr_css_set_property (css, "font-stretch", c);
-
- font->Attribute("variant", c, 256);
- sp_repr_css_set_property (css, "font-variant", c);
-
- font->Unref();
-
- // Set the list of font styles
- sp_text_fontstyle_populate(tbl);
-
- } else {
- g_warning(_("Failed to find font matching: %s\n"), newFontSpec.c_str());
- }
- }
- } else {
-
- // Either old font does not exist on system or ReplaceFontSpecificationFamily() failed.
- // Blindly fall back to setting the family to text in the font-family chooser.
+ Glib::ustring new_family = ink_comboboxentry_action_get_active_text( act );
+ // TODO: Think about how to handle handle multiple selections. While
+ // the font-family may be the same for all, the styles might be different.
+ // See: TextEdit::onApply() for example of looping over selected items.
+ Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
#ifdef DEBUG_TEXT
- std::cout << " Failed to find new font, blindly setting family: " << family << std::endl;
+ std::cout << " Old family: " << fontlister->get_font_family() << std::endl;
+ std::cout << " New family: " << new_family << std::endl;
+ std::cout << " Old active: " << fontlister->get_font_family_row() << std::endl;
+ std::cout << " New active: " << act->active << std::endl;
#endif
- sp_repr_css_set_property (css, "-inkscape-font-specification", family);
- sp_repr_css_set_property (css, "font-family", family);
- }
+ if( new_family.compare( fontlister->get_font_family() ) != 0 ) {
- // If querying returned nothing, update default style.
- if (result_fontspec == QUERY_STYLE_NOTHING)
- {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->mergeStyle("/tools/text/style", css);
- //sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace through a verb
- }
- else
- {
- sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true);
- }
+ std::pair<Glib::ustring,Glib::ustring> ui = fontlister->set_font_family( act->active );
+ // active text set in sp_text_toolbox_selection_changed()
- sp_style_unref(query);
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ fontlister->set_css( css );
- g_free (family);
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true); // Results in selection change called twice.
+ sp_repr_css_attr_unref (css);
- // Save for undo
- if (result_fontspec != QUERY_STYLE_NOTHING) {
- DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT,
_("Text: Change font family"));
}
- sp_repr_css_attr_unref (css);
// unfreeze
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- // focus to canvas (not useful if you want to choose font for your text)
- //gtk_widget_grab_focus (GTK_WIDGET((SP_ACTIVE_DESKTOP)->canvas));
-
#ifdef DEBUG_TEXT
std::cout << "sp_text_toolbox_fontfamily_changes: exit" << std::endl;
std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl;
@@ -473,7 +254,6 @@ static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObje
/*
* Font style
*/
-//static void sp_text_fontstyle_value_changed( EgeSelectOneAction *act, GObject *tbl )
static void sp_text_fontstyle_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
{
// quit if run by the _changed callbacks
@@ -482,95 +262,26 @@ static void sp_text_fontstyle_value_changed( Ink_ComboBoxEntry_Action *act, GObj
}
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- // First query font-specification, this is the most complete font face description.
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+ Glib::ustring new_style = ink_comboboxentry_action_get_active_text( act );
- // font_specification will not be set unless defined explicitily on a tspan.
- // This should be fixed!
- Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
+ Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
- if (fontSpec.empty()) {
- // Construct a new font specification if it does not yet exist
- // Must query font-family, font-style, font-weight, to find correct font face.
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if( new_style.compare( fontlister->get_font_style() ) != 0 ) {
- font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
- if ( fontFromStyle ) {
- fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
- fontFromStyle->Unref();
- }
- }
+ fontlister->set_font_style( new_style );
+ // active text set in sp_text_toolbox_seletion_changed()
- SPCSSAttr *css = sp_repr_css_attr_new ();
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ fontlister->set_css( css );
- Glib::ustring current_style = ink_comboboxentry_action_get_active_text( act );
- Glib::ustring fontFamily = "";
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
+ sp_repr_css_attr_unref (css);
- if (query->text->font_family.set) {
- fontFamily = query->text->font_family.value;
- } else {
- // if the font_family is not set, get it from the font family combo instead
- Ink_ComboBoxEntry_Action* act = INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
- fontFamily = ink_comboboxentry_action_get_active_text( act );
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT,
+ _("Text: Change font style"));
}
- font_instance *font = (font_factory::Default())->FaceFromUIStrings (fontFamily.c_str(), current_style.c_str());
-
- if (font) {
-
- gchar c[256];
-
- font->Attribute( "weight", c, 256);
- sp_repr_css_set_property (css, "font-weight", c);
-
- font->Attribute("style", c, 256);
- sp_repr_css_set_property (css, "font-style", c);
-
- font->Attribute("stretch", c, 256);
- sp_repr_css_set_property (css, "font-stretch", c);
-
- font->Attribute("variant", c, 256);
- sp_repr_css_set_property (css, "font-variant", c);
-
- font->Unref();
- font = NULL;
-
- } else {
-
- // Font not found on system, blindly update style
- // Options match choices in sp_text_fontstyle_populate
- sp_repr_css_set_property (css, "font-weight", "normal");
- sp_repr_css_set_property (css, "font-style", "normal" );
- if( current_style.find("Bold") != Glib::ustring::npos ) {
- sp_repr_css_set_property (css, "font-weight", "bold");
- }
- if( current_style.find("Italic") != Glib::ustring::npos ) {
- sp_repr_css_set_property (css, "font-style", "italic");
- }
- }
-
- // If querying returned nothing, update default style.
- if (result_fontspec == QUERY_STYLE_NOTHING)
- {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->mergeStyle("/tools/text/style", css);
- }
-
- sp_style_unref(query);
-
- // Do we need to update other CSS values?
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- sp_desktop_set_style (desktop, css, true, true);
- if (result_fontspec != QUERY_STYLE_NOTHING) {
- DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
- _("Text: Change font style"));
- }
-
- sp_repr_css_attr_unref (css);
-
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
@@ -1145,6 +856,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
#ifdef DEBUG_TEXT
std::cout << " Frozen, returning" << std::endl;
+ std::cout << "sp_text_toolbox_selection_changed: exit " << count << std::endl;
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
std::cout << std::endl;
#endif
@@ -1152,15 +864,21 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
}
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- // Update font list, but only if widget already created.
Ink_ComboBoxEntry_Action* fontFamilyAction =
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
+ Ink_ComboBoxEntry_Action* fontStyleAction =
+ INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontStyleAction" ) );
+
+ Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
+ fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP ));
+ fontlister->selection_update();
+
+ // Update font list, but only if widget already created.
if( fontFamilyAction->combobox != NULL ) {
- Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
- fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP ));
+ ink_comboboxentry_action_set_active_text( fontFamilyAction, fontlister->get_font_family().c_str(), fontlister->get_font_family_row() );
+ ink_comboboxentry_action_set_active_text( fontStyleAction, fontlister->get_font_style().c_str() );
}
-
// Only flowed text can be justified, only normal text can be kerned...
// Find out if we have flowed text now so we can use it several places
gboolean isFlow = false;
@@ -1207,6 +925,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
#ifdef DEBUG_TEXT
std::cout << " text_style_from_prefs: toolbar already set" << std:: endl;
+ std::cout << "sp_text_toolbox_selection_changed: exit " << count << std::endl;
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
std::cout << std::endl;
#endif
@@ -1225,15 +944,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
// If we have valid query data for text (font-family, font-specification) set toolbar accordingly.
if (query->text)
{
- // Font family
- if( query->text->font_family.value ) {
- gchar *fontFamily = query->text->font_family.value;
-
- Ink_ComboBoxEntry_Action* fontFamilyAction =
- INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
- ink_comboboxentry_action_set_active_text( fontFamilyAction, fontFamily );
- }
-
// Size (average of text selected)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT);
@@ -1247,16 +957,17 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
Ink_ComboBoxEntry_Action* fontSizeAction =
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) );
+
+ // Freeze to ignore callbacks.
+ //g_object_freeze_notify( G_OBJECT( fontSizeAction->combobox ) );
sp_text_set_sizes(GTK_LIST_STORE(ink_comboboxentry_action_get_model(fontSizeAction)), unit);
+ //g_object_thaw_notify( G_OBJECT( fontSizeAction->combobox ) );
+
ink_comboboxentry_action_set_active_text( fontSizeAction, os.str().c_str() );
Glib::ustring tooltip = Glib::ustring::format(_("Font size"), " (", sp_style_get_css_unit_string(unit), ")");
ink_comboboxentry_action_set_tooltip ( fontSizeAction, tooltip.c_str());
- // Font styles
- font_instance *font = font_factory::Default()->FaceFromStyle(query);
- sp_text_fontstyle_populate(tbl, font);
-
// Superscript
gboolean superscriptSet =
((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) &&
@@ -1438,6 +1149,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
}
#ifdef DEBUG_TEXT
+ std::cout << "sp_text_toolbox_selection_changed: exit " << count << std::endl;
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
std::cout << std::endl;
#endif
@@ -1457,41 +1169,47 @@ sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
sp_text_toolbox_selection_changed (NULL, tbl);
}
+// TODO: possibly share with font-selector by moving most code to font-lister (passing family name)
+static void sp_text_toolbox_select_cb( GtkEntry* entry, GtkEntryIconPosition /*position*/, GdkEvent /*event*/, gpointer /*data*/ ) {
-/* Recursively extract all "font-family" attributes from a document. */
-void
-sp_text_toolbox_get_font_list_in_doc_recursive (SPObject *r, std::list<Glib::ustring> *l)
-{
- if (!r) {
- return;
- }
+ Glib::ustring family = gtk_entry_get_text ( entry );
+ //std::cout << "text_toolbox_missing_font_cb: selecting: " << family << std::endl;
- const gchar *style = r->getRepr()->attribute("style");
- if( style != NULL ) {
- //std::cout << style << std::endl;
- std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(";", style );
- for( size_t i=0; i < tokens.size(); ++i ) {
- Glib::ustring token = tokens[i];
- size_t found = token.find("font-family:");
- if( found != Glib::ustring::npos ) {
- // Remove "font-family:"
- token.erase(found,12);
- // Remove any leading single or double quote
- if( token[0] == '\'' || token[0] == '"' ) {
- token.erase(0,1);
- }
- // Remove any trailing single or double quote
- if( token[token.length()-1] == '\'' || token[token.length()-1] == '"' ) {
- token.erase(token.length()-1);
- }
- l->push_back( token );
- }
- }
- }
+ // Get all items with matching font-family set (not inherited!).
+ GSList *selectList = NULL;
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *document = sp_desktop_document( desktop );
+ GSList *allList = get_all_items(NULL, document->getRoot(), desktop, false, false, true, NULL);
+ for (GSList *i = allList; i != NULL; i = i->next) {
+
+ SPItem *item = SP_ITEM(i->data);
+ SPStyle *style = item->style;
+
+ if (style && style->text) {
+
+ Glib::ustring family_style;
+ if (style->text->font_family.set) {
+ family_style = style->text->font_family.value;
+ //std::cout << " family style from font_family: " << family_style << std::endl;
+ }
+ else if (style->text->font_specification.set) {
+ family_style = style->text->font_specification.value;
+ //std::cout << " family style from font_spec: " << family_style << std::endl;
+ }
- for (SPObject *child = r->firstChild(); child; child = child->getNext()) {
- sp_text_toolbox_get_font_list_in_doc_recursive( child, l );
+ if (family_style.compare( family ) == 0 ) {
+ //std::cout << " found: " << item->getId() << std::endl;
+ selectList = g_slist_prepend (selectList, item);
+ }
}
+ }
+
+ // Update selection
+ Inkscape::Selection *selection = sp_desktop_selection (desktop );
+ selection->clear();
+ //std::cout << " list length: " << g_slist_length ( selectList ) << std::endl;
+ selection->setList(selectList);
}
@@ -1526,8 +1244,16 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
(gpointer)font_lister_separator_func,
GTK_WIDGET(desktop->canvas)); // Focus widget
ink_comboboxentry_action_popup_enable( act ); // Enable entry completion
+
+ gchar *const info = _("Select all text with this font-family");
+ ink_comboboxentry_action_set_info( act, info ); // Show selection icon
+ ink_comboboxentry_action_set_info_cb( act, (gpointer)sp_text_toolbox_select_cb );
+
gchar *const warning = _("Font not found on system");
- ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font
+ ink_comboboxentry_action_set_warning( act, warning ); // Show icon w/ tooltip if font missing
+ ink_comboboxentry_action_set_warning_cb( act, (gpointer)sp_text_toolbox_select_cb );
+
+ //ink_comboboxentry_action_set_warning_callback( act, sp_text_fontfamily_select_all );
ink_comboboxentry_action_set_altx_name( act, "altx-text" ); // Set Alt-X keyboard shortcut
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontfamily_value_changed), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
@@ -1577,18 +1303,20 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
/* Font styles */
{
- GtkListStore* model_style = gtk_list_store_new( 1, G_TYPE_STRING );
+ Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance();
+ Glib::RefPtr<Gtk::ListStore> store = fontlister->get_style_list();
+ GtkListStore* model_style = store->gobj();
- Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontStyleAction",
+ Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontStyleAction",
_("Font Style"),
_("Font style"),
NULL,
GTK_TREE_MODEL(model_style),
12, // Width in characters
- 0, // Extra list width
- NULL, // Cell layout
- NULL, // Separator
- GTK_WIDGET(desktop->canvas)); // Focus widget
+ 0, // Extra list width
+ NULL, // Cell layout
+ NULL, // Separator
+ GTK_WIDGET(desktop->canvas)); // Focus widget
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontstyle_value_changed), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );