From 10a42d2a553c5953b569804bd7262c604050d09c Mon Sep 17 00:00:00 2001 From: buliabyak <> Date: Sat, 27 Mar 2010 01:32:59 -0300 Subject: make SP_OBJECT_ID usable again (bzr r9237) --- src/sp-object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/sp-object.h b/src/sp-object.h index f7ca0f3a3..633091668 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -45,7 +45,7 @@ #define SP_OBJECT_WRITE_ALL (1 << 2) /* Convenience stuff */ -#define SP_OBJECT_ID(o) (((SPObject *) (o))->id) +#define SP_OBJECT_ID(o) (((SPObject *) (o))->getId()) #define SP_OBJECT_REPR(o) (((SPObject *) (o))->repr) #define SP_OBJECT_DOCUMENT(o) (((SPObject *) (o))->document) #define SP_OBJECT_PARENT(o) (((SPObject *) (o))->parent) -- cgit v1.2.3 From 1a73a9c8e678134478d99bafc3c0857a61072082 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 27 Mar 2010 00:50:41 -0700 Subject: Phase 1 - unify/reconcile copy-n-paste edit madness of Fill and Stroke edit panes. (bzr r9238) --- src/fill-or-stroke.h | 2 +- src/widgets/Makefile_insert | 1 + src/widgets/fill-n-stroke-factory.h | 34 ++ src/widgets/fill-style.cpp | 568 +++++++++++++++++++-------------- src/widgets/fill-style.h | 11 +- src/widgets/stroke-style.cpp | 606 ++++++++++++++++++++++++------------ src/widgets/stroke-style.h | 16 +- 7 files changed, 784 insertions(+), 454 deletions(-) create mode 100644 src/widgets/fill-n-stroke-factory.h (limited to 'src') diff --git a/src/fill-or-stroke.h b/src/fill-or-stroke.h index e4195324f..a38dfc32d 100644 --- a/src/fill-or-stroke.h +++ b/src/fill-or-stroke.h @@ -8,4 +8,4 @@ /** \post STROKE == 0, FILL != 0. */ enum FillOrStroke { STROKE = 0, FILL = 1 }; -#endif /* !SEEN_FILL_OR_STROKE_H */ +#endif // !SEEN_FILL_OR_STROKE_H diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert index 5d327d8a3..313e27528 100644 --- a/src/widgets/Makefile_insert +++ b/src/widgets/Makefile_insert @@ -13,6 +13,7 @@ ink_common_sources += \ widgets/ege-paint-def.h \ widgets/fill-style.cpp \ widgets/fill-style.h \ + widgets/fill-n-stroke-factory.h \ widgets/font-selector.cpp \ widgets/font-selector.h \ widgets/gradient-image.cpp \ diff --git a/src/widgets/fill-n-stroke-factory.h b/src/widgets/fill-n-stroke-factory.h new file mode 100644 index 000000000..14cbd6a58 --- /dev/null +++ b/src/widgets/fill-n-stroke-factory.h @@ -0,0 +1,34 @@ +#ifndef SEEN_FILL_N_STROKE_FACTORY_H +#define SEEN_FILL_N_STROKE_FACTORY_H +/* Authors: + * Jon A. Cruz + * + * Copyright (C) 2010 Jon A. Cruz + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "fill-or-stroke.h" + +typedef struct _GtkWidget GtkWidget; + +namespace Inkscape { +namespace Widgets { + +GtkWidget *createStyleWidget( FillOrStroke kind ); + +} // namespace Widgets +} // namespace Inkscape + +#endif // !SEEN_FILL_N_STROKE_FACTORY_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 3f2018b91..09c6951ad 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -35,159 +35,184 @@ #include "widgets/sp-widget.h" #include "xml/repr.h" -#include "widgets/fill-style.h" +#include "fill-style.h" +#include "fill-n-stroke-factory.h" // These can be deleted once we sort out the libart dependence. #define ART_WIND_RULE_NONZERO 0 -static void sp_fill_style_widget_construct ( SPWidget *spw, - SPPaintSelector *psel ); +/* Fill */ -static void sp_fill_style_widget_modify_selection ( SPWidget *spw, - Inkscape::Selection *selection, - guint flags, - SPPaintSelector *psel ); +static void fillnstroke_constructed(SPWidget *spw, SPPaintSelector *psel); +static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, SPWidget *spw); -static void sp_fill_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw ); +static void fillnstroke_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel); +static void fillnstroke_selection_changed(SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel); +static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); -static void sp_fill_style_widget_change_selection ( SPWidget *spw, - Inkscape::Selection *selection, - SPPaintSelector *psel ); +static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw); +static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw); +static void fillnstroke_paint_changed(SPPaintSelector *psel, SPWidget *spw); -static void sp_fill_style_widget_update (SPWidget *spw); +static void fillnstroke_transientize_called(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); -static void sp_fill_style_widget_paint_mode_changed( SPPaintSelector *psel, - SPPaintSelector::Mode mode, - SPWidget *spw ); -static void sp_fill_style_widget_fillrule_changed( SPPaintSelector *psel, - SPPaintSelector::FillRule mode, - SPWidget *spw ); +static void fillnstroke_performUpdate(SPWidget *spw); -static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw ); -static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw ); - -GtkWidget * -sp_fill_style_widget_new (void) +GtkWidget *sp_fill_style_widget_new(void) { - GtkWidget *spw = sp_widget_new_global (INKSCAPE); - - GtkWidget *vb = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vb); - gtk_container_add (GTK_CONTAINER (spw), vb); - - GtkWidget *psel = sp_paint_selector_new (true); // with fillrule selector - gtk_widget_show (psel); - gtk_box_pack_start (GTK_BOX (vb), psel, TRUE, TRUE, 0); - g_object_set_data (G_OBJECT (spw), "paint-selector", psel); - - g_signal_connect ( G_OBJECT (psel), "mode_changed", - G_CALLBACK (sp_fill_style_widget_paint_mode_changed), - spw ); - - g_signal_connect ( G_OBJECT (psel), "dragged", - G_CALLBACK (sp_fill_style_widget_paint_dragged), - spw ); - - g_signal_connect ( G_OBJECT (psel), "changed", - G_CALLBACK (sp_fill_style_widget_paint_changed), - spw ); - - g_signal_connect ( G_OBJECT (psel), "fillrule_changed", - G_CALLBACK (sp_fill_style_widget_fillrule_changed), - spw ); - + return Inkscape::Widgets::createStyleWidget( FILL ); +} - g_signal_connect ( G_OBJECT (spw), "construct", - G_CALLBACK (sp_fill_style_widget_construct), psel); +/** + * Create the fill or stroke style widget, and hook up all the signals. + */ +GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) +{ + GtkWidget *spw = sp_widget_new_global(INKSCAPE); + + // with or without fillrule selector + GtkWidget *psel = sp_paint_selector_new(kind == FILL); + gtk_widget_show(psel); + gtk_container_add(GTK_CONTAINER(spw), psel); + g_object_set_data(G_OBJECT(spw), "paint-selector", psel); + g_object_set_data(G_OBJECT(spw), "kind", GINT_TO_POINTER(kind)); + + if (kind == FILL) { + g_signal_connect( G_OBJECT(spw), "construct", + G_CALLBACK(fillnstroke_constructed), + psel ); + } //FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates //those anyway; then eliminate spw - g_signal_connect ( G_OBJECT (spw), "modify_selection", - G_CALLBACK (sp_fill_style_widget_modify_selection), psel); - - g_signal_connect ( G_OBJECT (spw), "change_selection", - G_CALLBACK (sp_fill_style_widget_change_selection), psel); + g_signal_connect( G_OBJECT(spw), "modify_selection", + G_CALLBACK(fillnstroke_selection_modified), + psel ); + + g_signal_connect( G_OBJECT(spw), "change_selection", + G_CALLBACK(fillnstroke_selection_changed), + psel ); + + g_signal_connect( INKSCAPE, "change_subselection", + G_CALLBACK(fillnstroke_subselection_changed), + spw ); + + if (kind == STROKE) { + g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", + G_CALLBACK(fillnstroke_transientize_called), + spw ); + } - g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_fill_style_widget_change_subselection), spw); + g_signal_connect( G_OBJECT(psel), "mode_changed", + G_CALLBACK(fillnstroke_paint_mode_changed), + spw ); - sp_fill_style_widget_update (SP_WIDGET (spw)); + g_signal_connect( G_OBJECT(psel), "dragged", + G_CALLBACK(fillnstroke_paint_dragged), + spw ); - return spw; + g_signal_connect( G_OBJECT(psel), "changed", + G_CALLBACK(fillnstroke_paint_changed), + spw ); -} // end of sp_fill_style_widget_new() + if (kind == FILL) { + g_signal_connect( G_OBJECT(psel), "fillrule_changed", + G_CALLBACK(fillnstroke_fillrule_changed), + spw ); + } + fillnstroke_performUpdate(SP_WIDGET(spw)); + return spw; +} -static void -sp_fill_style_widget_construct( SPWidget *spw, SPPaintSelector */*psel*/ ) +static void fillnstroke_constructed( SPWidget *spw, SPPaintSelector * /*psel*/ ) { #ifdef SP_FS_VERBOSE - g_print ( "Fill style widget constructed: inkscape %p\n", + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; + g_print( "[%s] style widget constructed: inkscape %p\n", + (kind == FILL) ? "fill" : "style", spw->inkscape ); #endif if (spw->inkscape) { - sp_fill_style_widget_update (spw); + fillnstroke_performUpdate(spw); } -} // end of sp_fill_style_widget_construct() +} -static void -sp_fill_style_widget_modify_selection( SPWidget *spw, - Inkscape::Selection */*selection*/, - guint flags, - SPPaintSelector */*psel*/ ) +/** + * On signal modified, invokes an update of the fill or stroke style paint object. + */ +static void fillnstroke_selection_modified( SPWidget *spw, + Inkscape::Selection * /*selection*/, + guint flags, + SPPaintSelector * /*psel*/ ) { if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG) ) - { + SP_OBJECT_STYLE_MODIFIED_FLAG) ) { #ifdef SP_FS_VERBOSE - g_message("sp_fill_style_widget_modify_selection()"); + g_message("fillnstroke_selection_modified()"); #endif - sp_fill_style_widget_update (spw); + fillnstroke_performUpdate(spw); } } -static void -sp_fill_style_widget_change_subselection( Inkscape::Application */*inkscape*/, - SPDesktop */*desktop*/, - SPWidget *spw ) +/** + * On signal selection changed, invokes an update of the fill or stroke style paint object. + */ +static void fillnstroke_selection_changed( SPWidget *spw, + Inkscape::Selection * /*selection*/, + SPPaintSelector * /*psel*/ ) { - sp_fill_style_widget_update (spw); + fillnstroke_performUpdate(spw); } -static void -sp_fill_style_widget_change_selection( SPWidget *spw, - Inkscape::Selection */*selection*/, - SPPaintSelector */*psel*/ ) +/** + * On signal change subselection, invoke an update of the fill or stroke style widget. + */ +static void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, + SPDesktop * /*desktop*/, + SPWidget *spw ) { - sp_fill_style_widget_update (spw); + fillnstroke_performUpdate(spw); } /** -* \param sel Selection to use, or NULL. -*/ -static void -sp_fill_style_widget_update (SPWidget *spw) + * Gets the active fill or stroke style property, then sets the appropriate + * color, alpha, gradient, pattern, etc. for the paint-selector. + * + * @param sel Selection to use, or NULL. + */ +static void fillnstroke_performUpdate( SPWidget *spw ) { - if (g_object_get_data (G_OBJECT (spw), "update")) + if ( g_object_get_data(G_OBJECT(spw), "update") ) { return; + } - if (g_object_get_data (G_OBJECT (spw), "local")) { - g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (FALSE)); // local change; do nothing, but reset the flag - return; + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; + + if (kind == FILL) { + if ( g_object_get_data(G_OBJECT(spw), "local") ) { + g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(FALSE)); // local change; do nothing, but reset the flag + return; + } } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - SPPaintSelector *psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector")); + SPPaintSelector *psel = SP_PAINT_SELECTOR(g_object_get_data(G_OBJECT(spw), "paint-selector")); // create temporary style - SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); + SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection - int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FILL); + int result = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); + + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; + SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity; switch (result) { case QUERY_STYLE_NOTHING: @@ -201,37 +226,39 @@ sp_fill_style_widget_update (SPWidget *spw) case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector case QUERY_STYLE_MULTIPLE_SAME: { - SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, true); + SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind == FILL); psel->setMode(pselmode); - psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO? - SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD); + if (kind == FILL) { + psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO? + SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD); + } - if (query->fill.set && query->fill.isColor()) { - psel->setColorAlpha(query->fill.value.color, SP_SCALE24_TO_FLOAT(query->fill_opacity.value)); - } else if (query->fill.set && query->fill.isPaintserver()) { + if (targPaint.set && targPaint.isColor()) { + psel->setColorAlpha(targPaint.value.color, SP_SCALE24_TO_FLOAT(targOpacity.value)); + } else if (targPaint.set && targPaint.isPaintserver()) { - SPPaintServer *server = query->getFillPaintServer(); + SPPaintServer *server = (kind == FILL) ? query->getFillPaintServer() : query->getStrokePaintServer(); if (server && SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setSwatch( vector ); - } else if (SP_IS_LINEARGRADIENT (server)) { + } else if (SP_IS_LINEARGRADIENT(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setGradientLinear( vector ); - SPLinearGradient *lg = SP_LINEARGRADIENT (server); + SPLinearGradient *lg = SP_LINEARGRADIENT(server); psel->setGradientProperties( SP_GRADIENT_UNITS(lg), SP_GRADIENT_SPREAD(lg) ); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if (SP_IS_RADIALGRADIENT(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setGradientRadial( vector ); - SPRadialGradient *rg = SP_RADIALGRADIENT (server); - psel->setGradientProperties( SP_GRADIENT_UNITS (rg), - SP_GRADIENT_SPREAD (rg) ); - } else if (SP_IS_PATTERN (server)) { - SPPattern *pat = pattern_getroot (SP_PATTERN (server)); + SPRadialGradient *rg = SP_RADIALGRADIENT(server); + psel->setGradientProperties( SP_GRADIENT_UNITS(rg), + SP_GRADIENT_SPREAD(rg) ); + } else if (SP_IS_PATTERN(server)) { + SPPattern *pat = pattern_getroot(SP_PATTERN(server)); psel->updatePatternList( pat ); } } @@ -247,101 +274,112 @@ sp_fill_style_widget_update (SPWidget *spw) sp_style_unref(query); - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); - + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } - -static void -sp_fill_style_widget_paint_mode_changed( SPPaintSelector *psel, - SPPaintSelector::Mode /*mode*/, - SPWidget *spw ) +/** + * When the mode is changed, invoke a regular changed handler. + */ +static void fillnstroke_paint_mode_changed( SPPaintSelector *psel, + SPPaintSelector::Mode /*mode*/, + SPWidget *spw ) { - if (g_object_get_data (G_OBJECT (spw), "update")) + if (g_object_get_data(G_OBJECT(spw), "update")) { return; + } #ifdef SP_FS_VERBOSE - g_message("sp_fill_style_widget_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw); + g_message("fillnstroke_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw); #endif - /* TODO: Does this work? */ - /* TODO: Not really, here we have to get old color back from object */ - /* Instead of relying on paint widget having meaningful colors set */ - sp_fill_style_widget_paint_changed (psel, spw); + /* TODO: Does this work? + * Not really, here we have to get old color back from object + * Instead of relying on paint widget having meaningful colors set + */ + fillnstroke_paint_changed(psel, spw); } -static void sp_fill_style_widget_fillrule_changed( SPPaintSelector */*psel*/, - SPPaintSelector::FillRule mode, - SPWidget *spw ) +static void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, + SPPaintSelector::FillRule mode, + SPWidget *spw ) { - if (g_object_get_data (G_OBJECT (spw), "update")) + if (g_object_get_data(G_OBJECT(spw), "update")) { return; + } SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPCSSAttr *css = sp_repr_css_attr_new (); + SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill-rule", mode == SPPaintSelector::FILLRULE_EVENODD? "evenodd":"nonzero"); - sp_desktop_set_style (desktop, css); + sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref (css); + sp_repr_css_attr_unref(css); + css = 0; - sp_document_done (SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, - _("Change fill rule")); + sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, + _("Change fill rule")); } -static gchar const *undo_label_1 = "fill:flatcolor:1"; -static gchar const *undo_label_2 = "fill:flatcolor:2"; -static gchar const *undo_label = undo_label_1; +static gchar const *undo_F_label_1 = "fill:flatcolor:1"; +static gchar const *undo_F_label_2 = "fill:flatcolor:2"; + +static gchar const *undo_S_label_1 = "stroke:flatcolor:1"; +static gchar const *undo_S_label_2 = "stroke:flatcolor:2"; + +static gchar const *undo_F_label = undo_F_label_1; +static gchar const *undo_S_label = undo_S_label_1; /** -This is called repeatedly while you are dragging a color slider, only for flat color -modes. Previously it set the color in style but did not update the repr for efficiency, however -this was flakey and didn't buy us almost anything. So now it does the same as _changed, except -lumps all its changes for undo. + * This is called repeatedly while you are dragging a color slider, only for flat color + * modes. Previously it set the color in style but did not update the repr for efficiency, however + * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except + * lumps all its changes for undo. */ -static void -sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw) +static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw) { if (!spw->inkscape) { return; } - if (g_object_get_data (G_OBJECT (spw), "update")) { + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } - if (g_object_get_data (G_OBJECT (spw), "local")) { - // previous local flag not cleared yet; - // this means dragged events come too fast, so we better skip this one to speed up display - // (it's safe to do this in any case) - return; + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; + + if (kind == FILL) { + if (g_object_get_data(G_OBJECT(spw), "local")) { + // previous local flag not cleared yet; + // this means dragged events come too fast, so we better skip this one to speed up display + // (it's safe to do this in any case) + return; + } } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); switch (psel->mode) { - case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { - psel->setFlatColor( SP_ACTIVE_DESKTOP, "fill", "fill-opacity" ); - sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE, - _("Set fill color")); - g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (TRUE)); // local change, do not update from selection + psel->setFlatColor( SP_ACTIVE_DESKTOP, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); + sp_document_maybe_done(sp_desktop_document(SP_ACTIVE_DESKTOP), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set fill color") : _("Set stroke color")); + if (kind == FILL) { + g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(TRUE)); // local change, do not update from selection + } break; } default: - g_warning ( "file %s: line %d: Paint %d should not emit 'dragged'", - __FILE__, __LINE__, psel->mode ); + g_warning( "file %s: line %d: Paint %d should not emit 'dragged'", + __FILE__, __LINE__, psel->mode ); break; - } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } - /** This is called (at least) when: 1 paint selector mode is switched (e.g. flat color -> gradient) @@ -349,33 +387,32 @@ This is called (at least) when: 3 you changed a gradient selector parameter (e.g. spread) Must update repr. */ -static void -sp_fill_style_widget_paint_changed ( SPPaintSelector *psel, - SPWidget *spw ) +static void fillnstroke_paint_changed( SPPaintSelector *psel, SPWidget *spw ) { #ifdef SP_FS_VERBOSE - g_message("sp_fill_style_widget_paint_changed(psel:%p, spw:%p)", psel, spw); + g_message("fillnstroke_paint_changed(psel:%p, spw:%p)", psel, spw); #endif - if (g_object_get_data (G_OBJECT (spw), "update")) { + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { return; } - SPDocument *document = sp_desktop_document (desktop); - Inkscape::Selection *selection = sp_desktop_selection (desktop); + SPDocument *document = sp_desktop_document(desktop); + Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); switch (psel->mode) { - case SPPaintSelector::MODE_EMPTY: // This should not happen. - g_warning ( "file %s: line %d: Paint %d should not emit 'changed'", - __FILE__, __LINE__, psel->mode); + g_warning( "file %s: line %d: Paint %d should not emit 'changed'", + __FILE__, __LINE__, psel->mode); break; case SPPaintSelector::MODE_MULTIPLE: // This happens when you switch multiple objects with different gradients to flat color; @@ -384,35 +421,46 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel, case SPPaintSelector::MODE_NONE: { - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, "fill", "none"); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none"); - sp_desktop_set_style (desktop, css); + sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref (css); + sp_repr_css_attr_unref(css); + css = 0; - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Remove fill")); + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Remove fill") : _("Remove stroke")); break; } case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { - // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events - sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); + if (kind == FILL) { + // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); + } + + psel->setFlatColor( desktop, + (kind == FILL) ? "fill" : "stroke", + (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); + sp_document_maybe_done(sp_desktop_document(desktop), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set fill color") : _("Set stroke color")); - psel->setFlatColor( desktop, "fill", "fill-opacity" ); - sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE, - _("Set fill color")); - // resume interruptibility - sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); + if (kind == FILL) { + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); + } // on release, toggle undo_label so that the next drag will not be lumped with this one - if (undo_label == undo_label_1) - undo_label = undo_label_2; - else - undo_label = undo_label_1; + if (undo_F_label == undo_F_label_1) { + undo_F_label = undo_F_label_2; + undo_S_label = undo_S_label_2; + } else { + undo_F_label = undo_F_label_1; + undo_S_label = undo_S_label_1; + } break; } @@ -425,22 +473,26 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel, ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL ); - // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, "fill-opacity", "1.0"); + SPCSSAttr *css = 0; + if (kind == FILL) { + // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs + css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "fill-opacity", "1.0"); + } SPGradient *vector = psel->getGradientVector(); if (!vector) { /* No vector in paint selector should mean that we just changed mode */ - SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - int result = objects_query_fillstroke ((GSList *) items, query, true); + SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; guint32 common_rgb = 0; if (result == QUERY_STYLE_MULTIPLE_SAME) { - if (!query->fill.isColor()) { - common_rgb = sp_desktop_get_color(desktop, true); + if (!targPaint.isColor()) { + common_rgb = sp_desktop_get_color(desktop, kind == FILL); } else { - common_rgb = query->fill.value.color.toRGBA32( 0xff ); + common_rgb = targPaint.value.color.toRGBA32( 0xff ); } vector = sp_document_default_gradient_vector(document, common_rgb); } @@ -448,33 +500,40 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel, for (GSList const *i = items; i != NULL; i = i->next) { //FIXME: see above - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + if (kind == FILL) { + sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + } if (!vector) { sp_item_set_gradient(SP_ITEM(i->data), - sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), true), - gradient_type, true); + sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL), + gradient_type, kind == FILL); } else { - sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true); + sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); } } } else { - /* We have changed from another gradient type, or modified spread/units within - * this gradient type. */ - vector = sp_gradient_ensure_vector_normalized (vector); + // We have changed from another gradient type, or modified spread/units within + // this gradient type. + vector = sp_gradient_ensure_vector_normalized(vector); for (GSList const *i = items; i != NULL; i = i->next) { //FIXME: see above - sp_repr_css_change_recursive (SP_OBJECT_REPR (i->data), css, "style"); + if (kind == FILL) { + sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + } - SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true); + SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); psel->pushAttrsToGradient( gr ); } } - sp_repr_css_attr_unref (css); + if (css) { + sp_repr_css_attr_unref(css); + css = 0; + } - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Set gradient on fill")); + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke")); } break; @@ -491,66 +550,101 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel, } else { Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern); - SPCSSAttr *css = sp_repr_css_attr_new (); - gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id")); - sp_repr_css_set_property (css, "fill", urltext); + SPCSSAttr *css = sp_repr_css_attr_new(); + gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id")); + sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext); // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs - sp_repr_css_set_property(css, "fill-opacity", "1.0"); + if (kind == FILL) { + sp_repr_css_set_property(css, "fill-opacity", "1.0"); + } // cannot just call sp_desktop_set_style, because we don't want to touch those // objects who already have the same root pattern but through a different href // chain. FIXME: move this to a sp_item_set_pattern for (GSList const *i = items; i != NULL; i = i->next) { - SPObject *selobj = SP_OBJECT (i->data); - - SPStyle *style = SP_OBJECT_STYLE (selobj); - if (style && style->fill.isPaintserver()) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (selobj); - if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern) + Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data); + if ( (kind == STROKE) && !selrepr) { + continue; + } + SPObject *selobj = SP_OBJECT(i->data); + + SPStyle *style = SP_OBJECT_STYLE(selobj); + if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) { + SPObject *server = (kind == FILL) ? + SP_OBJECT_STYLE_FILL_SERVER(selobj) : + SP_OBJECT_STYLE_STROKE_SERVER(selobj); + if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern) // only if this object's pattern is not rooted in our selected pattern, apply - continue; - } + continue; + } - sp_desktop_apply_css_recursive (selobj, css, true); - } + if (kind == FILL) { + sp_desktop_apply_css_recursive(selobj, css, true); + } else { + sp_repr_css_change_recursive(selrepr, css, "style"); + } + } - sp_repr_css_attr_unref (css); - g_free (urltext); + sp_repr_css_attr_unref(css); + css = 0; + g_free(urltext); } // end if - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Set pattern on fill")); - + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set pattern on fill") : + _("Set pattern on stroke")); } // end if break; case SPPaintSelector::MODE_UNSET: if (items) { - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_unset_property (css, "fill"); + SPCSSAttr *css = sp_repr_css_attr_new(); + if (kind == FILL) { + sp_repr_css_unset_property(css, "fill"); + } else { + sp_repr_css_unset_property(css, "stroke"); + sp_repr_css_unset_property(css, "stroke-opacity"); + sp_repr_css_unset_property(css, "stroke-width"); + sp_repr_css_unset_property(css, "stroke-miterlimit"); + sp_repr_css_unset_property(css, "stroke-linejoin"); + sp_repr_css_unset_property(css, "stroke-linecap"); + sp_repr_css_unset_property(css, "stroke-dashoffset"); + sp_repr_css_unset_property(css, "stroke-dasharray"); + } - sp_desktop_set_style (desktop, css); - sp_repr_css_attr_unref (css); + sp_desktop_set_style(desktop, css); + sp_repr_css_attr_unref(css); + css = 0; - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Unset fill")); + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Unset fill") : _("Unset stroke")); } break; default: - g_warning ( "file %s: line %d: Paint selector should not be in " - "mode %d", - __FILE__, __LINE__, psel->mode ); + g_warning( "file %s: line %d: Paint selector should not be in " + "mode %d", + __FILE__, __LINE__, + psel->mode ); break; } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } +static void fillnstroke_transientize_called(Inkscape::Application * /*inkscape*/, + SPDesktop * /*desktop*/, + SPWidget * /*spw*/ ) +{ +// TODO: Either of these will cause crashes sometimes +// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL); +// ink_markers_menu_update(spw); +} + /* Local Variables: mode:c++ diff --git a/src/widgets/fill-style.h b/src/widgets/fill-style.h index 3924412ec..ea97bd486 100644 --- a/src/widgets/fill-style.h +++ b/src/widgets/fill-style.h @@ -3,7 +3,9 @@ */ /* Authors: * Lauris Kaplinski + * Jon A. Cruz * + * Copyright (C) 2010 Jon A. Cruz * Copyright (C) 2002 Lauris Kaplinski * * Released under GNU GPL, read the file 'COPYING' for more information @@ -12,14 +14,11 @@ #ifndef SEEN_DIALOGS_SP_FILL_STYLE_H #define SEEN_DIALOGS_SP_FILL_STYLE_H -#include -#include -#include "forward.h" +typedef struct _GtkWidget GtkWidget; +GtkWidget *sp_fill_style_widget_new(void); -GtkWidget *sp_fill_style_widget_new (void); - -#endif +#endif // SEEN_DIALOGS_SP_FILL_STYLE_H /* Local Variables: diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index ddd1c92d3..54678dbb8 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -25,6 +25,7 @@ #include "desktop-handles.h" #include "desktop-style.h" #include "dialogs/dialog-events.h" +#include "display/canvas-bpath.h" // for SP_STROKE_LINEJOIN_* #include "display/nr-arena.h" #include "display/nr-arena-item.h" #include "document-private.h" @@ -54,23 +55,36 @@ #include "widgets/spw-utilities.h" #include "xml/repr.h" -#include "widgets/stroke-style.h" +#include "stroke-style.h" +#include "fill-n-stroke-factory.h" +namespace Inkscape { +namespace Widgets { +GtkWidget *createStyleWidgetS( FillOrStroke kind ); +} +} + + +// These can be deleted once we sort out the libart dependence. + +#define ART_WIND_RULE_NONZERO 0 /* Paint */ -static void sp_stroke_style_paint_selection_modified (SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel); -static void sp_stroke_style_paint_selection_changed (SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel); -static void sp_stroke_style_paint_update(SPWidget *spw); +static void fillnstroke_constructed(SPWidget *spw, SPPaintSelector *psel); +static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, SPWidget *spw); -static void sp_stroke_style_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw); -static void sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw); -static void sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw); +static void fillnstroke_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel); +static void fillnstroke_selection_changed(SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel); +static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); -static void sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw ); -static void sp_stroke_style_widget_transientize_callback(Inkscape::Application *inkscape, - SPDesktop *desktop, - SPWidget *spw ); +static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw); +static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw); +static void fillnstroke_paint_changed(SPPaintSelector *psel, SPWidget *spw); + +static void fillnstroke_transientize_called(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); + +static void fillnstroke_performUpdate(SPWidget *spw); /** Marker selection option menus */ static Gtk::OptionMenu * marker_start_menu = NULL; @@ -86,104 +100,159 @@ static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const static Inkscape::UI::Cache::SvgPreview svg_preview_cache; +GtkWidget *sp_stroke_style_paint_widget_new(void) +{ + return Inkscape::Widgets::createStyleWidgetS( STROKE ); +} + /** - * Create the stroke style widget, and hook up all the signals. + * Create the fill or stroke style widget, and hook up all the signals. */ -GtkWidget * -sp_stroke_style_paint_widget_new(void) +GtkWidget *Inkscape::Widgets::createStyleWidgetS( FillOrStroke kind ) { - GtkWidget *spw, *psel; - - spw = sp_widget_new_global(INKSCAPE); + GtkWidget *spw = sp_widget_new_global(INKSCAPE); - psel = sp_paint_selector_new(false); // without fillrule selector + // with or without fillrule selector + GtkWidget *psel = sp_paint_selector_new(kind == FILL); gtk_widget_show(psel); gtk_container_add(GTK_CONTAINER(spw), psel); - gtk_object_set_data(GTK_OBJECT(spw), "paint-selector", psel); - - gtk_signal_connect(GTK_OBJECT(spw), "modify_selection", - GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_modified), - psel); - gtk_signal_connect(GTK_OBJECT(spw), "change_selection", - GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_changed), - psel); - - g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_stroke_style_widget_change_subselection), spw); - - g_signal_connect (G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK (sp_stroke_style_widget_transientize_callback), spw ); - - gtk_signal_connect(GTK_OBJECT(psel), "mode_changed", - GTK_SIGNAL_FUNC(sp_stroke_style_paint_mode_changed), - spw); - gtk_signal_connect(GTK_OBJECT(psel), "dragged", - GTK_SIGNAL_FUNC(sp_stroke_style_paint_dragged), - spw); - gtk_signal_connect(GTK_OBJECT(psel), "changed", - GTK_SIGNAL_FUNC(sp_stroke_style_paint_changed), - spw); - - sp_stroke_style_paint_update (SP_WIDGET(spw)); + g_object_set_data(G_OBJECT(spw), "paint-selector", psel); + g_object_set_data(G_OBJECT(spw), "kind", GINT_TO_POINTER(kind)); + + if (kind == FILL) { + g_signal_connect( G_OBJECT(spw), "construct", + G_CALLBACK(fillnstroke_constructed), + psel ); + } + +//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates +//those anyway; then eliminate spw + g_signal_connect( G_OBJECT(spw), "modify_selection", + G_CALLBACK(fillnstroke_selection_modified), + psel ); + + g_signal_connect( G_OBJECT(spw), "change_selection", + G_CALLBACK(fillnstroke_selection_changed), + psel ); + + g_signal_connect( INKSCAPE, "change_subselection", + G_CALLBACK(fillnstroke_subselection_changed), + spw ); + + if (kind == STROKE) { + g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", + G_CALLBACK(fillnstroke_transientize_called), + spw ); + } + + g_signal_connect( G_OBJECT(psel), "mode_changed", + G_CALLBACK(fillnstroke_paint_mode_changed), + spw ); + + g_signal_connect( G_OBJECT(psel), "dragged", + G_CALLBACK(fillnstroke_paint_dragged), + spw ); + + g_signal_connect( G_OBJECT(psel), "changed", + G_CALLBACK(fillnstroke_paint_changed), + spw ); + + if (kind == FILL) { + g_signal_connect( G_OBJECT(psel), "fillrule_changed", + G_CALLBACK(fillnstroke_fillrule_changed), + spw ); + } + + fillnstroke_performUpdate(SP_WIDGET(spw)); + return spw; } +static void fillnstroke_constructed( SPWidget *spw, SPPaintSelector * /*psel*/ ) +{ +#ifdef SP_FS_VERBOSE + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; + g_print( "[%s] style widget constructed: inkscape %p\n", + (kind == FILL) ? "fill" : "style", + spw->inkscape ); +#endif + if (spw->inkscape) { + fillnstroke_performUpdate(spw); + } + +} + /** - * On signal modified, invokes an update of the stroke style paint object. + * On signal modified, invokes an update of the fill or stroke style paint object. */ -static void -sp_stroke_style_paint_selection_modified( SPWidget *spw, - Inkscape::Selection */*selection*/, - guint flags, - SPPaintSelector */*psel*/ ) +static void fillnstroke_selection_modified( SPWidget *spw, + Inkscape::Selection * /*selection*/, + guint flags, + SPPaintSelector * /*psel*/ ) { - if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | + if (flags & ( SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG) ) { - sp_stroke_style_paint_update(spw); +#ifdef SP_FS_VERBOSE + g_message("fillnstroke_selection_modified()"); +#endif + fillnstroke_performUpdate(spw); } } - /** - * On signal selection changed, invokes an update of the stroke style paint object. + * On signal selection changed, invokes an update of the fill or stroke style paint object. */ -static void -sp_stroke_style_paint_selection_changed( SPWidget *spw, - Inkscape::Selection */*selection*/, - SPPaintSelector */*psel*/ ) +static void fillnstroke_selection_changed( SPWidget *spw, + Inkscape::Selection * /*selection*/, + SPPaintSelector * /*psel*/ ) { - sp_stroke_style_paint_update (spw); + fillnstroke_performUpdate(spw); } - /** - * On signal change subselection, invoke an update of the stroke style widget. + * On signal change subselection, invoke an update of the fill or stroke style widget. */ -static void -sp_stroke_style_widget_change_subselection( Inkscape::Application */*inkscape*/, - SPDesktop */*desktop*/, - SPWidget *spw ) +static void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, + SPDesktop * /*desktop*/, + SPWidget *spw ) { - sp_stroke_style_paint_update (spw); + fillnstroke_performUpdate(spw); } /** - * Gets the active stroke style property, then sets the appropriate color, alpha, gradient, - * pattern, etc. for the paint-selector. + * Gets the active fill or stroke style property, then sets the appropriate + * color, alpha, gradient, pattern, etc. for the paint-selector. + * + * @param sel Selection to use, or NULL. */ -static void -sp_stroke_style_paint_update (SPWidget *spw) +static void fillnstroke_performUpdate( SPWidget *spw ) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { + if ( g_object_get_data(G_OBJECT(spw), "update") ) { return; } - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - SPPaintSelector *psel = SP_PAINT_SELECTOR(gtk_object_get_data(GTK_OBJECT(spw), "paint-selector")); + if (kind == FILL) { + if ( g_object_get_data(G_OBJECT(spw), "local") ) { + g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(FALSE)); // local change; do nothing, but reset the flag + return; + } + } + + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + + SPPaintSelector *psel = SP_PAINT_SELECTOR(g_object_get_data(G_OBJECT(spw), "paint-selector")); // create temporary style - SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - // query into it - int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE); + SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + + // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection + int result = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); + + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; + SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity; switch (result) { case QUERY_STYLE_NOTHING: @@ -197,36 +266,41 @@ sp_stroke_style_paint_update (SPWidget *spw) case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector case QUERY_STYLE_MULTIPLE_SAME: { - SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, false); + SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind == FILL); psel->setMode(pselmode); - if (query->stroke.set && query->stroke.isPaintserver()) { + if (kind == FILL) { + psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO? + SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD); + } + + if (targPaint.set && targPaint.isColor()) { + psel->setColorAlpha(targPaint.value.color, SP_SCALE24_TO_FLOAT(targOpacity.value)); + } else if (targPaint.set && targPaint.isPaintserver()) { - SPPaintServer *server = SP_STYLE_STROKE_SERVER (query); + SPPaintServer *server = (kind == FILL) ? query->getFillPaintServer() : query->getStrokePaintServer(); - if (server && server->isSwatch()) { + if (server && SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setSwatch( vector ); - } else if (SP_IS_LINEARGRADIENT (server)) { + } else if (SP_IS_LINEARGRADIENT(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setGradientLinear( vector ); - SPLinearGradient *lg = SP_LINEARGRADIENT (server); + SPLinearGradient *lg = SP_LINEARGRADIENT(server); psel->setGradientProperties( SP_GRADIENT_UNITS(lg), SP_GRADIENT_SPREAD(lg) ); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if (SP_IS_RADIALGRADIENT(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setGradientRadial( vector ); - SPRadialGradient *rg = SP_RADIALGRADIENT (server); + SPRadialGradient *rg = SP_RADIALGRADIENT(server); psel->setGradientProperties( SP_GRADIENT_UNITS(rg), SP_GRADIENT_SPREAD(rg) ); - } else if (SP_IS_PATTERN (server)) { - SPPattern *pat = pattern_getroot (SP_PATTERN (server)); + } else if (SP_IS_PATTERN(server)) { + SPPattern *pat = pattern_getroot(SP_PATTERN(server)); psel->updatePatternList( pat ); } - } else if (query->stroke.set && query->stroke.isColor()) { - psel->setColorAlpha(query->stroke.value.color, SP_SCALE24_TO_FLOAT(query->stroke_opacity.value)); } break; } @@ -240,83 +314,145 @@ sp_stroke_style_paint_update (SPWidget *spw) sp_style_unref(query); - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } /** * When the mode is changed, invoke a regular changed handler. */ -static void -sp_stroke_style_paint_mode_changed( SPPaintSelector *psel, +static void fillnstroke_paint_mode_changed( SPPaintSelector *psel, SPPaintSelector::Mode /*mode*/, SPWidget *spw ) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } +#ifdef SP_FS_VERBOSE + g_message("fillnstroke_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw); +#endif + /* TODO: Does this work? * Not really, here we have to get old color back from object * Instead of relying on paint widget having meaningful colors set */ - sp_stroke_style_paint_changed(psel, spw); + fillnstroke_paint_changed(psel, spw); +} + +static void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, + SPPaintSelector::FillRule mode, + SPWidget *spw ) +{ + if (g_object_get_data(G_OBJECT(spw), "update")) { + return; + } + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "fill-rule", mode == SPPaintSelector::FILLRULE_EVENODD? "evenodd":"nonzero"); + + sp_desktop_set_style(desktop, css); + + sp_repr_css_attr_unref(css); + css = 0; + + sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, + _("Change fill rule")); } -static gchar const *const undo_label_1 = "stroke:flatcolor:1"; -static gchar const *const undo_label_2 = "stroke:flatcolor:2"; -static gchar const *undo_label = undo_label_1; +static gchar const *undo_F_label_1 = "fill:flatcolor:1"; +static gchar const *undo_F_label_2 = "fill:flatcolor:2"; + +static gchar const *undo_S_label_1 = "stroke:flatcolor:1"; +static gchar const *undo_S_label_2 = "stroke:flatcolor:2"; + +static gchar const *undo_F_label = undo_F_label_1; +static gchar const *undo_S_label = undo_S_label_1; /** - * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK - * color mode, then set the stroke opacity to psel's flat color. + * This is called repeatedly while you are dragging a color slider, only for flat color + * modes. Previously it set the color in style but did not update the repr for efficiency, however + * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except + * lumps all its changes for undo. */ -static void -sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw) +static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { + if (!spw->inkscape) { + return; + } + + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; + + if (kind == FILL) { + if (g_object_get_data(G_OBJECT(spw), "local")) { + // previous local flag not cleared yet; + // this means dragged events come too fast, so we better skip this one to speed up display + // (it's safe to do this in any case) + return; + } + } + + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + switch (psel->mode) { case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { - psel->setFlatColor( SP_ACTIVE_DESKTOP, "stroke", "stroke-opacity" ); - sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE, - _("Set stroke color")); + psel->setFlatColor( SP_ACTIVE_DESKTOP, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); + sp_document_maybe_done(sp_desktop_document(SP_ACTIVE_DESKTOP), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set fill color") : _("Set stroke color")); + if (kind == FILL) { + g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(TRUE)); // local change, do not update from selection + } break; } default: g_warning( "file %s: line %d: Paint %d should not emit 'dragged'", - __FILE__, __LINE__, psel->mode); + __FILE__, __LINE__, psel->mode ); break; } + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } /** - * When the stroke style's paint settings change, this handler updates the - * repr's stroke css style and applies the style to relevant drawing items. +This is called (at least) when: +1 paint selector mode is switched (e.g. flat color -> gradient) +2 you finished dragging a gradient node and released mouse +3 you changed a gradient selector parameter (e.g. spread) +Must update repr. */ -static void -sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw) +static void fillnstroke_paint_changed( SPPaintSelector *psel, SPWidget *spw ) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { +#ifdef SP_FS_VERBOSE + g_message("fillnstroke_paint_changed(psel:%p, spw:%p)", psel, spw); +#endif + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + + FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPDocument *document = sp_desktop_document (desktop); - Inkscape::Selection *selection = sp_desktop_selection (desktop); + if (!desktop) { + return; + } + SPDocument *document = sp_desktop_document(desktop); + Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); switch (psel->mode) { case SPPaintSelector::MODE_EMPTY: // This should not happen. - g_warning ( "file %s: line %d: Paint %d should not emit 'changed'", - __FILE__, __LINE__, psel->mode); + g_warning( "file %s: line %d: Paint %d should not emit 'changed'", + __FILE__, __LINE__, psel->mode); break; case SPPaintSelector::MODE_MULTIPLE: // This happens when you switch multiple objects with different gradients to flat color; @@ -326,75 +462,118 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw) case SPPaintSelector::MODE_NONE: { SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, "stroke", "none"); + sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none"); - sp_desktop_set_style (desktop, css); + sp_desktop_set_style(desktop, css); sp_repr_css_attr_unref(css); + css = 0; sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - _("Remove stroke")); + (kind == FILL) ? _("Remove fill") : _("Remove stroke")); break; } case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { - psel->setFlatColor(desktop, "stroke", "stroke-opacity"); - sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE, - _("Set stroke color")); + if (kind == FILL) { + // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); + } + + psel->setFlatColor( desktop, + (kind == FILL) ? "fill" : "stroke", + (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); + sp_document_maybe_done(sp_desktop_document(desktop), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set fill color") : _("Set stroke color")); + + if (kind == FILL) { + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); + } // on release, toggle undo_label so that the next drag will not be lumped with this one - if (undo_label == undo_label_1) - undo_label = undo_label_2; - else - undo_label = undo_label_1; + if (undo_F_label == undo_F_label_1) { + undo_F_label = undo_F_label_2; + undo_S_label = undo_S_label_2; + } else { + undo_F_label = undo_F_label_1; + undo_S_label = undo_S_label_1; + } break; } case SPPaintSelector::MODE_GRADIENT_LINEAR: case SPPaintSelector::MODE_GRADIENT_RADIAL: + case SPPaintSelector::MODE_SWATCH: if (items) { - SPGradientType const gradient_type = ( psel->mode == SPPaintSelector::MODE_GRADIENT_LINEAR + SPGradientType const gradient_type = ( psel->mode != SPPaintSelector::MODE_GRADIENT_RADIAL ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL ); + + SPCSSAttr *css = 0; + if (kind == FILL) { + // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs + css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "fill-opacity", "1.0"); + } + SPGradient *vector = psel->getGradientVector(); if (!vector) { /* No vector in paint selector should mean that we just changed mode */ - SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - int result = objects_query_fillstroke ((GSList *) items, query, false); + SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; guint32 common_rgb = 0; if (result == QUERY_STYLE_MULTIPLE_SAME) { - if (!query->fill.isColor()) { - common_rgb = sp_desktop_get_color(desktop, false); + if (!targPaint.isColor()) { + common_rgb = sp_desktop_get_color(desktop, kind == FILL); } else { - common_rgb = query->stroke.value.color.toRGBA32( 0xff ); + common_rgb = targPaint.value.color.toRGBA32( 0xff ); } vector = sp_document_default_gradient_vector(document, common_rgb); } sp_style_unref(query); for (GSList const *i = items; i != NULL; i = i->next) { + //FIXME: see above + if (kind == FILL) { + sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + } + if (!vector) { sp_item_set_gradient(SP_ITEM(i->data), - sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), false), - gradient_type, false); + sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL), + gradient_type, kind == FILL); } else { - sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false); + sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); } } } else { + // We have changed from another gradient type, or modified spread/units within + // this gradient type. vector = sp_gradient_ensure_vector_normalized(vector); for (GSList const *i = items; i != NULL; i = i->next) { - SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false); + //FIXME: see above + if (kind == FILL) { + sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + } + + SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); psel->pushAttrsToGradient( gr ); } } + if (css) { + sp_repr_css_attr_unref(css); + css = 0; + } + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - _("Set gradient on stroke")); + (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke")); } break; @@ -411,59 +590,77 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw) } else { Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern); - SPCSSAttr *css = sp_repr_css_attr_new (); - gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id")); - sp_repr_css_set_property (css, "stroke", urltext); + SPCSSAttr *css = sp_repr_css_attr_new(); + gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id")); + sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext); - for (GSList const *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *selrepr = SP_OBJECT_REPR (i->data); - SPObject *selobj = SP_OBJECT (i->data); - if (!selrepr) - continue; + // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs + if (kind == FILL) { + sp_repr_css_set_property(css, "fill-opacity", "1.0"); + } - SPStyle *style = SP_OBJECT_STYLE (selobj); - if (style && style->stroke.isPaintserver()) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (selobj); - if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern) - // only if this object's pattern is not rooted in our selected pattern, apply - continue; - } + // cannot just call sp_desktop_set_style, because we don't want to touch those + // objects who already have the same root pattern but through a different href + // chain. FIXME: move this to a sp_item_set_pattern + for (GSList const *i = items; i != NULL; i = i->next) { + Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data); + if ( (kind == STROKE) && !selrepr) { + continue; + } + SPObject *selobj = SP_OBJECT(i->data); + + SPStyle *style = SP_OBJECT_STYLE(selobj); + if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) { + SPObject *server = (kind == FILL) ? + SP_OBJECT_STYLE_FILL_SERVER(selobj) : + SP_OBJECT_STYLE_STROKE_SERVER(selobj); + if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern) + // only if this object's pattern is not rooted in our selected pattern, apply + continue; + } - sp_repr_css_change_recursive (selrepr, css, "style"); - } + if (kind == FILL) { + sp_desktop_apply_css_recursive(selobj, css, true); + } else { + sp_repr_css_change_recursive(selrepr, css, "style"); + } + } - sp_repr_css_attr_unref (css); - g_free (urltext); + sp_repr_css_attr_unref(css); + css = 0; + g_free(urltext); } // end if - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Set pattern on stroke")); + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Set pattern on fill") : + _("Set pattern on stroke")); } // end if break; - case SPPaintSelector::MODE_SWATCH: - // TODO - break; - case SPPaintSelector::MODE_UNSET: if (items) { - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_unset_property (css, "stroke"); - sp_repr_css_unset_property (css, "stroke-opacity"); - sp_repr_css_unset_property (css, "stroke-width"); - sp_repr_css_unset_property (css, "stroke-miterlimit"); - sp_repr_css_unset_property (css, "stroke-linejoin"); - sp_repr_css_unset_property (css, "stroke-linecap"); - sp_repr_css_unset_property (css, "stroke-dashoffset"); - sp_repr_css_unset_property (css, "stroke-dasharray"); - - sp_desktop_set_style (desktop, css); - sp_repr_css_attr_unref (css); - - sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, - _("Unset stroke")); + SPCSSAttr *css = sp_repr_css_attr_new(); + if (kind == FILL) { + sp_repr_css_unset_property(css, "fill"); + } else { + sp_repr_css_unset_property(css, "stroke"); + sp_repr_css_unset_property(css, "stroke-opacity"); + sp_repr_css_unset_property(css, "stroke-width"); + sp_repr_css_unset_property(css, "stroke-miterlimit"); + sp_repr_css_unset_property(css, "stroke-linejoin"); + sp_repr_css_unset_property(css, "stroke-linecap"); + sp_repr_css_unset_property(css, "stroke-dashoffset"); + sp_repr_css_unset_property(css, "stroke-dasharray"); + } + + sp_desktop_set_style(desktop, css); + sp_repr_css_attr_unref(css); + css = 0; + + sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, + (kind == FILL) ? _("Unset fill") : _("Unset stroke")); } break; @@ -475,10 +672,19 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw) break; } - g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } +static void fillnstroke_transientize_called(Inkscape::Application * /*inkscape*/, + SPDesktop * /*desktop*/, + SPWidget * /*spw*/ ) +{ +// TODO: Either of these will cause crashes sometimes +// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL); +// ink_markers_menu_update(spw); +} + @@ -537,25 +743,15 @@ sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon, } -static void -sp_stroke_style_widget_transientize_callback(Inkscape::Application */*inkscape*/, - SPDesktop */*desktop*/, - SPWidget */*spw*/ ) -{ -// TODO: Either of these will cause crashes sometimes -// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL); -// ink_markers_menu_update(spw); -} - /** - * Creates a copy of the marker named mname, determines its visible and renderable + * Create sa copy of the marker named mname, determines its visible and renderable * area in menu_id's bounding box, and then renders it. This allows us to fill in * preview images of each marker in the marker menu. */ static Gtk::Image * sp_marker_prev_new(unsigned psize, gchar const *mname, SPDocument *source, SPDocument *sandbox, - gchar const *menu_id, NRArena const */*arena*/, unsigned /*visionkey*/, NRArenaItem *root) + gchar const *menu_id, NRArena const * /*arena*/, unsigned /*visionkey*/, NRArenaItem *root) { // Retrieve the marker named 'mname' from the source SVG document SPObject const *marker = source->getObjectById(mname); @@ -699,7 +895,7 @@ sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPD * */ static void -sp_marker_list_from_doc (Gtk::Menu *m, SPDocument */*current_doc*/, SPDocument *source, SPDocument */*markers_doc*/, SPDocument *sandbox, gchar const *menu_id) +sp_marker_list_from_doc (Gtk::Menu *m, SPDocument * /*current_doc*/, SPDocument *source, SPDocument * /*markers_doc*/, SPDocument *sandbox, gchar const *menu_id) { GSList *ml = ink_marker_list_get(source); GSList *clean_ml = NULL; @@ -808,7 +1004,7 @@ ink_marker_menu_create_menu(Gtk::Menu *m, gchar const *menu_id, SPDocument *doc, * Creates a menu widget to display markers from markers.svg */ static Gtk::OptionMenu * -ink_marker_menu(Gtk::Widget */*tbl*/, gchar const *menu_id, SPDocument *sandbox) +ink_marker_menu(Gtk::Widget * /*tbl*/, gchar const *menu_id, SPDocument *sandbox) { SPDesktop *desktop = inkscape_active_desktop(); SPDocument *doc = sp_desktop_document(desktop); @@ -903,6 +1099,7 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh } sp_repr_css_attr_unref(css); + css = 0; sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, _("Set markers")); @@ -1269,12 +1466,12 @@ sp_stroke_style_line_widget_new(void) // FIXME: we cheat and still use gtk+ signals - gtk_signal_connect(GTK_OBJECT(spw_old), "modify_selection", - GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_modified), - spw); - gtk_signal_connect(GTK_OBJECT(spw_old), "change_selection", - GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_changed), - spw); + g_signal_connect(G_OBJECT(spw_old), "modify_selection", + G_CALLBACK(sp_stroke_style_line_selection_modified), + spw); + g_signal_connect(G_OBJECT(spw_old), "change_selection", + G_CALLBACK(sp_stroke_style_line_selection_changed), + spw); sp_stroke_style_line_update(spw, desktop ? sp_desktop_selection(desktop) : NULL); @@ -1393,6 +1590,8 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel) spw->set_data("update", GINT_TO_POINTER(TRUE)); + FillOrStroke kind = GPOINTER_TO_INT(spw->get_data("kind")) ? FILL : STROKE; + Gtk::Table *sset = static_cast(spw->get_data("stroke")); Gtk::Adjustment *width = static_cast(spw->get_data("width")); Gtk::Adjustment *ml = static_cast(spw->get_data("miterlimit")); @@ -1406,10 +1605,11 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel) int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT); int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP); int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN); + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; if (!sel || sel->isEmpty()) { // Nothing selected, grey-out all controls in the stroke-style dialog - sset->set_sensitive(false); + sset->set_sensitive(false); spw->set_data("update", GINT_TO_POINTER(FALSE)); @@ -1439,7 +1639,7 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel) // if none of the selected objects has a stroke, than quite some controls should be disabled // The markers might still be shown though, so these will not be disabled - bool enabled = (result_sw != QUERY_STYLE_NOTHING) && !query->stroke.isNoneSet(); + bool enabled = (result_sw != QUERY_STYLE_NOTHING) && !targPaint.isNoneSet(); /* No objects stroked, set insensitive */ Gtk::RadioButton *tb = NULL; tb = static_cast(spw->get_data("miter join")); @@ -1454,11 +1654,11 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel) sb->set_sensitive(enabled); tb = static_cast(spw->get_data("cap butt")); - tb->set_sensitive(enabled); - tb = static_cast(spw->get_data("cap round")); - tb->set_sensitive(enabled); - tb = static_cast(spw->get_data("cap square")); - tb->set_sensitive(enabled); + tb->set_sensitive(enabled); + tb = static_cast(spw->get_data("cap round")); + tb->set_sensitive(enabled); + tb = static_cast(spw->get_data("cap square")); + tb->set_sensitive(enabled); dsel->set_sensitive(enabled); } @@ -1604,6 +1804,7 @@ sp_stroke_style_scale_line(Gtk::Container *spw) sp_desktop_set_style (desktop, css, false); sp_repr_css_attr_unref(css); + css = 0; sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, _("Set stroke style")); @@ -1700,6 +1901,7 @@ sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw) } sp_repr_css_attr_unref(css); + css = 0; sp_document_done(sp_desktop_document(desktop), SP_VERB_DIALOG_FILL_STROKE, _("Set stroke style")); diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h index b947209e3..9ed7e2a92 100644 --- a/src/widgets/stroke-style.h +++ b/src/widgets/stroke-style.h @@ -3,25 +3,25 @@ */ /* Author: * Lauris Kaplinski + * Jon A. Cruz * + * Copyright (C) 2010 Jon A. Cruz * Copyright (C) 2001 Ximian, Inc. + * * Released under GNU GPL, read the file 'COPYING' for more information */ #ifndef SEEN_DIALOGS_STROKE_STYLE_H #define SEEN_DIALOGS_STROKE_STYLE_H -#include - -#include +#include -#include "forward.h" -#include "display/canvas-bpath.h" +typedef struct _GtkWidget GtkWidget; -GtkWidget *sp_stroke_style_paint_widget_new (void); -Gtk::Container *sp_stroke_style_line_widget_new (void); +GtkWidget *sp_stroke_style_paint_widget_new(void); +Gtk::Container *sp_stroke_style_line_widget_new(void); -#endif +#endif // SEEN_DIALOGS_STROKE_STYLE_H /* Local Variables: -- cgit v1.2.3 From c94f9de0a6c484f837cfce3adbfcf7f8275e8cc5 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 27 Mar 2010 01:10:31 -0700 Subject: Phase 2 - remove duplicated code and leave a single copy of each function. (bzr r9239) --- src/widgets/stroke-style.cpp | 612 +------------------------------------------ 1 file changed, 1 insertion(+), 611 deletions(-) (limited to 'src') diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 54678dbb8..d6a38f978 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -58,34 +58,6 @@ #include "stroke-style.h" #include "fill-n-stroke-factory.h" -namespace Inkscape { -namespace Widgets { -GtkWidget *createStyleWidgetS( FillOrStroke kind ); -} -} - - -// These can be deleted once we sort out the libart dependence. - -#define ART_WIND_RULE_NONZERO 0 - -/* Paint */ - -static void fillnstroke_constructed(SPWidget *spw, SPPaintSelector *psel); -static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, SPWidget *spw); - -static void fillnstroke_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel); -static void fillnstroke_selection_changed(SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel); -static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); - -static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw); -static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw); -static void fillnstroke_paint_changed(SPPaintSelector *psel, SPWidget *spw); - -static void fillnstroke_transientize_called(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); - -static void fillnstroke_performUpdate(SPWidget *spw); - /** Marker selection option menus */ static Gtk::OptionMenu * marker_start_menu = NULL; static Gtk::OptionMenu * marker_mid_menu = NULL; @@ -102,591 +74,9 @@ static Inkscape::UI::Cache::SvgPreview svg_preview_cache; GtkWidget *sp_stroke_style_paint_widget_new(void) { - return Inkscape::Widgets::createStyleWidgetS( STROKE ); -} - -/** - * Create the fill or stroke style widget, and hook up all the signals. - */ -GtkWidget *Inkscape::Widgets::createStyleWidgetS( FillOrStroke kind ) -{ - GtkWidget *spw = sp_widget_new_global(INKSCAPE); - - // with or without fillrule selector - GtkWidget *psel = sp_paint_selector_new(kind == FILL); - gtk_widget_show(psel); - gtk_container_add(GTK_CONTAINER(spw), psel); - g_object_set_data(G_OBJECT(spw), "paint-selector", psel); - g_object_set_data(G_OBJECT(spw), "kind", GINT_TO_POINTER(kind)); - - if (kind == FILL) { - g_signal_connect( G_OBJECT(spw), "construct", - G_CALLBACK(fillnstroke_constructed), - psel ); - } - -//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates -//those anyway; then eliminate spw - g_signal_connect( G_OBJECT(spw), "modify_selection", - G_CALLBACK(fillnstroke_selection_modified), - psel ); - - g_signal_connect( G_OBJECT(spw), "change_selection", - G_CALLBACK(fillnstroke_selection_changed), - psel ); - - g_signal_connect( INKSCAPE, "change_subselection", - G_CALLBACK(fillnstroke_subselection_changed), - spw ); - - if (kind == STROKE) { - g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", - G_CALLBACK(fillnstroke_transientize_called), - spw ); - } - - g_signal_connect( G_OBJECT(psel), "mode_changed", - G_CALLBACK(fillnstroke_paint_mode_changed), - spw ); - - g_signal_connect( G_OBJECT(psel), "dragged", - G_CALLBACK(fillnstroke_paint_dragged), - spw ); - - g_signal_connect( G_OBJECT(psel), "changed", - G_CALLBACK(fillnstroke_paint_changed), - spw ); - - if (kind == FILL) { - g_signal_connect( G_OBJECT(psel), "fillrule_changed", - G_CALLBACK(fillnstroke_fillrule_changed), - spw ); - } - - fillnstroke_performUpdate(SP_WIDGET(spw)); - - return spw; -} - -static void fillnstroke_constructed( SPWidget *spw, SPPaintSelector * /*psel*/ ) -{ -#ifdef SP_FS_VERBOSE - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - g_print( "[%s] style widget constructed: inkscape %p\n", - (kind == FILL) ? "fill" : "style", - spw->inkscape ); -#endif - if (spw->inkscape) { - fillnstroke_performUpdate(spw); - } - -} - -/** - * On signal modified, invokes an update of the fill or stroke style paint object. - */ -static void fillnstroke_selection_modified( SPWidget *spw, - Inkscape::Selection * /*selection*/, - guint flags, - SPPaintSelector * /*psel*/ ) -{ - if (flags & ( SP_OBJECT_MODIFIED_FLAG | - SP_OBJECT_PARENT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG) ) { -#ifdef SP_FS_VERBOSE - g_message("fillnstroke_selection_modified()"); -#endif - fillnstroke_performUpdate(spw); - } -} - -/** - * On signal selection changed, invokes an update of the fill or stroke style paint object. - */ -static void fillnstroke_selection_changed( SPWidget *spw, - Inkscape::Selection * /*selection*/, - SPPaintSelector * /*psel*/ ) -{ - fillnstroke_performUpdate(spw); -} - -/** - * On signal change subselection, invoke an update of the fill or stroke style widget. - */ -static void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, - SPDesktop * /*desktop*/, - SPWidget *spw ) -{ - fillnstroke_performUpdate(spw); -} - -/** - * Gets the active fill or stroke style property, then sets the appropriate - * color, alpha, gradient, pattern, etc. for the paint-selector. - * - * @param sel Selection to use, or NULL. - */ -static void fillnstroke_performUpdate( SPWidget *spw ) -{ - if ( g_object_get_data(G_OBJECT(spw), "update") ) { - return; - } - - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - - if (kind == FILL) { - if ( g_object_get_data(G_OBJECT(spw), "local") ) { - g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(FALSE)); // local change; do nothing, but reset the flag - return; - } - } - - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - - SPPaintSelector *psel = SP_PAINT_SELECTOR(g_object_get_data(G_OBJECT(spw), "paint-selector")); - - // create temporary style - SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); - - // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection - int result = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); - - SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; - SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity; - - switch (result) { - case QUERY_STYLE_NOTHING: - { - /* No paint at all */ - psel->setMode(SPPaintSelector::MODE_EMPTY); - break; - } - - case QUERY_STYLE_SINGLE: - case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector - case QUERY_STYLE_MULTIPLE_SAME: - { - SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind == FILL); - psel->setMode(pselmode); - - if (kind == FILL) { - psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO? - SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD); - } - - if (targPaint.set && targPaint.isColor()) { - psel->setColorAlpha(targPaint.value.color, SP_SCALE24_TO_FLOAT(targOpacity.value)); - } else if (targPaint.set && targPaint.isPaintserver()) { - - SPPaintServer *server = (kind == FILL) ? query->getFillPaintServer() : query->getStrokePaintServer(); - - if (server && SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()) { - SPGradient *vector = SP_GRADIENT(server)->getVector(); - psel->setSwatch( vector ); - } else if (SP_IS_LINEARGRADIENT(server)) { - SPGradient *vector = SP_GRADIENT(server)->getVector(); - psel->setGradientLinear( vector ); - - SPLinearGradient *lg = SP_LINEARGRADIENT(server); - psel->setGradientProperties( SP_GRADIENT_UNITS(lg), - SP_GRADIENT_SPREAD(lg) ); - } else if (SP_IS_RADIALGRADIENT(server)) { - SPGradient *vector = SP_GRADIENT(server)->getVector(); - psel->setGradientRadial( vector ); - - SPRadialGradient *rg = SP_RADIALGRADIENT(server); - psel->setGradientProperties( SP_GRADIENT_UNITS(rg), - SP_GRADIENT_SPREAD(rg) ); - } else if (SP_IS_PATTERN(server)) { - SPPattern *pat = pattern_getroot(SP_PATTERN(server)); - psel->updatePatternList( pat ); - } - } - break; - } - - case QUERY_STYLE_MULTIPLE_DIFFERENT: - { - psel->setMode(SPPaintSelector::MODE_MULTIPLE); - break; - } - } - - sp_style_unref(query); - - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); -} - -/** - * When the mode is changed, invoke a regular changed handler. - */ -static void fillnstroke_paint_mode_changed( SPPaintSelector *psel, - SPPaintSelector::Mode /*mode*/, - SPWidget *spw ) -{ - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - -#ifdef SP_FS_VERBOSE - g_message("fillnstroke_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw); -#endif - - /* TODO: Does this work? - * Not really, here we have to get old color back from object - * Instead of relying on paint widget having meaningful colors set - */ - fillnstroke_paint_changed(psel, spw); + return Inkscape::Widgets::createStyleWidget( STROKE ); } -static void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, - SPPaintSelector::FillRule mode, - SPWidget *spw ) -{ - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, "fill-rule", mode == SPPaintSelector::FILLRULE_EVENODD? "evenodd":"nonzero"); - - sp_desktop_set_style(desktop, css); - - sp_repr_css_attr_unref(css); - css = 0; - - sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, - _("Change fill rule")); -} - -static gchar const *undo_F_label_1 = "fill:flatcolor:1"; -static gchar const *undo_F_label_2 = "fill:flatcolor:2"; - -static gchar const *undo_S_label_1 = "stroke:flatcolor:1"; -static gchar const *undo_S_label_2 = "stroke:flatcolor:2"; - -static gchar const *undo_F_label = undo_F_label_1; -static gchar const *undo_S_label = undo_S_label_1; - -/** - * This is called repeatedly while you are dragging a color slider, only for flat color - * modes. Previously it set the color in style but did not update the repr for efficiency, however - * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except - * lumps all its changes for undo. - */ -static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw) -{ - if (!spw->inkscape) { - return; - } - - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - - if (kind == FILL) { - if (g_object_get_data(G_OBJECT(spw), "local")) { - // previous local flag not cleared yet; - // this means dragged events come too fast, so we better skip this one to speed up display - // (it's safe to do this in any case) - return; - } - } - - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - - switch (psel->mode) { - case SPPaintSelector::MODE_COLOR_RGB: - case SPPaintSelector::MODE_COLOR_CMYK: - { - psel->setFlatColor( SP_ACTIVE_DESKTOP, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); - sp_document_maybe_done(sp_desktop_document(SP_ACTIVE_DESKTOP), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Set fill color") : _("Set stroke color")); - if (kind == FILL) { - g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(TRUE)); // local change, do not update from selection - } - break; - } - - default: - g_warning( "file %s: line %d: Paint %d should not emit 'dragged'", - __FILE__, __LINE__, psel->mode ); - break; - } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); -} - -/** -This is called (at least) when: -1 paint selector mode is switched (e.g. flat color -> gradient) -2 you finished dragging a gradient node and released mouse -3 you changed a gradient selector parameter (e.g. spread) -Must update repr. - */ -static void fillnstroke_paint_changed( SPPaintSelector *psel, SPWidget *spw ) -{ -#ifdef SP_FS_VERBOSE - g_message("fillnstroke_paint_changed(psel:%p, spw:%p)", psel, spw); -#endif - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { - return; - } - SPDocument *document = sp_desktop_document(desktop); - Inkscape::Selection *selection = sp_desktop_selection(desktop); - - GSList const *items = selection->itemList(); - - switch (psel->mode) { - case SPPaintSelector::MODE_EMPTY: - // This should not happen. - g_warning( "file %s: line %d: Paint %d should not emit 'changed'", - __FILE__, __LINE__, psel->mode); - break; - case SPPaintSelector::MODE_MULTIPLE: - // This happens when you switch multiple objects with different gradients to flat color; - // nothing to do here. - break; - - case SPPaintSelector::MODE_NONE: - { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none"); - - sp_desktop_set_style(desktop, css); - - sp_repr_css_attr_unref(css); - css = 0; - - sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Remove fill") : _("Remove stroke")); - break; - } - - case SPPaintSelector::MODE_COLOR_RGB: - case SPPaintSelector::MODE_COLOR_CMYK: - { - if (kind == FILL) { - // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events - sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); - } - - psel->setFlatColor( desktop, - (kind == FILL) ? "fill" : "stroke", - (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); - sp_document_maybe_done(sp_desktop_document(desktop), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Set fill color") : _("Set stroke color")); - - if (kind == FILL) { - // resume interruptibility - sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); - } - - // on release, toggle undo_label so that the next drag will not be lumped with this one - if (undo_F_label == undo_F_label_1) { - undo_F_label = undo_F_label_2; - undo_S_label = undo_S_label_2; - } else { - undo_F_label = undo_F_label_1; - undo_S_label = undo_S_label_1; - } - - break; - } - - case SPPaintSelector::MODE_GRADIENT_LINEAR: - case SPPaintSelector::MODE_GRADIENT_RADIAL: - case SPPaintSelector::MODE_SWATCH: - if (items) { - SPGradientType const gradient_type = ( psel->mode != SPPaintSelector::MODE_GRADIENT_RADIAL - ? SP_GRADIENT_TYPE_LINEAR - : SP_GRADIENT_TYPE_RADIAL ); - - SPCSSAttr *css = 0; - if (kind == FILL) { - // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs - css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, "fill-opacity", "1.0"); - } - - SPGradient *vector = psel->getGradientVector(); - if (!vector) { - /* No vector in paint selector should mean that we just changed mode */ - - SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); - int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); - SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; - guint32 common_rgb = 0; - if (result == QUERY_STYLE_MULTIPLE_SAME) { - if (!targPaint.isColor()) { - common_rgb = sp_desktop_get_color(desktop, kind == FILL); - } else { - common_rgb = targPaint.value.color.toRGBA32( 0xff ); - } - vector = sp_document_default_gradient_vector(document, common_rgb); - } - sp_style_unref(query); - - for (GSList const *i = items; i != NULL; i = i->next) { - //FIXME: see above - if (kind == FILL) { - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); - } - - if (!vector) { - sp_item_set_gradient(SP_ITEM(i->data), - sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL), - gradient_type, kind == FILL); - } else { - sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); - } - } - } else { - // We have changed from another gradient type, or modified spread/units within - // this gradient type. - vector = sp_gradient_ensure_vector_normalized(vector); - for (GSList const *i = items; i != NULL; i = i->next) { - //FIXME: see above - if (kind == FILL) { - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); - } - - SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); - psel->pushAttrsToGradient( gr ); - } - } - - if (css) { - sp_repr_css_attr_unref(css); - css = 0; - } - - sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke")); - } - break; - - case SPPaintSelector::MODE_PATTERN: - - if (items) { - - SPPattern *pattern = psel->getPattern(); - if (!pattern) { - - /* No Pattern in paint selector should mean that we just - * changed mode - dont do jack. - */ - - } else { - Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern); - SPCSSAttr *css = sp_repr_css_attr_new(); - gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id")); - sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext); - - // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs - if (kind == FILL) { - sp_repr_css_set_property(css, "fill-opacity", "1.0"); - } - - // cannot just call sp_desktop_set_style, because we don't want to touch those - // objects who already have the same root pattern but through a different href - // chain. FIXME: move this to a sp_item_set_pattern - for (GSList const *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data); - if ( (kind == STROKE) && !selrepr) { - continue; - } - SPObject *selobj = SP_OBJECT(i->data); - - SPStyle *style = SP_OBJECT_STYLE(selobj); - if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) { - SPObject *server = (kind == FILL) ? - SP_OBJECT_STYLE_FILL_SERVER(selobj) : - SP_OBJECT_STYLE_STROKE_SERVER(selobj); - if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern) - // only if this object's pattern is not rooted in our selected pattern, apply - continue; - } - - if (kind == FILL) { - sp_desktop_apply_css_recursive(selobj, css, true); - } else { - sp_repr_css_change_recursive(selrepr, css, "style"); - } - } - - sp_repr_css_attr_unref(css); - css = 0; - g_free(urltext); - - } // end if - - sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Set pattern on fill") : - _("Set pattern on stroke")); - } // end if - - break; - - case SPPaintSelector::MODE_UNSET: - if (items) { - SPCSSAttr *css = sp_repr_css_attr_new(); - if (kind == FILL) { - sp_repr_css_unset_property(css, "fill"); - } else { - sp_repr_css_unset_property(css, "stroke"); - sp_repr_css_unset_property(css, "stroke-opacity"); - sp_repr_css_unset_property(css, "stroke-width"); - sp_repr_css_unset_property(css, "stroke-miterlimit"); - sp_repr_css_unset_property(css, "stroke-linejoin"); - sp_repr_css_unset_property(css, "stroke-linecap"); - sp_repr_css_unset_property(css, "stroke-dashoffset"); - sp_repr_css_unset_property(css, "stroke-dasharray"); - } - - sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref(css); - css = 0; - - sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, - (kind == FILL) ? _("Unset fill") : _("Unset stroke")); - } - break; - - default: - g_warning( "file %s: line %d: Paint selector should not be in " - "mode %d", - __FILE__, __LINE__, - psel->mode ); - break; - } - - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); -} - - -static void fillnstroke_transientize_called(Inkscape::Application * /*inkscape*/, - SPDesktop * /*desktop*/, - SPWidget * /*spw*/ ) -{ -// TODO: Either of these will cause crashes sometimes -// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL); -// ink_markers_menu_update(spw); -} - - - /* Line */ -- cgit v1.2.3 From 77e16bbd9d4681532e4630de42871c265803aa37 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 27 Mar 2010 17:15:23 +0100 Subject: Fix incorrect use of std::auto_ptr in FontInstance.cpp (LP #549317) Fixed bugs: - https://launchpad.net/bugs/549317 (bzr r9240) --- src/libnrtype/FontInstance.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index be5eb86c8..50dbec61d 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -493,15 +493,15 @@ void font_instance::LoadGlyph(int glyph_id) // character has no visual representation, but is valid (eg whitespace) doAdd=true; } else { - std::auto_ptr buffer(new char[bufferSize]); - if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer.get(), &identity) <= 0 ) { + char *buffer = new char[bufferSize]; + if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) { // shit happened } else { // Platform SDK is rubbish, read KB87115 instead n_g.outline=new Path; DWORD polyOffset=0; while ( polyOffset < bufferSize ) { - TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer.get()+polyOffset); + TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset); if (polyOffset+polyHeader->cb > bufferSize) break; if (polyHeader->dwType == TT_POLYGON_TYPE) { @@ -509,7 +509,7 @@ void font_instance::LoadGlyph(int glyph_id) DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER); while ( curveOffset < polyOffset+polyHeader->cb ) { - TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer.get()+curveOffset); + TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset); POINTFX const *p=polyCurve->apfx; POINTFX const *endp=p+polyCurve->cpfx; @@ -554,6 +554,7 @@ void font_instance::LoadGlyph(int glyph_id) } doAdd=true; } + delete [] buffer; } #else if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) { -- cgit v1.2.3 From 6f7686718768091807fabc8437d53e54ef220bbe Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 27 Mar 2010 13:56:03 -0700 Subject: Phase 2b - remove use of SPWidget and wire signals directly. (bzr r9241) --- src/widgets/fill-style.cpp | 113 +++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 09c6951ad..6ea9f30b5 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -19,6 +19,7 @@ #endif #include +#include #include "desktop-handles.h" #include "desktop-style.h" @@ -32,7 +33,6 @@ #include "sp-radial-gradient.h" #include "style.h" #include "widgets/paint-selector.h" -#include "widgets/sp-widget.h" #include "xml/repr.h" #include "fill-style.h" @@ -45,20 +45,17 @@ /* Fill */ -static void fillnstroke_constructed(SPWidget *spw, SPPaintSelector *psel); -static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, SPWidget *spw); +static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, GtkWidget *spw); -static void fillnstroke_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel); -static void fillnstroke_selection_changed(SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel); -static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); +static void fillnstroke_selection_modified(Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, GtkWidget *spw); +static void fillnstroke_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, GtkWidget *spw); +static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, GtkWidget *spw); -static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw); -static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw); -static void fillnstroke_paint_changed(SPPaintSelector *psel, SPWidget *spw); +static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, GtkWidget *spw); +static void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw); +static void fillnstroke_paint_changed(SPPaintSelector *psel, GtkWidget *spw); -static void fillnstroke_transientize_called(Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw); - -static void fillnstroke_performUpdate(SPWidget *spw); +static void fillnstroke_performUpdate(GtkWidget *spw); GtkWidget *sp_fill_style_widget_new(void) { @@ -70,7 +67,8 @@ GtkWidget *sp_fill_style_widget_new(void) */ GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) { - GtkWidget *spw = sp_widget_new_global(INKSCAPE); + Inkscape::Application *appInstance = INKSCAPE; + GtkWidget *spw = gtk_vbox_new(FALSE, 0); // with or without fillrule selector GtkWidget *psel = sp_paint_selector_new(kind == FILL); @@ -79,32 +77,18 @@ GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) g_object_set_data(G_OBJECT(spw), "paint-selector", psel); g_object_set_data(G_OBJECT(spw), "kind", GINT_TO_POINTER(kind)); - if (kind == FILL) { - g_signal_connect( G_OBJECT(spw), "construct", - G_CALLBACK(fillnstroke_constructed), - psel ); - } - -//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates -//those anyway; then eliminate spw - g_signal_connect( G_OBJECT(spw), "modify_selection", + g_signal_connect( G_OBJECT(appInstance), "modify_selection", G_CALLBACK(fillnstroke_selection_modified), - psel ); + spw ); - g_signal_connect( G_OBJECT(spw), "change_selection", + g_signal_connect( G_OBJECT(appInstance), "change_selection", G_CALLBACK(fillnstroke_selection_changed), - psel ); + spw ); - g_signal_connect( INKSCAPE, "change_subselection", + g_signal_connect( G_OBJECT(appInstance), "change_subselection", G_CALLBACK(fillnstroke_subselection_changed), spw ); - if (kind == STROKE) { - g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", - G_CALLBACK(fillnstroke_transientize_called), - spw ); - } - g_signal_connect( G_OBJECT(psel), "mode_changed", G_CALLBACK(fillnstroke_paint_mode_changed), spw ); @@ -123,32 +107,18 @@ GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) spw ); } - fillnstroke_performUpdate(SP_WIDGET(spw)); + fillnstroke_performUpdate(spw); return spw; } -static void fillnstroke_constructed( SPWidget *spw, SPPaintSelector * /*psel*/ ) -{ -#ifdef SP_FS_VERBOSE - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - g_print( "[%s] style widget constructed: inkscape %p\n", - (kind == FILL) ? "fill" : "style", - spw->inkscape ); -#endif - if (spw->inkscape) { - fillnstroke_performUpdate(spw); - } - -} - /** * On signal modified, invokes an update of the fill or stroke style paint object. */ -static void fillnstroke_selection_modified( SPWidget *spw, - Inkscape::Selection * /*selection*/, - guint flags, - SPPaintSelector * /*psel*/ ) +void fillnstroke_selection_modified( Inkscape::Application * /*inkscape*/, + Inkscape::Selection * /*selection*/, + guint flags, + GtkWidget *spw ) { if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | @@ -163,9 +133,9 @@ static void fillnstroke_selection_modified( SPWidget *spw, /** * On signal selection changed, invokes an update of the fill or stroke style paint object. */ -static void fillnstroke_selection_changed( SPWidget *spw, - Inkscape::Selection * /*selection*/, - SPPaintSelector * /*psel*/ ) +void fillnstroke_selection_changed( Inkscape::Application * /*inkscape*/, + Inkscape::Selection */*selection*/, + GtkWidget *spw ) { fillnstroke_performUpdate(spw); } @@ -173,9 +143,9 @@ static void fillnstroke_selection_changed( SPWidget *spw, /** * On signal change subselection, invoke an update of the fill or stroke style widget. */ -static void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, - SPDesktop * /*desktop*/, - SPWidget *spw ) +void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, + SPDesktop * /*desktop*/, + GtkWidget *spw ) { fillnstroke_performUpdate(spw); } @@ -186,7 +156,7 @@ static void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape * * @param sel Selection to use, or NULL. */ -static void fillnstroke_performUpdate( SPWidget *spw ) +void fillnstroke_performUpdate( GtkWidget *spw ) { if ( g_object_get_data(G_OBJECT(spw), "update") ) { return; @@ -280,9 +250,9 @@ static void fillnstroke_performUpdate( SPWidget *spw ) /** * When the mode is changed, invoke a regular changed handler. */ -static void fillnstroke_paint_mode_changed( SPPaintSelector *psel, - SPPaintSelector::Mode /*mode*/, - SPWidget *spw ) +void fillnstroke_paint_mode_changed( SPPaintSelector *psel, + SPPaintSelector::Mode /*mode*/, + GtkWidget *spw ) { if (g_object_get_data(G_OBJECT(spw), "update")) { return; @@ -299,9 +269,9 @@ static void fillnstroke_paint_mode_changed( SPPaintSelector *psel, fillnstroke_paint_changed(psel, spw); } -static void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, - SPPaintSelector::FillRule mode, - SPWidget *spw ) +void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, + SPPaintSelector::FillRule mode, + GtkWidget *spw ) { if (g_object_get_data(G_OBJECT(spw), "update")) { return; @@ -336,9 +306,9 @@ static gchar const *undo_S_label = undo_S_label_1; * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except * lumps all its changes for undo. */ -static void fillnstroke_paint_dragged(SPPaintSelector *psel, SPWidget *spw) +void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw) { - if (!spw->inkscape) { + if (!INKSCAPE) { return; } @@ -387,7 +357,7 @@ This is called (at least) when: 3 you changed a gradient selector parameter (e.g. spread) Must update repr. */ -static void fillnstroke_paint_changed( SPPaintSelector *psel, SPWidget *spw ) +void fillnstroke_paint_changed( SPPaintSelector *psel, GtkWidget *spw ) { #ifdef SP_FS_VERBOSE g_message("fillnstroke_paint_changed(psel:%p, spw:%p)", psel, spw); @@ -636,15 +606,6 @@ static void fillnstroke_paint_changed( SPPaintSelector *psel, SPWidget *spw ) } -static void fillnstroke_transientize_called(Inkscape::Application * /*inkscape*/, - SPDesktop * /*desktop*/, - SPWidget * /*spw*/ ) -{ -// TODO: Either of these will cause crashes sometimes -// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL); -// ink_markers_menu_update(spw); -} - /* Local Variables: mode:c++ -- cgit v1.2.3 From 613d977b905aa4b2264f0fa1e791f26b50ca48ce Mon Sep 17 00:00:00 2001 From: buliabyak <> Date: Sat, 27 Mar 2010 19:40:38 -0300 Subject: inherit value as well as computed for linespacing and other spacing properties; fixes the linespacing display in text and font dialog (bzr r9243) --- src/style.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/style.cpp b/src/style.cpp index 6d73e62ea..19ff711da 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -1446,16 +1446,19 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent) } if (!style->line_height.set || style->line_height.inherit) { + style->line_height.value = parent->line_height.value; style->line_height.computed = parent->line_height.computed; style->line_height.normal = parent->line_height.normal; } if (!style->letter_spacing.set || style->letter_spacing.inherit) { + style->letter_spacing.value = parent->letter_spacing.value; style->letter_spacing.computed = parent->letter_spacing.computed; style->letter_spacing.normal = parent->letter_spacing.normal; } if (!style->word_spacing.set || style->word_spacing.inherit) { + style->word_spacing.value = parent->word_spacing.value; style->word_spacing.computed = parent->word_spacing.computed; style->word_spacing.normal = parent->word_spacing.normal; } -- cgit v1.2.3 From 58133b417e94e0bc15fb1624a9d6bbd7613cca5d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 27 Mar 2010 17:42:22 -0700 Subject: Phase 3 - Convert to C++ class, but still using C-style callbacks and signals. (bzr r9244) --- src/widgets/fill-style.cpp | 270 +++++++++++++++++++++++------------------ src/widgets/paint-selector.cpp | 15 ++- src/widgets/paint-selector.h | 6 +- 3 files changed, 161 insertions(+), 130 deletions(-) (limited to 'src') diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 6ea9f30b5..552668a88 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -5,9 +5,11 @@ * Lauris Kaplinski * Frank Felfe * bulia byak + * Jon A. Cruz * * Copyright (C) 1999-2005 authors * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 2010 Jon A. Cruz * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -19,6 +21,7 @@ #endif #include +#include #include #include "desktop-handles.h" @@ -45,17 +48,37 @@ /* Fill */ -static void fillnstroke_fillrule_changed(SPPaintSelector *psel, SPPaintSelector::FillRule mode, GtkWidget *spw); -static void fillnstroke_selection_modified(Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, GtkWidget *spw); -static void fillnstroke_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, GtkWidget *spw); -static void fillnstroke_subselection_changed(Inkscape::Application *inkscape, SPDesktop *desktop, GtkWidget *spw); -static void fillnstroke_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, GtkWidget *spw); -static void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw); -static void fillnstroke_paint_changed(SPPaintSelector *psel, GtkWidget *spw); +class FillNStroke : public Gtk::VBox +{ +public: + FillNStroke( FillOrStroke kind ); + ~FillNStroke(); + + void setFillrule( SPPaintSelector::FillRule mode ); + +private: + static void paintModeChangeCB(SPPaintSelector *psel, SPPaintSelector::Mode mode, FillNStroke *self); + static void paintChangedCB(SPPaintSelector *psel, FillNStroke *self); + static void paintDraggedCB(SPPaintSelector *psel, FillNStroke *self); + + static void fillruleChangedCB( SPPaintSelector *psel, SPPaintSelector::FillRule mode, FillNStroke *self ); + + static void selectionModifiedCB(Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, FillNStroke *self); + static void selectionChangedCB(Inkscape::Application *inkscape, void * data, FillNStroke *self); + + void dragFromPaint(); + void updateFromPaint(); + + void performUpdate(); + + FillOrStroke kind; + SPPaintSelector *psel; + bool update; + bool local; +}; -static void fillnstroke_performUpdate(GtkWidget *spw); GtkWidget *sp_fill_style_widget_new(void) { @@ -67,87 +90,92 @@ GtkWidget *sp_fill_style_widget_new(void) */ GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) { - Inkscape::Application *appInstance = INKSCAPE; - GtkWidget *spw = gtk_vbox_new(FALSE, 0); - - // with or without fillrule selector - GtkWidget *psel = sp_paint_selector_new(kind == FILL); - gtk_widget_show(psel); - gtk_container_add(GTK_CONTAINER(spw), psel); - g_object_set_data(G_OBJECT(spw), "paint-selector", psel); - g_object_set_data(G_OBJECT(spw), "kind", GINT_TO_POINTER(kind)); - - g_signal_connect( G_OBJECT(appInstance), "modify_selection", - G_CALLBACK(fillnstroke_selection_modified), - spw ); + FillNStroke *filler = Gtk::manage(new FillNStroke(kind)); - g_signal_connect( G_OBJECT(appInstance), "change_selection", - G_CALLBACK(fillnstroke_selection_changed), - spw ); - - g_signal_connect( G_OBJECT(appInstance), "change_subselection", - G_CALLBACK(fillnstroke_subselection_changed), - spw ); + return GTK_WIDGET(filler->gobj()); +} +FillNStroke::FillNStroke( FillOrStroke kind ) : + Gtk::VBox(), + kind(kind), + psel(0), + update(false), + local(false) +{ + // Add and connect up the paint selector widget: + psel = sp_paint_selector_new(kind); + gtk_widget_show(GTK_WIDGET(psel)); + gtk_container_add(GTK_CONTAINER(gobj()), GTK_WIDGET(psel)); g_signal_connect( G_OBJECT(psel), "mode_changed", - G_CALLBACK(fillnstroke_paint_mode_changed), - spw ); + G_CALLBACK(paintModeChangeCB), + this ); g_signal_connect( G_OBJECT(psel), "dragged", - G_CALLBACK(fillnstroke_paint_dragged), - spw ); + G_CALLBACK(paintDraggedCB), + this ); g_signal_connect( G_OBJECT(psel), "changed", - G_CALLBACK(fillnstroke_paint_changed), - spw ); - + G_CALLBACK(paintChangedCB), + this ); if (kind == FILL) { g_signal_connect( G_OBJECT(psel), "fillrule_changed", - G_CALLBACK(fillnstroke_fillrule_changed), - spw ); + G_CALLBACK(fillruleChangedCB), + this ); } - fillnstroke_performUpdate(spw); + // connect to the app instance to get selection notifications. + // TODO FIXME should really get connected to a Desktop instead. + Inkscape::Application *appInstance = INKSCAPE; + g_signal_connect( G_OBJECT(appInstance), "modify_selection", + G_CALLBACK(selectionModifiedCB), + this ); + + g_signal_connect( G_OBJECT(appInstance), "change_selection", + G_CALLBACK(selectionChangedCB), + this ); + + g_signal_connect( G_OBJECT(appInstance), "change_subselection", + G_CALLBACK(selectionChangedCB), + this ); - return spw; + + performUpdate(); +} + +FillNStroke::~FillNStroke() +{ + psel = 0; } /** * On signal modified, invokes an update of the fill or stroke style paint object. */ -void fillnstroke_selection_modified( Inkscape::Application * /*inkscape*/, - Inkscape::Selection * /*selection*/, - guint flags, - GtkWidget *spw ) +void FillNStroke::selectionModifiedCB( Inkscape::Application * /*inkscape*/, + Inkscape::Selection */*selection*/, + guint flags, + FillNStroke *self ) { - if (flags & ( SP_OBJECT_MODIFIED_FLAG | - SP_OBJECT_PARENT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG) ) { + if (self && + (flags & ( SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_PARENT_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG) ) ) { #ifdef SP_FS_VERBOSE - g_message("fillnstroke_selection_modified()"); + g_message("selectionModifiedCB(%p)", self); #endif - fillnstroke_performUpdate(spw); + self->performUpdate(); } } /** - * On signal selection changed, invokes an update of the fill or stroke style paint object. - */ -void fillnstroke_selection_changed( Inkscape::Application * /*inkscape*/, - Inkscape::Selection */*selection*/, - GtkWidget *spw ) -{ - fillnstroke_performUpdate(spw); -} - -/** - * On signal change subselection, invoke an update of the fill or stroke style widget. + * On signal selection changed or subselection changed, invokes an update of the fill or stroke style paint object. */ -void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, - SPDesktop * /*desktop*/, - GtkWidget *spw ) +void FillNStroke::selectionChangedCB( Inkscape::Application * /*inkscape*/, + void * /*data*/, + FillNStroke *self ) { - fillnstroke_performUpdate(spw); + if (self) { + self->performUpdate(); + } } /** @@ -156,24 +184,21 @@ void fillnstroke_subselection_changed( Inkscape::Application * /*inkscape*/, * * @param sel Selection to use, or NULL. */ -void fillnstroke_performUpdate( GtkWidget *spw ) +void FillNStroke::performUpdate() { - if ( g_object_get_data(G_OBJECT(spw), "update") ) { + if ( update ) { return; } - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - if (kind == FILL) { - if ( g_object_get_data(G_OBJECT(spw), "local") ) { - g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(FALSE)); // local change; do nothing, but reset the flag + // TODO check. This probably should happen for stroke as well as fill. + if ( local ) { + local = false; // local change; do nothing, but reset the flag return; } } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - - SPPaintSelector *psel = SP_PAINT_SELECTOR(g_object_get_data(G_OBJECT(spw), "paint-selector")); + update = true; // create temporary style SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); @@ -196,7 +221,7 @@ void fillnstroke_performUpdate( GtkWidget *spw ) case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector case QUERY_STYLE_MULTIPLE_SAME: { - SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind == FILL); + SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind); psel->setMode(pselmode); if (kind == FILL) { @@ -244,51 +269,49 @@ void fillnstroke_performUpdate( GtkWidget *spw ) sp_style_unref(query); - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + update = false; } /** * When the mode is changed, invoke a regular changed handler. */ -void fillnstroke_paint_mode_changed( SPPaintSelector *psel, +void FillNStroke::paintModeChangeCB( SPPaintSelector * /*psel*/, SPPaintSelector::Mode /*mode*/, - GtkWidget *spw ) + FillNStroke *self ) { - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - #ifdef SP_FS_VERBOSE - g_message("fillnstroke_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw); + g_message("paintModeChangeCB(psel, mode, self:%p)", self); #endif - - /* TODO: Does this work? - * Not really, here we have to get old color back from object - * Instead of relying on paint widget having meaningful colors set - */ - fillnstroke_paint_changed(psel, spw); + if (self && !self->update) { + self->updateFromPaint(); + } } -void fillnstroke_fillrule_changed( SPPaintSelector * /*psel*/, - SPPaintSelector::FillRule mode, - GtkWidget *spw ) +void FillNStroke::fillruleChangedCB( SPPaintSelector * /*psel*/, + SPPaintSelector::FillRule mode, + FillNStroke *self ) { - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; + if (self) { + self->setFillrule(mode); } +} - SPDesktop *desktop = SP_ACTIVE_DESKTOP; +void FillNStroke::setFillrule( SPPaintSelector::FillRule mode ) +{ + if (!update) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, "fill-rule", mode == SPPaintSelector::FILLRULE_EVENODD? "evenodd":"nonzero"); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "fill-rule", (mode == SPPaintSelector::FILLRULE_EVENODD) ? "evenodd":"nonzero"); - sp_desktop_set_style(desktop, css); + sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref(css); - css = 0; + sp_repr_css_attr_unref(css); + css = 0; - sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, - _("Change fill rule")); + sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, + _("Change fill rule")); + } } static gchar const *undo_F_label_1 = "fill:flatcolor:1"; @@ -300,26 +323,31 @@ static gchar const *undo_S_label_2 = "stroke:flatcolor:2"; static gchar const *undo_F_label = undo_F_label_1; static gchar const *undo_S_label = undo_S_label_1; + +void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self) +{ +#ifdef SP_FS_VERBOSE + g_message("paintDraggedCB(psel, spw:%p)", self); +#endif + if (self && !self->update) { + self->dragFromPaint(); + } +} + /** * This is called repeatedly while you are dragging a color slider, only for flat color * modes. Previously it set the color in style but did not update the repr for efficiency, however * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except * lumps all its changes for undo. */ -void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw) +void FillNStroke::dragFromPaint() { - if (!INKSCAPE) { + if (!INKSCAPE || update) { return; } - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; - } - - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; - if (kind == FILL) { - if (g_object_get_data(G_OBJECT(spw), "local")) { + if (local) { // previous local flag not cleared yet; // this means dragged events come too fast, so we better skip this one to speed up display // (it's safe to do this in any case) @@ -327,7 +355,7 @@ void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw) } } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + update = true; switch (psel->mode) { case SPPaintSelector::MODE_COLOR_RGB: @@ -337,7 +365,7 @@ void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw) sp_document_maybe_done(sp_desktop_document(SP_ACTIVE_DESKTOP), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, (kind == FILL) ? _("Set fill color") : _("Set stroke color")); if (kind == FILL) { - g_object_set_data(G_OBJECT(spw), "local", GINT_TO_POINTER(TRUE)); // local change, do not update from selection + local = true; // local change, do not update from selection } break; } @@ -347,7 +375,7 @@ void fillnstroke_paint_dragged(SPPaintSelector *psel, GtkWidget *spw) __FILE__, __LINE__, psel->mode ); break; } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + update = false; } /** @@ -357,22 +385,24 @@ This is called (at least) when: 3 you changed a gradient selector parameter (e.g. spread) Must update repr. */ -void fillnstroke_paint_changed( SPPaintSelector *psel, GtkWidget *spw ) +void FillNStroke::paintChangedCB( SPPaintSelector * /*psel*/, FillNStroke *self ) { #ifdef SP_FS_VERBOSE - g_message("fillnstroke_paint_changed(psel:%p, spw:%p)", psel, spw); + g_message("paintChangedCB(psel, spw:%p)", self); #endif - if (g_object_get_data(G_OBJECT(spw), "update")) { - return; + if (self && !self->update) { + self->updateFromPaint(); } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - - FillOrStroke kind = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(spw), "kind")) ? FILL : STROKE; +} +void FillNStroke::updateFromPaint() +{ SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { return; } + update = true; + SPDocument *document = sp_desktop_document(desktop); Inkscape::Selection *selection = sp_desktop_selection(desktop); @@ -602,7 +632,7 @@ void fillnstroke_paint_changed( SPPaintSelector *psel, GtkWidget *spw ) break; } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + update = false; } diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 288764177..d3092669a 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -352,8 +352,7 @@ sp_paint_selector_show_fillrule(SPPaintSelector *psel, bool is_fill) } -GtkWidget * -sp_paint_selector_new(bool is_fill) +SPPaintSelector *sp_paint_selector_new(FillOrStroke kind) { SPPaintSelector *psel = static_cast(gtk_type_new(SP_TYPE_PAINT_SELECTOR)); @@ -362,9 +361,9 @@ sp_paint_selector_new(bool is_fill) // This silliness is here because I don't know how to pass a parameter to the // GtkObject "constructor" (sp_paint_selector_init). Remove it when paint_selector // becomes a normal class. - sp_paint_selector_show_fillrule(psel, is_fill); + sp_paint_selector_show_fillrule(psel, kind == FILL); - return GTK_WIDGET(psel); + return psel; } void SPPaintSelector::setMode(Mode mode) @@ -1137,18 +1136,18 @@ void SPPaintSelector::setFlatColor( SPDesktop *desktop, gchar const *color_prope sp_repr_css_attr_unref(css); } -SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, bool isfill) +SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, FillOrStroke kind) { Mode mode = MODE_UNSET; - SPIPaint const & target = isfill ? style.fill : style.stroke; + SPIPaint const & target = (kind == FILL) ? style.fill : style.stroke; if ( !target.set ) { mode = MODE_UNSET; } else if ( target.isPaintserver() ) { - SPPaintServer const *server = isfill ? style.getFillPaintServer() : style.getStrokePaintServer(); + SPPaintServer const *server = (kind == FILL) ? style.getFillPaintServer() : style.getStrokePaintServer(); #ifdef SP_PS_VERBOSE - g_message("SPPaintSelector::getModeForStyle(%p, %d)", &style, isfill); + g_message("SPPaintSelector::getModeForStyle(%p, %d)", &style, kind); g_message("==== server:%p %s grad:%s swatch:%s", server, server->getId(), (SP_IS_GRADIENT(server)?"Y":"n"), (SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()?"Y":"n")); #endif // SP_PS_VERBOSE diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h index a3c4cb973..84209d1da 100644 --- a/src/widgets/paint-selector.h +++ b/src/widgets/paint-selector.h @@ -14,6 +14,8 @@ */ #include + +#include "fill-or-stroke.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" @@ -75,7 +77,7 @@ struct SPPaintSelector { SPColor color; float alpha; - static Mode getModeForStyle(SPStyle const & style, bool isfill); + static Mode getModeForStyle(SPStyle const & style, FillOrStroke kind); void setMode( Mode mode ); void setFillrule( FillRule fillrule ); @@ -114,7 +116,7 @@ struct SPPaintSelectorClass { GtkType sp_paint_selector_get_type (void); -GtkWidget *sp_paint_selector_new (bool is_fill); +SPPaintSelector *sp_paint_selector_new(FillOrStroke kind); -- cgit v1.2.3 From 440056330d258d3b66a5a4625848c5e9e230a6f1 Mon Sep 17 00:00:00 2001 From: buliabyak <> Date: Sun, 28 Mar 2010 00:15:37 -0300 Subject: reinstate wrongly ignored delta in pick; makes selecting small text objects much easier (bzr r9245) --- src/display/nr-arena-glyphs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index db0922915..ff320bd81 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -234,7 +234,7 @@ nr_arena_glyphs_clip(NRArenaItem *item, NRRectL */*area*/, NRPixBlock */*pb*/) } static NRArenaItem * -nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble /*delta*/, unsigned int /*sticky*/) +nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int /*sticky*/) { NRArenaGlyphs *glyphs; @@ -246,7 +246,7 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble /*delta*/, unsign double const x = p[Geom::X]; double const y = p[Geom::Y]; /* With text we take a simple approach: pick if the point is in a characher bbox */ - if ((x >= item->bbox.x0) && (y >= item->bbox.y0) && (x <= item->bbox.x1) && (y <= item->bbox.y1)) return item; + if ((x + delta >= item->bbox.x0) && (y + delta >= item->bbox.y0) && (x - delta <= item->bbox.x1) && (y - delta <= item->bbox.y1)) return item; return NULL; } -- cgit v1.2.3 From 7ac120f629403ac38ed209986dd4c256a52ef890 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 28 Mar 2010 22:17:31 +0200 Subject: Allow Inkscape to run from Unicode directories on Windows Fixed bugs: - https://launchpad.net/bugs/505107 (bzr r9248) --- src/extension/implementation/script.cpp | 251 ++++----- src/extension/implementation/script.h | 24 +- src/io/sys.cpp | 904 -------------------------------- src/main.cpp | 180 ++++--- src/prefix.cpp | 344 ++++++------ src/registrytool.cpp | 53 +- 6 files changed, 391 insertions(+), 1365 deletions(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 60623191f..256996663 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include "ui/view/view.h" @@ -101,14 +103,12 @@ Script::interpreter_t const Script::interpreterTab[] = { \param interpNameArg The name of the interpreter that we're looking for, should be an entry in interpreterTab */ -Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) +std::string Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) { - Glib::ustring interpName = interpNameArg; - interpreter_t const *interp = 0; bool foundInterp = false; for (interp = interpreterTab ; interp->identity ; interp++ ){ - if (interpName == interp->identity) { + if (interpNameArg == interp->identity) { foundInterp = true; break; } @@ -118,55 +118,26 @@ Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNa if (!foundInterp) { return ""; } - interpName = interp->defaultval; + std::string interpreter_path = Glib::filename_from_utf8(interp->defaultval); - // 1. Check preferences + // 1. Check preferences for an override. + // Note: this must be an absolute path. Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Glib::ustring prefInterp = prefs->getString("/extensions/" + Glib::ustring(interp->prefstring)); if (!prefInterp.empty()) { - interpName = prefInterp; - return interpName; - } - -#ifdef WIN32 - - // 2. Windows. Try looking relative to inkscape.exe - RegistryTool rt; - Glib::ustring fullPath; - Glib::ustring path; - Glib::ustring exeName; - if (rt.getExeInfo(fullPath, path, exeName)) { -// TODO replace with proper glib/glibmm path building routines: - Glib::ustring interpPath = path; - interpPath.append("\\"); - interpPath.append(interpNameArg); - interpPath.append("\\"); - interpPath.append(interpName); - interpPath.append(".exe"); - struct stat finfo; - if (stat(interpPath .c_str(), &finfo) == 0) { - g_message("Found local interpreter, '%s', Size: %d", - interpPath .c_str(), - (int)finfo.st_size); - return interpPath; - } + interpreter_path = Glib::filename_from_utf8(prefInterp); } - // 3. Try searching the path - char szExePath[MAX_PATH] = {0}; - char szCurrentDir[MAX_PATH] = {0}; - GetCurrentDirectory(sizeof(szCurrentDir), szCurrentDir); - HINSTANCE ret = FindExecutable(interpName.c_str(), szCurrentDir, szExePath); - if (ret > reinterpret_cast(32)) { - interpName = szExePath; - return interpName; + // 2. Search the path. + // Do this on all systems, for consistency. + // PATH is set up to contain the Python and Perl binary directories + // on Windows, so no extra code is necessary. + if (!Glib::path_is_absolute(interpreter_path)) { + interpreter_path = Glib::find_program_in_path(interpreter_path); } - -#endif // win32 - - - return interpName; + printf("Interpreter name: %s\n", interpreter_path.data()); + return interpreter_path; } /** \brief This function creates a script object and sets up the @@ -206,38 +177,33 @@ Script::~Script() string. This means that the caller of this function can always free what they are given (and should do it too!). */ -Glib::ustring +std::string Script::solve_reldir(Inkscape::XML::Node *reprin) { gchar const *s = reprin->attribute("reldir"); - if (!s) { + // right now the only recognized relative directory is "extensions" + if (!s || Glib::ustring(s) != "extensions") { Glib::ustring str = sp_repr_children(reprin)->content(); return str; } Glib::ustring reldir = s; - if (reldir == "extensions") { - - for (unsigned int i=0; - i < Inkscape::Extension::Extension::search_path.size(); - i++) { + for (unsigned int i=0; + i < Inkscape::Extension::Extension::search_path.size(); + i++) { - gchar * fname = g_build_filename( - Inkscape::Extension::Extension::search_path[i], - sp_repr_children(reprin)->content(), - NULL); - Glib::ustring filename = fname; - g_free(fname); + gchar * fname = g_build_filename( + Inkscape::Extension::Extension::search_path[i], + sp_repr_children(reprin)->content(), + NULL); + Glib::ustring filename = fname; + g_free(fname); - if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) { - return filename; - } + if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) { + return Glib::filename_from_utf8(filename); } - } else { - Glib::ustring str = sp_repr_children(reprin)->content(); - return str; } return ""; @@ -261,29 +227,25 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { then a TRUE is returned. If we get all the way through the path then a FALSE is returned, the command could not be found. */ -bool Script::check_existance(const Glib::ustring &command) +bool Script::check_existence(const std::string &command) { // Check the simple case first - if (command.size() == 0) { + if (command.empty()) { return false; } - //Don't search when it contains a slash. */ - if (command.find(G_DIR_SEPARATOR) != command.npos) { - if (Inkscape::IO::file_test(command.c_str(), G_FILE_TEST_EXISTS)) { + //Don't search when it is an absolute path. */ + if (!Glib::path_is_absolute(command)) { + if (Glib::file_test(command, Glib::FILE_TEST_EXISTS)) { return true; } else { return false; } } - - Glib::ustring path; - gchar *s = (gchar *) g_getenv("PATH"); - if (s) { - path = s; - } else { + std::string path = Glib::getenv("PATH"); + if (path.empty()) { /* There is no `PATH' in the environment. The default search path is the current directory */ path = G_SEARCHPATH_SEPARATOR_S; @@ -293,7 +255,7 @@ bool Script::check_existance(const Glib::ustring &command) std::string::size_type pos2 = 0; while ( pos < path.size() ) { - Glib::ustring localPath; + std::string localPath; pos2 = path.find(G_SEARCHPATH_SEPARATOR, pos); if (pos2 == path.npos) { @@ -305,11 +267,11 @@ bool Script::check_existance(const Glib::ustring &command) } //printf("### %s\n", localPath.c_str()); - Glib::ustring candidatePath = + std::string candidatePath = Glib::build_filename(localPath, command); - if (Inkscape::IO::file_test(candidatePath .c_str(), - G_FILE_TEST_EXISTS)) { + if (Glib::file_test(candidatePath, + Glib::FILE_TEST_EXISTS)) { return true; } @@ -357,16 +319,10 @@ bool Script::load(Inkscape::Extension::Extension *module) if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "command")) { const gchar *interpretstr = child_repr->attribute("interpreter"); if (interpretstr != NULL) { - Glib::ustring interpString = - resolveInterpreterExecutable(interpretstr); - //g_message("Found: %s and %s",interpString.c_str(),interpretstr); - command.insert(command.end(), interpretstr); + std::string interpString = resolveInterpreterExecutable(interpretstr); + command.insert(command.end(), interpString); } - Glib::ustring tmp = "\""; - tmp += solve_reldir(child_repr); - tmp += "\""; - - command.insert(command.end(), tmp); + command.insert(command.end(), solve_reldir(child_repr)); } if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "helper_extension")) { helper_extension = sp_repr_children(child_repr)->content(); @@ -419,10 +375,10 @@ Script::check(Inkscape::Extension::Extension *module) child_repr = sp_repr_children(child_repr); while (child_repr != NULL) { if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "check")) { - Glib::ustring command_text = solve_reldir(child_repr); - if (command_text.size() > 0) { + std::string command_text = solve_reldir(child_repr); + if (!command_text.empty()) { /* I've got the command */ - bool existance = check_existance(command_text); + bool existance = check_existence(command_text); if (!existance) return false; } @@ -763,8 +719,7 @@ void Script::effect(Inkscape::Extension::Effect *module, // make sure we don't leak file descriptors from g_file_open_tmp close(tempfd_out); - // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name - unlink(tempfilename_out.c_str()); + g_unlink(tempfilename_out.c_str()); /* Do something with mydoc.... */ if (mydoc) { @@ -937,89 +892,61 @@ int Script::execute (const std::list &in_command, const Glib::ustring &filein, file_listener &fileout) { - g_return_val_if_fail(in_command.size() > 0, 0); + g_return_val_if_fail(!in_command.empty(), 0); // printf("Executing\n"); - std::vector argv; - -/* - for (std::list::const_iterator i = in_command.begin(); - i != in_command.end(); i++) { - argv.push_back(*i); - } -*/ - // according to http://www.gtk.org/api/2.6/glib/glib-Spawning-Processes.html spawn quotes parameter containing spaces - // we tokenize so that spwan does not need to quote over all params - for (std::list::const_iterator i = in_command.begin(); - i != in_command.end(); i++) { - std::string param_str = *i; - do { - //g_message("param: %s", param_str.c_str()); - size_t first_space = param_str.find_first_of(' '); - size_t first_quote = param_str.find_first_of('"'); - //std::cout << "first space " << first_space << std::endl; - //std::cout << "first quote " << first_quote << std::endl; - - if ((first_quote != std::string::npos) && (first_quote == 0)) { - size_t next_quote = param_str.find_first_of('"', first_quote + 1); - //std::cout << "next quote " << next_quote << std::endl; - - if (next_quote != std::string::npos) { - //std::cout << "now split " << next_quote << std::endl; - //std::cout << "now split " << param_str.substr(1, next_quote - 1) << std::endl; - //std::cout << "now split " << param_str.substr(next_quote + 1) << std::endl; - std::string part_str = param_str.substr(1, next_quote - 1); - if (part_str.size() > 0) - argv.push_back(part_str); - param_str = param_str.substr(next_quote + 1); - - } else { - if (param_str.size() > 0) - argv.push_back(param_str); - param_str = ""; - } - - } else if (first_space != std::string::npos) { - //std::cout << "now split " << first_space << std::endl; - //std::cout << "now split " << param_str.substr(0, first_space) << std::endl; - //std::cout << "now split " << param_str.substr(first_space + 1) << std::endl; - std::string part_str = param_str.substr(0, first_space); - if (part_str.size() > 0) { - argv.push_back(part_str); - } - param_str = param_str.substr(first_space + 1); - } else { - if (param_str.size() > 0) { - argv.push_back(param_str); - } - param_str = ""; - } - } while (param_str.size() > 0); - } - - for (std::list::const_iterator i = in_params.begin(); - i != in_params.end(); i++) { - //g_message("Script parameter: %s",(*i)g.c_str()); - argv.push_back(*i); - } - - if (!(filein.empty())) { + std::vector argv; + + bool interpreted = (in_command.size() == 2); + std::string program = in_command.front(); + std::string script = interpreted ? in_command.back() : ""; + std::string working_directory = ""; + + // Use Glib::find_program_in_path instead of the equivalent + // Glib::spawn_* functionality, because _wspawnp is broken on Windows: + // it doesn't work when PATH contains Unicode directories + if (!Glib::path_is_absolute(program)) { + program = Glib::find_program_in_path(program); + } + argv.push_back(program); + + if (interpreted) { + // On Windows, Python garbles Unicode command line parameters + // in an useless way. This means extensions fail when Inkscape + // is run from an Unicode directory. + // As a workaround, we set the working directory to the one + // containing the script. + working_directory = Glib::path_get_dirname(script); + script = Glib::path_get_basename(script); + #ifdef G_OS_WIN32 + // ANNOYING: glibmm does not wrap g_win32_locale_filename_from_utf8 + gchar *workdir_s = g_win32_locale_filename_from_utf8(working_directory.data()); + working_directory = workdir_s; + g_free(workdir_s); + #endif + + argv.push_back(script); + } + + // assemble the rest of argv + std::copy(in_params.begin(), in_params.end(), std::back_inserter(argv)); + if (!filein.empty()) { argv.push_back(filein); } int stdout_pipe, stderr_pipe; try { - Inkscape::IO::spawn_async_with_pipes(Glib::get_current_dir(), // working directory + Glib::spawn_async_with_pipes(working_directory, // working directory argv, // arg v - Glib::SPAWN_SEARCH_PATH /*| Glib::SPAWN_DO_NOT_REAP_CHILD*/, + static_cast(0), // no flags sigc::slot(), &_pid, // Pid NULL, // STDIN &stdout_pipe, // STDOUT &stderr_pipe); // STDERR - } catch (Glib::SpawnError e) { - printf("Can't Spawn!!! spawn returns: %d\n", e.code()); + } catch (Glib::Error e) { + printf("Can't Spawn!!! spawn returns: %s\n", e.what().data()); return 0; } diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h index e0b6701bf..f37f27966 100644 --- a/src/extension/implementation/script.h +++ b/src/extension/implementation/script.h @@ -115,31 +115,14 @@ private: */ Glib::ustring helper_extension; - /** - * Just a quick function to find and resolve relative paths for - * the incoming scripts - */ - Glib::ustring solve_reldir (Inkscape::XML::Node *reprin); - - /** - * - */ - bool check_existance (const Glib::ustring &command); - - /** - * - */ + std::string solve_reldir (Inkscape::XML::Node *reprin); + bool check_existence (const std::string &command); void copy_doc (Inkscape::XML::Node * olddoc, Inkscape::XML::Node * newdoc); - - /** - * - */ void checkStderr (const Glib::ustring &filename, Gtk::MessageType type, const Glib::ustring &message); - class file_listener { Glib::ustring _string; sigc::connection _conn; @@ -184,7 +167,6 @@ private: return true; }; - // Note, doing a copy here, on purpose Glib::ustring string (void) { return _string; }; bool toFile (const Glib::ustring &name) { @@ -215,7 +197,7 @@ private: }; static interpreter_t const interpreterTab[]; - Glib::ustring resolveInterpreterExecutable(const Glib::ustring &interpNameArg); + std::string resolveInterpreterExecutable(const Glib::ustring &interpNameArg); }; // class Script diff --git a/src/io/sys.cpp b/src/io/sys.cpp index 34160b648..a68d02707 100644 --- a/src/io/sys.cpp +++ b/src/io/sys.cpp @@ -29,41 +29,9 @@ #include "sys.h" #ifdef WIN32 - -#define BYPASS_GLIB_SPAWN 1 - -#ifdef BYPASS_GLIB_SPAWN - -#include // declares spawn functions -#include // declares _wspawn functions - -#ifndef __MINGW32__ -# ifdef __cplusplus -extern "C" { -# endif -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnl (int, const wchar_t*, const wchar_t*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnle (int, const wchar_t*, const wchar_t*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlp (int, const wchar_t*, const wchar_t*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlpe (int, const wchar_t*, const wchar_t*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnv (int, const wchar_t*, const wchar_t* const*); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnve (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvp (int, const wchar_t*, const wchar_t* const*); -_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvpe (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*); -# ifdef __cplusplus -} -# endif -#endif -#include -#include -#include -#include - -#endif // BYPASS_GLIB_SPAWN - // For now to get at is_os_wide(). #include "extension/internal/win32.h" using Inkscape::Extension::Internal::PrintWin32; - #endif // WIN32 //#define INK_DUMP_FILENAME_CONV 1 @@ -217,32 +185,7 @@ int Inkscape::IO::mkdir_utf8name( char const *utf8name ) * */ int Inkscape::IO::file_open_tmp(std::string& name_used, const std::string& prefix) { -#ifndef WIN32 return Glib::file_open_tmp(name_used, prefix); -#else - /* Special case for WIN32 due to a bug in glibmm - * (only needed for Windows Vista, but since there is only one windows build all builds get the workaround) - * The workaround can be removed if the bug is fixed in glibmm - * - * The code is mostly identical to the implementation in glibmm - * http://svn.gnome.org/svn/glibmm/branches/glibmm-2-12/glib/src/fileutils.ccg - * */ - - std::string basename_template (prefix); - basename_template += "XXXXXX"; // this sillyness shouldn't be in the interface - - GError* error = 0; - gchar *buf_name_used; - - gint fileno = g_file_open_tmp(basename_template.c_str(), &buf_name_used, &error); - - if(error) - Glib::Error::throw_exception(error); - - name_used = g_strdup(buf_name_used); - g_free(buf_name_used); - return fileno; -#endif } bool Inkscape::IO::file_test( char const *utf8name, GFileTest test ) @@ -372,842 +315,6 @@ gchar* Inkscape::IO::locale_to_utf8_fallback( const gchar *opsysstring, return result; } -#ifdef BYPASS_GLIB_SPAWN -/* - this code was taken from the original glib sources -*/ -#define GSPAWN_HELPER - -enum -{ - CHILD_NO_ERROR, - CHILD_CHDIR_FAILED, - CHILD_SPAWN_FAILED, -}; - -enum { - ARG_CHILD_ERR_REPORT = 1, - ARG_HELPER_SYNC, - ARG_STDIN, - ARG_STDOUT, - ARG_STDERR, - ARG_WORKING_DIRECTORY, - ARG_CLOSE_DESCRIPTORS, - ARG_USE_PATH, - ARG_WAIT, - ARG_PROGRAM, - ARG_COUNT = ARG_PROGRAM -}; -static int debug = 0; -#define HELPER_PROCESS "gspawn-win32-helper" - - -static int -dup_noninherited (int fd, - int mode) -{ - HANDLE filehandle; - - DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd), - GetCurrentProcess (), &filehandle, - 0, FALSE, DUPLICATE_SAME_ACCESS); - close (fd); - return _open_osfhandle(reinterpret_cast(filehandle), mode | _O_NOINHERIT); -} - -/* The helper process writes a status report back to us, through a - * pipe, consisting of two ints. - */ -static gboolean -read_helper_report (int fd, - gint report[2], - GError **error) -{ - gint bytes = 0; - - while (bytes < sizeof(gint)*2) - { - gint chunk; - - if (debug) - g_print ("%s:read_helper_report: read %d...\n", - __FILE__, - sizeof(gint)*2 - bytes); - - chunk = read (fd, ((gchar*)report) + bytes, - sizeof(gint)*2 - bytes); - - if (debug) - g_print ("...got %d bytes\n", chunk); - - if (chunk < 0) - { - /* Some weird shit happened, bail out */ - - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to read from child pipe (%s)"), - g_strerror (errno)); - - return FALSE; - } - else if (chunk == 0) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to read from child pipe (%s)"), - "EOF"); - break; /* EOF */ - } - else - bytes += chunk; - } - - if (bytes < sizeof(gint)*2) - return FALSE; - - return TRUE; -} - - -static void -set_child_error (gint report[2], - const gchar *working_directory, - GError **error) -{ - switch (report[0]) - { - case CHILD_CHDIR_FAILED: - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR, - _("Failed to change to directory '%s' (%s)"), - working_directory, - g_strerror (report[1])); - break; - case CHILD_SPAWN_FAILED: - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to execute child process (%s)"), - g_strerror (report[1])); - break; - default: - g_assert_not_reached (); - } -} - -static gchar * -protect_argv_string (const gchar *string) -{ - const gchar *p = string; - gchar *retval, *q; - gint len = 0; - gboolean need_dblquotes = FALSE; - while (*p) - { - if (*p == ' ' || *p == '\t') - need_dblquotes = TRUE; - else if (*p == '"') - len++; - else if (*p == '\\') - { - const gchar *pp = p; - while (*pp && *pp == '\\') - pp++; - if (*pp == '"') - len++; - } - len++; - p++; - } - - q = retval = (gchar *)g_malloc (len + need_dblquotes*2 + 1); - p = string; - - if (need_dblquotes) - *q++ = '"'; - - while (*p) - { - if (*p == '"') - *q++ = '\\'; - else if (*p == '\\') - { - const gchar *pp = p; - while (*pp && *pp == '\\') - pp++; - if (*pp == '"') - *q++ = '\\'; - } - *q++ = *p; - p++; - } - - if (need_dblquotes) - *q++ = '"'; - *q++ = '\0'; - - return retval; -} - - -static gint -protect_argv (gchar **argv, - gchar ***new_argv) -{ - gint i; - gint argc = 0; - - while (argv[argc]) - ++argc; - *new_argv = g_new (gchar *, argc+1); - - /* Quote each argv element if necessary, so that it will get - * reconstructed correctly in the C runtime startup code. Note that - * the unquoting algorithm in the C runtime is really weird, and - * rather different than what Unix shells do. See stdargv.c in the C - * runtime sources (in the Platform SDK, in src/crt). - * - * Note that an new_argv[0] constructed by this function should - * *not* be passed as the filename argument to a spawn* or exec* - * family function. That argument should be the real file name - * without any quoting. - */ - for (i = 0; i < argc; i++) - (*new_argv)[i] = protect_argv_string (argv[i]); - - (*new_argv)[argc] = NULL; - - return argc; -} - - -static gboolean -utf8_charv_to_wcharv (char **utf8_charv, - wchar_t ***wcharv, - int *error_index, - GError **error) -{ - wchar_t **retval = NULL; - - *wcharv = NULL; - if (utf8_charv != NULL) - { - int n = 0, i; - - while (utf8_charv[n]) - n++; - retval = g_new (wchar_t *, n + 1); - - for (i = 0; i < n; i++) - { - retval[i] = (wchar_t *)g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error); - if (retval[i] == NULL) - { - if (error_index) - *error_index = i; - while (i) - g_free (retval[--i]); - g_free (retval); - return FALSE; - } - } - - retval[n] = NULL; - } - *wcharv = retval; - return TRUE; -} - - -/* Avoids a danger in threaded situations (calling close() - * on a file descriptor twice, and another thread has - * re-opened it since the first close) - */ -static void -close_and_invalidate (gint *fd) -{ - if (*fd < 0) - return; - - close (*fd); - *fd = -1; -} - - -static gboolean -do_spawn_directly (gint *exit_status, - gboolean do_return_handle, - GSpawnFlags flags, - gchar **argv, - char **envp, - char **protected_argv, - GSpawnChildSetupFunc child_setup, - gpointer user_data, - GPid *child_handle, - GError **error) -{ - const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT; - char **new_argv; - int rc = -1; - int saved_errno; - GError *conv_error = NULL; - gint conv_error_index; - wchar_t *wargv0, **wargv, **wenvp; - - new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv; - - wargv0 = (wchar_t *)g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error); - if (wargv0 == NULL) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Invalid program name: %s"), - conv_error->message); - g_error_free (conv_error); - - return FALSE; - } - - if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error)) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Invalid string in argument vector at %d: %s"), - conv_error_index, conv_error->message); - g_error_free (conv_error); - g_free (wargv0); - - return FALSE; - } - - if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error)) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Invalid string in environment: %s"), - conv_error->message); - g_error_free (conv_error); - g_free (wargv0); - g_strfreev ((gchar **) wargv); - - return FALSE; - } - - if (child_setup) - (* child_setup) (user_data); - - if (flags & G_SPAWN_SEARCH_PATH) - if (wenvp != NULL) - rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); - else - rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv); - else - if (wenvp != NULL) - rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); - else - rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv); - - g_free (wargv0); - g_strfreev ((gchar **) wargv); - g_strfreev ((gchar **) wenvp); - - saved_errno = errno; - - if (rc == -1 && saved_errno != 0) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to execute child process (%s)"), - g_strerror (saved_errno)); - return FALSE; - } - - if (exit_status == NULL) - { - if (child_handle && do_return_handle) - *child_handle = (GPid) rc; - else - { - CloseHandle ((HANDLE) rc); - if (child_handle) - *child_handle = 0; - } - } - else - *exit_status = rc; - - return TRUE; -} - -static gboolean -make_pipe (gint p[2], - GError **error) -{ - if (_pipe (p, 4096, _O_BINARY) < 0) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to create pipe for communicating with child process (%s)"), - g_strerror (errno)); - return FALSE; - } - else - return TRUE; -} - - -static gboolean -do_spawn_with_pipes (gint *exit_status, - gboolean do_return_handle, - const gchar *working_directory, - gchar **argv, - char **envp, - GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, - GPid *child_handle, - gint *standard_input, - gint *standard_output, - gint *standard_error, - gint *err_report, - GError **error) -{ - char **protected_argv; - char args[ARG_COUNT][10]; - char **new_argv; - int i; - int rc = -1; - int saved_errno; - int argc; - int stdin_pipe[2] = { -1, -1 }; - int stdout_pipe[2] = { -1, -1 }; - int stderr_pipe[2] = { -1, -1 }; - int child_err_report_pipe[2] = { -1, -1 }; - int helper_sync_pipe[2] = { -1, -1 }; - int helper_report[2]; - static gboolean warned_about_child_setup = FALSE; - GError *conv_error = NULL; - gint conv_error_index; - gchar *helper_process; - CONSOLE_CURSOR_INFO cursor_info; - wchar_t *whelper, **wargv, **wenvp; - //extern gchar *_glib_get_installation_directory (void); - gchar *glib_top; - - if (child_setup && !warned_about_child_setup) - { - warned_about_child_setup = TRUE; - g_warning ("passing a child setup function to the g_spawn functions is pointless and dangerous on Win32"); - } - - argc = protect_argv (argv, &protected_argv); - - if (!standard_input && !standard_output && !standard_error && - (flags & G_SPAWN_CHILD_INHERITS_STDIN) && - !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) && - !(flags & G_SPAWN_STDERR_TO_DEV_NULL) && - (working_directory == NULL || !*working_directory) && - (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN)) - { - /* We can do without the helper process */ - gboolean retval = - do_spawn_directly (exit_status, do_return_handle, flags, - argv, envp, protected_argv, - child_setup, user_data, child_handle, - error); - g_strfreev (protected_argv); - return retval; - } - - if (standard_input && !make_pipe (stdin_pipe, error)) - goto cleanup_and_fail; - - if (standard_output && !make_pipe (stdout_pipe, error)) - goto cleanup_and_fail; - - if (standard_error && !make_pipe (stderr_pipe, error)) - goto cleanup_and_fail; - - if (!make_pipe (child_err_report_pipe, error)) - goto cleanup_and_fail; - - if (!make_pipe (helper_sync_pipe, error)) - goto cleanup_and_fail; - - new_argv = g_new (char *, argc + 1 + ARG_COUNT); - if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info)) - helper_process = HELPER_PROCESS "-console.exe"; - else - helper_process = HELPER_PROCESS ".exe"; - - glib_top = NULL; - if (glib_top != NULL) - { - helper_process = g_build_filename (glib_top, "bin", helper_process, NULL); - g_free (glib_top); - } - else - helper_process = g_strdup (helper_process); - - new_argv[0] = protect_argv_string (helper_process); - - sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]); - new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT]; - - /* Make the read end of the child error report pipe - * noninherited. Otherwise it will needlessly be inherited by the - * helper process, and the started actual user process. As such that - * shouldn't harm, but it is unnecessary. - */ - child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY); - - if (flags & G_SPAWN_FILE_AND_ARGV_ZERO) - { - /* Overload ARG_CHILD_ERR_REPORT to also encode the - * G_SPAWN_FILE_AND_ARGV_ZERO functionality. - */ - strcat (args[ARG_CHILD_ERR_REPORT], "#"); - } - - sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]); - new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC]; - - /* Make the write end of the sync pipe noninherited. Otherwise the - * helper process will inherit it, and thus if this process happens - * to crash before writing the sync byte to the pipe, the helper - * process won't read but won't get any EOF either, as it has the - * write end open itself. - */ - helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY); - - if (standard_input) - { - sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]); - new_argv[ARG_STDIN] = args[ARG_STDIN]; - } - else if (flags & G_SPAWN_CHILD_INHERITS_STDIN) - { - /* Let stdin be alone */ - new_argv[ARG_STDIN] = "-"; - } - else - { - /* Keep process from blocking on a read of stdin */ - new_argv[ARG_STDIN] = "z"; - } - - if (standard_output) - { - sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]); - new_argv[ARG_STDOUT] = args[ARG_STDOUT]; - } - else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL) - { - new_argv[ARG_STDOUT] = "z"; - } - else - { - new_argv[ARG_STDOUT] = "-"; - } - - if (standard_error) - { - sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]); - new_argv[ARG_STDERR] = args[ARG_STDERR]; - } - else if (flags & G_SPAWN_STDERR_TO_DEV_NULL) - { - new_argv[ARG_STDERR] = "z"; - } - else - { - new_argv[ARG_STDERR] = "-"; - } - - if (working_directory && *working_directory) - new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory); - else - new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-"); - - if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN)) - new_argv[ARG_CLOSE_DESCRIPTORS] = "y"; - else - new_argv[ARG_CLOSE_DESCRIPTORS] = "-"; - - if (flags & G_SPAWN_SEARCH_PATH) - new_argv[ARG_USE_PATH] = "y"; - else - new_argv[ARG_USE_PATH] = "-"; - - if (exit_status == NULL) - new_argv[ARG_WAIT] = "-"; - else - new_argv[ARG_WAIT] = "w"; - - for (i = 0; i <= argc; i++) - new_argv[ARG_PROGRAM + i] = protected_argv[i]; - - //SETUP_DEBUG(); - - if (debug) - { - g_print ("calling %s with argv:\n", helper_process); - for (i = 0; i < argc + 1 + ARG_COUNT; i++) - g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL")); - } - - if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error)) - { - if (conv_error_index == ARG_WORKING_DIRECTORY) - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR, - _("Invalid working directory: %s"), - conv_error->message); - else - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Invalid string in argument vector at %d: %s"), - conv_error_index - ARG_PROGRAM, conv_error->message); - g_error_free (conv_error); - g_strfreev (protected_argv); - g_free (new_argv[0]); - g_free (new_argv[ARG_WORKING_DIRECTORY]); - g_free (new_argv); - g_free (helper_process); - - goto cleanup_and_fail; - } - - if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error)) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Invalid string in environment: %s"), - conv_error->message); - g_error_free (conv_error); - g_strfreev (protected_argv); - g_free (new_argv[0]); - g_free (new_argv[ARG_WORKING_DIRECTORY]); - g_free (new_argv); - g_free (helper_process); - g_strfreev ((gchar **) wargv); - - goto cleanup_and_fail; - } - - if (child_setup) - (* child_setup) (user_data); - - whelper = (wchar_t *)g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL); - g_free (helper_process); - - if (wenvp != NULL) - rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp); - else - rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv); - - saved_errno = errno; - - g_free (whelper); - g_strfreev ((gchar **) wargv); - g_strfreev ((gchar **) wenvp); - - /* Close the other process's ends of the pipes in this process, - * otherwise the reader will never get EOF. - */ - close_and_invalidate (&child_err_report_pipe[1]); - close_and_invalidate (&helper_sync_pipe[0]); - close_and_invalidate (&stdin_pipe[0]); - close_and_invalidate (&stdout_pipe[1]); - close_and_invalidate (&stderr_pipe[1]); - - g_strfreev (protected_argv); - - g_free (new_argv[0]); - g_free (new_argv[ARG_WORKING_DIRECTORY]); - g_free (new_argv); - - /* Check if gspawn-win32-helper couldn't be run */ - if (rc == -1 && saved_errno != 0) - { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, - _("Failed to execute helper program (%s)"), - g_strerror (saved_errno)); - goto cleanup_and_fail; - } - - if (exit_status != NULL) - { - /* Synchronous case. Pass helper's report pipe back to caller, - * which takes care of reading it after the grandchild has - * finished. - */ - g_assert (err_report != NULL); - *err_report = child_err_report_pipe[0]; - write (helper_sync_pipe[1], " ", 1); - close_and_invalidate (&helper_sync_pipe[1]); - } - else - { - /* Asynchronous case. We read the helper's report right away. */ - if (!read_helper_report (child_err_report_pipe[0], helper_report, error)) - goto cleanup_and_fail; - - close_and_invalidate (&child_err_report_pipe[0]); - - switch (helper_report[0]) - { - case CHILD_NO_ERROR: - if (child_handle && do_return_handle) - { - /* rc is our HANDLE for gspawn-win32-helper. It has - * told us the HANDLE of its child. Duplicate that into - * a HANDLE valid in this process. - */ - if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1], - GetCurrentProcess (), (LPHANDLE) child_handle, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - char *emsg = g_win32_error_message (GetLastError ()); - g_print("%s\n", emsg); - *child_handle = 0; - } - } - else if (child_handle) - *child_handle = 0; - write (helper_sync_pipe[1], " ", 1); - close_and_invalidate (&helper_sync_pipe[1]); - break; - - default: - write (helper_sync_pipe[1], " ", 1); - close_and_invalidate (&helper_sync_pipe[1]); - set_child_error (helper_report, working_directory, error); - goto cleanup_and_fail; - } - } - - /* Success against all odds! return the information */ - - if (standard_input) - *standard_input = stdin_pipe[1]; - if (standard_output) - *standard_output = stdout_pipe[0]; - if (standard_error) - *standard_error = stderr_pipe[0]; - if (rc != -1) - CloseHandle ((HANDLE) rc); - - return TRUE; - - cleanup_and_fail: - - if (rc != -1) - CloseHandle ((HANDLE) rc); - if (child_err_report_pipe[0] != -1) - close (child_err_report_pipe[0]); - if (child_err_report_pipe[1] != -1) - close (child_err_report_pipe[1]); - if (helper_sync_pipe[0] != -1) - close (helper_sync_pipe[0]); - if (helper_sync_pipe[1] != -1) - close (helper_sync_pipe[1]); - if (stdin_pipe[0] != -1) - close (stdin_pipe[0]); - if (stdin_pipe[1] != -1) - close (stdin_pipe[1]); - if (stdout_pipe[0] != -1) - close (stdout_pipe[0]); - if (stdout_pipe[1] != -1) - close (stdout_pipe[1]); - if (stderr_pipe[0] != -1) - close (stderr_pipe[0]); - if (stderr_pipe[1] != -1) - close (stderr_pipe[1]); - - return FALSE; -} - -gboolean -my_spawn_async_with_pipes_utf8 (const gchar *working_directory, - gchar **argv, - gchar **envp, - GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, - GPid *child_handle, - gint *standard_input, - gint *standard_output, - gint *standard_error, - GError **error) -{ - g_return_val_if_fail (argv != NULL, FALSE); - g_return_val_if_fail (standard_output == NULL || - !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); - g_return_val_if_fail (standard_error == NULL || - !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); - /* can't inherit stdin if we have an input pipe. */ - g_return_val_if_fail (standard_input == NULL || - !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE); - - return do_spawn_with_pipes (NULL, - (flags & G_SPAWN_DO_NOT_REAP_CHILD), - working_directory, - argv, - envp, - flags, - child_setup, - user_data, - child_handle, - standard_input, - standard_output, - standard_error, - NULL, - error); -} - -typedef GPid Pid; - -// _WRAP_ENUM(SpawnFlags, GSpawnFlags, NO_GTYPE) - -/* Helper callback to invoke the actual sigc++ slot. - * We don't need to worry about (un)referencing, since the - * child process gets its own copy of the parent's memory anyway. - */ -static void child_setup_callback(void* user_data) -{ - #ifdef GLIBMM_EXCEPTIONS_ENABLED - try - { - #endif //GLIBMM_EXCEPTIONS_ENABLED - (*reinterpret_cast*>(user_data))(); - #ifdef GLIBMM_EXCEPTIONS_ENABLED - } - catch(...) - { - Glib::exception_handlers_invoke(); - } - #endif //GLIBMM_EXCEPTIONS_ENABLED -} - - -void my_spawn_async_with_pipes(const std::string& working_directory, - const Glib::ArrayHandle& argv, - GSpawnFlags flags, - const sigc::slot& child_setup, - Pid* child_pid, - int* standard_input, - int* standard_output, - int* standard_error) -{ - const bool setup_slot = !child_setup.empty(); - sigc::slot child_setup_ = child_setup; - GError* error = 0; - - my_spawn_async_with_pipes_utf8( - working_directory.c_str(), - const_cast(argv.data()), 0, - static_cast(unsigned(flags)), - (setup_slot) ? &child_setup_callback : 0, - (setup_slot) ? &child_setup_ : 0, - child_pid, - standard_input, standard_output, standard_error, - &error); - - if(error) - Glib::Error::throw_exception(error); -} - -#endif - void Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory, const Glib::ArrayHandle& argv, @@ -1218,7 +325,6 @@ Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory, int* standard_output, int* standard_error) { -#ifndef BYPASS_GLIB_SPAWN Glib::spawn_async_with_pipes(working_directory, argv, flags, @@ -1227,16 +333,6 @@ Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory, standard_input, standard_output, standard_error); -#else - my_spawn_async_with_pipes(working_directory, - argv, - static_cast(flags), - child_setup, - child_pid, - standard_input, - standard_output, - standard_error); -#endif } diff --git a/src/main.cpp b/src/main.cpp index d11222203..a4ed5d77b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,8 @@ #endif /* Not def: POPT_TABLEEND */ #include +#include +#include #include #include #include @@ -471,61 +473,71 @@ gchar * blankParam = g_strdup(""); #ifdef WIN32 -/** - * Return the directory of the .exe that is currently running - */ -static Glib::ustring _win32_getExePath() -{ - char exeName[MAX_PATH+1]; - // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8 - GetModuleFileName(NULL, exeName, MAX_PATH); - char *slashPos = strrchr(exeName, '\\'); - if (slashPos) { - *slashPos = '\0'; - } - Glib::ustring s = exeName; - return s; -} - /** * Set up the PATH and PYTHONPATH environment variables on * win32 + * @param exe Inkscape executable directory in UTF-8 */ -static int _win32_set_inkscape_env(const Glib::ustring &exePath) +static void _win32_set_inkscape_env(gchar const *exe) { - // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows - - char *oldenv = getenv("PATH"); - Glib::ustring tmp = "PATH="; - tmp += exePath; - tmp += ";"; - tmp += exePath; - tmp += "\\python;"; - tmp += exePath; - tmp += "\\python\\Scripts;"; // for uniconv.cmd - tmp += exePath; - tmp += "\\perl"; - if(oldenv != NULL) { - tmp += ";"; - tmp += oldenv; + gchar const *path = g_getenv("PATH"); + gchar const *pythonpath = g_getenv("PYTHONPATH"); + + gchar *python = g_build_filename(exe, "python", NULL); + gchar *scripts = g_build_filename(exe, "python", "Scripts", NULL); + gchar *perl = g_build_filename(exe, "python", NULL); + gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL); + gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL); + + // Python 2.x needs short paths in PYTHONPATH. + // Otherwise it doesn't work when Inkscape is installed in Unicode directories. + // g_win32_locale_filename_from_utf8 is the Glib equivalent + // of GetShortPathName. + // Remove this once we move to Python 3.0. + gchar *python_s = g_win32_locale_filename_from_utf8(python); + gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib); + gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll); + + gchar *new_path; + gchar *new_pythonpath; + if (path) { + new_path = g_strdup_printf("%s;%s;%s;%s;%s", exe, python, scripts, perl, path); + } else { + new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl); } - _putenv(tmp.c_str()); - - oldenv = getenv("PYTHONPATH"); - tmp = "PYTHONPATH="; - tmp += exePath; - tmp += "\\python;"; - tmp += exePath; - tmp += "\\python\\Lib;"; - tmp += exePath; - tmp += "\\python\\DLLs"; - if(oldenv != NULL) { - tmp += ";"; - tmp += oldenv; + if (pythonpath) { + new_pythonpath = g_strdup_printf("%s;%s;%s;%s", python_s, pythonlib_s, pythondll_s, pythonpath); + } else { + new_pythonpath = g_strdup_printf("%s;%s;%s", python_s, pythonlib_s, pythondll_s); } - _putenv(tmp.c_str()); - return 0; + g_setenv("PATH", new_path, TRUE); + g_setenv("PYTHONPATH", new_pythonpath, TRUE); + + /* + printf("PATH = %s\n\n", g_getenv("PATH")); + printf("PYTHONPATH = %s\n\n", g_getenv("PYTHONPATH")); + + gchar *p = g_find_program_in_path("python"); + if (p) { + printf("python in %s\n\n", p); + g_free(p); + } else { + printf("python not found\n\n"); + }*/ + + g_free(python); + g_free(scripts); + g_free(perl); + g_free(pythonlib); + g_free(pythondll); + + g_free(python_s); + g_free(pythonlib_s); + g_free(pythondll_s); + + g_free(new_path); + g_free(new_pythonpath); } #endif @@ -568,55 +580,68 @@ main(int argc, char **argv) when inkscape.exe is executed from another directory. We use relative paths on win32. HKCR\svgfile\shell\open\command is a good example + + TODO: this breaks the CLI on Windows, see LP #167455 + However, the CLI is broken anyway, because we are a GUI app */ - Glib::ustring homedir = _win32_getExePath(); - // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8 - SetCurrentDirectory(homedir.c_str()); - _win32_set_inkscape_env(homedir); + const int pathbuf = 2048; + gunichar2 *path = g_new(gunichar2, pathbuf); + GetModuleFileNameW(NULL, (WCHAR*) path, pathbuf); + gchar *inkscape = g_utf16_to_utf8(path, -1, NULL, NULL, NULL); + gchar *exedir = g_path_get_dirname(inkscape); + gunichar2 *dirw = g_utf8_to_utf16(exedir, -1, NULL, NULL, NULL); + SetCurrentDirectoryW((WCHAR*) dirw); + _win32_set_inkscape_env(exedir); + +# ifdef ENABLE_NLS + // obtain short path to executable dir and pass it + // to bindtextdomain (it doesn't understand UTF-8) + gchar *shortexedir = g_win32_locale_filename_from_utf8(exedir); + gchar *localepath = g_build_filename(shortexedir, PACKAGE_LOCALE_DIR, NULL); + bindtextdomain(GETTEXT_PACKAGE, localepath); + g_free(shortexedir); + g_free(localepath); +# endif + + g_free(path); + g_free(inkscape); + g_free(exedir); + g_free(dirw); + // Don't touch the registry (works fine without it) for Inkscape Portable gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR"); if (!val) { RegistryTool rt; rt.setPathInfo(); } -#endif - - // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) - Gtk::Main::init_gtkmm_internals(); - - // Bug #197475 - set_extensions_env(); - - /** - * Call bindtextdomain() for various machines's paths - */ -#ifdef ENABLE_NLS -#ifdef WIN32 - Glib::ustring localePath = homedir; - localePath += "\\"; - localePath += PACKAGE_LOCALE_DIR; - bindtextdomain(GETTEXT_PACKAGE, localePath.c_str()); -#else -#ifdef ENABLE_BINRELOC +#elif defined(ENABLE_NLS) +# ifdef ENABLE_BINRELOC bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR("")); -#else +# else bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); +# endif #endif -#endif + + // the bit below compiles regardless of platform +#ifdef ENABLE_NLS // Allow the user to override the locale directory by setting // the environment variable INKSCAPE_LOCALEDIR. - char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR"); + char const *inkscape_localedir = g_getenv("INKSCAPE_LOCALEDIR"); if (inkscape_localedir != NULL) { bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir); } -#endif + // common setup bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - -#ifdef ENABLE_NLS textdomain(GETTEXT_PACKAGE); #endif + // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) + Gtk::Main::init_gtkmm_internals(); + + // Bug #197475 + set_extensions_env(); + LIBXML_TEST_VERSION Inkscape::GC::init(); @@ -626,8 +651,7 @@ main(int argc, char **argv) gboolean use_gui; #ifndef WIN32 - // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows - use_gui = (getenv("DISPLAY") != NULL); + use_gui = (g_getenv("DISPLAY") != NULL); #else use_gui = TRUE; #endif diff --git a/src/prefix.cpp b/src/prefix.cpp index f1fa3c2cd..8c1dd4f00 100644 --- a/src/prefix.cpp +++ b/src/prefix.cpp @@ -31,14 +31,7 @@ #endif -/* PLEASE NOTE: We use GThreads now for portability */ -/* @see http://developer.gnome.org/doc/API/2.0/glib/glib-Threads.html */ -#ifndef BR_THREADS - /* Change 1 to 0 if you don't want thread support */ - #define BR_THREADS 1 - #include //for GThreads -#endif /* BR_THREADS */ - +#include #include #include #include @@ -55,9 +48,9 @@ extern "C" { #define NULL ((void *) 0) #ifdef __GNUC__ - #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;} + #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;} #else - #define br_return_val_if_fail(expr,val) if (!(expr)) return val + #define br_return_val_if_fail(expr,val) if (!(expr)) return val #endif /* __GNUC__ */ @@ -72,8 +65,8 @@ extern "C" { * br_locate: * symbol: A symbol that belongs to the app/library you want to locate. * Returns: A newly allocated string containing the full path of the - * app/library that func belongs to, or NULL on error. This - * string should be freed when not when no longer needed. + * app/library that func belongs to, or NULL on error. This + * string should be freed when not when no longer needed. * * Finds out to which application or library symbol belongs, then locate * the full path of that application or library. @@ -85,70 +78,70 @@ extern "C" { * #include "libfoo.h" * * int main (int argc, char *argv[]) { - * printf ("Full path of this app: %s\n", br_locate (&argc)); - * libfoo_start (); - * return 0; + * printf ("Full path of this app: %s\n", br_locate (&argc)); + * libfoo_start (); + * return 0; * } * * --> libfoo.c starts here * #include "prefix.h" * * void libfoo_start () { - * --> "" is a symbol that belongs to libfoo (because it's called - * --> from libfoo_start()); that's why this works. - * printf ("libfoo is located in: %s\n", br_locate ("")); + * --> "" is a symbol that belongs to libfoo (because it's called + * --> from libfoo_start()); that's why this works. + * printf ("libfoo is located in: %s\n", br_locate ("")); * } */ char * br_locate (void *symbol) { - char line[5000]; - FILE *f; - char *path; - - br_return_val_if_fail (symbol != NULL, NULL); - - f = fopen ("/proc/self/maps", "r"); - if (!f) - return NULL; - - while (!feof (f)) - { - unsigned long start, end; - - if (!fgets (line, sizeof (line), f)) - continue; - if (!strstr (line, " r-xp ") || !strchr (line, '/')) - continue; - - sscanf (line, "%lx-%lx ", &start, &end); - if (symbol >= (void *) start && symbol < (void *) end) - { - char *tmp; - size_t len; - - /* Extract the filename; it is always an absolute path */ - path = strchr (line, '/'); - - /* Get rid of the newline */ - tmp = strrchr (path, '\n'); - if (tmp) *tmp = 0; - - /* Get rid of "(deleted)" */ - len = strlen (path); - if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0) - { - tmp = path + len - 10; - *tmp = 0; - } - - fclose(f); - return strdup (path); - } - } - - fclose (f); - return NULL; + char line[5000]; + FILE *f; + char *path; + + br_return_val_if_fail (symbol != NULL, NULL); + + f = fopen ("/proc/self/maps", "r"); + if (!f) + return NULL; + + while (!feof (f)) + { + unsigned long start, end; + + if (!fgets (line, sizeof (line), f)) + continue; + if (!strstr (line, " r-xp ") || !strchr (line, '/')) + continue; + + sscanf (line, "%lx-%lx ", &start, &end); + if (symbol >= (void *) start && symbol < (void *) end) + { + char *tmp; + size_t len; + + /* Extract the filename; it is always an absolute path */ + path = strchr (line, '/'); + + /* Get rid of the newline */ + tmp = strrchr (path, '\n'); + if (tmp) *tmp = 0; + + /* Get rid of "(deleted)" */ + len = strlen (path); + if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0) + { + tmp = path + len - 10; + *tmp = 0; + } + + fclose(f); + return strdup (path); + } + } + + fclose (f); + return NULL; } @@ -168,16 +161,16 @@ br_locate (void *symbol) char * br_locate_prefix (void *symbol) { - char *path, *prefix; + char *path, *prefix; - br_return_val_if_fail (symbol != NULL, NULL); + br_return_val_if_fail (symbol != NULL, NULL); - path = br_locate (symbol); - if (!path) return NULL; + path = br_locate (symbol); + if (!path) return NULL; - prefix = br_extract_prefix (path); - free (path); - return prefix; + prefix = br_extract_prefix (path); + free (path); + return prefix; } @@ -186,7 +179,7 @@ br_locate_prefix (void *symbol) * symbol: A symbol that belongs to the app/library you want to locate. * path: The path that you want to prepend the prefix to. * Returns: The new path, or NULL on error. This string should be freed when no - * longer needed. + * longer needed. * * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path. * Note that symbol cannot be a pointer to a function. That will not work. @@ -198,24 +191,24 @@ br_locate_prefix (void *symbol) char * br_prepend_prefix (void *symbol, char *path) { - char *tmp, *newpath; + char *tmp, *newpath; - br_return_val_if_fail (symbol != NULL, NULL); - br_return_val_if_fail (path != NULL, NULL); + br_return_val_if_fail (symbol != NULL, NULL); + br_return_val_if_fail (path != NULL, NULL); - tmp = br_locate_prefix (symbol); - if (!tmp) return NULL; + tmp = br_locate_prefix (symbol); + if (!tmp) return NULL; - if (strcmp (tmp, "/") == 0) - newpath = strdup (path); - else - newpath = br_strcat (tmp, path); + if (strcmp (tmp, "/") == 0) + newpath = strdup (path); + else + newpath = br_strcat (tmp, path); - /* Get rid of compiler warning ("br_prepend_prefix never used") */ - if (0) br_prepend_prefix (NULL, NULL); + /* Get rid of compiler warning ("br_prepend_prefix never used") */ + if (0) br_prepend_prefix (NULL, NULL); - free (tmp); - return newpath; + free (tmp); + return newpath; } #endif /* ENABLE_BINRELOC */ @@ -264,33 +257,33 @@ br_free_last_value () const char * br_thread_local_store (char *str) { - #if BR_THREADS + #if BR_THREADS if (!g_thread_supported ()) { g_thread_init ((GThreadFunctions *)NULL); br_thread_key = g_private_new (g_free); } - char *specific = (char *) g_private_get (br_thread_key); - if (specific) + char *specific = (char *) g_private_get (br_thread_key); + if (specific) free (specific); g_private_set (br_thread_key, str); - #else /* !BR_THREADS */ - static int initialized = 0; + #else /* !BR_THREADS */ + static int initialized = 0; - if (!initialized) - { - atexit (br_free_last_value); - initialized = 1; - } + if (!initialized) + { + atexit (br_free_last_value); + initialized = 1; + } - if (br_last_value) - free (br_last_value); - br_last_value = str; - #endif /* BR_THREADS */ + if (br_last_value) + free (br_last_value); + br_last_value = str; + #endif /* BR_THREADS */ - return (const char *) str; + return (const char *) str; } @@ -305,21 +298,21 @@ br_thread_local_store (char *str) char * br_strcat (const char *str1, const char *str2) { - char *result; - size_t len1, len2; + char *result; + size_t len1, len2; - if (!str1) str1 = ""; - if (!str2) str2 = ""; + if (!str1) str1 = ""; + if (!str2) str2 = ""; - len1 = strlen (str1); - len2 = strlen (str2); + len1 = strlen (str1); + len2 = strlen (str2); - result = (char *) malloc (len1 + len2 + 1); - memcpy (result, str1, len1); - memcpy (result + len1, str2, len2); - result[len1 + len2] = '\0'; + result = (char *) malloc (len1 + len2 + 1); + memcpy (result, str1, len1); + memcpy (result + len1, str2, len2); + result[len1 + len2] = '\0'; - return result; + return result; } @@ -327,18 +320,18 @@ br_strcat (const char *str1, const char *str2) static char * br_strndup (char *str, size_t size) { - char *result = (char*)NULL; - size_t len; + char *result = (char*)NULL; + size_t len; - br_return_val_if_fail (str != (char*)NULL, (char*)NULL); + br_return_val_if_fail (str != (char*)NULL, (char*)NULL); - len = strlen (str); - if (!len) return strdup (""); - if (size > len) size = len; + len = strlen (str); + if (!len) return strdup (""); + if (size > len) size = len; - result = (char *) calloc (sizeof (char), len + 1); - memcpy (result, str, size); - return result; + result = (char *) calloc (sizeof (char), len + 1); + memcpy (result, str, size); + return result; } @@ -356,23 +349,23 @@ br_strndup (char *str, size_t size) char * br_extract_dir (const char *path) { - const char *end; - char *result; - - br_return_val_if_fail (path != (char*)NULL, (char*)NULL); - - end = strrchr (path, '/'); - if (!end) return strdup ("."); - - while (end > path && *end == '/') - end--; - result = br_strndup ((char *) path, end - path + 1); - if (!*result) - { - free (result); - return strdup ("/"); - } else - return result; + const char *end; + char *result; + + br_return_val_if_fail (path != (char*)NULL, (char*)NULL); + + end = strrchr (path, '/'); + if (!end) return strdup ("."); + + while (end > path && *end == '/') + end--; + result = br_strndup ((char *) path, end - path + 1); + if (!*result) + { + free (result); + return strdup ("/"); + } else + return result; } @@ -392,34 +385,34 @@ br_extract_dir (const char *path) char * br_extract_prefix (const char *path) { - const char *end; - char *tmp, *result; - - br_return_val_if_fail (path != (char*)NULL, (char*)NULL); - - if (!*path) return strdup ("/"); - end = strrchr (path, '/'); - if (!end) return strdup (path); - - tmp = br_strndup ((char *) path, end - path); - if (!*tmp) - { - free (tmp); - return strdup ("/"); - } - end = strrchr (tmp, '/'); - if (!end) return tmp; - - result = br_strndup (tmp, end - tmp); - free (tmp); - - if (!*result) - { - free (result); - result = strdup ("/"); - } - - return result; + const char *end; + char *tmp, *result; + + br_return_val_if_fail (path != (char*)NULL, (char*)NULL); + + if (!*path) return strdup ("/"); + end = strrchr (path, '/'); + if (!end) return strdup (path); + + tmp = br_strndup ((char *) path, end - path); + if (!*tmp) + { + free (tmp); + return strdup ("/"); + } + end = strrchr (tmp, '/'); + if (!end) return tmp; + + result = br_strndup (tmp, end - tmp); + free (tmp); + + if (!*result) + { + free (result); + result = strdup ("/"); + } + + return result; } @@ -444,13 +437,14 @@ br_extract_prefix (const char *path) */ static Glib::ustring win32_getExePath() { - char exeName[MAX_PATH+1]; - GetModuleFileName(NULL, exeName, MAX_PATH); - char *slashPos = strrchr(exeName, '\\'); - if (slashPos) - *slashPos = '\0'; - Glib::ustring s = exeName; - return s; + gunichar2 path[2048]; + GetModuleFileNameW(NULL, (WCHAR*) path, 2048); + gchar *exe = g_utf16_to_utf8(path, -1, NULL, NULL, NULL); + gchar *dir = g_path_get_dirname(exe); + Glib::ustring ret = dir; + g_free(dir); + g_free(exe); + return ret; } @@ -461,8 +455,8 @@ static Glib::ustring win32_getExePath() static Glib::ustring win32_getDataDir() { Glib::ustring dir = win32_getExePath(); - if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR && - strcmp(INKSCAPE_DATADIR, ".") != 0) + if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR && + strcmp(INKSCAPE_DATADIR, ".") != 0) { dir += "\\"; dir += INKSCAPE_DATADIR; diff --git a/src/registrytool.cpp b/src/registrytool.cpp index 2017f50c7..af41c3eaf 100644 --- a/src/registrytool.cpp +++ b/src/registrytool.cpp @@ -60,6 +60,7 @@ bool RegistryTool::setStringValue(const Glib::ustring &keyNameArg, const Glib::ustring &value) { Glib::ustring keyName = keyNameArg; + bool ret = false; HKEY rootKey = HKEY_LOCAL_MACHINE; //default root //Trim out the root key if necessary @@ -74,28 +75,35 @@ bool RegistryTool::setStringValue(const Glib::ustring &keyNameArg, //printf("trimmed string: '%s'\n", keyName.c_str()); //Get or create the key + gunichar2 *keyw = g_utf8_to_utf16(keyName.data(), -1, 0,0,0); + gunichar2 *valuenamew = g_utf8_to_utf16(valueName.data(), -1, 0,0,0); + HKEY key; - if (RegCreateKeyEx(rootKey, keyName.c_str(), + if (RegCreateKeyExW(rootKey, (WCHAR*) keyw, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL)) - { + { fprintf(stderr, "RegistryTool: Could not create the registry key '%s'\n", keyName.c_str()); - return false; - } + goto fail; + } - //Set the value - if (RegSetValueEx(key, valueName.c_str(), - 0, REG_SZ, (LPBYTE) value.c_str(), (DWORD) value.size())) - { + // Set the value + if (RegSetValueExW(key, (WCHAR*) valuenamew, + 0, REG_SZ, (LPBYTE) value.data(), (DWORD) (value.size() + 1))) + { fprintf(stderr, "RegistryTool: Could not set the value '%s'\n", value.c_str()); - RegCloseKey(key); - return false; - } - + goto failkey; + } + ret = true; + + failkey: RegCloseKey(key); - - return true; + + fail: + g_free(keyw); + g_free(valuenamew); + return ret; } @@ -107,19 +115,14 @@ bool RegistryTool::getExeInfo(Glib::ustring &fullPath, Glib::ustring &path, Glib::ustring &exeName) { + const int pathbuf = 2048; + gunichar2 pathw[pathbuf]; + GetModuleFileNameW(NULL, (WCHAR*) pathw, pathbuf); - char buf[MAX_PATH+1]; - if (!GetModuleFileName(NULL, buf, MAX_PATH)) - { - fprintf(stderr, "Could not fetch executable file name\n"); - return false; - } - else - { - //printf("Executable file name: '%s'\n", buf); - } + gchar *utf8path = g_utf16_to_utf8(pathw, -1, 0,0,0); + fullPath = utf8path; + g_free(utf8path); - fullPath = buf; path = ""; exeName = ""; Glib::ustring::size_type pos = fullPath.rfind('\\'); -- cgit v1.2.3 From 45b0106614f265c2b5c8e2d0925f4047837583d2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 28 Mar 2010 22:22:11 +0200 Subject: Remove leftover debug output (bzr r9249) --- src/extension/implementation/script.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 256996663..53a666e25 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -136,7 +136,6 @@ std::string Script::resolveInterpreterExecutable(const Glib::ustring &interpName if (!Glib::path_is_absolute(interpreter_path)) { interpreter_path = Glib::find_program_in_path(interpreter_path); } - printf("Interpreter name: %s\n", interpreter_path.data()); return interpreter_path; } -- cgit v1.2.3 From 9219826d44dbe32de525ab43e8215f8abaf04fbd Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 29 Mar 2010 01:13:04 +0200 Subject: Fix regression (inkex.py not found for extensions in user's directory) (bzr r9250) --- src/main.cpp | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index a4ed5d77b..c50ba7311 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -474,8 +474,7 @@ gchar * blankParam = g_strdup(""); #ifdef WIN32 /** - * Set up the PATH and PYTHONPATH environment variables on - * win32 + * Set up the PATH and PYTHONPATH environment variables on Windows * @param exe Inkscape executable directory in UTF-8 */ static void _win32_set_inkscape_env(gchar const *exe) @@ -488,15 +487,16 @@ static void _win32_set_inkscape_env(gchar const *exe) gchar *perl = g_build_filename(exe, "python", NULL); gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL); gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL); + gchar *extdir = g_build_filename(exe, "share", "extensions", NULL); // Python 2.x needs short paths in PYTHONPATH. // Otherwise it doesn't work when Inkscape is installed in Unicode directories. - // g_win32_locale_filename_from_utf8 is the Glib equivalent - // of GetShortPathName. + // g_win32_locale_filename_from_utf8 is the GLib wrapper for GetShortPathName. // Remove this once we move to Python 3.0. gchar *python_s = g_win32_locale_filename_from_utf8(python); gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib); gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll); + gchar *extdir_s = g_win32_locale_filename_from_utf8(extdir); gchar *new_path; gchar *new_pythonpath; @@ -506,9 +506,11 @@ static void _win32_set_inkscape_env(gchar const *exe) new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl); } if (pythonpath) { - new_pythonpath = g_strdup_printf("%s;%s;%s;%s", python_s, pythonlib_s, pythondll_s, pythonpath); + new_pythonpath = g_strdup_printf("%s;%s;%s;%s;%s", + extdir_s, python_s, pythonlib_s, pythondll_s, pythonpath); } else { - new_pythonpath = g_strdup_printf("%s;%s;%s", python_s, pythonlib_s, pythondll_s); + new_pythonpath = g_strdup_printf("%s;%s;%s;%s", + extdir_s, python_s, pythonlib_s, pythondll_s); } g_setenv("PATH", new_path, TRUE); @@ -541,24 +543,6 @@ static void _win32_set_inkscape_env(gchar const *exe) } #endif -/** - * Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home - * can find inkex.py et al. (Bug #197475) - */ -static int set_extensions_env() -{ - char *oldenv = getenv("PYTHONPATH"); - Glib::ustring tmp = INKSCAPE_EXTENSIONDIR; - if (oldenv != NULL) { - tmp += G_SEARCHPATH_SEPARATOR; - tmp += oldenv; - } - g_setenv("PYTHONPATH", tmp.c_str(), TRUE); - - return 0; -} - - /** * This is the classic main() entry point of the program, though on some * architectures it might be called by something else. @@ -639,9 +623,6 @@ main(int argc, char **argv) // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) Gtk::Main::init_gtkmm_internals(); - // Bug #197475 - set_extensions_env(); - LIBXML_TEST_VERSION Inkscape::GC::init(); -- cgit v1.2.3 From 4f8ab4cea8237d843a25d033d077851ba2fd6a5d Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 29 Mar 2010 01:23:56 +0200 Subject: Oops - obviously the previous fix didn't work outside Windows (bzr r9251) --- src/main.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index c50ba7311..a6dfb37f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -487,7 +487,6 @@ static void _win32_set_inkscape_env(gchar const *exe) gchar *perl = g_build_filename(exe, "python", NULL); gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL); gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL); - gchar *extdir = g_build_filename(exe, "share", "extensions", NULL); // Python 2.x needs short paths in PYTHONPATH. // Otherwise it doesn't work when Inkscape is installed in Unicode directories. @@ -496,7 +495,6 @@ static void _win32_set_inkscape_env(gchar const *exe) gchar *python_s = g_win32_locale_filename_from_utf8(python); gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib); gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll); - gchar *extdir_s = g_win32_locale_filename_from_utf8(extdir); gchar *new_path; gchar *new_pythonpath; @@ -506,11 +504,11 @@ static void _win32_set_inkscape_env(gchar const *exe) new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl); } if (pythonpath) { - new_pythonpath = g_strdup_printf("%s;%s;%s;%s;%s", - extdir_s, python_s, pythonlib_s, pythondll_s, pythonpath); - } else { new_pythonpath = g_strdup_printf("%s;%s;%s;%s", - extdir_s, python_s, pythonlib_s, pythondll_s); + python_s, pythonlib_s, pythondll_s, pythonpath); + } else { + new_pythonpath = g_strdup_printf("%s;%s;%s", + python_s, pythonlib_s, pythondll_s); } g_setenv("PATH", new_path, TRUE); @@ -543,6 +541,24 @@ static void _win32_set_inkscape_env(gchar const *exe) } #endif +static void set_extensions_env() +{ + gchar const *pythonpath = g_getenv("PYTHONPATH"); + gchar *extdir; + +#ifdef WIN32 + extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR); +#else + extdir = g_strdup(INKSCAPE_EXTENSIONDIR); +#endif + + gchar *new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", + extdir, pythonpath); + g_setenv("PYTHONPATH", new_pythonpath, TRUE); + g_free(extdir); + g_free(new_pythonpath); +} + /** * This is the classic main() entry point of the program, though on some * architectures it might be called by something else. @@ -620,6 +636,8 @@ main(int argc, char **argv) textdomain(GETTEXT_PACKAGE); #endif + set_extensions_env(); + // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) Gtk::Main::init_gtkmm_internals(); -- cgit v1.2.3 From ff6d2ea9a273ac0aa3a95ece22cd783a5b49aa23 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 28 Mar 2010 22:00:58 -0700 Subject: Purge use of SP_ACTIVE_* and encapsulate by moving 'active' desktop tracking out of lower-level panels. Fixes bug #270623. Fixed bugs: - https://launchpad.net/bugs/270623 (bzr r9252) --- src/ui/dialog/fill-and-stroke.cpp | 69 +++++++++++++++++++-- src/ui/dialog/fill-and-stroke.h | 19 +++++- src/widgets/fill-n-stroke-factory.h | 6 +- src/widgets/fill-style.cpp | 120 ++++++++++++++++++++---------------- src/widgets/fill-style.h | 10 ++- src/widgets/stroke-style.cpp | 9 ++- src/widgets/stroke-style.h | 11 ++-- 7 files changed, 176 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index fe63c6e24..fae2e873c 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -6,8 +6,10 @@ /* Authors: * Bryce W. Harrington * Gustav Broberg + * Jon A. Cruz * * Copyright (C) 2004--2007 Authors + * Copyright (C) 2010 Jon A. Cruz * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -29,6 +31,8 @@ #include "widgets/stroke-style.h" #include "xml/repr.h" +#include "ui/view/view-widget.h" + namespace Inkscape { namespace UI { namespace Dialog { @@ -38,7 +42,12 @@ FillAndStroke::FillAndStroke() _page_fill(1, 1, true, true), _page_stroke_paint(1, 1, true, true), _page_stroke_style(1, 1, true, true), - _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", SimpleFilterModifier::BLUR) + _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", SimpleFilterModifier::BLUR), + hierID(0), + trackActive(false), + targetDesktop(0), + fillWdgt(0), + strokeWdgt(0) { Gtk::Box *contents = _getContents(); contents->set_spacing(0); @@ -58,25 +67,75 @@ FillAndStroke::FillAndStroke() show_all_children(); _composite_settings.setSubject(&_subject); + + // Use C/gobject callbacks to avoid gtkmm rewrap-during-destruct issues: + hierID = g_signal_connect( G_OBJECT(gobj()), "hierarchy-changed", G_CALLBACK(hierarchyChangeCB), this ); + + g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( activateDesktopCB ), this ); } FillAndStroke::~FillAndStroke() { _composite_settings.setSubject(NULL); + if (hierID) { + g_signal_handler_disconnect(G_OBJECT(gobj()), hierID); + hierID = 0; + } +} + +gboolean FillAndStroke::activateDesktopCB(Inkscape::Application */*inkscape*/, SPDesktop *desktop, FillAndStroke *self ) +{ + if (self && self->trackActive) { + self->setTargetDesktop(desktop); + } + return FALSE; +} + +bool FillAndStroke::hierarchyChangeCB(GtkWidget *widget, GtkWidget* /*prev*/, FillAndStroke *self) +{ + if (self) { + GtkWidget *ww = gtk_widget_get_ancestor(widget, SP_TYPE_VIEW_WIDGET); + bool newFlag = (ww == 0); + if (newFlag != self->trackActive) { + self->trackActive = newFlag; + if (self->trackActive) { + self->setTargetDesktop(SP_ACTIVE_DESKTOP); + } else { + self->setTargetDesktop(self->getDesktop()); + } + } + } + return false; +} + +void FillAndStroke::setDesktop(SPDesktop *desktop) +{ + Panel::setDesktop(desktop); + setTargetDesktop(desktop); +} + +void FillAndStroke::setTargetDesktop(SPDesktop *desktop) +{ + if (fillWdgt) { + sp_fill_style_widget_set_desktop(fillWdgt, desktop); + } + if (strokeWdgt) { + sp_stroke_style_widget_set_desktop(strokeWdgt, desktop); + } } void FillAndStroke::_layoutPageFill() { - Gtk::Widget *fs = manage(Glib::wrap(sp_fill_style_widget_new())); - _page_fill.table().attach(*fs, 0, 1, 0, 1); + fillWdgt = manage(sp_fill_style_widget_new()); + _page_fill.table().attach(*fillWdgt, 0, 1, 0, 1); } void FillAndStroke::_layoutPageStrokePaint() { - Gtk::Widget *ssp = manage(Glib::wrap(sp_stroke_style_paint_widget_new())); - _page_stroke_paint.table().attach(*ssp, 0, 1, 0, 1); + strokeWdgt = manage(sp_stroke_style_paint_widget_new()); + _page_stroke_paint.table().attach(*strokeWdgt, 0, 1, 0, 1); } void diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 7dc892fea..f0d68ced8 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -4,8 +4,10 @@ /* Authors: * Bryce W. Harrington * Gustav Broberg + * Jon A. Cruz * * Copyright (C) 2004--2007 Authors + * Copyright (C) 2010 Jon A. Cruz * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -37,6 +39,12 @@ public: static FillAndStroke &getInstance() { return *new FillAndStroke(); } + + virtual void setDesktop(SPDesktop *desktop); + + // temporary work-around until panel dialog itself tracks 'focus' properly. + virtual void setTargetDesktop(SPDesktop *desktop); + void selectionChanged(Inkscape::Application *inkscape, Inkscape::Selection *selection); @@ -54,7 +62,7 @@ protected: StyleSubject::Selection _subject; ObjectCompositeSettings _composite_settings; - Gtk::HBox &_createPageTabLabel(const Glib::ustring &label, + Gtk::HBox &_createPageTabLabel(const Glib::ustring &label, const char *label_image); void _layoutPageFill(); @@ -64,6 +72,15 @@ protected: private: FillAndStroke(FillAndStroke const &d); FillAndStroke& operator=(FillAndStroke const &d); + + static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, FillAndStroke *self ); + static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, FillAndStroke *self); + + gulong hierID; + bool trackActive; + SPDesktop *targetDesktop; + Gtk::Widget *fillWdgt; + Gtk::Widget *strokeWdgt; }; } // namespace Dialog diff --git a/src/widgets/fill-n-stroke-factory.h b/src/widgets/fill-n-stroke-factory.h index 14cbd6a58..74339a07f 100644 --- a/src/widgets/fill-n-stroke-factory.h +++ b/src/widgets/fill-n-stroke-factory.h @@ -10,12 +10,14 @@ #include "fill-or-stroke.h" -typedef struct _GtkWidget GtkWidget; +namespace Gtk { +class Widget; +} namespace Inkscape { namespace Widgets { -GtkWidget *createStyleWidget( FillOrStroke kind ); +Gtk::Widget *createStyleWidget( FillOrStroke kind ); } // namespace Widgets } // namespace Inkscape diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 552668a88..63def4c87 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -24,6 +24,8 @@ #include #include +#include "desktop.h" +#include "selection.h" #include "desktop-handles.h" #include "desktop-style.h" #include "display/sp-canvas.h" @@ -49,6 +51,13 @@ /* Fill */ +Gtk::Widget *sp_fill_style_widget_new(void) +{ + return Inkscape::Widgets::createStyleWidget( FILL ); +} + + +namespace Inkscape { class FillNStroke : public Gtk::VBox { @@ -58,6 +67,8 @@ public: void setFillrule( SPPaintSelector::FillRule mode ); + void setDesktop(SPDesktop *desktop); + private: static void paintModeChangeCB(SPPaintSelector *psel, SPPaintSelector::Mode mode, FillNStroke *self); static void paintChangedCB(SPPaintSelector *psel, FillNStroke *self); @@ -65,8 +76,7 @@ private: static void fillruleChangedCB( SPPaintSelector *psel, SPPaintSelector::FillRule mode, FillNStroke *self ); - static void selectionModifiedCB(Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, FillNStroke *self); - static void selectionChangedCB(Inkscape::Application *inkscape, void * data, FillNStroke *self); + void selectionModifiedCB(guint flags); void dragFromPaint(); void updateFromPaint(); @@ -74,33 +84,47 @@ private: void performUpdate(); FillOrStroke kind; + SPDesktop *desktop; SPPaintSelector *psel; bool update; bool local; + sigc::connection selectChangedConn; + sigc::connection subselChangedConn; + sigc::connection selectModifiedConn; }; +} // namespace Inkscape -GtkWidget *sp_fill_style_widget_new(void) +void sp_fill_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop) { - return Inkscape::Widgets::createStyleWidget( FILL ); + Inkscape::FillNStroke *fs = dynamic_cast(widget); + if (fs) { + fs->setDesktop(desktop); + } } +namespace Inkscape { + /** * Create the fill or stroke style widget, and hook up all the signals. */ -GtkWidget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) +Gtk::Widget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind ) { - FillNStroke *filler = Gtk::manage(new FillNStroke(kind)); + FillNStroke *filler = new FillNStroke(kind); - return GTK_WIDGET(filler->gobj()); + return filler; } FillNStroke::FillNStroke( FillOrStroke kind ) : Gtk::VBox(), kind(kind), + desktop(0), psel(0), update(false), - local(false) + local(false), + selectChangedConn(), + subselChangedConn(), + selectModifiedConn() { // Add and connect up the paint selector widget: psel = sp_paint_selector_new(kind); @@ -123,58 +147,50 @@ FillNStroke::FillNStroke( FillOrStroke kind ) : this ); } - // connect to the app instance to get selection notifications. - // TODO FIXME should really get connected to a Desktop instead. - Inkscape::Application *appInstance = INKSCAPE; - g_signal_connect( G_OBJECT(appInstance), "modify_selection", - G_CALLBACK(selectionModifiedCB), - this ); - - g_signal_connect( G_OBJECT(appInstance), "change_selection", - G_CALLBACK(selectionChangedCB), - this ); - - g_signal_connect( G_OBJECT(appInstance), "change_subselection", - G_CALLBACK(selectionChangedCB), - this ); - - performUpdate(); } FillNStroke::~FillNStroke() { psel = 0; + selectModifiedConn.disconnect(); + subselChangedConn.disconnect(); + selectChangedConn.disconnect(); } /** * On signal modified, invokes an update of the fill or stroke style paint object. */ -void FillNStroke::selectionModifiedCB( Inkscape::Application * /*inkscape*/, - Inkscape::Selection */*selection*/, - guint flags, - FillNStroke *self ) +void FillNStroke::selectionModifiedCB( guint flags ) { - if (self && - (flags & ( SP_OBJECT_MODIFIED_FLAG | + if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG) ) ) { + SP_OBJECT_STYLE_MODIFIED_FLAG) ) { #ifdef SP_FS_VERBOSE - g_message("selectionModifiedCB(%p)", self); + g_message("selectionModifiedCB(%d) on %p", flags, this); #endif - self->performUpdate(); + performUpdate(); } } -/** - * On signal selection changed or subselection changed, invokes an update of the fill or stroke style paint object. - */ -void FillNStroke::selectionChangedCB( Inkscape::Application * /*inkscape*/, - void * /*data*/, - FillNStroke *self ) +void FillNStroke::setDesktop(SPDesktop *desktop) { - if (self) { - self->performUpdate(); + if (this->desktop != desktop) { + if (this->desktop) { + selectModifiedConn.disconnect(); + subselChangedConn.disconnect(); + selectChangedConn.disconnect(); + } + this->desktop = desktop; + if (desktop && desktop->selection) { + selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate))); + subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate))); + + // Must check flags, so can't call performUpdate() directly. + selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &FillNStroke::selectionModifiedCB))); + + } + performUpdate(); } } @@ -186,7 +202,7 @@ void FillNStroke::selectionChangedCB( Inkscape::Application * /*inkscape*/, */ void FillNStroke::performUpdate() { - if ( update ) { + if ( update || !desktop ) { return; } @@ -201,10 +217,10 @@ void FillNStroke::performUpdate() update = true; // create temporary style - SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + SPStyle *query = sp_style_new(desktop->doc()); // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection - int result = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); + int result = sp_desktop_query_style(desktop, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity; @@ -298,9 +314,7 @@ void FillNStroke::fillruleChangedCB( SPPaintSelector * /*psel*/, void FillNStroke::setFillrule( SPPaintSelector::FillRule mode ) { - if (!update) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - + if (!update && desktop) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill-rule", (mode == SPPaintSelector::FILLRULE_EVENODD) ? "evenodd":"nonzero"); @@ -309,7 +323,7 @@ void FillNStroke::setFillrule( SPPaintSelector::FillRule mode ) sp_repr_css_attr_unref(css); css = 0; - sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE, + sp_document_done(desktop->doc(), SP_VERB_DIALOG_FILL_STROKE, _("Change fill rule")); } } @@ -342,7 +356,7 @@ void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self) */ void FillNStroke::dragFromPaint() { - if (!INKSCAPE || update) { + if (!desktop || update) { return; } @@ -361,8 +375,8 @@ void FillNStroke::dragFromPaint() case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { - psel->setFlatColor( SP_ACTIVE_DESKTOP, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); - sp_document_maybe_done(sp_desktop_document(SP_ACTIVE_DESKTOP), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, + psel->setFlatColor( desktop, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); + sp_document_maybe_done(desktop->doc(), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, (kind == FILL) ? _("Set fill color") : _("Set stroke color")); if (kind == FILL) { local = true; // local change, do not update from selection @@ -397,7 +411,6 @@ void FillNStroke::paintChangedCB( SPPaintSelector * /*psel*/, FillNStroke *self void FillNStroke::updateFromPaint() { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { return; } @@ -484,7 +497,7 @@ void FillNStroke::updateFromPaint() if (!vector) { /* No vector in paint selector should mean that we just changed mode */ - SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + SPStyle *query = sp_style_new(desktop->doc()); int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; guint32 common_rgb = 0; @@ -635,6 +648,7 @@ void FillNStroke::updateFromPaint() update = false; } +} // namespace Inkscape /* Local Variables: diff --git a/src/widgets/fill-style.h b/src/widgets/fill-style.h index ea97bd486..ef19d7788 100644 --- a/src/widgets/fill-style.h +++ b/src/widgets/fill-style.h @@ -14,9 +14,15 @@ #ifndef SEEN_DIALOGS_SP_FILL_STYLE_H #define SEEN_DIALOGS_SP_FILL_STYLE_H -typedef struct _GtkWidget GtkWidget; +namespace Gtk { +class Widget; +} -GtkWidget *sp_fill_style_widget_new(void); +class SPDesktop; + +Gtk::Widget *sp_fill_style_widget_new(void); + +void sp_fill_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop); #endif // SEEN_DIALOGS_SP_FILL_STYLE_H diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index d6a38f978..f020b0c3a 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -56,6 +56,7 @@ #include "xml/repr.h" #include "stroke-style.h" +#include "fill-style.h" // to get sp_fill_style_widget_set_desktop #include "fill-n-stroke-factory.h" /** Marker selection option menus */ @@ -72,11 +73,17 @@ static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const static Inkscape::UI::Cache::SvgPreview svg_preview_cache; -GtkWidget *sp_stroke_style_paint_widget_new(void) +Gtk::Widget *sp_stroke_style_paint_widget_new(void) { return Inkscape::Widgets::createStyleWidget( STROKE ); } +void sp_stroke_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop) +{ + sp_fill_style_widget_set_desktop(widget, desktop); +} + + /* Line */ diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h index 9ed7e2a92..72dc5449a 100644 --- a/src/widgets/stroke-style.h +++ b/src/widgets/stroke-style.h @@ -14,13 +14,16 @@ #ifndef SEEN_DIALOGS_STROKE_STYLE_H #define SEEN_DIALOGS_STROKE_STYLE_H -#include +namespace Gtk { +class Widget; +class Container; +} -typedef struct _GtkWidget GtkWidget; - -GtkWidget *sp_stroke_style_paint_widget_new(void); +Gtk::Widget *sp_stroke_style_paint_widget_new(void); Gtk::Container *sp_stroke_style_line_widget_new(void); +void sp_stroke_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop); + #endif // SEEN_DIALOGS_STROKE_STYLE_H /* -- cgit v1.2.3 From b8859cd12327c84f5ca8d4bf8614f0d0913d3c25 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 29 Mar 2010 22:32:32 +0200 Subject: Add console helper application based on inkscapec.exe from Jos Hirth, which provides Unix-like behavior on Windows. (bzr r9254) --- src/winconsole.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/winconsole.cpp (limited to 'src') diff --git a/src/winconsole.cpp b/src/winconsole.cpp new file mode 100644 index 000000000..f6ee49e13 --- /dev/null +++ b/src/winconsole.cpp @@ -0,0 +1,153 @@ +/** \file + * @brief Command-line wrapper for Windows. + * + * Windows has two types of executables: GUI and console. + * The GUI executables detach immediately when run from the command + * prompt (cmd.exe), and whatever you write to standard output + * disappears into a black hole. Console executables handle + * do display standard output and take standard input from the console, + * but when you run them from the GUI, an extra console window appears. + * It's possible to hide it, but it still flashes from a fraction + * of a second. + * + * To provide an Unix-like experienve, where the application will behave + * correctly in command line mode and at the same time won't create + * the ugly console window when run from the GUI, we have to have two + * executables. The first one, inkscape.exe, is the GUI application. + * Its entry points are in main.cpp and winmain.cpp. The second one, + * called inkscape.com, is a small helper application contained in + * this file. It spawns the GUI application and redirects its output + * to the console. + * + * Note that inkscape.com has nothing to do with "compact executables" + * from DOS. It's a normal PE executable renamed to .com. The trick + * is that cmd.exe picks .com over .exe when both are present in PATH, + * so when you type "inkscape" into the command prompt, inkscape.com + * gets run. The Windows program loader does not inspect the extension, + * just like an Unix program loader; it determines the binary format + * based on the contents of the file. + * + *//* + * Authors: + * Jos Hirth + * Krzysztof Kosiñski + * + * Copyright (C) 2008-2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef WIN32 +#undef DATADIR +#include + +struct echo_thread_info { + HANDLE echo_read; + HANDLE echo_write; + unsigned buffer_size; +}; + +// thread function for echoing from one file handle to another +DWORD WINAPI echo_thread(void *info_void) +{ + echo_thread_info *info = static_cast(info_void); + char *buffer = reinterpret_cast(LocalAlloc(LMEM_FIXED, info->buffer_size)); + DWORD bytes_read, bytes_written; + + while(true){ + if (!ReadFile(info->echo_read, buffer, info->buffer_size, &bytes_read, NULL) || bytes_read == 0) + if (GetLastError() == ERROR_BROKEN_PIPE) + break; + + if (!WriteFile(info->echo_write, buffer, bytes_read, &bytes_written, NULL)) { + if (GetLastError() == ERROR_NO_DATA) + break; + } + } + + LocalFree(reinterpret_cast(buffer)); + CloseHandle(info->echo_read); + CloseHandle(info->echo_write); + + return 1; +} + +int main() +{ + // structs that will store information for our I/O threads + echo_thread_info stdin = {NULL, NULL, 4096}; + echo_thread_info stdout = {NULL, NULL, 4096}; + echo_thread_info stderr = {NULL, NULL, 4096}; + // handles we'll pass to inkscape.exe + HANDLE inkscape_stdin, inkscape_stdout, inkscape_stderr; + HANDLE stdin_thread, stdout_thread, stderr_thread; + + SECURITY_ATTRIBUTES sa; + sa.nLength=sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor=NULL; + sa.bInheritHandle=TRUE; + + // Determine the path to the Inkscape executable. + // Do this by looking up the name of this one and redacting the extension to ".exe" + const int pathbuf = 2048; + WCHAR *inkscape = reinterpret_cast(LocalAlloc(LMEM_FIXED, pathbuf * sizeof(WCHAR))); + GetModuleFileNameW(NULL, inkscape, pathbuf); + WCHAR *dot_index = wcsrchr(inkscape, L'.'); + wcsncpy(dot_index, L".exe", 4); + + // we simply reuse our own command line for inkscape.exe + // it guarantees perfect behavior w.r.t. quoting + WCHAR *cmd = GetCommandLineW(); + + // set up the pipes and handles + stdin.echo_read = GetStdHandle(STD_INPUT_HANDLE); + stdout.echo_write = GetStdHandle(STD_OUTPUT_HANDLE); + stderr.echo_write = GetStdHandle(STD_ERROR_HANDLE); + CreatePipe(&inkscape_stdin, &stdin.echo_write, &sa, 0); + CreatePipe(&stdout.echo_read, &inkscape_stdout, &sa, 0); + CreatePipe(&stderr.echo_read, &inkscape_stderr, &sa, 0); + + // fill in standard IO handles to be used by the process + PROCESS_INFORMATION pi; + STARTUPINFOW si; + + ZeroMemory(&si,sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = inkscape_stdin; + si.hStdOutput = inkscape_stdout; + si.hStdError = inkscape_stderr; + + // spawn inkscape.exe + CreateProcessW(inkscape, // path to inkscape.exe + cmd, // command line as a single string + NULL, // process security attributes - unused + NULL, // thread security attributes - unused + TRUE, // inherit handles + 0, // flags + NULL, // environment - NULL = inherit from us + NULL, // working directory - NULL = inherit ours + &si, // startup info - see above + &pi); // information about the created process - unused + + // clean up a bit + LocalFree(reinterpret_cast(inkscape)); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + CloseHandle(inkscape_stdin); + CloseHandle(inkscape_stdout); + CloseHandle(inkscape_stderr); + + // create IO echo threads + DWORD unused; + stdin_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdin, 0, &unused); + stdout_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdout, 0, &unused); + stderr_thread = CreateThread(NULL, 0, echo_thread, (void*) &stderr, 0, &unused); + + // wait until the standard output thread terminates + WaitForSingleObject(stdout_thread, INFINITE); + + return 0; +} + +#endif -- cgit v1.2.3 From 8a39d60c95dc8367e398eb420c5722b54aa7fb5a Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 29 Mar 2010 23:06:33 +0200 Subject: Remove remnants of rather pointless MMX optimizations, and fix build failure caused by recent extension renames (bzr r9255) --- src/libnr/Makefile_insert | 8 - src/libnr/have_mmx.S | 47 ----- src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S | 125 ------------ src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S | 231 ---------------------- src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S | 227 --------------------- 5 files changed, 638 deletions(-) delete mode 100644 src/libnr/have_mmx.S delete mode 100644 src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S delete mode 100644 src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S delete mode 100644 src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S (limited to 'src') diff --git a/src/libnr/Makefile_insert b/src/libnr/Makefile_insert index 4b19028f9..8dd3c46e3 100644 --- a/src/libnr/Makefile_insert +++ b/src/libnr/Makefile_insert @@ -1,13 +1,5 @@ ## Makefile.am fragment sourced by src/Makefile.am. -if USE_MMX -libnr_mmx_sources = \ - libnr/have_mmx.S \ - libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S \ - libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S \ - libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S -endif - ink_common_sources += \ libnr/in-svg-plane.h \ libnr/nr-blit.cpp \ diff --git a/src/libnr/have_mmx.S b/src/libnr/have_mmx.S deleted file mode 100644 index d6428191e..000000000 --- a/src/libnr/have_mmx.S +++ /dev/null @@ -1,47 +0,0 @@ - .file "have_mmx.S" - -# Ensure Inkscape is execshield protected - .section .note.GNU-stack - .previous - - .version "01.01" -gcc2_compiled.: -.text - .align 16 -.globl nr_have_mmx - .type nr_have_mmx,@function - -nr_have_mmx: - push %ebx - -# Check if bit 21 in flags word is writeable - - pushfl - popl %eax - movl %eax,%ebx - xorl $0x00200000, %eax - pushl %eax - popfl - pushfl - popl %eax - - cmpl %eax, %ebx - - je .notfound - -# OK, we have CPUID - - movl $1, %eax - cpuid - - test $0x00800000, %edx - jz .notfound - - movl $1, %eax - jmp .out - -.notfound: - movl $0, %eax -.out: - popl %ebx - ret diff --git a/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S b/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S deleted file mode 100644 index db2cbec5a..000000000 --- a/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S +++ /dev/null @@ -1,125 +0,0 @@ - .file "nr-compose.c" - -# Ensure Inkscape is execshield protected - .section .note.GNU-stack - .previous - - .text - .align 2 -.globl nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP - .type nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP,@function - -/* - * This code is in public domain - * - * c 32(%ebp) - * srs 28(%ebp) - * spx 24(%ebp) - * rs 20(%ebp) - * h 16(%ebp) - * w 12(%ebp) - * px 8(%ebp) - * r -8(%ebp) - * g -12(%ebp) - * b -16(%ebp) - * a -20(%ebp) - * s -24(%ebp) -> %esi - * d -28(%ebp) -> %edi - * x -32(%ebp) -> %ebx - * y -36(%ebp) - * ca -40(%ebp) - * - * mm0 Fg - * mm1 FgA - * mm2 FgPre - * mm3 - * mm4 - * mm5 - * mm6 128 - * mm7 0 - * -*/ - -nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP: - pushl %ebp - movl %esp, %ebp - pushl %ebx - subl $36, %esp - pushl %edi - pushl %esi - -/* Load %mm7 with [0 0 0 0] */ - movl $0, %eax - movd %eax, %mm7 - -/* Load %mm6 with [128 128 128 128] */ - movl $0x80808080, %eax - movd %eax, %mm6 - punpcklbw %mm7, %mm6 - -/* FgC -> %mm0 */ - movl 32(%ebp), %eax - movd (%eax), %mm0 - punpcklbw %mm7, %mm0 - -/* for (y = ...) */ - movl 16(%ebp), %ecx -.fory: - -/* d = px */ -/* s = spx */ - movl 8(%ebp), %edi - movl 24(%ebp), %esi - -/* for (x = ...) */ - movl 12(%ebp), %ebx -.forx: - -/* [m m m m] -> %mm1 */ - movzbl (%esi), %eax - testb $0xff, %al - jz .clip - movd %eax, %mm1 - punpcklwd %mm1, %mm1 - punpckldq %mm1, %mm1 - -/* Fg -> mm2 */ - movq %mm0, %mm2 - pmullw %mm1, %mm2 - paddw %mm6, %mm2 - movq %mm2, %mm3 - psrlw $8, %mm3 - paddw %mm3, %mm2 - psrlw $8, %mm2 - -/* Store pixel */ - packuswb %mm2, %mm2 - movd %mm2, (%edi) - -.clip: - addl $4, %edi - incl %esi - - decl %ebx - jnz .forx - - movl 20(%ebp), %eax - addl %eax, 8(%ebp) - movl 28(%ebp), %eax - addl %eax, 24(%ebp) - - decl %ecx - jnz .fory - -.exit: - emms - popl %esi - popl %edi - addl $36, %esp - popl %ebx - popl %ebp - ret - -.Lfe1: - .size nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP,.Lfe1-nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP - .ident "GCC: (GNU) 3.2" diff --git a/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S b/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S deleted file mode 100644 index fe1d9be57..000000000 --- a/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S +++ /dev/null @@ -1,231 +0,0 @@ - .file "nr-compose.c" - -# Ensure Inkscape is execshield protected - .section .note.GNU-stack - .previous - - .text - .align 2 -.globl nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP - .type nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP,@function - -/* - * This code is in public domain - * - * c 32(%ebp) - * srs 28(%ebp) - * spx 24(%ebp) - * rs 20(%ebp) - * h 16(%ebp) - * w 12(%ebp) - * px 8(%ebp) - * r -8(%ebp) - * g -12(%ebp) - * b -16(%ebp) - * a -20(%ebp) - * s -24(%ebp) -> %esi - * d -28(%ebp) -> %edi - * x -32(%ebp) -> %ebx - * y -36(%ebp) - * ca -40(%ebp) - * - * mm0 Fg - * mm1 MMMM - * mm2 FgM - * mm3 - * mm4 - * mm5 255 - * mm6 128 - * mm7 0 - * -*/ - -nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP: - pushl %ebp - movl %esp, %ebp - pushl %ebx - subl $36, %esp - pushl %edi - pushl %esi - -/* Load %mm7 with [0 0 0 0] */ - movl $0, %eax - movd %eax, %mm7 - -/* Load %mm6 with [128 128 128 128] */ - movl $0x80808080, %eax - movd %eax, %mm6 - punpcklbw %mm7, %mm6 - -/* Load %mm5 with [255 255 255 255] */ - movl $0xffffffff, %eax - movd %eax, %mm5 - punpcklbw %mm7, %mm5 - -/* FgC -> %mm0 */ - movl 32(%ebp), %eax - movd (%eax), %mm0 - punpcklbw %mm7, %mm0 - -/* Check full opacity */ - cmpb $0xff, %al - jz .opaque - -/* for (y = ...) */ - movl 16(%ebp), %ecx -.fory: - -/* d = px */ -/* s = spx */ - movl 8(%ebp), %edi - movl 24(%ebp), %esi - -/* for (x = ...) */ - movl 12(%ebp), %ebx -.forx: - -/* [m m m m] -> %mm1 */ - movzbl (%esi), %eax - testb $0xff, %al - jz .clip - movd %eax, %mm1 - punpcklwd %mm1, %mm1 - punpckldq %mm1, %mm1 - -/* Fg -> mm2 */ - movq %mm0, %mm2 - pmullw %mm1, %mm2 - paddw %mm6, %mm2 - movq %mm2, %mm3 - psrlw $8, %mm3 - paddw %mm3, %mm2 - psrlw $8, %mm2 - -/* [255 - FgA] -> mm1 */ - movq %mm2, %mm1 - punpckhwd %mm1, %mm1 - punpckhdq %mm1, %mm1 - pxor %mm5, %mm1 - -/* Bg -> mm3 */ - movd (%edi), %mm3 - punpcklbw %mm7, %mm3 - -/* Fg + ((255 - FgA) * Bg) / 255 */ - pmullw %mm1, %mm3 - paddw %mm6, %mm3 - movq %mm3, %mm4 - psrlw $8, %mm4 - paddw %mm4, %mm3 - psrlw $8, %mm3 - paddw %mm2, %mm3 - -/* Store pixel */ - packuswb %mm3, %mm3 - movd %mm3, (%edi) - -.clip: - addl $4, %edi - incl %esi - - decl %ebx - jnz .forx - - movl 20(%ebp), %eax - addl %eax, 8(%ebp) - movl 28(%ebp), %eax - addl %eax, 24(%ebp) - - decl %ecx - jnz .fory - -.exit: - emms - popl %esi - popl %edi - addl $36, %esp - popl %ebx - popl %ebp - ret - -.opaque: -/* for (y = ...) */ - movl 16(%ebp), %ecx -.o_fory: - -/* d = px */ -/* s = spx */ - movl 8(%ebp), %edi - movl 24(%ebp), %esi - -/* for (x = ...) */ - movl 12(%ebp), %ebx -.o_forx: - -/* [m m m m] -> %mm1 */ - movzbl (%esi), %eax - testb $0xff, %al - jz .o_clip - cmpb $0xff, %al - jz .o_full - movd %eax, %mm1 - punpcklwd %mm1, %mm1 - punpckldq %mm1, %mm1 - -/* Fg -> mm2 */ - movq %mm0, %mm2 - pmullw %mm1, %mm2 - paddw %mm6, %mm2 - movq %mm2, %mm3 - psrlw $8, %mm3 - paddw %mm3, %mm2 - psrlw $8, %mm2 - -/* [255 - FgA] -> mm1 */ - movq %mm2, %mm1 - punpckhwd %mm1, %mm1 - punpckhdq %mm1, %mm1 - pxor %mm5, %mm1 - -/* Bg -> mm3 */ - movd (%edi), %mm3 - punpcklbw %mm7, %mm3 - -/* Fg + ((255 - FgA) * Bg) / 255 */ - pmullw %mm1, %mm3 - paddw %mm6, %mm3 - movq %mm3, %mm4 - psrlw $8, %mm4 - paddw %mm4, %mm3 - psrlw $8, %mm3 - paddw %mm2, %mm3 - - jmp .o_store - -.o_full: - movq %mm0, %mm3 - -.o_store: -/* Store pixel */ - packuswb %mm3, %mm3 - movd %mm3, (%edi) - -.o_clip: - addl $4, %edi - incl %esi - - decl %ebx - jnz .o_forx - - movl 20(%ebp), %eax - addl %eax, 8(%ebp) - movl 28(%ebp), %eax - addl %eax, 24(%ebp) - - decl %ecx - jnz .o_fory - jmp .exit - -.Lfe1: - .size nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP,.Lfe1-nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP - .ident "GCC: (GNU) 3.2" diff --git a/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S b/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S deleted file mode 100644 index 37261e572..000000000 --- a/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S +++ /dev/null @@ -1,227 +0,0 @@ - .file "nr-compose.c" - -# Ensure Inkscape is execshield protected - .section .note.GNU-stack - .previous - - .text - .align 2 -.globl nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P - .type nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P,@function - -/* - * This code is in public domain - * - * alpha 32(%ebp) - * srs 28(%ebp) - * spx 24(%ebp) - * rs 20(%ebp) - * h 16(%ebp) - * w 12(%ebp) - * px 8(%ebp) - * r -8(%ebp) - * g -12(%ebp) - * b -16(%ebp) - * a -20(%ebp) - * s -24(%ebp) -> %esi - * d -28(%ebp) -> %edi - * x -32(%ebp) -> %ebx - * y -36(%ebp) - * ca -40(%ebp) - * - * mm0 A - * mm1 FgA - * mm2 FgPre - * mm3 - * mm4 - * mm5 255 - * mm6 128 - * mm7 0 - * -*/ - -nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P: - pushl %ebp - movl %esp, %ebp - pushl %ebx - subl $36, %esp - pushl %edi - pushl %esi - -/* Load %mm7 with [0 0 0 0] */ - movl $0, %eax - movd %eax, %mm7 - -/* Load %mm6 with [128 128 128 128] */ - movl $0x80808080, %eax - movd %eax, %mm6 - punpcklbw %mm7, %mm6 - -/* Load %mm5 with [255 255 255 255] */ - movl $0xffffffff, %eax - movd %eax, %mm5 - punpcklbw %mm7, %mm5 - -/* Load %mm0 with [a a a a] */ -/* Check full opacity */ - movzbl 32(%ebp), %eax - cmpb $0xff, %al - jz .opaque - movd %eax, %mm0 - punpcklwd %mm0, %mm0 - punpckldq %mm0, %mm0 - -/* for (y = ...) */ - movl 16(%ebp), %ecx -.fory: - -/* d = px */ -/* s = spx */ - movl 8(%ebp), %edi - movl 24(%ebp), %esi - -/* for (x = ...) */ - movl 12(%ebp), %ebx -.forx: - -/* Fg -> %mm1 */ -/* fixme: Do we have to bother about alignment here? (Lauris) */ - movl (%esi), %eax - testl $0xff000000, %eax - jz .clip - movd %eax, %mm1 - punpcklbw %mm7, %mm1 - -/* [Fg * a] -> mm1 */ - pmullw %mm0, %mm1 - paddw %mm6, %mm1 - movq %mm1, %mm2 - psrlw $8, %mm2 - paddw %mm2, %mm1 - psrlw $8, %mm1 - -/* [255 - FgA] -> mm2 */ - movq %mm1, %mm2 - punpckhwd %mm2, %mm2 - punpckhdq %mm2, %mm2 - pxor %mm5, %mm2 - -/* Bg -> mm3 */ - movd (%edi), %mm3 - punpcklbw %mm7, %mm3 - -/* Fg + ((255 - FgA) * Bg) / 255 */ - pmullw %mm2, %mm3 - paddw %mm6, %mm3 - movq %mm3, %mm4 - psrlw $8, %mm4 - paddw %mm4, %mm3 - psrlw $8, %mm3 - paddw %mm1, %mm3 - -/* Store pixel */ - packuswb %mm3, %mm3 - movd %mm3, %eax - movb %al, 0(%edi) - shrl $8, %eax - movb %al, 1(%edi) - shrl $8, %eax - movb %al, 2(%edi) - -.clip: - addl $3, %edi - addl $4, %esi - - decl %ebx - jnz .forx - - movl 20(%ebp), %eax - addl %eax, 8(%ebp) - movl 28(%ebp), %eax - addl %eax, 24(%ebp) - - decl %ecx - jnz .fory - -.exit: - emms - popl %esi - popl %edi - addl $36, %esp - popl %ebx - popl %ebp - ret - -.opaque: -/* for (y = ...) */ - movl 16(%ebp), %ecx -.o_fory: - -/* d = px */ -/* s = spx */ - movl 8(%ebp), %edi - movl 24(%ebp), %esi - -/* for (x = ...) */ - movl 12(%ebp), %ebx -.o_forx: - -/* Fg -> %mm1 */ -/* fixme: Do we have to bother about alignment here? (Lauris) */ - movl (%esi), %eax - testl $0xff000000, %eax - jz .o_clip - cmpl $0xff000000, %eax - jnb .o_store - movd %eax, %mm1 - punpcklbw %mm7, %mm1 - -/* [255 - FgA] -> mm2 */ - movq %mm1, %mm2 - punpckhwd %mm2, %mm2 - punpckhdq %mm2, %mm2 - pxor %mm5, %mm2 - -/* Bg -> mm3 */ - movd (%edi), %mm3 - punpcklbw %mm7, %mm3 - -/* Fg + ((255 - FgA) * Bg) / 255 */ - pmullw %mm2, %mm3 - paddw %mm6, %mm3 - movq %mm3, %mm4 - psrlw $8, %mm4 - paddw %mm4, %mm3 - psrlw $8, %mm3 - paddw %mm1, %mm3 - -/* Store pixel */ - packuswb %mm3, %mm3 - movd %mm3, %eax -.o_store: - movb %al, 0(%edi) - shrl $8, %eax - movb %al, 1(%edi) - shrl $8, %eax - movb %al, 2(%edi) - -.o_clip: - addl $3, %edi - addl $4, %esi - - decl %ebx - jnz .o_forx - - movl 20(%ebp), %eax - addl %eax, 8(%ebp) - movl 28(%ebp), %eax - addl %eax, 24(%ebp) - - decl %ecx - jnz .o_fory - - jmp .exit - -.Lfe1: - .size nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P,.Lfe1-nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P - .ident "GCC: (GNU) 3.2" -- cgit v1.2.3 From 58a6b2ed5541bad9c7369aa357d7fbe43d1e5c66 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 30 Mar 2010 00:22:39 +0200 Subject: More correct setting of PYTHONPATH at startup (bzr r9257) --- src/Makefile.am | 1 + src/main.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 74bfa01d6..03b58c610 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -186,6 +186,7 @@ EXTRA_DIST = \ extension/internal/emf-win32-print.h \ helper/sp-marshal.list \ show-preview.bmp \ + winconsole.cpp \ $(jabber_whiteboard_SOURCES) \ $(CXXTEST_TEMPLATE) diff --git a/src/main.cpp b/src/main.cpp index a6dfb37f0..cd60d9fa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -545,18 +545,24 @@ static void set_extensions_env() { gchar const *pythonpath = g_getenv("PYTHONPATH"); gchar *extdir; + gchar *new_pythonpath; #ifdef WIN32 extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR); #else extdir = g_strdup(INKSCAPE_EXTENSIONDIR); #endif + if (pythonpath) { + new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", + extdir, pythonpath); + g_free(extdir); + } else { + new_pythonpath = extdir; + } - gchar *new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", - extdir, pythonpath); g_setenv("PYTHONPATH", new_pythonpath, TRUE); - g_free(extdir); g_free(new_pythonpath); + printf("PYTHONPATH = %s", g_getenv("PYTHONPATH")); } /** -- cgit v1.2.3 From 1a93dffd72bbaa37a4e5fa25e6b6292906ce2f5f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 29 Mar 2010 21:41:28 -0700 Subject: Fix logic to avoid too many updates while dragging color sliders. Fixes bug# 168557. Fixed bugs: - https://launchpad.net/bugs/168557 (bzr r9258) --- src/widgets/fill-style.cpp | 76 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 63def4c87..15d8b6cc2 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -73,6 +73,7 @@ private: static void paintModeChangeCB(SPPaintSelector *psel, SPPaintSelector::Mode mode, FillNStroke *self); static void paintChangedCB(SPPaintSelector *psel, FillNStroke *self); static void paintDraggedCB(SPPaintSelector *psel, FillNStroke *self); + static gboolean dragDelayCB(gpointer data); static void fillruleChangedCB( SPPaintSelector *psel, SPPaintSelector::FillRule mode, FillNStroke *self ); @@ -86,8 +87,9 @@ private: FillOrStroke kind; SPDesktop *desktop; SPPaintSelector *psel; + guint32 lastDrag; + guint dragId; bool update; - bool local; sigc::connection selectChangedConn; sigc::connection subselChangedConn; sigc::connection selectModifiedConn; @@ -120,8 +122,9 @@ FillNStroke::FillNStroke( FillOrStroke kind ) : kind(kind), desktop(0), psel(0), + lastDrag(0), + dragId(0), update(false), - local(false), selectChangedConn(), subselChangedConn(), selectModifiedConn() @@ -152,6 +155,10 @@ FillNStroke::FillNStroke( FillOrStroke kind ) : FillNStroke::~FillNStroke() { + if (dragId) { + g_source_remove(dragId); + dragId = 0; + } psel = 0; selectModifiedConn.disconnect(); subselChangedConn.disconnect(); @@ -176,6 +183,10 @@ void FillNStroke::selectionModifiedCB( guint flags ) void FillNStroke::setDesktop(SPDesktop *desktop) { if (this->desktop != desktop) { + if (dragId) { + g_source_remove(dragId); + dragId = 0; + } if (this->desktop) { selectModifiedConn.disconnect(); subselChangedConn.disconnect(); @@ -188,7 +199,6 @@ void FillNStroke::setDesktop(SPDesktop *desktop) // Must check flags, so can't call performUpdate() directly. selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &FillNStroke::selectionModifiedCB))); - } performUpdate(); } @@ -206,12 +216,11 @@ void FillNStroke::performUpdate() return; } - if (kind == FILL) { - // TODO check. This probably should happen for stroke as well as fill. - if ( local ) { - local = false; // local change; do nothing, but reset the flag - return; - } + if ( dragId ) { + // local change; do nothing, but reset the flag + g_source_remove(dragId); + dragId = 0; + return; } update = true; @@ -348,6 +357,28 @@ void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self) } } + +gboolean FillNStroke::dragDelayCB(gpointer data) +{ + gboolean keepGoing = TRUE; + if (data) { + FillNStroke *self = reinterpret_cast(data); + if (!self->update) { + if (self->dragId) { + g_source_remove(self->dragId); + self->dragId = 0; + + self->dragFromPaint(); + self->performUpdate(); + } + keepGoing = FALSE; + } + } else { + keepGoing = FALSE; + } + return keepGoing; +} + /** * This is called repeatedly while you are dragging a color slider, only for flat color * modes. Previously it set the color in style but did not update the repr for efficiency, however @@ -360,27 +391,34 @@ void FillNStroke::dragFromPaint() return; } - if (kind == FILL) { - if (local) { - // previous local flag not cleared yet; - // this means dragged events come too fast, so we better skip this one to speed up display - // (it's safe to do this in any case) - return; - } + guint32 when = gtk_get_current_event_time(); + + // Don't attempt too many updates per second. + // Assume a base 15.625ms resolution on the timer. + if (!dragId && lastDrag && when && ((when - lastDrag) < 32)) { + // local change, do not update from selection + dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 33, dragDelayCB, this, 0); } + if (dragId) { + // previous local flag not cleared yet; + // this means dragged events come too fast, so we better skip this one to speed up display + // (it's safe to do this in any case) + return; + } + lastDrag = when; + update = true; switch (psel->mode) { case SPPaintSelector::MODE_COLOR_RGB: case SPPaintSelector::MODE_COLOR_CMYK: { + // local change, do not update from selection + dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 100, dragDelayCB, this, 0); psel->setFlatColor( desktop, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" ); sp_document_maybe_done(desktop->doc(), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE, (kind == FILL) ? _("Set fill color") : _("Set stroke color")); - if (kind == FILL) { - local = true; // local change, do not update from selection - } break; } -- cgit v1.2.3 From d7d33e03d7daac4be14018d31cd6f534fcb7f7a4 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 30 Mar 2010 01:07:19 -0700 Subject: Corrected string-to-number conversion to use locale-independent conversion and to handle missing/null values. Fixes bug #544833. Fixed bugs: - https://launchpad.net/bugs/544833 (bzr r9259) --- src/sp-font-face.cpp | 106 +++++++++++++++++++++++++++++++++-------------- src/sp-font.cpp | 43 +++++++++++++------ src/sp-glyph-kerning.cpp | 36 ++++++++++++---- src/sp-glyph.cpp | 48 ++++++++++++++------- src/sp-missing-glyph.cpp | 36 ++++++++++------ 5 files changed, 190 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/sp-font-face.cpp b/src/sp-font-face.cpp index 704985b8c..1912676d4 100644 --- a/src/sp-font-face.cpp +++ b/src/sp-font-face.cpp @@ -24,7 +24,6 @@ #include "attributes.h" #include "sp-font-face.h" #include "document.h" -#include "helper-fns.h" //TODO: apparently unused. Maybe should be removed. class ObjectContainer @@ -486,7 +485,6 @@ static void sp_fontface_release(SPObject *object) static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *value) { SPFontFace *face = SP_FONTFACE(object); - double number; std::vector style; std::vector variant; std::vector weight; @@ -494,7 +492,9 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val switch (key) { case SP_PROP_FONT_FAMILY: - if (face->font_family) g_free(face->font_family); + if (face->font_family) { + g_free(face->font_family); + } face->font_family = g_strdup(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; @@ -505,7 +505,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val object->requestModified(SP_OBJECT_MODIFIED_FLAG); } else { for (unsigned int i=0;ifont_style[i]){ + if (style[i] != face->font_style[i]){ face->font_style = style; object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; @@ -520,7 +520,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val object->requestModified(SP_OBJECT_MODIFIED_FLAG); } else { for (unsigned int i=0;ifont_variant[i]){ + if (variant[i] != face->font_variant[i]){ face->font_variant = variant; object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; @@ -535,7 +535,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val object->requestModified(SP_OBJECT_MODIFIED_FLAG); } else { for (unsigned int i=0;ifont_weight[i]){ + if (weight[i] != face->font_weight[i]){ face->font_weight = weight; object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; @@ -550,7 +550,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val object->requestModified(SP_OBJECT_MODIFIED_FLAG); } else { for (unsigned int i=0;ifont_stretch[i]){ + if (stretch[i] != face->font_stretch[i]){ face->font_stretch = stretch; object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; @@ -559,166 +559,212 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val } break; case SP_ATTR_UNITS_PER_EM: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->units_per_em){ face->units_per_em = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_STEMV: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->stemv){ face->stemv = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_STEMH: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->stemh){ face->stemh = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_SLOPE: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->slope){ face->slope = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_CAP_HEIGHT: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->cap_height){ face->cap_height = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_X_HEIGHT: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->x_height){ face->x_height = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_ACCENT_HEIGHT: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->accent_height){ face->accent_height = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_ASCENT: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->ascent){ face->ascent = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_DESCENT: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->descent){ face->descent = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_IDEOGRAPHIC: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->ideographic){ face->ideographic = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_ALPHABETIC: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->alphabetic){ face->alphabetic = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_MATHEMATICAL: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->mathematical){ face->mathematical = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_HANGING: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->hanging){ face->hanging = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_V_IDEOGRAPHIC: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->v_ideographic){ face->v_ideographic = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_V_ALPHABETIC: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->v_alphabetic){ face->v_alphabetic = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_V_MATHEMATICAL: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->v_mathematical){ face->v_mathematical = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_V_HANGING: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->v_hanging){ face->v_hanging = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_UNDERLINE_POSITION: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->underline_position){ face->underline_position = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_UNDERLINE_THICKNESS: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->underline_thickness){ face->underline_thickness = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_STRIKETHROUGH_POSITION: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->strikethrough_position){ face->strikethrough_position = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_STRIKETHROUGH_THICKNESS: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->strikethrough_thickness){ face->strikethrough_thickness = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_OVERLINE_POSITION: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->overline_position){ face->overline_position = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_OVERLINE_THICKNESS: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != face->overline_thickness){ face->overline_thickness = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } default: if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); diff --git a/src/sp-font.cpp b/src/sp-font.cpp index de272c72f..b2003cf08 100644 --- a/src/sp-font.cpp +++ b/src/sp-font.cpp @@ -21,7 +21,6 @@ #include "sp-glyph.h" #include "sp-missing-glyph.h" #include "document.h" -#include "helper-fns.h" #include "display/nr-svgfonts.h" @@ -79,15 +78,21 @@ static void sp_font_class_init(SPFontClass *fc) sp_object_class->update = sp_font_update; } +//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html + +// TODO determine better values and/or make these dynamic: +double FNT_DEFAULT_ADV = 90; // TODO determine proper default +double FNT_DEFAULT_ASCENT = 90; // TODO determine proper default +double FNT_UNITS_PER_EM = 90; // TODO determine proper default + static void sp_font_init(SPFont *font) { font->horiz_origin_x = 0; font->horiz_origin_y = 0; - font->horiz_adv_x = 0; -//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html - font->vert_origin_x = 0; - font->vert_origin_y = 0; - font->vert_adv_y = 0; + font->horiz_adv_x = FNT_DEFAULT_ADV; + font->vert_origin_x = FNT_DEFAULT_ADV / 2.0; + font->vert_origin_y = FNT_DEFAULT_ASCENT; + font->vert_adv_y = FNT_UNITS_PER_EM; } static void sp_font_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) @@ -155,51 +160,63 @@ static void sp_font_release(SPObject *object) static void sp_font_set(SPObject *object, unsigned int key, const gchar *value) { SPFont *font = SP_FONT(object); - double number; + // TODO these are floating point, so some epsilon comparison would be good switch (key) { case SP_ATTR_HORIZ_ORIGIN_X: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != font->horiz_origin_x){ font->horiz_origin_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_HORIZ_ORIGIN_Y: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != font->horiz_origin_y){ font->horiz_origin_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_HORIZ_ADV_X: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ADV; if (number != font->horiz_adv_x){ font->horiz_adv_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_VERT_ORIGIN_X: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ADV / 2.0; if (number != font->vert_origin_x){ font->vert_origin_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_VERT_ORIGIN_Y: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ASCENT; if (number != font->vert_origin_y){ font->vert_origin_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_VERT_ADV_Y: - number = helperfns_read_number(value); + { + double number = value ? g_ascii_strtod(value, 0) : FNT_UNITS_PER_EM; if (number != font->vert_adv_y){ font->vert_adv_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } default: if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); diff --git a/src/sp-glyph-kerning.cpp b/src/sp-glyph-kerning.cpp index 872efc853..d62fbb2c2 100644 --- a/src/sp-glyph-kerning.cpp +++ b/src/sp-glyph-kerning.cpp @@ -22,7 +22,6 @@ #include "sp-glyph-kerning.h" #include "document.h" -#include "helper-fns.h" #include static void sp_glyph_kerning_class_init(SPGlyphKerningClass *gc); @@ -149,41 +148,60 @@ bool GlyphNames::contains(const char* name){ static void sp_glyph_kerning_set(SPObject *object, unsigned int key, const gchar *value) { SPGlyphKerning * glyphkern = (SPGlyphKerning*) object; //even if it is a VKern this will work. I did it this way just to avoind warnings. - double number; switch (key) { case SP_ATTR_U1: - if (glyphkern->u1) delete glyphkern->u1; + { + if (glyphkern->u1) { + delete glyphkern->u1; + } glyphkern->u1 = new UnicodeRange(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_U2: - if (glyphkern->u2) delete glyphkern->u2; + { + if (glyphkern->u2) { + delete glyphkern->u2; + } glyphkern->u2 = new UnicodeRange(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_G1: - if (glyphkern->g1) delete glyphkern->g1; + { + if (glyphkern->g1) { + delete glyphkern->g1; + } glyphkern->g1 = new GlyphNames(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_G2: - if (glyphkern->g2) delete glyphkern->g2; + { + if (glyphkern->g2) { + delete glyphkern->g2; + } glyphkern->g2 = new GlyphNames(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_K: - number = helperfns_read_number(value); + } + case SP_ATTR_K: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyphkern->k){ glyphkern->k = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - default: + } + default: + { if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); } break; + } } } diff --git a/src/sp-glyph.cpp b/src/sp-glyph.cpp index 37e266da0..0b3b85d3f 100644 --- a/src/sp-glyph.cpp +++ b/src/sp-glyph.cpp @@ -20,7 +20,6 @@ #include "attributes.h" #include "sp-glyph.h" #include "document.h" -#include "helper-fns.h" static void sp_glyph_class_init(SPGlyphClass *gc); static void sp_glyph_init(SPGlyph *glyph); @@ -146,78 +145,97 @@ static glyphOrientation sp_glyph_read_orientation(gchar const *value){ static void sp_glyph_set(SPObject *object, unsigned int key, const gchar *value) { SPGlyph *glyph = SP_GLYPH(object); - double number; - glyphOrientation orient; - glyphArabicForm form; switch (key) { case SP_ATTR_UNICODE: + { glyph->unicode.clear(); if (value) glyph->unicode.append(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_GLYPH_NAME: + { glyph->glyph_name.clear(); if (value) glyph->glyph_name.append(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_D: + { if (glyph->d) g_free(glyph->d); glyph->d = g_strdup(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + } case SP_ATTR_ORIENTATION: - orient = sp_glyph_read_orientation(value); + { + glyphOrientation orient = sp_glyph_read_orientation(value); if (glyph->orientation != orient){ glyph->orientation = orient; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_ARABIC_FORM: - form = sp_glyph_read_arabic_form(value); + { + glyphArabicForm form = sp_glyph_read_arabic_form(value); if (glyph->arabic_form != form){ glyph->arabic_form = form; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; + } case SP_ATTR_LANG: + { if (glyph->lang) g_free(glyph->lang); glyph->lang = g_strdup(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_HORIZ_ADV_X: - number = helperfns_read_number(value); + } + case SP_ATTR_HORIZ_ADV_X: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->horiz_adv_x){ glyph->horiz_adv_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ORIGIN_X: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ORIGIN_X: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_origin_x){ glyph->vert_origin_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ORIGIN_Y: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ORIGIN_Y: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_origin_y){ glyph->vert_origin_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ADV_Y: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ADV_Y: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_adv_y){ glyph->vert_adv_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - default: + } + default: + { if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); } break; + } } } diff --git a/src/sp-missing-glyph.cpp b/src/sp-missing-glyph.cpp index d25a5f812..7d5c42763 100644 --- a/src/sp-missing-glyph.cpp +++ b/src/sp-missing-glyph.cpp @@ -20,7 +20,6 @@ #include "attributes.h" #include "sp-missing-glyph.h" #include "document.h" -#include "helper-fns.h" static void sp_missing_glyph_class_init(SPMissingGlyphClass *gc); static void sp_missing_glyph_init(SPMissingGlyph *glyph); @@ -102,47 +101,60 @@ static void sp_missing_glyph_release(SPObject *object) static void sp_missing_glyph_set(SPObject *object, unsigned int key, const gchar *value) { SPMissingGlyph *glyph = SP_MISSING_GLYPH(object); - double number; switch (key) { case SP_ATTR_D: - if (glyph->d) g_free(glyph->d); + { + if (glyph->d) { + g_free(glyph->d); + } glyph->d = g_strdup(value); object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; - case SP_ATTR_HORIZ_ADV_X: - number = helperfns_read_number(value); + } + case SP_ATTR_HORIZ_ADV_X: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->horiz_adv_x){ glyph->horiz_adv_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ORIGIN_X: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ORIGIN_X: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_origin_x){ glyph->vert_origin_x = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ORIGIN_Y: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ORIGIN_Y: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_origin_y){ glyph->vert_origin_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - case SP_ATTR_VERT_ADV_Y: - number = helperfns_read_number(value); + } + case SP_ATTR_VERT_ADV_Y: + { + double number = value ? g_ascii_strtod(value, 0) : 0; if (number != glyph->vert_adv_y){ glyph->vert_adv_y = number; object->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; - default: + } + default: + { if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); } break; + } } } -- cgit v1.2.3 From 7dd671c8bf7f9aa02afb4128f75fcd3684e9641d Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 30 Mar 2010 18:05:21 +0200 Subject: Make all paths in PYTHONPATH absolute. Fixed bugs: - https://launchpad.net/bugs/551433 (bzr r9261) --- src/main.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index cd60d9fa1..32102f3b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -552,6 +552,19 @@ static void set_extensions_env() #else extdir = g_strdup(INKSCAPE_EXTENSIONDIR); #endif + + // On some platforms, INKSCAPE_EXTENSIONDIR is not absolute, + // but relative to the directory that contains the Inkscape executable. + // Since we spawn Python chdir'ed into the script's directory, + // we need to obtain the absolute path here. + if (!g_path_is_absolute(extdir)) { + gchar *curdir = g_get_current_dir(); + gchar *extdir_new = g_build_filename(curdir, extdir, NULL); + g_free(extdir); + g_free(curdir); + extdir = extdir_new; + } + if (pythonpath) { new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", extdir, pythonpath); @@ -562,7 +575,7 @@ static void set_extensions_env() g_setenv("PYTHONPATH", new_pythonpath, TRUE); g_free(new_pythonpath); - printf("PYTHONPATH = %s", g_getenv("PYTHONPATH")); + printf("PYTHONPATH = %s\n", g_getenv("PYTHONPATH")); } /** @@ -588,7 +601,6 @@ main(int argc, char **argv) HKCR\svgfile\shell\open\command is a good example TODO: this breaks the CLI on Windows, see LP #167455 - However, the CLI is broken anyway, because we are a GUI app */ const int pathbuf = 2048; gunichar2 *path = g_new(gunichar2, pathbuf); -- cgit v1.2.3 From dbac090dfa98747f78504a20113df43fa9a78fc2 Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Thu, 1 Apr 2010 01:14:55 -0700 Subject: Patch by Daniel_J for 522327 (bzr r9267) --- src/eraser-context.cpp | 2 +- src/extension/internal/filter/filter-file.cpp | 2 +- src/extension/internal/filter/filter.cpp | 2 +- src/flood-context.cpp | 4 ++-- src/gradient-context.cpp | 2 +- src/select-context.cpp | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp index 022de4090..6afa07d77 100644 --- a/src/eraser-context.cpp +++ b/src/eraser-context.cpp @@ -749,7 +749,7 @@ set_to_accumulated(SPEraserContext *dc) if ( eraserMode ) { toWorkOn = sp_document_partial_items_in_box(sp_desktop_document(desktop), desktop->dkey, bounds); } else { - Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop); + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); toWorkOn = sp_document_items_at_points(sp_desktop_document(desktop), desktop->dkey, r->getPoints()); } toWorkOn = g_slist_remove( toWorkOn, acid ); diff --git a/src/extension/internal/filter/filter-file.cpp b/src/extension/internal/filter/filter-file.cpp index 7cb671f51..89afca133 100644 --- a/src/extension/internal/filter/filter-file.cpp +++ b/src/extension/internal/filter/filter-file.cpp @@ -161,7 +161,7 @@ Filter::filters_load_node (Inkscape::XML::Node * node, gchar * menuname) mywriter writer; sp_repr_write_stream(node, writer, 0, FALSE, g_quark_from_static_string("svg"), 0, 0); - Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(g_strdup(writer.c_str()))); + Inkscape::Extension::build_from_mem(xml_str, new Filter(g_strdup(writer.c_str()))); g_free(xml_str); return; } diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp index 30e622507..c2d80b28b 100644 --- a/src/extension/internal/filter/filter.cpp +++ b/src/extension/internal/filter/filter.cpp @@ -219,7 +219,7 @@ Filter::filter_init (gchar const * id, gchar const * name, gchar const * submenu "%s\n" "\n" "\n", name, id, submenu, tip); - Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(filter)); + Inkscape::Extension::build_from_mem(xml_str, new Filter(filter)); g_free(xml_str); return; } diff --git a/src/flood-context.cpp b/src/flood-context.cpp index 7b6223384..612ae1cfc 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -900,7 +900,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even if (is_point_fill) { fill_points.push_back(Geom::Point(event->button.x, event->button.y)); } else { - Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop); + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); fill_points = r->getPoints(); } @@ -1206,7 +1206,7 @@ static gint sp_flood_context_root_handler(SPEventContext *event_context, GdkEven case GDK_BUTTON_RELEASE: if (event->button.button == 1 && !event_context->space_panning) { - Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop); + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); if (r->is_started()) { // set "busy" cursor desktop->setWaitingCursor(); diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index ed20f9b61..ddb153ffd 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -650,7 +650,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event) if (!event_context->within_tolerance) { // we've been dragging, either do nothing (grdrag handles that), // or rubberband-select if we have rubberband - Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop); + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); if (r->is_started() && !event_context->within_tolerance) { // this was a rubberband drag if (r->getMode() == RUBBERBAND_MODE_RECT) { diff --git a/src/select-context.cpp b/src/select-context.cpp index a9e1ff623..028c8634b 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -608,7 +608,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) } sc->item = NULL; } else { - Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop); + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); if (r->is_started() && !within_tolerance) { // this was a rubberband drag GSList *items = NULL; -- cgit v1.2.3 From ca353feacd19d98d8fee95bcd1bd018431034a1e Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 1 Apr 2010 02:36:46 -0700 Subject: Initial cut of glyph selector dialog is in. Fixes bug #343186. Fixed bugs: - https://launchpad.net/bugs/343186 (bzr r9268) --- src/menus-skeleton.h | 1 + src/ui/dialog/Makefile_insert | 2 ++ src/ui/dialog/dialog-manager.cpp | 7 +++++-- src/ui/widget/panel.cpp | 12 ++++++------ src/verbs.cpp | 6 ++++++ src/verbs.h | 1 + 6 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 581b8b39c..978b555b0 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -228,6 +228,7 @@ static char const menus_skeleton[] = #ifdef ENABLE_SVG_FONTS " \n" #endif // ENABLE_SVG_FONTS +" \n" " \n" " \n" " \n" diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 033bec875..7546bc195 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -50,6 +50,8 @@ ink_common_sources += \ ui/dialog/find.h \ ui/dialog/floating-behavior.cpp \ ui/dialog/floating-behavior.h \ + ui/dialog/glyphs.cpp \ + ui/dialog/glyphs.h \ ui/dialog/guides.cpp \ ui/dialog/guides.h \ ui/dialog/icon-preview.cpp \ diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 30cbed649..6d3bc817e 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -25,6 +25,7 @@ #include "ui/dialog/fill-and-stroke.h" #include "ui/dialog/filter-effects-dialog.h" #include "ui/dialog/find.h" +#include "ui/dialog/glyphs.h" #include "ui/dialog/inkscape-preferences.h" #include "ui/dialog/input.h" #include "ui/dialog/livepatheffect-editor.h" @@ -96,6 +97,7 @@ DialogManager::DialogManager() { registerFactory("FillAndStroke", &create); registerFactory("FilterEffectsDialog", &create); registerFactory("Find", &create); + registerFactory("Glyphs", &create); registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); @@ -123,6 +125,7 @@ DialogManager::DialogManager() { registerFactory("FillAndStroke", &create); registerFactory("FilterEffectsDialog", &create); registerFactory("Find", &create); + registerFactory("Glyphs", &create); registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); @@ -159,11 +162,11 @@ DialogManager &DialogManager::getInstance() /* Use singleton behavior for floating dialogs */ if (dialogs_type == FLOATING) { static DialogManager *instance = 0; - + if (!instance) instance = new DialogManager(); return *instance; - } + } return *new DialogManager(); } diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp index 93a950d1a..4b806afb5 100644 --- a/src/ui/widget/panel.cpp +++ b/src/ui/widget/panel.cpp @@ -133,9 +133,9 @@ void Panel::_init() { //TRANSLATORS: only translate "string" in "context|string". // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS - Glib::ustring heightItemLabel(Q_("swatches|Size")); + Glib::ustring heightItemLabel(Q_("swatches|Size")); - //TRANSLATORS: Indicates size of colour swatches + //TRANSLATORS: Indicates size of colour swatches const gchar *heightLabels[] = { N_("tiny"), N_("small"), @@ -157,7 +157,7 @@ void Panel::_init() Gtk::RadioMenuItem* _item = manage(new Gtk::RadioMenuItem(heightGroup, _label)); sizeMenu->append(*_item); if (i == panel_size) { - _item->set_active(true); + _item->set_active(true); } _item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i)); } @@ -198,11 +198,11 @@ void Panel::_init() } } for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) { - Glib::ustring _label(Q_(widthLabels[i])); + Glib::ustring _label(Q_(widthLabels[i])); Gtk::RadioMenuItem *_item = manage(new Gtk::RadioMenuItem(widthGroup, _label)); type_menu->append(*_item); if ( i <= hot_index ) { - _item->set_active(true); + _item->set_active(true); } _item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SHAPE, values[i])); } @@ -212,7 +212,7 @@ void Panel::_init() //TRANSLATORS: only translate "string" in "context|string". // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS // "Wrap" indicates how colour swatches are displayed - Glib::ustring wrap_label(Q_("swatches|Wrap")); + Glib::ustring wrap_label(Q_("swatches|Wrap")); Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label)); check->set_active(panel_wrap); _menu->append(*check); diff --git a/src/verbs.cpp b/src/verbs.cpp index dc1116953..66b6140b4 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -73,6 +73,7 @@ #include "ui/dialog/dialog-manager.h" #include "ui/dialog/document-properties.h" #include "ui/dialog/extensions.h" +#include "ui/dialog/glyphs.h" #include "ui/dialog/icon-preview.h" #include "ui/dialog/inkscape-preferences.h" #include "ui/dialog/layer-properties.h" @@ -1731,6 +1732,9 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/) case SP_VERB_DIALOG_FILL_STROKE: dt->_dlg_mgr->showDialog("FillAndStroke"); break; + case SP_VERB_DIALOG_GLYPHS: + dt->_dlg_mgr->showDialog("Glyphs"); + break; case SP_VERB_DIALOG_SWATCHES: dt->_dlg_mgr->showDialog("Swatches"); break; @@ -2597,6 +2601,8 @@ Verb *Verb::_base_verbs[] = { N_("Edit document metadata (to be saved with the document)"), INKSCAPE_ICON_DOCUMENT_METADATA ), new DialogVerb(SP_VERB_DIALOG_FILL_STROKE, "DialogFillStroke", N_("_Fill and Stroke..."), N_("Edit objects' colors, gradients, stroke width, arrowheads, dash patterns..."), INKSCAPE_ICON_DIALOG_FILL_AND_STROKE), + new DialogVerb(SP_VERB_DIALOG_GLYPHS, "DialogGlyphs", N_("Glyphs..."), + N_("Select characters from a glyphs palette"), GTK_STOCK_SELECT_FONT), // TRANSLATORS: "Swatches" means: color samples new DialogVerb(SP_VERB_DIALOG_SWATCHES, "DialogSwatches", N_("S_watches..."), N_("Select colors from a swatches palette"), GTK_STOCK_SELECT_COLOR), diff --git a/src/verbs.h b/src/verbs.h index 7cc580f26..eea6042c0 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -227,6 +227,7 @@ enum { SP_VERB_DIALOG_NAMEDVIEW, SP_VERB_DIALOG_METADATA, SP_VERB_DIALOG_FILL_STROKE, + SP_VERB_DIALOG_GLYPHS, SP_VERB_DIALOG_SWATCHES, SP_VERB_DIALOG_TRANSFORM, SP_VERB_DIALOG_ALIGN_DISTRIBUTE, -- cgit v1.2.3 From 983c299b39427d90feed545fa912de5add44193d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 1 Apr 2010 18:02:40 -0700 Subject: Adding missing files for bug #343186. Fixed bugs: - https://launchpad.net/bugs/343186 (bzr r9269) --- src/ui/dialog/glyphs.cpp | 223 +++++++++++++++++++++++++++++++++++++++++++++++ src/ui/dialog/glyphs.h | 86 ++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100644 src/ui/dialog/glyphs.cpp create mode 100644 src/ui/dialog/glyphs.h (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp new file mode 100644 index 000000000..7a4731124 --- /dev/null +++ b/src/ui/dialog/glyphs.cpp @@ -0,0 +1,223 @@ +/** + * Glyph selector dialog. + */ + +/* Authors: + * Jon A. Cruz + * + * Copyright (C) 2010 Jon A. Cruz + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "glyphs.h" + +#include "verbs.h" +#include "widgets/font-selector.h" +#include "libnrtype/font-instance.h" + +namespace Inkscape { +namespace UI { +namespace Dialogs { + + +GlyphsPanel &GlyphsPanel::getInstance() +{ + return *new GlyphsPanel(); +} + + +class GlyphColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + Gtk::TreeModelColumn code; + Gtk::TreeModelColumn name; + + GlyphColumns() + { + add(code); + add(name); + } +}; + +GlyphColumns *GlyphsPanel::getColumns() +{ + static GlyphColumns *columns = new GlyphColumns(); + + return columns; +} + +/** + * Constructor + */ +GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_GLYPHS, "", false), + store(Gtk::ListStore::create(*getColumns())), + iconView(0), + entry(0), + label(0) +{ + Gtk::Table *table = new Gtk::Table(3, 1, false); + _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); + guint row = 0; + +// ------------------------------- + + GtkWidget *fontsel = sp_font_selector_new(); + g_signal_connect( G_OBJECT(fontsel), "font_set", G_CALLBACK(fontChangeCB), this ); + + table->attach(*Gtk::manage(Glib::wrap(fontsel)), + 0, 1, row, row + 1, + Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL); + row++; + + +// ------------------------------- + + GlyphColumns *columns = getColumns(); + + iconView = new Gtk::IconView(store); + iconView->set_text_column(columns->name); + //iconView->set_columns(16); + + iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated)); + iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged)); + + + Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow(); + scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + scroller->add(*Gtk::manage(iconView)); + table->attach(*Gtk::manage(scroller), + 0, 1, row, row + 1, + Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL); + row++; + +// ------------------------------- + + Gtk::HBox *box = new Gtk::HBox(); + + entry = new Gtk::Entry(); + box->pack_start(*Gtk::manage(entry)); + + label = new Gtk::Label(" "); + box->pack_start(*Gtk::manage(label), Gtk::PACK_EXPAND_PADDING); + + GtkWidget *applyBtn = gtk_button_new_from_stock(GTK_STOCK_APPLY); + GTK_WIDGET_SET_FLAGS(applyBtn, GTK_CAN_DEFAULT | GTK_HAS_DEFAULT); + gtk_widget_set_sensitive(applyBtn, FALSE); + + box->pack_end(*Gtk::manage(Glib::wrap(applyBtn)), Gtk::PACK_SHRINK); + + table->attach( *Gtk::manage(box), + 0, 1, row, row + 1, + Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); + row++; + +// ------------------------------- + + + show_all_children(); + + restorePanelPrefs(); +} + +GlyphsPanel::~GlyphsPanel() +{ +} + + +void GlyphsPanel::glyphActivated(Gtk::TreeModel::Path const & path) +{ + Gtk::ListStore::iterator row = store->get_iter(path); + gunichar ch = (*row)[getColumns()->code]; + Glib::ustring tmp; + tmp += ch; + + int startPos = 0; + int endPos = 0; + if (entry->get_selection_bounds(startPos, endPos)) { + // there was something selected. + entry->delete_text(startPos, endPos); + } + startPos = entry->get_position(); + entry->insert_text(tmp, -1, startPos); + entry->set_position(startPos); +} + +void GlyphsPanel::glyphSelectionChanged() +{ + Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items(); + if (itemArray.empty()) { + label->set_text(" "); + } else { + Gtk::TreeModel::Path const & path = *itemArray.begin(); + Gtk::ListStore::iterator row = store->get_iter(path); + gunichar ch = (*row)[getColumns()->code]; + + gchar * tmp = g_strdup_printf("U+%04X", ch); + label->set_text(tmp); + } +} + +void GlyphsPanel::fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self) +{ + if (self) { + self->handleFontChange(fontsel, font); + } +} + + +void GlyphsPanel::handleFontChange(SPFontSelector * /*fontsel*/, font_instance *font) +{ + if (font) { + gunichar maxUni = 0; + std::vector present; + for (gunichar ch = 0; ch < 65536; ch++) { + int glyphId = font->MapUnicodeChar(ch); + if (glyphId > 0) { + maxUni = std::max(maxUni, ch); + present.push_back(ch); + } + } + + GlyphColumns *columns = getColumns(); + store->clear(); + for (std::vector::iterator it = present.begin(); it != present.end(); ++it) + { + Gtk::ListStore::iterator row = store->append(); + Glib::ustring tmp; + tmp += *it; + (*row)[columns->code] = *it; + (*row)[columns->name] = tmp; + } + } +} + + +} // namespace Dialogs +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h new file mode 100644 index 000000000..ed969fe1d --- /dev/null +++ b/src/ui/dialog/glyphs.h @@ -0,0 +1,86 @@ +/** + * Glyph selector dialog. + */ + +/* Authors: + * Jon A. Cruz + * + * Copyright (C) 2010 Jon A. Cruz + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifndef SEEN_DIALOGS_GLYPHS_H +#define SEEN_DIALOGS_GLYPHS_H + +#include +#include "ui/widget/panel.h" + + +namespace Gtk { +class Entry; +class IconView; +class Label; +class ListStore; +} + +class SPFontSelector; +class font_instance; + + +namespace Inkscape { +namespace UI { + +class PreviewHolder; + +namespace Dialogs { + +class GlyphColumns; + +/** + * A panel that displays character glyphs. + */ + +class GlyphsPanel : public Inkscape::UI::Widget::Panel +{ +public: + GlyphsPanel(gchar const *prefsPath = "/dialogs/glyphs"); + virtual ~GlyphsPanel(); + + static GlyphsPanel& getInstance(); + +protected: + +private: + GlyphsPanel(GlyphsPanel const &); // no copy + GlyphsPanel &operator=(GlyphsPanel const &); // no assign + + static GlyphColumns *getColumns(); + + static void fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self); + + void handleFontChange(SPFontSelector *fontsel, font_instance *font); + void glyphActivated(Gtk::TreeModel::Path const & path); + void glyphSelectionChanged(); + + + Glib::RefPtr store; + Gtk::IconView *iconView; + Gtk::Entry *entry; + Gtk::Label *label; +}; + + +} // namespace Dialogs +} // namespace UI +} // namespace Inkscape + +#endif // SEEN_DIALOGS_GLYPHS_H +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 65c7d9f4d3a52fd8fe806efc6a4d4f836b17b0a8 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 1 Apr 2010 19:35:48 -0700 Subject: Add character script range to description (bzr r9270) --- src/ui/dialog/glyphs.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 7a4731124..3f25fa817 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -40,6 +41,102 @@ GlyphsPanel &GlyphsPanel::getInstance() } +//enum GUnicodeScript +#if GLIB_CHECK_VERSION(2,14,0) +static std::map &getScriptToName() +{ + static bool init = false; + static std::map mappings; + if (!init) { + init = true; + mappings[G_UNICODE_SCRIPT_INVALID_CODE] = _("all"); + mappings[G_UNICODE_SCRIPT_COMMON] = _("common"); + mappings[G_UNICODE_SCRIPT_INHERITED] = _("inherited"); + mappings[G_UNICODE_SCRIPT_ARABIC] = _("Arabic"); + mappings[G_UNICODE_SCRIPT_ARMENIAN] = _("Armenian"); + mappings[G_UNICODE_SCRIPT_BENGALI] = _("Bengali"); + mappings[G_UNICODE_SCRIPT_BOPOMOFO] = _("Bopomofo"); + mappings[G_UNICODE_SCRIPT_CHEROKEE] = _("Cherokee"); + mappings[G_UNICODE_SCRIPT_COPTIC] = _("Coptic"); + mappings[G_UNICODE_SCRIPT_CYRILLIC] = _("Cyrillic"); + mappings[G_UNICODE_SCRIPT_DESERET] = _("Deseret"); + mappings[G_UNICODE_SCRIPT_DEVANAGARI] = _("Devanagari"); + mappings[G_UNICODE_SCRIPT_ETHIOPIC] = _("Ethiopic"); + mappings[G_UNICODE_SCRIPT_GEORGIAN] = _("Georgian"); + mappings[G_UNICODE_SCRIPT_GOTHIC] = _("Gothic"); + mappings[G_UNICODE_SCRIPT_GREEK] = _("Greek"); + mappings[G_UNICODE_SCRIPT_GUJARATI] = _("Gujarati"); + mappings[G_UNICODE_SCRIPT_GURMUKHI] = _("Gurmukhi"); + mappings[G_UNICODE_SCRIPT_HAN] = _("Han"); + mappings[G_UNICODE_SCRIPT_HANGUL] = _("Hangul"); + mappings[G_UNICODE_SCRIPT_HEBREW] = _("Hebrew"); + mappings[G_UNICODE_SCRIPT_HIRAGANA] = _("Hiragana"); + mappings[G_UNICODE_SCRIPT_KANNADA] = _("Kannada"); + mappings[G_UNICODE_SCRIPT_KATAKANA] = _("Katakana"); + mappings[G_UNICODE_SCRIPT_KHMER] = _("Khmer"); + mappings[G_UNICODE_SCRIPT_LAO] = _("Lao"); + mappings[G_UNICODE_SCRIPT_LATIN] = _("Latin"); + mappings[G_UNICODE_SCRIPT_MALAYALAM] = _("Malayalam"); + mappings[G_UNICODE_SCRIPT_MONGOLIAN] = _("Mongolian"); + mappings[G_UNICODE_SCRIPT_MYANMAR] = _("Myanmar"); + mappings[G_UNICODE_SCRIPT_OGHAM] = _("Ogham"); + mappings[G_UNICODE_SCRIPT_OLD_ITALIC] = _("Old Italic"); + mappings[G_UNICODE_SCRIPT_ORIYA] = _("Oriya"); + mappings[G_UNICODE_SCRIPT_RUNIC] = _("Runic"); + mappings[G_UNICODE_SCRIPT_SINHALA] = _("Sinhala"); + mappings[G_UNICODE_SCRIPT_SYRIAC] = _("Syriac"); + mappings[G_UNICODE_SCRIPT_TAMIL] = _("Tamil"); + mappings[G_UNICODE_SCRIPT_TELUGU] = _("Telugu"); + mappings[G_UNICODE_SCRIPT_THAANA] = _("Thaana"); + mappings[G_UNICODE_SCRIPT_THAI] = _("Thai"); + mappings[G_UNICODE_SCRIPT_TIBETAN] = _("Tibetan"); + mappings[G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL] = _("Canadian Aboriginal"); + mappings[G_UNICODE_SCRIPT_YI] = _("Yi"); + mappings[G_UNICODE_SCRIPT_TAGALOG] = _("Tagalog"); + mappings[G_UNICODE_SCRIPT_HANUNOO] = _("Hanunoo"); + mappings[G_UNICODE_SCRIPT_BUHID] = _("Buhid"); + mappings[G_UNICODE_SCRIPT_TAGBANWA] = _("Tagbanwa"); + mappings[G_UNICODE_SCRIPT_BRAILLE] = _("Braille"); + mappings[G_UNICODE_SCRIPT_CYPRIOT] = _("Cypriot"); + mappings[G_UNICODE_SCRIPT_LIMBU] = _("Limbu"); + mappings[G_UNICODE_SCRIPT_OSMANYA] = _("Osmanya"); + mappings[G_UNICODE_SCRIPT_SHAVIAN] = _("Shavian"); + mappings[G_UNICODE_SCRIPT_LINEAR_B] = _("Linear B"); + mappings[G_UNICODE_SCRIPT_TAI_LE] = _("Tai Le"); + mappings[G_UNICODE_SCRIPT_UGARITIC] = _("Ugaritic"); + mappings[G_UNICODE_SCRIPT_NEW_TAI_LUE] = _("New Tai Lue"); + mappings[G_UNICODE_SCRIPT_BUGINESE] = _("Buginese"); + mappings[G_UNICODE_SCRIPT_GLAGOLITIC] = _("Glagolitic"); + mappings[G_UNICODE_SCRIPT_TIFINAGH] = _("Tifinagh"); + mappings[G_UNICODE_SCRIPT_SYLOTI_NAGRI] = _("Syloti Nagri"); + mappings[G_UNICODE_SCRIPT_OLD_PERSIAN] = _("Old Persian"); + mappings[G_UNICODE_SCRIPT_KHAROSHTHI] = _("Kharoshthi"); + mappings[G_UNICODE_SCRIPT_UNKNOWN] = _("unassigned"); + mappings[G_UNICODE_SCRIPT_BALINESE] = _("Balinese"); + mappings[G_UNICODE_SCRIPT_CUNEIFORM] = _("Cuneiform"); + mappings[G_UNICODE_SCRIPT_PHOENICIAN] = _("Phoenician"); + mappings[G_UNICODE_SCRIPT_PHAGS_PA] = _("Phags-pa"); + mappings[G_UNICODE_SCRIPT_NKO] = _("N'Ko"); + +#if GLIB_CHECK_VERSION(2,14,0) + mappings[G_UNICODE_SCRIPT_KAYAH_LI] = _("Kayah Li"); + mappings[G_UNICODE_SCRIPT_LEPCHA] = _("Lepcha"); + mappings[G_UNICODE_SCRIPT_REJANG] = _("Rejang"); + mappings[G_UNICODE_SCRIPT_SUNDANESE] = _("Sundanese"); + mappings[G_UNICODE_SCRIPT_SAURASHTRA] = _("Saurashtra"); + mappings[G_UNICODE_SCRIPT_CHAM] = _("Cham"); + mappings[G_UNICODE_SCRIPT_OL_CHIKI] = _("Ol Chiki"); + mappings[G_UNICODE_SCRIPT_VAI] = _("Vai"); + mappings[G_UNICODE_SCRIPT_CARIAN] = _("Carian"); + mappings[G_UNICODE_SCRIPT_LYCIAN] = _("Lycian"); + mappings[G_UNICODE_SCRIPT_LYDIAN] = _("Lydian"); +#endif // GLIB_CHECK_VERSION(2,14,0) + } + return mappings; +} +#endif // GLIB_CHECK_VERSION(2,14,0) + + class GlyphColumns : public Gtk::TreeModel::ColumnRecord { public: @@ -110,7 +207,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : Gtk::HBox *box = new Gtk::HBox(); entry = new Gtk::Entry(); - box->pack_start(*Gtk::manage(entry)); + entry->set_width_chars(12); + box->pack_start(*Gtk::manage(entry), Gtk::PACK_SHRINK); label = new Gtk::Label(" "); box->pack_start(*Gtk::manage(label), Gtk::PACK_EXPAND_PADDING); @@ -167,7 +265,16 @@ void GlyphsPanel::glyphSelectionChanged() Gtk::ListStore::iterator row = store->get_iter(path); gunichar ch = (*row)[getColumns()->code]; - gchar * tmp = g_strdup_printf("U+%04X", ch); + + Glib::ustring scriptName; +#if GLIB_CHECK_VERSION(2,14,0) + GUnicodeScript script = g_unichar_get_script(ch); + std::map mappings = getScriptToName(); + if (mappings.find(script) != mappings.end()) { + scriptName = mappings[script]; + } +#endif + gchar * tmp = g_strdup_printf("U+%04X %s", ch, scriptName.c_str()); label->set_text(tmp); } } -- cgit v1.2.3 From 443bc0bfa2c58179e3de608391a2d73139571d2d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Apr 2010 00:09:09 -0700 Subject: Allow filtering by glyph script. (bzr r9272) --- src/ui/dialog/glyphs.cpp | 101 ++++++++++++++++++++++++++++++++++++++++------- src/ui/dialog/glyphs.h | 11 +++++- 2 files changed, 96 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 3f25fa817..1c875e8cc 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -41,7 +41,6 @@ GlyphsPanel &GlyphsPanel::getInstance() } -//enum GUnicodeScript #if GLIB_CHECK_VERSION(2,14,0) static std::map &getScriptToName() { @@ -165,7 +164,14 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : store(Gtk::ListStore::create(*getColumns())), iconView(0), entry(0), - label(0) + label(0), +#if GLIB_CHECK_VERSION(2,14,0) + scriptCombo(0), +#endif // GLIB_CHECK_VERSION(2,14,0) + fsel(0), + iconActiveConn(), + iconSelectConn(), + scriptSelectConn() { Gtk::Table *table = new Gtk::Table(3, 1, false); _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); @@ -174,14 +180,50 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : // ------------------------------- GtkWidget *fontsel = sp_font_selector_new(); + fsel = SP_FONT_SELECTOR(fontsel); + sp_font_selector_set_font(fsel, sp_font_selector_get_font(fsel), 12.0); + g_signal_connect( G_OBJECT(fontsel), "font_set", G_CALLBACK(fontChangeCB), this ); table->attach(*Gtk::manage(Glib::wrap(fontsel)), - 0, 1, row, row + 1, + 0, 3, row, row + 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL); row++; +// ------------------------------- + +#if GLIB_CHECK_VERSION(2,14,0) + { + Gtk::Label *label = new Gtk::Label(_("Script: ")); + table->attach( *Gtk::manage(label), + 0, 1, row, row + 1, + Gtk::SHRINK, Gtk::SHRINK); + + scriptCombo = new Gtk::ComboBoxText(); + + std::map items = getScriptToName(); + for (std::map::iterator it = items.begin(); it != items.end(); ++it) + { + scriptCombo->append_text(it->second); + } + + scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]); + scriptSelectConn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + + table->attach( *Gtk::manage(scriptCombo), + 1, 2, row, row + 1, + Gtk::SHRINK, Gtk::SHRINK); + + label = new Gtk::Label(""); + table->attach( *Gtk::manage(label), + 2, 3, row, row + 1, + Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); + } + + row++; +#endif // GLIB_CHECK_VERSION(2,14,0) + // ------------------------------- GlyphColumns *columns = getColumns(); @@ -190,15 +232,15 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : iconView->set_text_column(columns->name); //iconView->set_columns(16); - iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated)); - iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged)); + iconActiveConn = iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated)); + iconSelectConn = iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged)); Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow(); scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); scroller->add(*Gtk::manage(iconView)); table->attach(*Gtk::manage(scroller), - 0, 1, row, row + 1, + 0, 3, row, row + 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL); row++; @@ -207,11 +249,18 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : Gtk::HBox *box = new Gtk::HBox(); entry = new Gtk::Entry(); - entry->set_width_chars(12); + entry->set_width_chars(18); box->pack_start(*Gtk::manage(entry), Gtk::PACK_SHRINK); + Gtk::Label *pad = new Gtk::Label(" "); + box->pack_start(*Gtk::manage(pad), Gtk::PACK_SHRINK); + label = new Gtk::Label(" "); - box->pack_start(*Gtk::manage(label), Gtk::PACK_EXPAND_PADDING); + box->pack_start(*Gtk::manage(label), Gtk::PACK_SHRINK); + + pad = new Gtk::Label(""); + box->pack_start(*Gtk::manage(pad), Gtk::PACK_EXPAND_WIDGET); + GtkWidget *applyBtn = gtk_button_new_from_stock(GTK_STOCK_APPLY); GTK_WIDGET_SET_FLAGS(applyBtn, GTK_CAN_DEFAULT | GTK_HAS_DEFAULT); @@ -220,7 +269,7 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : box->pack_end(*Gtk::manage(Glib::wrap(applyBtn)), Gtk::PACK_SHRINK); table->attach( *Gtk::manage(box), - 0, 1, row, row + 1, + 0, 3, row, row + 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); row++; @@ -234,6 +283,9 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : GlyphsPanel::~GlyphsPanel() { + iconActiveConn.disconnect(); + iconSelectConn.disconnect(); + scriptSelectConn.disconnect(); } @@ -279,24 +331,43 @@ void GlyphsPanel::glyphSelectionChanged() } } -void GlyphsPanel::fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self) +void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*font*/, GlyphsPanel *self) { if (self) { - self->handleFontChange(fontsel, font); + self->rebuild(); } } -void GlyphsPanel::handleFontChange(SPFontSelector * /*fontsel*/, font_instance *font) +void GlyphsPanel::rebuild() { + font_instance *font = fsel ? sp_font_selector_get_font(fsel) : 0; if (font) { - gunichar maxUni = 0; + //double sp_font_selector_get_size (SPFontSelector *fsel); + +#if GLIB_CHECK_VERSION(2,14,0) + GUnicodeScript script = G_UNICODE_SCRIPT_INVALID_CODE; + Glib::ustring scriptName = scriptCombo->get_active_text(); + std::map items = getScriptToName(); + for (std::map::iterator it = items.begin(); it != items.end(); ++it) { + if (scriptName == it->second) { + script = it->first; + break; + } + } +#endif // GLIB_CHECK_VERSION(2,14,0) + std::vector present; - for (gunichar ch = 0; ch < 65536; ch++) { + for (gunichar ch = 1; ch < 65535; ch++) { int glyphId = font->MapUnicodeChar(ch); if (glyphId > 0) { - maxUni = std::max(maxUni, ch); +#if GLIB_CHECK_VERSION(2,14,0) + if ((script == G_UNICODE_SCRIPT_INVALID_CODE) || (script == g_unichar_get_script(ch))) { + present.push_back(ch); + } +#else present.push_back(ch); +#endif } } diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index ed969fe1d..49ead3d6b 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -16,6 +16,7 @@ namespace Gtk { +class ComboBoxText; class Entry; class IconView; class Label; @@ -57,7 +58,8 @@ private: static void fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self); - void handleFontChange(SPFontSelector *fontsel, font_instance *font); + void rebuild(); + void glyphActivated(Gtk::TreeModel::Path const & path); void glyphSelectionChanged(); @@ -66,6 +68,13 @@ private: Gtk::IconView *iconView; Gtk::Entry *entry; Gtk::Label *label; +#if GLIB_CHECK_VERSION(2,14,0) + Gtk::ComboBoxText *scriptCombo; +#endif //GLIB_CHECK_VERSION(2,14,0) + SPFontSelector *fsel; + sigc::connection iconActiveConn; + sigc::connection iconSelectConn; + sigc::connection scriptSelectConn; }; -- cgit v1.2.3 From c9fafe6180e54d0ef2c4db0563fbfc2785de0360 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Apr 2010 01:26:18 -0700 Subject: Corrected "using namespace" contamination from ui/dialog header files. (bzr r9273) --- src/ui/dialog/align-and-distribute.h | 2 - src/ui/dialog/document-metadata.cpp | 2 + src/ui/dialog/document-metadata.h | 11 +- src/ui/dialog/document-properties.h | 32 ++- src/ui/dialog/fill-and-stroke.cpp | 2 +- src/ui/dialog/fill-and-stroke.h | 13 +- src/ui/dialog/filter-effects-dialog.cpp | 6 + src/ui/dialog/filter-effects-dialog.h | 8 +- src/ui/dialog/inkscape-preferences.cpp | 7 + src/ui/dialog/inkscape-preferences.h | 382 +++++++++++++++++++------------- src/ui/dialog/panel-dialog.h | 24 +- src/ui/dialog/transformation.h | 62 +++--- 12 files changed, 324 insertions(+), 227 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index 0d41bb221..297b3d2a1 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -32,8 +32,6 @@ #include "ui/widget/panel.h" #include "ui/widget/notebook-page.h" -using namespace Inkscape::UI::Widget; - class SPItem; diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp index 96cad1fbe..55eb94f92 100644 --- a/src/ui/dialog/document-metadata.cpp +++ b/src/ui/dialog/document-metadata.cpp @@ -148,6 +148,8 @@ attach_all (Gtk::Table &table, const Gtk::Widget *arr[], unsigned size, int star void DocumentMetadata::build_metadata() { + using Inkscape::UI::Widget::EntityEntry; + _page_metadata1.show(); Gtk::Label *label = manage (new Gtk::Label); diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h index 7f718e9f7..f21bb0d83 100644 --- a/src/ui/dialog/document-metadata.h +++ b/src/ui/dialog/document-metadata.h @@ -23,8 +23,6 @@ #include "ui/widget/notebook-page.h" #include "ui/widget/registry.h" -using namespace Inkscape::UI::Widget; - namespace Inkscape { namespace XML { class Node; @@ -35,7 +33,7 @@ namespace Inkscape { } namespace Dialog { -typedef std::list RDElist; +typedef std::list RDElist; class DocumentMetadata : public Inkscape::UI::Widget::Panel { public: @@ -56,13 +54,14 @@ protected: Gtk::Tooltips _tt; Gtk::Notebook _notebook; - NotebookPage _page_metadata1, _page_metadata2; + UI::Widget::NotebookPage _page_metadata1; + UI::Widget::NotebookPage _page_metadata2; //--------------------------------------------------------------- RDElist _rdflist; - Licensor _licensor; + UI::Widget::Licensor _licensor; - Registry _wr; + UI::Widget::Registry _wr; private: virtual ~DocumentMetadata(); diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 136ae2c89..c67dc9706 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -28,8 +28,6 @@ #include "xml/helper-observer.h" -using namespace Inkscape::UI::Widget; - namespace Inkscape { namespace UI { namespace Dialog { @@ -78,21 +76,31 @@ protected: Gtk::Tooltips _tt; Gtk::Notebook _notebook; - NotebookPage _page_page, _page_guides; - NotebookPage _page_snap, _page_cms, _page_scripting; + UI::Widget::NotebookPage _page_page; + UI::Widget::NotebookPage _page_guides; + UI::Widget::NotebookPage _page_snap; + UI::Widget::NotebookPage _page_cms; + UI::Widget::NotebookPage _page_scripting; Gtk::VBox _grids_vbox; - Registry _wr; + UI::Widget::Registry _wr; //--------------------------------------------------------------- - RegisteredCheckButton _rcb_canb, _rcb_bord, _rcb_shad; - RegisteredColorPicker _rcp_bg, _rcp_bord; - RegisteredUnitMenu _rum_deflt; - PageSizer _page_sizer; + UI::Widget::RegisteredCheckButton _rcb_canb; + UI::Widget::RegisteredCheckButton _rcb_bord; + UI::Widget::RegisteredCheckButton _rcb_shad; + UI::Widget::RegisteredColorPicker _rcp_bg; + UI::Widget::RegisteredColorPicker _rcp_bord; + UI::Widget::RegisteredUnitMenu _rum_deflt; + UI::Widget::PageSizer _page_sizer; //--------------------------------------------------------------- - RegisteredCheckButton _rcb_sgui, _rcbsng; - RegisteredColorPicker _rcp_gui, _rcp_hgui; + UI::Widget::RegisteredCheckButton _rcb_sgui; + UI::Widget::RegisteredCheckButton _rcbsng; + UI::Widget::RegisteredColorPicker _rcp_gui; + UI::Widget::RegisteredColorPicker _rcp_hgui; //--------------------------------------------------------------- - ToleranceSlider _rsu_sno, _rsu_sn, _rsu_gusn; + UI::Widget::ToleranceSlider _rsu_sno; + UI::Widget::ToleranceSlider _rsu_sn; + UI::Widget::ToleranceSlider _rsu_gusn; //--------------------------------------------------------------- Gtk::Menu _menu; Gtk::OptionMenu _combo_avail; diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index fae2e873c..6ee076a94 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -42,7 +42,7 @@ FillAndStroke::FillAndStroke() _page_fill(1, 1, true, true), _page_stroke_paint(1, 1, true, true), _page_stroke_style(1, 1, true, true), - _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", SimpleFilterModifier::BLUR), + _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", UI::Widget::SimpleFilterModifier::BLUR), hierID(0), trackActive(false), targetDesktop(0), diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index f0d68ced8..a5fe4906a 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -26,8 +26,6 @@ #include "ui/widget/notebook-page.h" #include "ui/widget/object-composite-settings.h" -using namespace Inkscape::UI::Widget; - namespace Inkscape { namespace UI { namespace Dialog { @@ -55,12 +53,12 @@ public: protected: Gtk::Notebook _notebook; - NotebookPage _page_fill; - NotebookPage _page_stroke_paint; - NotebookPage _page_stroke_style; + UI::Widget::NotebookPage _page_fill; + UI::Widget::NotebookPage _page_stroke_paint; + UI::Widget::NotebookPage _page_stroke_style; - StyleSubject::Selection _subject; - ObjectCompositeSettings _composite_settings; + UI::Widget::StyleSubject::Selection _subject; + UI::Widget::ObjectCompositeSettings _composite_settings; Gtk::HBox &_createPageTabLabel(const Glib::ustring &label, const char *label_image); @@ -87,6 +85,7 @@ private: } // namespace UI } // namespace Inkscape + #endif // INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H /* diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 132e5fd4e..1672c4b69 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -74,6 +74,12 @@ namespace Inkscape { namespace UI { namespace Dialog { +using Inkscape::UI::Widget::AttrWidget; +using Inkscape::UI::Widget::ComboBoxEnum; +using Inkscape::UI::Widget::DualSpinSlider; +using Inkscape::UI::Widget::SpinSlider; + + // Returns the number of inputs available for the filter primitive type int input_count(const SPFilterPrimitive* prim) { diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h index 3fb9a46fb..a14c85a91 100644 --- a/src/ui/dialog/filter-effects-dialog.h +++ b/src/ui/dialog/filter-effects-dialog.h @@ -35,8 +35,6 @@ #include "ui/widget/spin-slider.h" #include "xml/helper-observer.h" -using namespace Inkscape::UI::Widget; - namespace Inkscape { namespace UI { namespace Dialog { @@ -214,9 +212,9 @@ private: void duplicate_primitive(); void convolve_order_changed(); - void set_attr_direct(const AttrWidget*); - void set_child_attr_direct(const AttrWidget*); - void set_filternode_attr(const AttrWidget*); + void set_attr_direct(const UI::Widget::AttrWidget*); + void set_child_attr_direct(const UI::Widget::AttrWidget*); + void set_filternode_attr(const UI::Widget::AttrWidget*); void set_attr(SPObject*, const SPAttributeEnum, const gchar* val); void update_settings_view(); void update_filter_general_settings_view(); diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 40efc8282..00e72bd4f 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -56,6 +56,13 @@ namespace Inkscape { namespace UI { namespace Dialog { +using Inkscape::UI::Widget::DialogPage; +using Inkscape::UI::Widget::PrefCheckButton; +using Inkscape::UI::Widget::PrefRadioButton; +using Inkscape::UI::Widget::PrefSpinButton; +using Inkscape::UI::Widget::StyleSwatch; + + InkscapePreferences::InkscapePreferences() : UI::Widget::Panel ("", "/dialogs/preferences", SP_VERB_DIALOG_DISPLAY), _max_dialog_width(0), diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 0ba8c965d..5ee916e4c 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -82,8 +82,6 @@ enum { PREFS_PAGE_MISC }; -using namespace Inkscape::UI::Widget; - namespace Inkscape { namespace UI { namespace Dialog { @@ -108,188 +106,272 @@ protected: { Gtk::TreeModelColumnRecord::add(_col_name); Gtk::TreeModelColumnRecord::add(_col_page); Gtk::TreeModelColumnRecord::add(_col_id); } Gtk::TreeModelColumn _col_name; Gtk::TreeModelColumn _col_id; - Gtk::TreeModelColumn _col_page; + Gtk::TreeModelColumn _col_page; }; PageListModelColumns _page_list_columns; Gtk::TreeModel::Path _path_tools; Gtk::TreeModel::Path _path_shapes; - DialogPage _page_mouse, _page_scrolling, _page_snapping, _page_steps, _page_tools, _page_windows, - _page_clones, _page_mask, _page_transforms, _page_filters, _page_select, - _page_importexport, _page_cms, _page_grids, _page_svgoutput, _page_misc, - _page_ui, _page_save, _page_bitmaps, _page_spellcheck; - DialogPage _page_selector, _page_node, _page_tweak, _page_spray, _page_zoom, _page_shapes, _page_pencil, _page_pen, - _page_calligraphy, _page_text, _page_gradient, _page_connector, _page_dropper, _page_lpetool; - DialogPage _page_rectangle, _page_3dbox, _page_ellipse, _page_star, _page_spiral, _page_paintbucket, _page_eraser; - - PrefSpinButton _mouse_sens, _mouse_thres; - PrefCheckButton _mouse_use_ext_input; - PrefCheckButton _mouse_switch_on_ext_input; - - PrefSpinButton _scroll_wheel, _scroll_arrow_px, _scroll_arrow_acc, _scroll_auto_speed, _scroll_auto_thres; - PrefCheckButton _scroll_space; - PrefCheckButton _wheel_zoom; + UI::Widget::DialogPage _page_mouse; + UI::Widget::DialogPage _page_scrolling; + UI::Widget::DialogPage _page_snapping; + UI::Widget::DialogPage _page_steps; + UI::Widget::DialogPage _page_tools; + UI::Widget::DialogPage _page_windows; + UI::Widget::DialogPage _page_clones; + UI::Widget::DialogPage _page_mask; + UI::Widget::DialogPage _page_transforms; + UI::Widget::DialogPage _page_filters; + UI::Widget::DialogPage _page_select; + UI::Widget::DialogPage _page_importexport; + UI::Widget::DialogPage _page_cms; + UI::Widget::DialogPage _page_grids; + UI::Widget::DialogPage _page_svgoutput; + UI::Widget::DialogPage _page_misc; + UI::Widget::DialogPage _page_ui; + UI::Widget::DialogPage _page_save; + UI::Widget::DialogPage _page_bitmaps; + UI::Widget::DialogPage _page_spellcheck; + + UI::Widget::DialogPage _page_selector; + UI::Widget::DialogPage _page_node; + UI::Widget::DialogPage _page_tweak; + UI::Widget::DialogPage _page_spray; + UI::Widget::DialogPage _page_zoom; + UI::Widget::DialogPage _page_shapes; + UI::Widget::DialogPage _page_pencil; + UI::Widget::DialogPage _page_pen; + UI::Widget::DialogPage _page_calligraphy; + UI::Widget::DialogPage _page_text; + UI::Widget::DialogPage _page_gradient; + UI::Widget::DialogPage _page_connector; + UI::Widget::DialogPage _page_dropper; + UI::Widget::DialogPage _page_lpetool; + + UI::Widget::DialogPage _page_rectangle; + UI::Widget::DialogPage _page_3dbox; + UI::Widget::DialogPage _page_ellipse; + UI::Widget::DialogPage _page_star; + UI::Widget::DialogPage _page_spiral; + UI::Widget::DialogPage _page_paintbucket; + UI::Widget::DialogPage _page_eraser; + + UI::Widget::PrefSpinButton _mouse_sens; + UI::Widget::PrefSpinButton _mouse_thres; + UI::Widget::PrefCheckButton _mouse_use_ext_input; + UI::Widget::PrefCheckButton _mouse_switch_on_ext_input; + + UI::Widget::PrefSpinButton _scroll_wheel; + UI::Widget::PrefSpinButton _scroll_arrow_px; + UI::Widget::PrefSpinButton _scroll_arrow_acc; + UI::Widget::PrefSpinButton _scroll_auto_speed; + UI::Widget::PrefSpinButton _scroll_auto_thres; + UI::Widget::PrefCheckButton _scroll_space; + UI::Widget::PrefCheckButton _wheel_zoom; Gtk::HScale *_slider_snapping_delay; - PrefCheckButton _snap_indicator, _snap_closest_only, _snap_mouse_pointer; - - PrefCombo _steps_rot_snap; - PrefCheckButton _steps_compass; - PrefSpinButton _steps_arrow, _steps_scale, _steps_inset, _steps_zoom; - - PrefRadioButton _t_sel_trans_obj, _t_sel_trans_outl, _t_sel_cue_none, _t_sel_cue_mark, - _t_sel_cue_box, _t_bbox_visual, _t_bbox_geometric; - PrefCheckButton _t_cvg_keep_objects, _t_cvg_convert_whole_groups; - PrefCheckButton _t_node_show_outline; - PrefCheckButton _t_node_live_outline; - PrefCheckButton _t_node_live_objects; - PrefCheckButton _t_node_pathflash_enabled; - PrefCheckButton _t_node_pathflash_selected; - PrefSpinButton _t_node_pathflash_timeout; - PrefCheckButton _t_node_show_path_direction; - PrefCheckButton _t_node_single_node_transform_handles; - PrefCheckButton _t_node_delete_preserves_shape; - PrefColorPicker _t_node_pathoutline_color; - - PrefRadioButton _win_dockable, _win_floating; - PrefRadioButton _win_ontop_none, _win_ontop_normal, _win_ontop_agressive; - PrefRadioButton _win_save_geom_off, _win_save_geom, _win_save_geom_prefs; - PrefCheckButton _win_hide_task, _win_zoom_resize , _win_show_close; - PrefSpinButton _win_trans_focus; /**< The dialog transparency setting for when the dialog is focused. */ - PrefSpinButton _win_trans_blur; /**< The dialog transparency setting for when the dialog is out of focus. */ - PrefSpinButton _win_trans_time; /**< How much time to go from one transparency setting to another */ - - PrefCheckButton _pencil_average_all_sketches; - - PrefCheckButton _calligrapy_use_abs_size; - PrefCheckButton _calligrapy_keep_selected; - - PrefCheckButton _connector_ignore_text; - - PrefRadioButton _clone_option_parallel, _clone_option_stay, _clone_option_transform, - _clone_option_unlink, _clone_option_delete; - PrefCheckButton _clone_relink_on_duplicate; - - PrefCheckButton _mask_mask_on_top; - PrefCheckButton _mask_mask_remove; - PrefRadioButton _mask_grouping_none, _mask_grouping_separate, _mask_grouping_all; - PrefCheckButton _mask_ungrouping; - - PrefRadioButton _blur_quality_best, _blur_quality_better, _blur_quality_normal, _blur_quality_worse, _blur_quality_worst; - PrefRadioButton _filter_quality_best, _filter_quality_better, _filter_quality_normal, _filter_quality_worse, _filter_quality_worst; - PrefCheckButton _show_filters_info_box; - PrefSpinButton _filter_multi_threaded; - - PrefCheckButton _trans_scale_stroke, _trans_scale_corner, _trans_gradient,_trans_pattern; - PrefRadioButton _trans_optimized, _trans_preserved; - - PrefRadioButton _sel_all; - PrefRadioButton _sel_current; - PrefRadioButton _sel_recursive; - PrefCheckButton _sel_hidden, _sel_locked; - PrefCheckButton _sel_layer_deselects; - - PrefSpinButton _importexport_export, _misc_simpl; - PrefSlider _snap_delay, _snap_weight; - PrefSpinButton _misc_latency_skew; - PrefCheckButton _misc_comment, _misc_forkvectors, _misc_scripts, _misc_namedicon_delay; + UI::Widget::PrefCheckButton _snap_indicator; + UI::Widget::PrefCheckButton _snap_closest_only; + UI::Widget::PrefCheckButton _snap_mouse_pointer; + + UI::Widget::PrefCombo _steps_rot_snap; + UI::Widget::PrefCheckButton _steps_compass; + UI::Widget::PrefSpinButton _steps_arrow; + UI::Widget::PrefSpinButton _steps_scale; + UI::Widget::PrefSpinButton _steps_inset; + UI::Widget::PrefSpinButton _steps_zoom; + + UI::Widget::PrefRadioButton _t_sel_trans_obj; + UI::Widget::PrefRadioButton _t_sel_trans_outl; + UI::Widget::PrefRadioButton _t_sel_cue_none; + UI::Widget::PrefRadioButton _t_sel_cue_mark; + UI::Widget::PrefRadioButton _t_sel_cue_box; + UI::Widget::PrefRadioButton _t_bbox_visual; + UI::Widget::PrefRadioButton _t_bbox_geometric; + + UI::Widget::PrefCheckButton _t_cvg_keep_objects; + UI::Widget::PrefCheckButton _t_cvg_convert_whole_groups; + UI::Widget::PrefCheckButton _t_node_show_outline; + UI::Widget::PrefCheckButton _t_node_live_outline; + UI::Widget::PrefCheckButton _t_node_live_objects; + UI::Widget::PrefCheckButton _t_node_pathflash_enabled; + UI::Widget::PrefCheckButton _t_node_pathflash_selected; + UI::Widget::PrefSpinButton _t_node_pathflash_timeout; + UI::Widget::PrefCheckButton _t_node_show_path_direction; + UI::Widget::PrefCheckButton _t_node_single_node_transform_handles; + UI::Widget::PrefCheckButton _t_node_delete_preserves_shape; + UI::Widget::PrefColorPicker _t_node_pathoutline_color; + + UI::Widget::PrefRadioButton _win_dockable; + UI::Widget::PrefRadioButton _win_floating; + UI::Widget::PrefRadioButton _win_ontop_none; + UI::Widget::PrefRadioButton _win_ontop_normal; + UI::Widget::PrefRadioButton _win_ontop_agressive; + UI::Widget::PrefRadioButton _win_save_geom_off; + UI::Widget::PrefRadioButton _win_save_geom; + UI::Widget::PrefRadioButton _win_save_geom_prefs; + UI::Widget::PrefCheckButton _win_hide_task; + UI::Widget::PrefCheckButton _win_zoom_resize; + UI::Widget::PrefCheckButton _win_show_close; + UI::Widget::PrefSpinButton _win_trans_focus; /**< The dialog transparency setting for when the dialog is focused. */ + UI::Widget::PrefSpinButton _win_trans_blur; /**< The dialog transparency setting for when the dialog is out of focus. */ + UI::Widget::PrefSpinButton _win_trans_time; /**< How much time to go from one transparency setting to another */ + + UI::Widget::PrefCheckButton _pencil_average_all_sketches; + + UI::Widget::PrefCheckButton _calligrapy_use_abs_size; + UI::Widget::PrefCheckButton _calligrapy_keep_selected; + + UI::Widget::PrefCheckButton _connector_ignore_text; + + UI::Widget::PrefRadioButton _clone_option_parallel; + UI::Widget::PrefRadioButton _clone_option_stay; + UI::Widget::PrefRadioButton _clone_option_transform; + UI::Widget::PrefRadioButton _clone_option_unlink; + UI::Widget::PrefRadioButton _clone_option_delete; + UI::Widget::PrefCheckButton _clone_relink_on_duplicate; + + UI::Widget::PrefCheckButton _mask_mask_on_top; + UI::Widget::PrefCheckButton _mask_mask_remove; + UI::Widget::PrefRadioButton _mask_grouping_none; + UI::Widget::PrefRadioButton _mask_grouping_separate; + UI::Widget::PrefRadioButton _mask_grouping_all; + UI::Widget::PrefCheckButton _mask_ungrouping; + + UI::Widget::PrefRadioButton _blur_quality_best; + UI::Widget::PrefRadioButton _blur_quality_better; + UI::Widget::PrefRadioButton _blur_quality_normal; + UI::Widget::PrefRadioButton _blur_quality_worse; + UI::Widget::PrefRadioButton _blur_quality_worst; + UI::Widget::PrefRadioButton _filter_quality_best; + UI::Widget::PrefRadioButton _filter_quality_better; + UI::Widget::PrefRadioButton _filter_quality_normal; + UI::Widget::PrefRadioButton _filter_quality_worse; + UI::Widget::PrefRadioButton _filter_quality_worst; + UI::Widget::PrefCheckButton _show_filters_info_box; + UI::Widget::PrefSpinButton _filter_multi_threaded; + + UI::Widget::PrefCheckButton _trans_scale_stroke; + UI::Widget::PrefCheckButton _trans_scale_corner; + UI::Widget::PrefCheckButton _trans_gradient; + UI::Widget::PrefCheckButton _trans_pattern; + UI::Widget::PrefRadioButton _trans_optimized; + UI::Widget::PrefRadioButton _trans_preserved; + + UI::Widget::PrefRadioButton _sel_all; + UI::Widget::PrefRadioButton _sel_current; + UI::Widget::PrefRadioButton _sel_recursive; + UI::Widget::PrefCheckButton _sel_hidden; + UI::Widget::PrefCheckButton _sel_locked; + UI::Widget::PrefCheckButton _sel_layer_deselects; + + UI::Widget::PrefSpinButton _importexport_export; + UI::Widget::PrefSpinButton _misc_simpl; + UI::Widget::PrefSlider _snap_delay; + UI::Widget::PrefSlider _snap_weight; + UI::Widget::PrefSpinButton _misc_latency_skew; + UI::Widget::PrefCheckButton _misc_comment; + UI::Widget::PrefCheckButton _misc_forkvectors; + UI::Widget::PrefCheckButton _misc_scripts; + UI::Widget::PrefCheckButton _misc_namedicon_delay; Gtk::TextView _misc_info; Gtk::ScrolledWindow _misc_info_scroll; // UI page - PrefCombo _ui_languages; - PrefCombo _misc_small_toolbar; - PrefCombo _misc_small_secondary; - PrefCombo _misc_small_tools; - PrefCheckButton _ui_colorsliders_top; - PrefSpinButton _misc_recent; - PrefCheckButton _ui_partialdynamic; - ZoomCorrRulerSlider _ui_zoom_correction; + UI::Widget::PrefCombo _ui_languages; + UI::Widget::PrefCombo _misc_small_toolbar; + UI::Widget::PrefCombo _misc_small_secondary; + UI::Widget::PrefCombo _misc_small_tools; + UI::Widget::PrefCheckButton _ui_colorsliders_top; + UI::Widget::PrefSpinButton _misc_recent; + UI::Widget::PrefCheckButton _ui_partialdynamic; + UI::Widget::ZoomCorrRulerSlider _ui_zoom_correction; //Spellcheck - PrefCombo _spell_language; - PrefCombo _spell_language2; - PrefCombo _spell_language3; - PrefCheckButton _spell_ignorenumbers; - PrefCheckButton _spell_ignoreallcaps; - - PrefCombo _misc_overs_bitmap; - PrefCombo _misc_bitmap_editor; - PrefCheckButton _misc_bitmap_autoreload; - PrefSpinButton _bitmap_copy_res; - - PrefCheckButton _save_use_current_dir; - PrefCheckButton _save_autosave_enable; - PrefSpinButton _save_autosave_interval; - PrefEntry _save_autosave_path; - PrefSpinButton _save_autosave_max; + UI::Widget::PrefCombo _spell_language; + UI::Widget::PrefCombo _spell_language2; + UI::Widget::PrefCombo _spell_language3; + UI::Widget::PrefCheckButton _spell_ignorenumbers; + UI::Widget::PrefCheckButton _spell_ignoreallcaps; + + UI::Widget::PrefCombo _misc_overs_bitmap; + UI::Widget::PrefCombo _misc_bitmap_editor; + UI::Widget::PrefCheckButton _misc_bitmap_autoreload; + UI::Widget::PrefSpinButton _bitmap_copy_res; + + UI::Widget::PrefCheckButton _save_use_current_dir; + UI::Widget::PrefCheckButton _save_autosave_enable; + UI::Widget::PrefSpinButton _save_autosave_interval; + UI::Widget::PrefEntry _save_autosave_path; + UI::Widget::PrefSpinButton _save_autosave_max; Gtk::ComboBoxText _cms_display_profile; - PrefCheckButton _cms_from_display; - PrefCombo _cms_intent; + UI::Widget::PrefCheckButton _cms_from_display; + UI::Widget::PrefCombo _cms_intent; - PrefCheckButton _cms_softproof; - PrefCheckButton _cms_gamutwarn; + UI::Widget::PrefCheckButton _cms_softproof; + UI::Widget::PrefCheckButton _cms_gamutwarn; Gtk::ColorButton _cms_gamutcolor; Gtk::ComboBoxText _cms_proof_profile; - PrefCombo _cms_proof_intent; - PrefCheckButton _cms_proof_blackpoint; - PrefCheckButton _cms_proof_preserveblack; + UI::Widget::PrefCombo _cms_proof_intent; + UI::Widget::PrefCheckButton _cms_proof_blackpoint; + UI::Widget::PrefCheckButton _cms_proof_preserveblack; Gtk::Notebook _grids_notebook; - PrefCheckButton _grids_no_emphasize_on_zoom; - DialogPage _grids_xy, _grids_axonom; + UI::Widget::PrefCheckButton _grids_no_emphasize_on_zoom; + UI::Widget::DialogPage _grids_xy; + UI::Widget::DialogPage _grids_axonom; // CanvasXYGrid properties: - PrefUnit _grids_xy_units; - PrefSpinButton _grids_xy_origin_x; - PrefSpinButton _grids_xy_origin_y; - PrefSpinButton _grids_xy_spacing_x; - PrefSpinButton _grids_xy_spacing_y; - PrefColorPicker _grids_xy_color; - PrefColorPicker _grids_xy_empcolor; - PrefSpinButton _grids_xy_empspacing; - PrefCheckButton _grids_xy_dotted; + UI::Widget::PrefUnit _grids_xy_units; + UI::Widget::PrefSpinButton _grids_xy_origin_x; + UI::Widget::PrefSpinButton _grids_xy_origin_y; + UI::Widget::PrefSpinButton _grids_xy_spacing_x; + UI::Widget::PrefSpinButton _grids_xy_spacing_y; + UI::Widget::PrefColorPicker _grids_xy_color; + UI::Widget::PrefColorPicker _grids_xy_empcolor; + UI::Widget::PrefSpinButton _grids_xy_empspacing; + UI::Widget::PrefCheckButton _grids_xy_dotted; // CanvasAxonomGrid properties: - PrefUnit _grids_axonom_units; - PrefSpinButton _grids_axonom_origin_x; - PrefSpinButton _grids_axonom_origin_y; - PrefSpinButton _grids_axonom_spacing_y; - PrefSpinButton _grids_axonom_angle_x; - PrefSpinButton _grids_axonom_angle_z; - PrefColorPicker _grids_axonom_color; - PrefColorPicker _grids_axonom_empcolor; - PrefSpinButton _grids_axonom_empspacing; + UI::Widget::PrefUnit _grids_axonom_units; + UI::Widget::PrefSpinButton _grids_axonom_origin_x; + UI::Widget::PrefSpinButton _grids_axonom_origin_y; + UI::Widget::PrefSpinButton _grids_axonom_spacing_y; + UI::Widget::PrefSpinButton _grids_axonom_angle_x; + UI::Widget::PrefSpinButton _grids_axonom_angle_z; + UI::Widget::PrefColorPicker _grids_axonom_color; + UI::Widget::PrefColorPicker _grids_axonom_empcolor; + UI::Widget::PrefSpinButton _grids_axonom_empspacing; // SVG Output page: - PrefCheckButton _svgoutput_usenamedcolors; - PrefSpinButton _svgoutput_numericprecision; - PrefSpinButton _svgoutput_minimumexponent; - PrefCheckButton _svgoutput_inlineattrs; - PrefSpinButton _svgoutput_indent; - PrefCheckButton _svgoutput_allowrelativecoordinates; - PrefCheckButton _svgoutput_forcerepeatcommands; - - PrefEntryButtonHBox _importexport_ocal_url; - PrefEntry _importexport_ocal_username; - PrefEntry _importexport_ocal_password; + UI::Widget::PrefCheckButton _svgoutput_usenamedcolors; + UI::Widget::PrefSpinButton _svgoutput_numericprecision; + UI::Widget::PrefSpinButton _svgoutput_minimumexponent; + UI::Widget::PrefCheckButton _svgoutput_inlineattrs; + UI::Widget::PrefSpinButton _svgoutput_indent; + UI::Widget::PrefCheckButton _svgoutput_allowrelativecoordinates; + UI::Widget::PrefCheckButton _svgoutput_forcerepeatcommands; + + UI::Widget::PrefEntryButtonHBox _importexport_ocal_url; + UI::Widget::PrefEntry _importexport_ocal_username; + UI::Widget::PrefEntry _importexport_ocal_password; int _max_dialog_width; int _max_dialog_height; int _sb_width; - DialogPage* _current_page; + UI::Widget::DialogPage* _current_page; - Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title, int id); - Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent, int id); + Gtk::TreeModel::iterator AddPage(UI::Widget::DialogPage& p, Glib::ustring title, int id); + Gtk::TreeModel::iterator AddPage(UI::Widget::DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent, int id); bool SetMaxDialogSize(const Gtk::TreeModel::iterator& iter); bool PresentPage(const Gtk::TreeModel::iterator& iter); - static void AddSelcueCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value); - static void AddGradientCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value); - static void AddConvertGuidesCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value); - static void AddDotSizeSpinbutton(DialogPage& p, Glib::ustring const &prefs_path, double def_value); - static void AddNewObjectsStyle(DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL); + static void AddSelcueCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value); + static void AddGradientCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value); + static void AddConvertGuidesCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value); + static void AddDotSizeSpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value); + static void AddNewObjectsStyle(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL); void on_pagelist_selection_changed(); void on_reset_open_recent_clicked(); diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h index 7dbb6dd4a..dc01c6a29 100644 --- a/src/ui/dialog/panel-dialog.h +++ b/src/ui/dialog/panel-dialog.h @@ -30,14 +30,14 @@ namespace Dialog { class PanelDialogBase { public: - PanelDialogBase(Panel &panel, char const */*prefs_path*/, int const /*verb_num*/, + PanelDialogBase(UI::Widget::Panel &panel, char const */*prefs_path*/, int const /*verb_num*/, Glib::ustring const &/*apply_label*/) : _panel (panel) { } virtual void present() = 0; virtual ~PanelDialogBase() {} - virtual Panel &getPanel() { return _panel; } + virtual UI::Widget::Panel &getPanel() { return _panel; } protected: static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) { @@ -54,7 +54,7 @@ protected: inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *); inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *); - Panel &_panel; + UI::Widget::Panel &_panel; sigc::connection _document_replaced_connection; }; @@ -62,7 +62,7 @@ template class PanelDialog : public PanelDialogBase, public Inkscape::UI::Dialog::Dialog { public: - PanelDialog(Panel &contents, char const *prefs_path, int const verb_num, + PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num, Glib::ustring const &apply_label); virtual ~PanelDialog() {} @@ -86,7 +86,7 @@ class PanelDialog : public PanelDialogBase, public Inkscape::UI::Dialog::Dialog { public: - inline PanelDialog(Panel &contents, char const *prefs_path, int const verb_num, + inline PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num, Glib::ustring const &apply_label); virtual ~PanelDialog() {} @@ -128,7 +128,7 @@ PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application template -PanelDialog::PanelDialog(Panel &panel, char const *prefs_path, int const verb_num, +PanelDialog::PanelDialog(Widget::Panel &panel, char const *prefs_path, int const verb_num, Glib::ustring const &apply_label) : PanelDialogBase(panel, prefs_path, verb_num, apply_label), Dialog(&B::create, prefs_path, verb_num, apply_label) @@ -163,7 +163,7 @@ template template PanelDialog * PanelDialog::create() { - Panel &panel = P::getInstance(); + UI::Widget::Panel &panel = P::getInstance(); return new PanelDialog(panel, panel.getPrefsPath(), panel.getVerb(), panel.getApplyLabel()); } @@ -171,17 +171,17 @@ template void PanelDialog::present() { - _panel.present(); + _panel.present(); } template void PanelDialog::_presentDialog() { - Dialog::present(); + Dialog::present(); } -PanelDialog::PanelDialog(Panel &panel, char const *prefs_path, +PanelDialog::PanelDialog(UI::Widget::Panel &panel, char const *prefs_path, int const verb_num, Glib::ustring const &apply_label) : PanelDialogBase(panel, prefs_path, verb_num, apply_label), Dialog(&Behavior::FloatingBehavior::create, prefs_path, verb_num, apply_label) @@ -213,7 +213,7 @@ PanelDialog::PanelDialog(Panel &panel, char const *p void PanelDialog::present() -{ +{ Dialog::present(); _panel.present(); } @@ -226,7 +226,7 @@ template PanelDialog * PanelDialog::create() { - Panel &panel = P::getInstance(); + UI::Widget::Panel &panel = P::getInstance(); PanelDialog *instance = new PanelDialog(panel, panel.getPrefsPath(), panel.getVerb(), panel.getApplyLabel()); diff --git a/src/ui/dialog/transformation.h b/src/ui/dialog/transformation.h index 9d05713ad..0607871fd 100644 --- a/src/ui/dialog/transformation.h +++ b/src/ui/dialog/transformation.h @@ -26,8 +26,6 @@ #include "ui/widget/button.h" -using namespace Inkscape::UI::Widget; - namespace Inkscape { @@ -105,36 +103,36 @@ protected: Gtk::Notebook _notebook; - NotebookPage _page_move; - NotebookPage _page_scale; - NotebookPage _page_rotate; - NotebookPage _page_skew; - NotebookPage _page_transform; - - UnitMenu _units_move; - UnitMenu _units_scale; - UnitMenu _units_rotate; - UnitMenu _units_skew; - - ScalarUnit _scalar_move_horizontal; - ScalarUnit _scalar_move_vertical; - ScalarUnit _scalar_scale_horizontal; - ScalarUnit _scalar_scale_vertical; - ScalarUnit _scalar_rotate; - ScalarUnit _scalar_skew_horizontal; - ScalarUnit _scalar_skew_vertical; - - Scalar _scalar_transform_a; - Scalar _scalar_transform_b; - Scalar _scalar_transform_c; - Scalar _scalar_transform_d; - Scalar _scalar_transform_e; - Scalar _scalar_transform_f; - - CheckButton _check_move_relative; - CheckButton _check_scale_proportional; - CheckButton _check_apply_separately; - CheckButton _check_replace_matrix; + UI::Widget::NotebookPage _page_move; + UI::Widget::NotebookPage _page_scale; + UI::Widget::NotebookPage _page_rotate; + UI::Widget::NotebookPage _page_skew; + UI::Widget::NotebookPage _page_transform; + + UI::Widget::UnitMenu _units_move; + UI::Widget::UnitMenu _units_scale; + UI::Widget::UnitMenu _units_rotate; + UI::Widget::UnitMenu _units_skew; + + UI::Widget::ScalarUnit _scalar_move_horizontal; + UI::Widget::ScalarUnit _scalar_move_vertical; + UI::Widget::ScalarUnit _scalar_scale_horizontal; + UI::Widget::ScalarUnit _scalar_scale_vertical; + UI::Widget::ScalarUnit _scalar_rotate; + UI::Widget::ScalarUnit _scalar_skew_horizontal; + UI::Widget::ScalarUnit _scalar_skew_vertical; + + UI::Widget::Scalar _scalar_transform_a; + UI::Widget::Scalar _scalar_transform_b; + UI::Widget::Scalar _scalar_transform_c; + UI::Widget::Scalar _scalar_transform_d; + UI::Widget::Scalar _scalar_transform_e; + UI::Widget::Scalar _scalar_transform_f; + + UI::Widget::CheckButton _check_move_relative; + UI::Widget::CheckButton _check_scale_proportional; + UI::Widget::CheckButton _check_apply_separately; + UI::Widget::CheckButton _check_replace_matrix; /** * Layout the GUI components, and prepare for use -- cgit v1.2.3 From b9ef8969f950ac525cc171dbfdb7684190003db1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 2 Apr 2010 20:11:38 +0200 Subject: Add Ctrl+H as a shortcut for "show handles" in the node tool. Fixed bugs: - https://launchpad.net/bugs/324208 (bzr r9277) --- src/ui/tool/node-tool.cpp | 12 +++++++++++- src/ui/tool/node-tool.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index 443e7f258..b5f420597 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -316,7 +316,8 @@ void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value) Glib::ustring entry_name = value->getEntryName(); if (entry_name == "show_handles") { - nt->_multipath->showHandles(value->getBool(true)); + nt->show_handles = value->getBool(true); + nt->_multipath->showHandles(nt->show_handles); } else if (entry_name == "show_outline") { nt->show_outline = value->getBool(); nt->_multipath->showOutline(nt->show_outline); @@ -491,6 +492,7 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) ink_node_tool_update_tip(nt, event); return TRUE; case GDK_a: + case GDK_A: if (held_control(event->key) && held_alt(event->key)) { nt->_selected_nodes->selectAll(); // Ctrl+A is handled in selection-chemistry.cpp via verb @@ -498,6 +500,14 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) return TRUE; } break; + case GDK_h: + case GDK_H: + if (held_only_control(event->key)) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/tools/nodes/show_handles", !nt->show_handles); + return TRUE; + } + break; default: break; } diff --git a/src/ui/tool/node-tool.h b/src/ui/tool/node-tool.h index baac642ac..641d064c1 100644 --- a/src/ui/tool/node-tool.h +++ b/src/ui/tool/node-tool.h @@ -58,6 +58,7 @@ struct InkNodeTool : public SPEventContext SPItem *_last_over; unsigned cursor_drag : 1; + unsigned show_handles : 1; unsigned show_outline : 1; unsigned live_outline : 1; unsigned live_objects : 1; -- cgit v1.2.3 From 6851867b2f6e0d58d32a564a123e3b3c12458342 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 2 Apr 2010 20:13:21 +0200 Subject: Do not print PYTHONPATH on every invocation (stale debug output) Fixed bugs: - https://launchpad.net/bugs/554109 (bzr r9278) --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 32102f3b3..5aa164df8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -575,7 +575,7 @@ static void set_extensions_env() g_setenv("PYTHONPATH", new_pythonpath, TRUE); g_free(new_pythonpath); - printf("PYTHONPATH = %s\n", g_getenv("PYTHONPATH")); + //printf("PYTHONPATH = %s\n", g_getenv("PYTHONPATH")); } /** -- cgit v1.2.3 From a870a3f925fe2dd16a60f48a956af772988b805b Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 01:47:43 +0200 Subject: Fix command line invocation on Windows (LP #167455). Fixed bugs: - https://launchpad.net/bugs/167455 (bzr r9281) --- src/main.cpp | 21 +-------------------- src/prefix.cpp | 8 ++++---- src/prefix.h | 15 +++++++-------- src/ui/dialog/glyphs.cpp | 4 ++-- src/ui/dialog/glyphs.h | 2 +- 5 files changed, 15 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 5aa164df8..9f7bc9ad3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -593,22 +593,7 @@ main(int argc, char **argv) #endif #ifdef WIN32 - /* - Set the current directory to the directory of the - executable. This seems redundant, but is needed for - when inkscape.exe is executed from another directory. - We use relative paths on win32. - HKCR\svgfile\shell\open\command is a good example - - TODO: this breaks the CLI on Windows, see LP #167455 - */ - const int pathbuf = 2048; - gunichar2 *path = g_new(gunichar2, pathbuf); - GetModuleFileNameW(NULL, (WCHAR*) path, pathbuf); - gchar *inkscape = g_utf16_to_utf8(path, -1, NULL, NULL, NULL); - gchar *exedir = g_path_get_dirname(inkscape); - gunichar2 *dirw = g_utf8_to_utf16(exedir, -1, NULL, NULL, NULL); - SetCurrentDirectoryW((WCHAR*) dirw); + gchar *exedir = g_strdup(win32_getExePath().data()); _win32_set_inkscape_env(exedir); # ifdef ENABLE_NLS @@ -620,11 +605,7 @@ main(int argc, char **argv) g_free(shortexedir); g_free(localepath); # endif - - g_free(path); - g_free(inkscape); g_free(exedir); - g_free(dirw); // Don't touch the registry (works fine without it) for Inkscape Portable gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR"); diff --git a/src/prefix.cpp b/src/prefix.cpp index 8c1dd4f00..92409a7d2 100644 --- a/src/prefix.cpp +++ b/src/prefix.cpp @@ -435,11 +435,11 @@ br_extract_prefix (const char *path) /** * Return the directory of the .exe that is currently running */ -static Glib::ustring win32_getExePath() +Glib::ustring win32_getExePath() { gunichar2 path[2048]; - GetModuleFileNameW(NULL, (WCHAR*) path, 2048); - gchar *exe = g_utf16_to_utf8(path, -1, NULL, NULL, NULL); + GetModuleFileNameW(0, (WCHAR*) path, 2048); + gchar *exe = g_utf16_to_utf8(path, -1, 0,0,0); gchar *dir = g_path_get_dirname(exe); Glib::ustring ret = dir; g_free(dir); @@ -481,7 +481,7 @@ static Glib::ustring win32_getResourcePath(const Glib::ustring &childPath) */ char *win32_relative_path(const char *childPath) { - static char *returnPath = NULL; + static char *returnPath = 0; if (!childPath) childPath = ""; Glib::ustring resourcePath = win32_getResourcePath(childPath); diff --git a/src/prefix.h b/src/prefix.h index 0c2db5b58..af96fa746 100644 --- a/src/prefix.h +++ b/src/prefix.h @@ -114,20 +114,19 @@ char *br_strcat (const char *str1, const char *str2); char *br_extract_dir (const char *path); char *br_extract_prefix(const char *path); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + #ifdef __WIN32__ -/** - * Win32 version of a relocatable function - */ +#include + +Glib::ustring win32_getExePath(); char *win32_relative_path(const char *childPath); #define WIN32_DATADIR(suffix) (win32_relative_path(suffix)) #endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - #endif /* _PREFIX_H_ */ diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 1c875e8cc..bc96b0575 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -159,8 +159,8 @@ GlyphColumns *GlyphsPanel::getColumns() /** * Constructor */ -GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : - Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_GLYPHS, "", false), +GlyphsPanel::GlyphsPanel() : + Inkscape::UI::Widget::Panel("", "/dialogs/glyphs", SP_VERB_DIALOG_GLYPHS, "", false), store(Gtk::ListStore::create(*getColumns())), iconView(0), entry(0), diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index 49ead3d6b..b4876f3c1 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -43,7 +43,7 @@ class GlyphColumns; class GlyphsPanel : public Inkscape::UI::Widget::Panel { public: - GlyphsPanel(gchar const *prefsPath = "/dialogs/glyphs"); + GlyphsPanel(); virtual ~GlyphsPanel(); static GlyphsPanel& getInstance(); -- cgit v1.2.3 From d12b9c9fa87c4fc4f7842e5d6512c4f17298cce7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 03:56:36 +0200 Subject: Initial fix for the inverted coordinate system bug (bzr r9281.1.1) --- src/desktop.cpp | 14 ++++++-------- src/helper/png-write.cpp | 21 +++------------------ src/select-context.cpp | 16 ++++++++-------- src/selection-chemistry.cpp | 6 +++--- src/seltrans-handles.cpp | 24 ++++++++++++------------ src/sp-item.cpp | 6 ++---- src/ui/tool/control-point-selection.cpp | 4 ++-- src/ui/tool/path-manipulator.cpp | 2 +- src/ui/tool/transform-handle-set.cpp | 24 ++++++++++++------------ src/widgets/desktop-widget.cpp | 8 ++++---- 10 files changed, 53 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index 52f172577..c45cf8004 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -158,7 +158,7 @@ SPDesktop::SPDesktop() : _active( false ), _w2d(), _d2w(), - _doc2dt( Geom::Scale(1, -1) ), + _doc2dt( Geom::identity() ), grids_visible( false ) { _d2w.setIdentity(); @@ -272,7 +272,6 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid /* Connect event for page resize */ - _doc2dt[5] = sp_document_height (document); sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -793,8 +792,8 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double int clear = FALSE; if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) { // zoom changed - set new zoom factors - _d2w = Geom::Scale(newscale, -newscale); - _w2d = Geom::Scale(1/newscale, 1/-newscale); + _d2w = Geom::Scale(newscale); + _w2d = Geom::Scale(1/newscale); sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w); clear = TRUE; signal_zoom_changed.emit(_d2w.descrim()); @@ -802,10 +801,10 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double /* Calculate top left corner (in document pixels) */ x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale; - y1 = cy + 0.5 * viewbox.dimensions()[Geom::Y] / newscale; + y0 = cy - 0.5 * viewbox.dimensions()[Geom::Y] / newscale; /* Scroll */ - sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); + sp_canvas_scroll_to (canvas, x0 * newscale - border, y0 * newscale - border, clear); /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ sp_box3d_context_update_lines(event_context); @@ -829,8 +828,7 @@ Geom::Rect SPDesktop::get_display_area() const double const scale = _d2w[0]; - return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale), - Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale)); + return viewbox * (1./scale); } /** diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index b1c135db0..8eb9e27bf 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -424,24 +424,9 @@ sp_export_png_file(SPDocument *doc, gchar const *filename, sp_document_ensure_up_to_date(doc); - /* Calculate translation by transforming to document coordinates (flipping Y)*/ - Geom::Point translation = Geom::Point(-area[Geom::X][0], area[Geom::Y][1] - sp_document_height(doc)); - - /* This calculation is only valid when assumed that (x0,y0)= area.corner(0) and (x1,y1) = area.corner(2) - * 1) a[0] * x0 + a[2] * y1 + a[4] = 0.0 - * 2) a[1] * x0 + a[3] * y1 + a[5] = 0.0 - * 3) a[0] * x1 + a[2] * y1 + a[4] = width - * 4) a[1] * x0 + a[3] * y0 + a[5] = height - * 5) a[1] = 0.0; - * 6) a[2] = 0.0; - * - * (1,3) a[0] * x1 - a[0] * x0 = width - * a[0] = width / (x1 - x0) - * (2,4) a[3] * y0 - a[3] * y1 = height - * a[3] = height / (y0 - y1) - * (1) a[4] = -a[0] * x0 - * (2) a[5] = -a[3] * y1 - */ + /* Calculate translation */ + Geom::Point translation = Geom::Point(-area[Geom::X][0], -area[Geom::Y][0]); + Geom::Matrix const affine(Geom::Translate(translation) * Geom::Scale(width / area.width(), diff --git a/src/select-context.cpp b/src/select-context.cpp index 028c8634b..8500e9084 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -765,12 +765,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__ALT) { // alt - if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*10); // shift - else sp_selection_move_screen(desktop, 0, mul*1); // no shift + if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*-10); // shift + else sp_selection_move_screen(desktop, 0, mul*-1); // no shift } else { // no alt - if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*10*nudge); // shift - else sp_selection_move(desktop, 0, mul*nudge); // no shift + if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*-10*nudge); // shift + else sp_selection_move(desktop, 0, mul*-nudge); // no shift } ret = TRUE; } @@ -799,12 +799,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__ALT) { // alt - if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*-10); // shift - else sp_selection_move_screen(desktop, 0, mul*-1); // no shift + if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*10); // shift + else sp_selection_move_screen(desktop, 0, mul*1); // no shift } else { // no alt - if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*-10*nudge); // shift - else sp_selection_move(desktop, 0, mul*-nudge); // no shift + if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*10*nudge); // shift + else sp_selection_move(desktop, 0, mul*nudge); // no shift } ret = TRUE; } diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 730467ee5..7ac2e5471 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2748,12 +2748,12 @@ sp_selection_create_bitmap_copy(SPDesktop *desktop) Geom::Matrix t; double shift_x = bbox.x0; - double shift_y = bbox.y1; + double shift_y = bbox.y0; if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid shift_x = round(shift_x); - shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone + shift_y = round(shift_y); } - t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse(); + t = Geom::Translate(shift_x, shift_y) * eek.inverse(); // Do the export sp_export_png_file(document, filepath, diff --git a/src/seltrans-handles.cpp b/src/seltrans-handles.cpp index 95b680c5e..ba18b2a5b 100644 --- a/src/seltrans-handles.cpp +++ b/src/seltrans-handles.cpp @@ -5,24 +5,24 @@ SPSelTransHandle const handles_scale[] = { //anchor cursor control action request x y - {GTK_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1}, - {GTK_ANCHOR_S, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1}, - {GTK_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1}, + {GTK_ANCHOR_NE, GDK_TOP_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1}, + {GTK_ANCHOR_N, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1}, + {GTK_ANCHOR_NW, GDK_TOP_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1}, {GTK_ANCHOR_W, GDK_RIGHT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 1, 0.5}, - {GTK_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0}, - {GTK_ANCHOR_N, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0}, - {GTK_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0}, + {GTK_ANCHOR_SW, GDK_BOTTOM_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0}, + {GTK_ANCHOR_S, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0}, + {GTK_ANCHOR_SE, GDK_BOTTOM_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0}, {GTK_ANCHOR_E, GDK_LEFT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0, 0.5} }; SPSelTransHandle const handles_rotate[] = { - {GTK_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1}, - {GTK_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1}, - {GTK_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1}, + {GTK_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1}, + {GTK_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1}, + {GTK_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1}, {GTK_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 7, sp_sel_trans_skew, sp_sel_trans_skew_request, 1, 0.5}, - {GTK_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0}, - {GTK_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0}, - {GTK_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0}, + {GTK_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0}, + {GTK_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0}, + {GTK_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0}, {GTK_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, sp_sel_trans_skew, sp_sel_trans_skew_request, 0, 0.5} }; diff --git a/src/sp-item.cpp b/src/sp-item.cpp index c4411e47d..f60a2b27a 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -1574,8 +1574,7 @@ Geom::Matrix sp_item_i2d_affine(SPItem const *item) g_assert(SP_IS_ITEM(item)); Geom::Matrix const ret( sp_item_i2doc_affine(item) - * Geom::Scale(1, -1) - * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); + ); return ret; } @@ -1588,8 +1587,7 @@ void sp_item_set_i2d_affine(SPItem *item, Geom::Matrix const &i2dt) if (SP_OBJECT_PARENT(item)) { dt2p = sp_item_i2d_affine((SPItem *) SP_OBJECT_PARENT(item)).inverse(); } else { - dt2p = ( Geom::Translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) - * Geom::Scale(1, -1) ); + dt2p = ( Geom::identity() ); } Geom::Matrix const i2p( i2dt * dt2p ); diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index f880d2ddf..dfbf1170a 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -545,11 +545,11 @@ bool ControlPointSelection::event(GdkEvent *event) case GDK_Up: case GDK_KP_Up: case GDK_KP_8: - return _keyboardMove(event->key, Geom::Point(0, 1)); + return _keyboardMove(event->key, Geom::Point(0, -1)); case GDK_Down: case GDK_KP_Down: case GDK_KP_2: - return _keyboardMove(event->key, Geom::Point(0, -1)); + return _keyboardMove(event->key, Geom::Point(0, 1)); case GDK_Right: case GDK_KP_Right: case GDK_KP_6: diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 66f72f379..a50be873a 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -1193,7 +1193,7 @@ void PathManipulator::_updateOutline() Geom::Point at = j->pointAt(0.5); Geom::Point ut = j->unitTangentAt(0.5); // rotate the point - ut *= Geom::Rotate(150.0 / 180.0 * M_PI); + ut *= Geom::Rotate(210.0 / 180.0 * M_PI); Geom::Point arrow_end = _desktop->w2d( _desktop->d2w(at) + Geom::unit_vector(_desktop->d2w(ut)) * 10.0); diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 1af848b96..4cbc5ed4d 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -34,17 +34,17 @@ namespace UI { namespace { Gtk::AnchorType corner_to_anchor(unsigned c) { switch (c % 4) { - case 0: return Gtk::ANCHOR_NE; - case 1: return Gtk::ANCHOR_NW; - case 2: return Gtk::ANCHOR_SW; - default: return Gtk::ANCHOR_SE; + case 0: return Gtk::ANCHOR_SE; + case 1: return Gtk::ANCHOR_SW; + case 2: return Gtk::ANCHOR_NW; + default: return Gtk::ANCHOR_NE; } } Gtk::AnchorType side_to_anchor(unsigned s) { switch (s % 4) { - case 0: return Gtk::ANCHOR_N; + case 0: return Gtk::ANCHOR_S; case 1: return Gtk::ANCHOR_W; - case 2: return Gtk::ANCHOR_S; + case 2: return Gtk::ANCHOR_N; default: return Gtk::ANCHOR_E; } } @@ -208,8 +208,8 @@ private: static Glib::RefPtr _corner_to_pixbuf(unsigned c) { sp_select_context_get_type(); switch (c % 2) { - case 0: return Glib::wrap(handles[1], true); - default: return Glib::wrap(handles[0], true); + case 0: return Glib::wrap(handles[0], true); + default: return Glib::wrap(handles[1], true); } } Geom::Point _sc_center; @@ -332,10 +332,10 @@ private: static Glib::RefPtr _corner_to_pixbuf(unsigned c) { sp_select_context_get_type(); switch (c % 4) { - case 0: return Glib::wrap(handles[10], true); - case 1: return Glib::wrap(handles[8], true); - case 2: return Glib::wrap(handles[6], true); - default: return Glib::wrap(handles[4], true); + case 0: return Glib::wrap(handles[4], true); + case 1: return Glib::wrap(handles[6], true); + case 2: return Glib::wrap(handles[8], true); + default: return Glib::wrap(handles[10], true); } } Geom::Point _rot_center; diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index ab440595f..48317aa3e 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1493,8 +1493,8 @@ sp_desktop_widget_update_vruler (SPDesktopWidget *dtw) NR::IRect viewbox = dtw->canvas->getViewboxIntegers(); double const scale = dtw->desktop->current_zoom(); - double s = viewbox.min()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; - double e = viewbox.max()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; + double s = viewbox.min()[Geom::Y] / scale - dtw->ruler_origin[Geom::Y]; + double e = viewbox.max()[Geom::Y] / scale - dtw->ruler_origin[Geom::Y]; gtk_ruler_set_range(GTK_RULER(dtw->vruler), s, e, GTK_RULER(dtw->vruler)->position, (e - s)); } @@ -1809,8 +1809,8 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) Geom::OptRect deskarea = Geom::unify(darea, sp_item_bbox_desktop(item)); /* Canvas region we always show unconditionally */ - Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64), - Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) ); + Geom::Rect carea( Geom::Point(deskarea->left() * scale - 64, deskarea->top() * scale - 64), + Geom::Point(deskarea->right() * scale + 64, deskarea->bottom() * scale + 64) ); Geom::Rect viewbox = dtw->canvas->getViewbox(); -- cgit v1.2.3 From 078d8b361e3b5c390a5f1b49986b7347f8003d67 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 04:24:37 +0200 Subject: Fix rotation in node and select tool (bzr r9281.1.2) --- src/select-context.cpp | 8 ++++---- src/ui/tool/control-point-selection.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/select-context.cpp b/src/select-context.cpp index 8500e9084..9035021d6 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -842,9 +842,9 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) get_group0_keyval(&event->key), 0); // with any mask sp_selection_rotate_screen(selection, mul*1); } else if (MOD__CTRL) { - sp_selection_rotate(selection, 90); + sp_selection_rotate(selection, -90); } else if (snaps) { - sp_selection_rotate(selection, 180/snaps); + sp_selection_rotate(selection, -180/snaps); } ret = TRUE; break; @@ -854,9 +854,9 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) get_group0_keyval(&event->key), 0); // with any mask sp_selection_rotate_screen(selection, -1*mul); } else if (MOD__CTRL) { - sp_selection_rotate(selection, -90); + sp_selection_rotate(selection, 90); } else if (snaps) { - sp_selection_rotate(selection, -180/snaps); + sp_selection_rotate(selection, 180/snaps); } ret = TRUE; break; diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index dfbf1170a..c7fc8a3cc 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -561,9 +561,9 @@ bool ControlPointSelection::event(GdkEvent *event) // rotates case GDK_bracketleft: - return _keyboardRotate(event->key, 1); - case GDK_bracketright: return _keyboardRotate(event->key, -1); + case GDK_bracketright: + return _keyboardRotate(event->key, 1); // scaling case GDK_less: -- cgit v1.2.3 From 726ae9f136c9cc3ee212af2594ab9991716e5389 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 04:24:54 +0200 Subject: Fix align & distribute dialog (bzr r9281.1.3) --- src/ui/dialog/align-and-distribute.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index a75a8d68d..f27c49f61 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -252,11 +252,11 @@ ActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = { {.5, .5, 0., 0., .5, .5, 0., 0.}, {0., 1., 0., 0., 0., 1., 0., 0.}, {0., 1., 0., 0., 1., 0., 0., 0.}, - {0., 0., 0., 1., 0., 0., 1., 0.}, - {0., 0., 0., 1., 0., 0., 0., 1.}, - {0., 0., .5, .5, 0., 0., .5, .5}, + {0., 0., 1., 0., 0., 0., 0., 1.}, {0., 0., 1., 0., 0., 0., 1., 0.}, - {0., 0., 1., 0., 0., 0., 0., 1.} + {0., 0., .5, .5, 0., 0., .5, .5}, + {0., 0., 0., 1., 0., 0., 0., 1.}, + {0., 0., 0., 1., 0., 0., 1., 0.} }; BBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) : @@ -866,13 +866,13 @@ AlignAndDistribute::AlignAndDistribute() addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_TOP, _("Distribute top edges equidistantly"), - 1, 1, false, Geom::Y, 0, 1); + 1, 1, false, Geom::Y, 1., 0.); addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_CENTER, _("Distribute centers equidistantly vertically"), 1, 2, false, Geom::Y, .5, .5); addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_BOTTOM, _("Distribute bottom edges equidistantly"), - 1, 3, false, Geom::Y, 1., 0.); + 1, 3, false, Geom::Y, 0., 1.); //Baseline distribs addBaselineButton(INKSCAPE_ICON_DISTRIBUTE_HORIZONTAL_BASELINE, -- cgit v1.2.3 From 60e01e694ad379737b6ef436b8973e67871979b1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 05:05:19 +0200 Subject: Fix single-handle keybindings (bzr r9281.1.4) --- src/ui/tool/multi-path-manipulator.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 2025a12d7..392518207 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -470,12 +470,10 @@ bool MultiPathManipulator::event(GdkEvent *event) // single handle functions // rotation case GDK_bracketleft: - case GDK_braceleft: - pm.rotateHandle(n, which, 1, one_pixel); + pm.rotateHandle(n, which, -1, one_pixel); break; case GDK_bracketright: - case GDK_braceright: - pm.rotateHandle(n, which, -1, one_pixel); + pm.rotateHandle(n, which, 1, one_pixel); break; // adjust length case GDK_period: -- cgit v1.2.3 From b6598056bef518e40e03bc463e3965e8ffca4dd2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 05:05:38 +0200 Subject: Fix spray tool (bzr r9281.1.5) --- src/spray-context.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 2bdac197f..9b9caee15 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -501,7 +501,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); //Move the cursor p Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); did = true; } } @@ -556,7 +556,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale)); sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale)); sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); // union and duplication selection->clear(); @@ -593,7 +593,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale)); sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); Inkscape::GC::release(clone); -- cgit v1.2.3 From 331723c687c97a0a6d886a80b0bd2f5d7dbfb953 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 05:25:05 +0200 Subject: Fix tweak and paint bucket tools (bzr r9281.1.6) --- src/flood-context.cpp | 4 ++-- src/tweak-context.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/flood-context.cpp b/src/flood-context.cpp index 612ae1cfc..910b5dd80 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -798,7 +798,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even unsigned int height = (int)ceil(screen.height() * zoom_scale * padding); Geom::Point origin(screen.min()[Geom::X], - sp_document_height(document) - screen.height() - screen.min()[Geom::Y]); + screen.min()[Geom::Y]); origin[Geom::X] = origin[Geom::X] + (screen.width() * ((1 - padding) / 2)); origin[Geom::Y] = origin[Geom::Y] + (screen.height() * ((1 - padding) / 2)); @@ -905,7 +905,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even } for (unsigned int i = 0; i < fill_points.size(); i++) { - Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, sp_document_height(document) + (fill_points[i][Geom::Y] / zoom_scale)) * affine; + Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, (fill_points[i][Geom::Y] / zoom_scale)) * affine; pw[Geom::X] = (int)MIN(width - 1, MAX(0, pw[Geom::X])); pw[Geom::Y] = (int)MIN(height - 1, MAX(0, pw[Geom::Y])); diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 13299b5a4..a34a61f53 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -448,7 +448,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * vector; - sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); did = true; } } @@ -462,7 +462,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * (reverse? (a->midpoint() - p) : (p - a->midpoint())); - sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); did = true; } } @@ -477,7 +477,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * Geom::Point(cos(dp)*dr, sin(dp)*dr); - sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); did = true; } } @@ -502,7 +502,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { - double angle = (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; + double angle = (reverse? -force : force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; sp_item_rotate_rel(item, Geom::Rotate(angle)); did = true; } -- cgit v1.2.3 From 3711eca2865718dca833c2d1ed84c44c513dcd28 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Apr 2010 23:08:32 -0700 Subject: Split dynamic desktop tracking into common, shared code. (bzr r9282) --- src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/desktop-tracker.cpp | 159 ++++++++++++++++++++++++++++++++++++++ src/ui/dialog/desktop-tracker.h | 73 +++++++++++++++++ src/ui/dialog/fill-and-stroke.cpp | 58 ++++---------- src/ui/dialog/fill-and-stroke.h | 11 +-- src/ui/dialog/glyphs.cpp | 22 +++++- src/ui/dialog/glyphs.h | 9 ++- 7 files changed, 284 insertions(+), 50 deletions(-) create mode 100644 src/ui/dialog/desktop-tracker.cpp create mode 100644 src/ui/dialog/desktop-tracker.h (limited to 'src') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 7546bc195..da9be1e7c 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -22,6 +22,8 @@ ink_common_sources += \ ui/dialog/color-item.h \ ui/dialog/debug.cpp \ ui/dialog/debug.h \ + ui/dialog/desktop-tracker.cpp \ + ui/dialog/desktop-tracker.h \ ui/dialog/dialog.cpp \ ui/dialog/dialog.h \ ui/dialog/dialog-manager.cpp \ diff --git a/src/ui/dialog/desktop-tracker.cpp b/src/ui/dialog/desktop-tracker.cpp new file mode 100644 index 000000000..f527f1c05 --- /dev/null +++ b/src/ui/dialog/desktop-tracker.cpp @@ -0,0 +1,159 @@ +/** + * Glyph selector dialog. + */ + +/* Authors: + * Jon A. Cruz + * + * Copyright (C) 2010 Jon A. Cruz + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include + +#include "desktop-tracker.h" + +#include "inkscape.h" +#include "desktop.h" +#include "widgets/desktop-widget.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +DesktopTracker::DesktopTracker() : + base(0), + desktop(0), + widget(0), + hierID(0), + inkID(0), + trackActive(false), + desktopChangedSig() +{ +} + +DesktopTracker::~DesktopTracker() +{ + disconnect(); +} + +void DesktopTracker::connect(GtkWidget *widget) +{ + disconnect(); + + this->widget = widget; + + // Use C/gobject callbacks to avoid gtkmm rewrap-during-destruct issues: + hierID = g_signal_connect( G_OBJECT(widget), "hierarchy-changed", G_CALLBACK(hierarchyChangeCB), this ); + inkID = g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(activateDesktopCB), this ); + + GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); + if (wdgt && !base) { + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); + if (dtw && dtw->desktop) { + setBase(dtw->desktop); // may also set desktop + } + } +} + +void DesktopTracker::disconnect() +{ + if (hierID) { + if (widget) { + g_signal_handler_disconnect(G_OBJECT(widget), hierID); + } + hierID = 0; + } + if (inkID) { + if (INKSCAPE) { + g_signal_handler_disconnect(G_OBJECT(INKSCAPE), inkID); + } + inkID = 0; + } +} + +void DesktopTracker::setBase(SPDesktop *desktop) +{ + if (this->base != desktop) { + base = desktop; + // Do not override an existing target desktop + if (!this->desktop) { + setDesktop(desktop); + } + } +} + +SPDesktop *DesktopTracker::getBase() const +{ + return base; +} + +SPDesktop *DesktopTracker::getDesktop() const +{ + return desktop; +} + +sigc::connection DesktopTracker::connectDesktopChanged( const sigc::slot & slot ) +{ + return desktopChangedSig.connect(slot); +} + +gboolean DesktopTracker::activateDesktopCB(Inkscape::Application */*inkscape*/, SPDesktop *desktop, DesktopTracker *self ) +{ + if (self && self->trackActive) { + self->setDesktop(desktop); + } + return FALSE; +} + +bool DesktopTracker::hierarchyChangeCB(GtkWidget * /*widget*/, GtkWidget* /*prev*/, DesktopTracker *self) +{ + if (self) { + self->handleHierarchyChange(); + } + return false; +} + +void DesktopTracker::handleHierarchyChange() +{ + GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); + bool newFlag = (wdgt == 0); // true means not in an SPDesktopWidget, thus floating. + if (wdgt && !base) { + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); + if (dtw && dtw->desktop) { + setBase(dtw->desktop); // may also set desktop + } + } + if (newFlag != trackActive) { + trackActive = newFlag; + if (trackActive) { + setDesktop(SP_ACTIVE_DESKTOP); + } else if (desktop != base) { + setDesktop(getBase()); + } + } +} + +void DesktopTracker::setDesktop(SPDesktop *desktop) +{ + if (desktop != this->desktop) { + this->desktop = desktop; + desktopChangedSig.emit(desktop); + } +} + + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h new file mode 100644 index 000000000..7a5bc39c2 --- /dev/null +++ b/src/ui/dialog/desktop-tracker.h @@ -0,0 +1,73 @@ +/** + * Glyph selector dialog. + */ + +/* Authors: + * Jon A. Cruz + * + * Copyright (C) 2010 Jon A. Cruz + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifndef SEEN_DIALOG_DESKTOP_TRACKER +#define SEEN_DIALOG_DESKTOP_TRACKER + +#include +#include + +typedef struct _GtkWidget GtkWidget; +class SPDesktop; + +namespace Inkscape { + +class Application; + +namespace UI { +namespace Dialog { + +class DesktopTracker +{ +public: + DesktopTracker(); + virtual ~DesktopTracker(); + + void connect(GtkWidget *widget); + void disconnect(); + + SPDesktop *getDesktop() const; + + void setBase(SPDesktop *desktop); + SPDesktop *getBase() const; + + sigc::connection connectDesktopChanged( const sigc::slot & slot ); + +private: + static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, DesktopTracker *self ); + static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, DesktopTracker *self); + + void handleHierarchyChange(); + void setDesktop(SPDesktop *desktop); + + SPDesktop *base; + SPDesktop *desktop; + GtkWidget *widget; + gulong hierID; + gulong inkID; + bool trackActive; + sigc::signal desktopChangedSig; +}; + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // SEEN_DIALOG_DESKTOP_TRACKER +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 6ee076a94..8c86e1ca4 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -43,11 +43,11 @@ FillAndStroke::FillAndStroke() _page_stroke_paint(1, 1, true, true), _page_stroke_style(1, 1, true, true), _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", UI::Widget::SimpleFilterModifier::BLUR), - hierID(0), - trackActive(false), + deskTrack(), targetDesktop(0), fillWdgt(0), - strokeWdgt(0) + strokeWdgt(0), + desktopChangeConn() { Gtk::Box *contents = _getContents(); contents->set_spacing(0); @@ -68,59 +68,35 @@ FillAndStroke::FillAndStroke() _composite_settings.setSubject(&_subject); - // Use C/gobject callbacks to avoid gtkmm rewrap-during-destruct issues: - hierID = g_signal_connect( G_OBJECT(gobj()), "hierarchy-changed", G_CALLBACK(hierarchyChangeCB), this ); - - g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( activateDesktopCB ), this ); + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &FillAndStroke::setTargetDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); } FillAndStroke::~FillAndStroke() { _composite_settings.setSubject(NULL); - if (hierID) { - g_signal_handler_disconnect(G_OBJECT(gobj()), hierID); - hierID = 0; - } -} -gboolean FillAndStroke::activateDesktopCB(Inkscape::Application */*inkscape*/, SPDesktop *desktop, FillAndStroke *self ) -{ - if (self && self->trackActive) { - self->setTargetDesktop(desktop); - } - return FALSE; -} - -bool FillAndStroke::hierarchyChangeCB(GtkWidget *widget, GtkWidget* /*prev*/, FillAndStroke *self) -{ - if (self) { - GtkWidget *ww = gtk_widget_get_ancestor(widget, SP_TYPE_VIEW_WIDGET); - bool newFlag = (ww == 0); - if (newFlag != self->trackActive) { - self->trackActive = newFlag; - if (self->trackActive) { - self->setTargetDesktop(SP_ACTIVE_DESKTOP); - } else { - self->setTargetDesktop(self->getDesktop()); - } - } - } - return false; + desktopChangeConn.disconnect(); + deskTrack.disconnect(); } void FillAndStroke::setDesktop(SPDesktop *desktop) { Panel::setDesktop(desktop); - setTargetDesktop(desktop); + deskTrack.setBase(desktop); } void FillAndStroke::setTargetDesktop(SPDesktop *desktop) { - if (fillWdgt) { - sp_fill_style_widget_set_desktop(fillWdgt, desktop); - } - if (strokeWdgt) { - sp_stroke_style_widget_set_desktop(strokeWdgt, desktop); + if (targetDesktop != desktop) { + targetDesktop = desktop; + if (fillWdgt) { + sp_fill_style_widget_set_desktop(fillWdgt, desktop); + } + if (strokeWdgt) { + sp_stroke_style_widget_set_desktop(strokeWdgt, desktop); + } } } diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index a5fe4906a..2d4e90d73 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -25,6 +25,7 @@ #include "ui/widget/panel.h" #include "ui/widget/notebook-page.h" #include "ui/widget/object-composite-settings.h" +#include "ui/dialog/desktop-tracker.h" namespace Inkscape { namespace UI { @@ -40,9 +41,6 @@ public: virtual void setDesktop(SPDesktop *desktop); - // temporary work-around until panel dialog itself tracks 'focus' properly. - virtual void setTargetDesktop(SPDesktop *desktop); - void selectionChanged(Inkscape::Application *inkscape, Inkscape::Selection *selection); @@ -71,14 +69,13 @@ private: FillAndStroke(FillAndStroke const &d); FillAndStroke& operator=(FillAndStroke const &d); - static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, FillAndStroke *self ); - static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, FillAndStroke *self); + void setTargetDesktop(SPDesktop *desktop); - gulong hierID; - bool trackActive; + DesktopTracker deskTrack; SPDesktop *targetDesktop; Gtk::Widget *fillWdgt; Gtk::Widget *strokeWdgt; + sigc::connection desktopChangeConn; }; } // namespace Dialog diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index bc96b0575..c099b0718 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -32,7 +32,7 @@ namespace Inkscape { namespace UI { -namespace Dialogs { +namespace Dialog { GlyphsPanel &GlyphsPanel::getInstance() @@ -169,6 +169,8 @@ GlyphsPanel::GlyphsPanel() : scriptCombo(0), #endif // GLIB_CHECK_VERSION(2,14,0) fsel(0), + targetDesktop(0), + deskTrack(), iconActiveConn(), iconSelectConn(), scriptSelectConn() @@ -279,6 +281,10 @@ GlyphsPanel::GlyphsPanel() : show_all_children(); restorePanelPrefs(); + + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &GlyphsPanel::setTargetDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); } GlyphsPanel::~GlyphsPanel() @@ -286,8 +292,22 @@ GlyphsPanel::~GlyphsPanel() iconActiveConn.disconnect(); iconSelectConn.disconnect(); scriptSelectConn.disconnect(); + desktopChangeConn.disconnect(); +} + + +void GlyphsPanel::setDesktop(SPDesktop *desktop) +{ + Panel::setDesktop(desktop); + deskTrack.setBase(desktop); } +void GlyphsPanel::setTargetDesktop(SPDesktop *desktop) +{ + if (targetDesktop != desktop) { + targetDesktop = desktop; + } +} void GlyphsPanel::glyphActivated(Gtk::TreeModel::Path const & path) { diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index b4876f3c1..e41472e24 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -13,6 +13,7 @@ #include #include "ui/widget/panel.h" +#include "ui/dialog/desktop-tracker.h" namespace Gtk { @@ -32,7 +33,7 @@ namespace UI { class PreviewHolder; -namespace Dialogs { +namespace Dialog { class GlyphColumns; @@ -48,6 +49,8 @@ public: static GlyphsPanel& getInstance(); + virtual void setDesktop(SPDesktop *desktop); + protected: private: @@ -62,6 +65,7 @@ private: void glyphActivated(Gtk::TreeModel::Path const & path); void glyphSelectionChanged(); + void setTargetDesktop(SPDesktop *desktop); Glib::RefPtr store; @@ -72,9 +76,12 @@ private: Gtk::ComboBoxText *scriptCombo; #endif //GLIB_CHECK_VERSION(2,14,0) SPFontSelector *fsel; + SPDesktop *targetDesktop; + DesktopTracker deskTrack; sigc::connection iconActiveConn; sigc::connection iconSelectConn; sigc::connection scriptSelectConn; + sigc::connection desktopChangeConn; }; -- cgit v1.2.3 From 241ef69dd6570a569fdd72c4df0cf50c1a9b1a69 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Apr 2010 23:18:15 -0700 Subject: Repair arbitrary change lumped in with Win32 fixes of #9281. (bzr r9283) --- src/ui/dialog/glyphs.cpp | 4 ++-- src/ui/dialog/glyphs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index c099b0718..6cced05c5 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -159,8 +159,8 @@ GlyphColumns *GlyphsPanel::getColumns() /** * Constructor */ -GlyphsPanel::GlyphsPanel() : - Inkscape::UI::Widget::Panel("", "/dialogs/glyphs", SP_VERB_DIALOG_GLYPHS, "", false), +GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_GLYPHS, "", false), store(Gtk::ListStore::create(*getColumns())), iconView(0), entry(0), diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index e41472e24..ffd5757b0 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -44,7 +44,7 @@ class GlyphColumns; class GlyphsPanel : public Inkscape::UI::Widget::Panel { public: - GlyphsPanel(); + GlyphsPanel(gchar const *prefsPath = "/dialogs/glyphs"); virtual ~GlyphsPanel(); static GlyphsPanel& getInstance(); -- cgit v1.2.3 From 9d2728f0f7188a0de2df79398d5b68f7071f02f1 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Apr 2010 01:07:41 -0700 Subject: Start with glyphs limited to "Common" as a short term mitigation for bug #553911. Fixed bugs: - https://launchpad.net/bugs/553911 (bzr r9284) --- src/ui/dialog/glyphs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 6cced05c5..8677bcda2 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -210,7 +210,7 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : scriptCombo->append_text(it->second); } - scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]); + scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_COMMON]); // default to a smaller set scriptSelectConn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); table->attach( *Gtk::manage(scriptCombo), @@ -366,7 +366,7 @@ void GlyphsPanel::rebuild() //double sp_font_selector_get_size (SPFontSelector *fsel); #if GLIB_CHECK_VERSION(2,14,0) - GUnicodeScript script = G_UNICODE_SCRIPT_INVALID_CODE; + GUnicodeScript script = G_UNICODE_SCRIPT_COMMON; Glib::ustring scriptName = scriptCombo->get_active_text(); std::map items = getScriptToName(); for (std::map::iterator it = items.begin(); it != items.end(); ++it) { -- cgit v1.2.3 From 66cf0e990e566d1324370fe9b68db0e63cee97ab Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Apr 2010 02:28:11 -0700 Subject: Disconnect Glyphs UI while updating the model. 5X+ performance boost on CJK fonts. Partially fixes bug #553911. Fixed bugs: - https://launchpad.net/bugs/553911 (bzr r9286) --- src/ui/dialog/glyphs.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 8677bcda2..133cf01ea 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -377,6 +377,10 @@ void GlyphsPanel::rebuild() } #endif // GLIB_CHECK_VERSION(2,14,0) + // Disconnect the model while we update it. Simple work-around for 5x+ performance boost. + Glib::RefPtr tmp = Gtk::ListStore::create(*getColumns()); + iconView->set_model(tmp); + std::vector present; for (gunichar ch = 1; ch < 65535; ch++) { int glyphId = font->MapUnicodeChar(ch); @@ -401,6 +405,9 @@ void GlyphsPanel::rebuild() (*row)[columns->code] = *it; (*row)[columns->name] = tmp; } + + // Reconnect the model once it has been updated: + iconView->set_model(store); } } -- cgit v1.2.3 From c2b0be4faa9e98c00ecce70c4aeb8e2fe1afdb2b Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 14:47:02 +0200 Subject: Fix behavior when loading a document (bzr r9281.1.7) --- src/desktop.cpp | 1 - src/helper/pixbuf-ops.cpp | 2 +- src/selection-chemistry.cpp | 8 +++----- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index c45cf8004..1953ae2a6 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1543,7 +1543,6 @@ SPDesktop::onDocumentURISet (gchar const* uri) void SPDesktop::onDocumentResized (gdouble width, gdouble height) { - _doc2dt[5] = height; sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); Geom::Rect const a(Geom::Point(0, 0), Geom::Point(width, height)); SP_CTRLRECT(page)->setRectangle(a); diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index 3be63aa68..c26d55b8b 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -113,7 +113,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, double padding = 1.0; Geom::Point origin(screen.min()[Geom::X], - sp_document_height(doc) - screen[Geom::Y].extent() - screen.min()[Geom::Y]); + screen.min()[Geom::Y]); origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2)); origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2)); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 7ac2e5471..452a4ff9d 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2273,9 +2273,8 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - *c; - move_p[Geom::Y] = -move_p[Geom::Y]; - Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); + Geom::Point move_p = -*c; + Geom::Matrix move = Geom::Translate(move_p); GSList *items = g_slist_copy((GSList *) selection->itemList()); @@ -2396,8 +2395,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); - move_p[Geom::Y] = -move_p[Geom::Y]; + Geom::Point move_p = -(r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); GSList *items = g_slist_copy((GSList *) selection->itemList()); -- cgit v1.2.3 From ed4a746f67bc196ee240fa68f58359501455f45d Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Sat, 3 Apr 2010 16:21:28 +0200 Subject: A few small fixes/clarifications for Gaussian blur. (bzr r9287) --- src/display/nr-filter-gaussian.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index d80782d20..9509eaef7 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -345,7 +345,7 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2, // Filters over 1st dimension // Assumes kernel is symmetric -// scr_len should be size of kernel - 1 +// Kernel should have scr_len+1 elements template static void filter2D_FIR(PT *const dst, int const dstr1, int const dstr2, @@ -377,7 +377,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2, for ( int c1 = 0 ; c1 < n1 ; c1++ ) { int const src_disp = src_line + c1 * sstr1; - int const dst_disp = dst_line + c1 * sstr1; + int const dst_disp = dst_line + c1 * dstr1; // update history for(int i=scr_len; i>0; i--) copy_n(history[i-1], PC, history[i]); @@ -433,7 +433,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2, // optimization: if there was no variation within this point's neighborhood, // skip ahead while we keep seeing the same last_in byte: // blurring flat color would not change it anyway - if (different_count <= 1) { + if (different_count <= 1) { // note that different_count is at least 1, because last_in is initialized to -1 int pos = c1 + 1; int nb_src_disp = src_disp + (1+scr_len)*sstr1 + byte; // src_line + (pos+scr_len) * sstr1 + byte int nb_dst_disp = dst_disp + (1) *dstr1 + byte; // dst_line + (pos) * sstr1 + byte @@ -441,7 +441,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2, dst[nb_dst_disp] = last_in; pos++; nb_src_disp += sstr1; - nb_dst_disp += sstr1; + nb_dst_disp += dstr1; } skipbuf[byte] = pos; } @@ -645,6 +645,8 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) } } } + + // Resampling (if necessary), goes from in -> out (setting ssin to out if used) NRPixBlock *ssin = in; if ( resampling ) { ssin = out; @@ -667,6 +669,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) }; } + // Horizontal filtering, goes from ssin -> out (ssin might be equal to out, but these algorithms can be used in-place) if (use_IIR_x) { // Filter variables IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point) @@ -702,9 +705,9 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) default: assert(false); }; - } else if ( scr_len_x > 1 ) { // !use_IIR_x + } else if ( scr_len_x > 0 ) { // !use_IIR_x // Filter kernel for x direction - FIRValue kernel[scr_len_x]; + FIRValue kernel[scr_len_x+1]; _make_kernel(kernel, deviation_x); // Filter (x) @@ -728,6 +731,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) nr_blit_pixblock_pixblock(out, ssin); } + // Vertical filtering, goes from out -> out if (use_IIR_y) { // Filter variables IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point) @@ -763,9 +767,9 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) default: assert(false); }; - } else if ( scr_len_y > 1 ) { // !use_IIR_y + } else if ( scr_len_y > 0 ) { // !use_IIR_y // Filter kernel for y direction - FIRValue kernel[scr_len_y]; + FIRValue kernel[scr_len_y+1]; _make_kernel(kernel, deviation_y); // Filter (y) @@ -791,6 +795,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) delete[] tmpdata[i]; // deleting a nullptr has no effect, so this is safe } + // Upsampling, stores (the upsampled) out using slot.set(_output, ...) if ( !resampling ) { // No upsampling needed out->empty = FALSE; @@ -835,6 +840,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) slot.set(_output, finalout); } + // If we downsampled the input, clean up the downsampled data if (in != original_in) nr_pixblock_free(in); return 0; -- cgit v1.2.3 From b94b072224b78998569f077fb57a3a02dc752a18 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 18:21:48 +0200 Subject: Fix canvas resize (bzr r9281.1.8) --- src/document.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index 101c54e30..f137ba60d 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -662,7 +662,6 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double const w = rect.width(); double const h = rect.height(); - double const old_height = sp_document_height(this); SPUnit const &px(sp_unit_get_by_id(SP_UNIT_PX)); /* in px */ @@ -696,16 +695,14 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) } Geom::Rect const rect_with_margins( - rect.min() - Geom::Point(margin_left, margin_bottom), - rect.max() + Geom::Point(margin_right, margin_top)); + rect.min() - Geom::Point(margin_left, margin_top), + rect.max() + Geom::Point(margin_right, margin_bottom)); sp_document_set_width(this, rect_with_margins.width(), &px); sp_document_set_height(this, rect_with_margins.height(), &px); - Geom::Translate const tr( - Geom::Point(0, old_height - rect_with_margins.height()) - - to_2geom(rect_with_margins.min())); + Geom::Translate const tr(-to_2geom(rect_with_margins.min())); SP_GROUP(root)->translateChildItems(tr); if(nv) { @@ -713,7 +710,7 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) nv->translateGuides(tr2); // update the viewport so the drawing appears to stay where it was - nv->scrollAllDesktops(-tr2[0], tr2[1], false); + nv->scrollAllDesktops(-tr2[0], -tr2[1], false); } } -- cgit v1.2.3 From e296b61aafbdf6404a394781aedda3235a45d8b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 18:22:32 +0200 Subject: Fix pattern knotholder (bzr r9281.1.9) --- src/knot-holder-entity.cpp | 129 ++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 2d0d5eb02..6fcb26247 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -135,21 +135,16 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: /* TODO: this pattern manipulation is not able to handle general transformation matrices. Only matrices that are the result of a pure scale times a pure rotation. */ -static gdouble sp_pattern_extract_theta(SPPattern *pat) +Geom::Point +PatternKnotHolderEntityXY::knot_get() { - Geom::Matrix transf = pat->patternTransform; - return Geom::atan2(transf.xAxis()); -} + SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); -static Geom::Point sp_pattern_extract_scale(SPPattern *pat) -{ - Geom::Matrix transf = pat->patternTransform; - return Geom::Point( transf.expansionX(), transf.expansionY() ); -} + gdouble x = 0; + gdouble y = -pattern_height(pat); -static Geom::Point sp_pattern_extract_trans(SPPattern const *pat) -{ - return Geom::Point(pat->patternTransform[4], pat->patternTransform[5]); + Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; + return delta; } void @@ -169,32 +164,23 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori } if (state) { - Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat); + Geom::Point knot_relpos(0, -pattern_height(pat)); + Geom::Point const q = p_snapped - (knot_relpos * pat->patternTransform); sp_item_adjust_pattern(item, Geom::Matrix(Geom::Translate(q))); } item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -Geom::Point -PatternKnotHolderEntityXY::knot_get() -{ - SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - return sp_pattern_extract_trans(pat); -} - Geom::Point PatternKnotHolderEntityAngle::knot_get() { SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - gdouble x = (pattern_width(pat)); - gdouble y = 0; - Geom::Point delta = Geom::Point(x,y); - Geom::Point scale = sp_pattern_extract_scale(pat); - gdouble theta = sp_pattern_extract_theta(pat); - delta = delta * Geom::Matrix(Geom::Scale(scale))*Geom::Matrix(Geom::Rotate(theta)); - delta = delta + sp_pattern_extract_trans(pat); + gdouble x = pattern_width(pat); + gdouble y = -pattern_height(pat); + + Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; return delta; } @@ -206,24 +192,38 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const & SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - // get the angle from pattern 0,0 to the cursor pos - Geom::Point delta = p - sp_pattern_extract_trans(pat); - gdouble theta = atan2(delta); + // rotate pattern around XY knot position + Geom::Point knot_relpos(pattern_width(pat), -pattern_height(pat)); + Geom::Point xy_knot_relpos(0, -pattern_height(pat)); + Geom::Point transform_origin = xy_knot_relpos * pat->patternTransform; + + Geom::Point oldp = (knot_relpos * pat->patternTransform) - transform_origin; + Geom::Point newp = p - transform_origin; + + gdouble theta = Geom::angle_between(oldp, newp); if ( state & GDK_CONTROL_MASK ) { theta = sp_round(theta, M_PI/snaps); } - // get the scale from the current transform so we can keep it. - Geom::Point scl = sp_pattern_extract_scale(pat); - Geom::Matrix rot = Geom::Matrix(Geom::Scale(scl)) * Geom::Matrix(Geom::Rotate(theta)); - Geom::Point const t = sp_pattern_extract_trans(pat); - rot[4] = t[Geom::X]; - rot[5] = t[Geom::Y]; - sp_item_adjust_pattern(item, rot, true); + Geom::Matrix rot = Geom::Matrix(Geom::Translate(-transform_origin)) + * Geom::Rotate(theta) + * Geom::Translate(transform_origin); + sp_item_adjust_pattern(item, rot); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +Geom::Point +PatternKnotHolderEntityScale::knot_get() +{ + SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); + + gdouble x = pattern_width(pat); + gdouble y = 0; + Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; + return delta; +} + void PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { @@ -232,49 +232,32 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const & // FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used. Geom::Point p_snapped = snap_knot_position(p); - // get angle from current transform - gdouble theta = sp_pattern_extract_theta(pat); + Geom::Point knot_relpos(pattern_width(pat), 0); + Geom::Point xy_knot_relpos(0, -pattern_height(pat)); + Geom::Point transform_origin = xy_knot_relpos * pat->patternTransform; - // Get the new scale from the position of the knotholder - Geom::Point d = p_snapped - sp_pattern_extract_trans(pat); - gdouble pat_x = pattern_width(pat); - gdouble pat_y = pattern_height(pat); - Geom::Scale scl(1); - if ( state & GDK_CONTROL_MASK ) { - // if ctrl is pressed: use 1:1 scaling - gdouble pat_h = hypot(pat_x, pat_y); - scl = Geom::Scale(d.length() / pat_h); + // do the scaling in pattern coordinate space + Geom::Point oldp = knot_relpos - xy_knot_relpos; + Geom::Point newp = p_snapped * pat->patternTransform.inverse() - xy_knot_relpos; + + if (Geom::are_near(newp.length(), 0)) return; + + Geom::Scale s(1); + if (state & GDK_CONTROL_MASK) { + // uniform scaling + s = Geom::Scale(oldp * (newp.length() * oldp.length())); } else { - d *= Geom::Rotate(-theta); - scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y); + s = Geom::Scale(newp[Geom::X] / oldp[Geom::X], newp[Geom::Y] / oldp[Geom::Y]); } - Geom::Matrix rot = (Geom::Matrix)scl * Geom::Rotate(theta); - - Geom::Point const t = sp_pattern_extract_trans(pat); - rot[4] = t[Geom::X]; - rot[5] = t[Geom::Y]; - sp_item_adjust_pattern(item, rot, true); + Geom::Matrix scl = Geom::Matrix(Geom::Translate(-xy_knot_relpos)) + * s + * Geom::Translate(xy_knot_relpos) + * pat->patternTransform; + sp_item_adjust_pattern(item, scl, true); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } - -Geom::Point -PatternKnotHolderEntityScale::knot_get() -{ - SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - - gdouble x = pattern_width(pat); - gdouble y = pattern_height(pat); - Geom::Point delta = Geom::Point(x,y); - Geom::Matrix a = pat->patternTransform; - a[4] = 0; - a[5] = 0; - delta = delta * a; - delta = delta + sp_pattern_extract_trans(pat); - return delta; -} - /* Local Variables: mode:c++ -- cgit v1.2.3 From d037400fcf3fba455e092ed6c1e34163eb6c7b7f Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 3 Apr 2010 18:50:12 +0200 Subject: Fix grid extension (bzr r9281.1.10) --- src/extension/internal/grid.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index d4b35b261..deef367a4 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -46,13 +46,12 @@ Grid::load (Inkscape::Extension::Extension */*module*/) namespace { -Glib::ustring build_lines(int axis, Geom::Rect bounding_area, - float offset, float spacing) +void build_lines(int axis, Geom::Rect bounding_area, float offset, + float spacing, SVG::PathString &path_data) { Geom::Point point_offset(0.0, 0.0); point_offset[axis] = offset; - SVG::PathString path_data; for (Geom::Point start_point = bounding_area.min(); start_point[axis] + offset <= (bounding_area.max())[axis]; start_point[axis] += spacing) { @@ -62,8 +61,6 @@ Glib::ustring build_lines(int axis, Geom::Rect bounding_area, path_data.moveTo(start_point + point_offset) .lineTo(end_point + point_offset); } - - return path_data; } } @@ -89,10 +86,8 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc if (bounds) { bounding_area = *bounds; } - - gdouble doc_height = sp_document_height(document->doc()); - Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]), - Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y])); + Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], bounding_area.min()[Geom::Y]), + Geom::Point(bounding_area.max()[Geom::X], bounding_area.max()[Geom::Y])); bounding_area = temprec; } @@ -103,10 +98,9 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc float offsets[2] = { module->get_param_float("xoffset"), module->get_param_float("yoffset") }; - Glib::ustring path_data(""); + SVG::PathString path_data; for ( int axis = 0 ; axis < 2 ; ++axis ) { - path_data += build_lines(axis, bounding_area, - offsets[axis], spacings[axis]); + build_lines(axis, bounding_area, offsets[axis], spacings[axis], path_data); } Inkscape::XML::Document * xml_doc = sp_document_repr_doc(document->doc()); -- cgit v1.2.3 From 62342e4e8ab205fed32748197f926595071743cc Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sun, 4 Apr 2010 00:00:17 +0200 Subject: remove debug text from cairo-render-context.cpp (bzr r9289) --- src/extension/internal/cairo-render-context.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 877bdb952..cf3c72432 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -80,7 +80,8 @@ #include //#define TRACE(_args) g_printf _args -#define TRACE(_args) g_message _args +//#define TRACE(_args) g_message _args +#define TRACE(_args) //#define TEST(_args) _args #define TEST(_args) @@ -819,7 +820,6 @@ CairoRenderContext::setSurfaceTarget(cairo_surface_t *surface, bool is_vector, c bool CairoRenderContext::_finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t *ctm) { -g_message("enter"); if(surface == NULL) { return false; } @@ -846,7 +846,7 @@ g_message("enter"); } _is_valid = TRUE; -g_message("leave"); + return true; } -- cgit v1.2.3 From 2b115a6b3457a06498167e978a2fdf47f5f2655c Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 4 Apr 2010 00:19:13 +0200 Subject: Fix --export-page-drawing option in PDF, PS and LaTeX export. (bzr r9290) --- src/extension/internal/cairo-renderer.cpp | 6 +----- src/extension/internal/latex-text-renderer.cpp | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 6e4bb3b7e..52f070591 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -631,12 +631,8 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page if (ret && !pageBoundingBox) { - double high = sp_document_height(doc); - if (ctx->_vector_based_target) - high *= PT_PER_PX; - Geom::Matrix tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), - (d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); + -d.y0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); ctx->transform(&tp); } diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 28bba1beb..1fdf1d7fd 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -501,7 +501,8 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * if (!pageBoundingBox) { - push_transform( Geom::Translate( - d->min() ) ); + Geom::Translate t(-d->min()[Geom::X], d->max()[Geom::Y] - sp_document_height(doc)); + push_transform( t ); } // flip y-axis -- cgit v1.2.3 From e10efc8dc1b2370f7f54970ca8e8f57b0f2d9666 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Apr 2010 17:17:51 -0700 Subject: zero out pointers to deleted members. might expose problems if a stail pointer is related to bug #494722. (bzr r9291) --- src/ui/dialog/dialog.cpp | 1 + src/ui/dialog/dialog.h | 10 ++--- src/ui/dialog/floating-behavior.cpp | 89 +++++++++++++++++++------------------ src/ui/dialog/floating-behavior.h | 16 +++---- 4 files changed, 59 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 2b39eb3c9..2483dc50e 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -139,6 +139,7 @@ Dialog::~Dialog() save_geometry(); delete _behavior; + _behavior = 0; } diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h index 1a59a236c..f07c1bc86 100644 --- a/src/ui/dialog/dialog.h +++ b/src/ui/dialog/dialog.h @@ -21,9 +21,9 @@ class SPDesktop; -namespace Inkscape { -class Selection; -class Application; +namespace Inkscape { +class Selection; +class Application; } namespace Inkscape { @@ -36,7 +36,7 @@ void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpoi gboolean sp_retransientize_again(gpointer dlgPtr); void sp_dialog_shutdown(GtkObject *object, gpointer dlgPtr); -/** +/** * @brief Base class for Inkscape dialogs * This class provides certain common behaviors and styles wanted of all dialogs * in the application. Fundamental parts of the dialog's behavior are controlled by @@ -46,7 +46,7 @@ class Dialog { public: - Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path = NULL, + Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path = NULL, int verb_num = 0, Glib::ustring const &apply_label = ""); virtual ~Dialog(); diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp index 19147f2c7..85f078439 100644 --- a/src/ui/dialog/floating-behavior.cpp +++ b/src/ui/dialog/floating-behavior.cpp @@ -33,11 +33,11 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) : Behavior(dialog), _d (new Gtk::Dialog(_dialog._title)) #if GTK_VERSION_GE(2, 12) - ,_dialog_active(_d->property_is_active()) - ,_steps(0) - ,_trans_focus(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0)) - ,_trans_blur(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0)) - ,_trans_time(Inkscape::Preferences::get()->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000)) + ,_dialog_active(_d->property_is_active()) + ,_steps(0) + ,_trans_focus(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0)) + ,_trans_blur(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0)) + ,_trans_time(Inkscape::Preferences::get()->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000)) #endif { hide(); @@ -49,8 +49,8 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) : _dialog.retransientize_suppress = false; #if GTK_VERSION_GE(2, 12) - _focus_event(); - _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event)); + _focus_event(); + _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event)); #endif } @@ -58,12 +58,12 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) : #if GTK_VERSION_GE(2, 12) /** \brief A function called when the window gets focus - This function gets called on a focus event. It figures out how much - time is required for a transition, and the number of steps that'll take, - and sets up the _trans_timer function to do the work. If the transition - time is set to 0 ms it just calls _trans_timer once with _steps equal to - zero so that the transition happens instantaneously. This occurs on - windows as opacity changes cause flicker there. + This function gets called on a focus event. It figures out how much + time is required for a transition, and the number of steps that'll take, + and sets up the _trans_timer function to do the work. If the transition + time is set to 0 ms it just calls _trans_timer once with _steps equal to + zero so that the transition happens instantaneously. This occurs on + windows as opacity changes cause flicker there. */ void FloatingBehavior::_focus_event (void) { @@ -93,42 +93,43 @@ void FloatingBehavior::_focus_event (void) /** \brief Move the opacity of a window towards our goal - This is a timer function that is set up by _focus_event to slightly - move the opacity of the window along in an animated fashion. It moves - the opacity half way to the goal until it runs out of steps, and then - it just forces the goal. + This is a timer function that is set up by _focus_event to slightly + move the opacity of the window along in an animated fashion. It moves + the opacity half way to the goal until it runs out of steps, and then + it just forces the goal. */ bool FloatingBehavior::_trans_timer (void) { - // printf("Go go gadget timer: %d\n", _steps); - if (_steps == 0) { - if (_dialog_active.get_value()) { - _d->set_opacity(_trans_focus); - } else { - _d->set_opacity(_trans_blur); - } - - return false; - } - - float goal, current; - goal = current = _d->get_opacity(); - - if (_dialog_active.get_value()) { - goal = _trans_focus; - } else { - goal = _trans_blur; - } - - _d->set_opacity(current - ((current - goal) / 2)); - _steps--; - return true; + // printf("Go go gadget timer: %d\n", _steps); + if (_steps == 0) { + if (_dialog_active.get_value()) { + _d->set_opacity(_trans_focus); + } else { + _d->set_opacity(_trans_blur); + } + + return false; + } + + float goal, current; + goal = current = _d->get_opacity(); + + if (_dialog_active.get_value()) { + goal = _trans_focus; + } else { + goal = _trans_blur; + } + + _d->set_opacity(current - ((current - goal) / 2)); + _steps--; + return true; } #endif -FloatingBehavior::~FloatingBehavior() -{ +FloatingBehavior::~FloatingBehavior() +{ delete _d; + _d = 0; } Behavior * @@ -184,9 +185,9 @@ FloatingBehavior::onDesktopActivated (SPDesktop *desktop) #ifdef WIN32 // Win32 special code to enable transient dialogs transient_policy = 2; -#endif +#endif - if (!transient_policy) + if (!transient_policy) return; GtkWindow *dialog_win = GTK_WINDOW(_d->gobj()); diff --git a/src/ui/dialog/floating-behavior.h b/src/ui/dialog/floating-behavior.h index 0360ccf49..30ecaa053 100644 --- a/src/ui/dialog/floating-behavior.h +++ b/src/ui/dialog/floating-behavior.h @@ -64,14 +64,14 @@ private: Gtk::Dialog *_d; //< the actual dialog #if GTK_VERSION_GE(2, 12) - void _focus_event (void); - bool _trans_timer (void); - - Glib::PropertyProxy_ReadOnly _dialog_active; //< Variable proxy to track whether the dialog is the active window - int _steps; //< Number of steps for the timer to animate the transparent dialog - float _trans_focus; //< The percentage opacity when the dialog is focused - float _trans_blur; //< The percentage opactiy when the dialog is not focused - int _trans_time; //< The amount of time (in ms) for the dialog to change it's transparency + void _focus_event (void); + bool _trans_timer (void); + + Glib::PropertyProxy_ReadOnly _dialog_active; //< Variable proxy to track whether the dialog is the active window + int _steps; //< Number of steps for the timer to animate the transparent dialog + float _trans_focus; //< The percentage opacity when the dialog is focused + float _trans_blur; //< The percentage opactiy when the dialog is not focused + int _trans_time; //< The amount of time (in ms) for the dialog to change it's transparency #endif }; -- cgit v1.2.3 From a4d3cee5535b8e5ac23039f189a6e6b029ed4f6f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 4 Apr 2010 09:46:40 -0700 Subject: Turn off debugging. (bzr r9292) --- src/widgets/sp-color-icc-selector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/sp-color-icc-selector.cpp b/src/widgets/sp-color-icc-selector.cpp index 3b4b6b711..6bd1957a8 100644 --- a/src/widgets/sp-color-icc-selector.cpp +++ b/src/widgets/sp-color-icc-selector.cpp @@ -17,7 +17,7 @@ #include "inkscape.h" #include "profile-manager.h" -#define DEBUG_LCMS +#define noDEBUG_LCMS #if ENABLE_LCMS #include "color-profile-fns.h" -- cgit v1.2.3 From 9be023097049db674965a3367e0b75bc6402140e Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 4 Apr 2010 10:16:55 -0700 Subject: Added control to select Unicode range limiting. Switched to using "Basic Latin" there as a default instead of the script. Fixes bug #553911. Fixed bugs: - https://launchpad.net/bugs/553911 (bzr r9293) --- src/ui/dialog/glyphs.cpp | 221 ++++++++++++++++++++++++++++++++++++++++++++--- src/ui/dialog/glyphs.h | 2 + 2 files changed, 209 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 133cf01ea..72fdf7e68 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -42,7 +42,7 @@ GlyphsPanel &GlyphsPanel::getInstance() #if GLIB_CHECK_VERSION(2,14,0) -static std::map &getScriptToName() +static std::map & getScriptToName() { static bool init = false; static std::map mappings; @@ -135,6 +135,170 @@ static std::map &getScriptToName() } #endif // GLIB_CHECK_VERSION(2,14,0) +typedef std::pair Range; +typedef std::pair NamedRange; + +static std::vector & getRanges() +{ + static bool init = false; + static std::vector ranges; + if (!init) { + init = true; + ranges.push_back(std::make_pair(std::make_pair(0x0000, 0xFFFD), _("all"))); + ranges.push_back(std::make_pair(std::make_pair(0x0000, 0x007F), _("Basic Latin"))); + ranges.push_back(std::make_pair(std::make_pair(0x0080, 0x00FF), _("Latin-1 Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x0100, 0x017F), _("Latin Extended-A"))); + ranges.push_back(std::make_pair(std::make_pair(0x0180, 0x024F), _("Latin Extended-B"))); + ranges.push_back(std::make_pair(std::make_pair(0x0250, 0x02AF), _("IPA Extensions"))); + ranges.push_back(std::make_pair(std::make_pair(0x02B0, 0x02FF), _("Spacing Modifier Letters"))); + ranges.push_back(std::make_pair(std::make_pair(0x0300, 0x036F), _("Combining Diacritical Marks"))); + ranges.push_back(std::make_pair(std::make_pair(0x0370, 0x03FF), _("Greek and Coptic"))); + ranges.push_back(std::make_pair(std::make_pair(0x0400, 0x04FF), _("Cyrillic"))); + ranges.push_back(std::make_pair(std::make_pair(0x0500, 0x052F), _("Cyrillic Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x0530, 0x058F), _("Armenian"))); + ranges.push_back(std::make_pair(std::make_pair(0x0590, 0x05FF), _("Hebrew"))); + ranges.push_back(std::make_pair(std::make_pair(0x0600, 0x06FF), _("Arabic"))); + ranges.push_back(std::make_pair(std::make_pair(0x0700, 0x074F), _("Syriac"))); + ranges.push_back(std::make_pair(std::make_pair(0x0750, 0x077F), _("Arabic Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x0780, 0x07BF), _("Thaana"))); + ranges.push_back(std::make_pair(std::make_pair(0x07C0, 0x07FF), _("NKo"))); + ranges.push_back(std::make_pair(std::make_pair(0x0800, 0x083F), _("Samaritan"))); + ranges.push_back(std::make_pair(std::make_pair(0x0900, 0x097F), _("Devanagari"))); + ranges.push_back(std::make_pair(std::make_pair(0x0980, 0x09FF), _("Bengali"))); + ranges.push_back(std::make_pair(std::make_pair(0x0A00, 0x0A7F), _("Gurmukhi"))); + ranges.push_back(std::make_pair(std::make_pair(0x0A80, 0x0AFF), _("Gujarati"))); + ranges.push_back(std::make_pair(std::make_pair(0x0B00, 0x0B7F), _("Oriya"))); + ranges.push_back(std::make_pair(std::make_pair(0x0B80, 0x0BFF), _("Tamil"))); + ranges.push_back(std::make_pair(std::make_pair(0x0C00, 0x0C7F), _("Telugu"))); + ranges.push_back(std::make_pair(std::make_pair(0x0C80, 0x0CFF), _("Kannada"))); + ranges.push_back(std::make_pair(std::make_pair(0x0D00, 0x0D7F), _("Malayalam"))); + ranges.push_back(std::make_pair(std::make_pair(0x0D80, 0x0DFF), _("Sinhala"))); + ranges.push_back(std::make_pair(std::make_pair(0x0E00, 0x0E7F), _("Thai"))); + ranges.push_back(std::make_pair(std::make_pair(0x0E80, 0x0EFF), _("Lao"))); + ranges.push_back(std::make_pair(std::make_pair(0x0F00, 0x0FFF), _("Tibetan"))); + ranges.push_back(std::make_pair(std::make_pair(0x1000, 0x109F), _("Myanmar"))); + ranges.push_back(std::make_pair(std::make_pair(0x10A0, 0x10FF), _("Georgian"))); + ranges.push_back(std::make_pair(std::make_pair(0x1100, 0x11FF), _("Hangul Jamo"))); + ranges.push_back(std::make_pair(std::make_pair(0x1200, 0x137F), _("Ethiopic"))); + ranges.push_back(std::make_pair(std::make_pair(0x1380, 0x139F), _("Ethiopic Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x13A0, 0x13FF), _("Cherokee"))); + ranges.push_back(std::make_pair(std::make_pair(0x1400, 0x167F), _("Unified Canadian Aboriginal Syllabics"))); + ranges.push_back(std::make_pair(std::make_pair(0x1680, 0x169F), _("Ogham"))); + ranges.push_back(std::make_pair(std::make_pair(0x16A0, 0x16FF), _("Runic"))); + ranges.push_back(std::make_pair(std::make_pair(0x1700, 0x171F), _("Tagalog"))); + ranges.push_back(std::make_pair(std::make_pair(0x1720, 0x173F), _("Hanunoo"))); + ranges.push_back(std::make_pair(std::make_pair(0x1740, 0x175F), _("Buhid"))); + ranges.push_back(std::make_pair(std::make_pair(0x1760, 0x177F), _("Tagbanwa"))); + ranges.push_back(std::make_pair(std::make_pair(0x1780, 0x17FF), _("Khmer"))); + ranges.push_back(std::make_pair(std::make_pair(0x1800, 0x18AF), _("Mongolian"))); + ranges.push_back(std::make_pair(std::make_pair(0x18B0, 0x18FF), _("Unified Canadian Aboriginal Syllabics Extended"))); + ranges.push_back(std::make_pair(std::make_pair(0x1900, 0x194F), _("Limbu"))); + ranges.push_back(std::make_pair(std::make_pair(0x1950, 0x197F), _("Tai Le"))); + ranges.push_back(std::make_pair(std::make_pair(0x1980, 0x19DF), _("New Tai Lue"))); + ranges.push_back(std::make_pair(std::make_pair(0x19E0, 0x19FF), _("Khmer Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x1A00, 0x1A1F), _("Buginese"))); + ranges.push_back(std::make_pair(std::make_pair(0x1A20, 0x1AAF), _("Tai Tham"))); + ranges.push_back(std::make_pair(std::make_pair(0x1B00, 0x1B7F), _("Balinese"))); + ranges.push_back(std::make_pair(std::make_pair(0x1B80, 0x1BBF), _("Sundanese"))); + ranges.push_back(std::make_pair(std::make_pair(0x1C00, 0x1C4F), _("Lepcha"))); + ranges.push_back(std::make_pair(std::make_pair(0x1C50, 0x1C7F), _("Ol Chiki"))); + ranges.push_back(std::make_pair(std::make_pair(0x1CD0, 0x1CFF), _("Vedic Extensions"))); + ranges.push_back(std::make_pair(std::make_pair(0x1D00, 0x1D7F), _("Phonetic Extensions"))); + ranges.push_back(std::make_pair(std::make_pair(0x1D80, 0x1DBF), _("Phonetic Extensions Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x1DC0, 0x1DFF), _("Combining Diacritical Marks Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x1E00, 0x1EFF), _("Latin Extended Additional"))); + ranges.push_back(std::make_pair(std::make_pair(0x1F00, 0x1FFF), _("Greek Extended"))); + ranges.push_back(std::make_pair(std::make_pair(0x2000, 0x206F), _("General Punctuation"))); + ranges.push_back(std::make_pair(std::make_pair(0x2070, 0x209F), _("Superscripts and Subscripts"))); + ranges.push_back(std::make_pair(std::make_pair(0x20A0, 0x20CF), _("Currency Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x20D0, 0x20FF), _("Combining Diacritical Marks for Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x2100, 0x214F), _("Letterlike Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x2150, 0x218F), _("Number Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0x2190, 0x21FF), _("Arrows"))); + ranges.push_back(std::make_pair(std::make_pair(0x2200, 0x22FF), _("Mathematical Operators"))); + ranges.push_back(std::make_pair(std::make_pair(0x2300, 0x23FF), _("Miscellaneous Technical"))); + ranges.push_back(std::make_pair(std::make_pair(0x2400, 0x243F), _("Control Pictures"))); + ranges.push_back(std::make_pair(std::make_pair(0x2440, 0x245F), _("Optical Character Recognition"))); + ranges.push_back(std::make_pair(std::make_pair(0x2460, 0x24FF), _("Enclosed Alphanumerics"))); + ranges.push_back(std::make_pair(std::make_pair(0x2500, 0x257F), _("Box Drawing"))); + ranges.push_back(std::make_pair(std::make_pair(0x2580, 0x259F), _("Block Elements"))); + ranges.push_back(std::make_pair(std::make_pair(0x25A0, 0x25FF), _("Geometric Shapes"))); + ranges.push_back(std::make_pair(std::make_pair(0x2600, 0x26FF), _("Miscellaneous Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x2700, 0x27BF), _("Dingbats"))); + ranges.push_back(std::make_pair(std::make_pair(0x27C0, 0x27EF), _("Miscellaneous Mathematical Symbols-A"))); + ranges.push_back(std::make_pair(std::make_pair(0x27F0, 0x27FF), _("Supplemental Arrows-A"))); + ranges.push_back(std::make_pair(std::make_pair(0x2800, 0x28FF), _("Braille Patterns"))); + ranges.push_back(std::make_pair(std::make_pair(0x2900, 0x297F), _("Supplemental Arrows-B"))); + ranges.push_back(std::make_pair(std::make_pair(0x2980, 0x29FF), _("Miscellaneous Mathematical Symbols-B"))); + ranges.push_back(std::make_pair(std::make_pair(0x2A00, 0x2AFF), _("Supplemental Mathematical Operators"))); + ranges.push_back(std::make_pair(std::make_pair(0x2B00, 0x2BFF), _("Miscellaneous Symbols and Arrows"))); + ranges.push_back(std::make_pair(std::make_pair(0x2C00, 0x2C5F), _("Glagolitic"))); + ranges.push_back(std::make_pair(std::make_pair(0x2C60, 0x2C7F), _("Latin Extended-C"))); + ranges.push_back(std::make_pair(std::make_pair(0x2C80, 0x2CFF), _("Coptic"))); + ranges.push_back(std::make_pair(std::make_pair(0x2D00, 0x2D2F), _("Georgian Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x2D30, 0x2D7F), _("Tifinagh"))); + ranges.push_back(std::make_pair(std::make_pair(0x2D80, 0x2DDF), _("Ethiopic Extended"))); + ranges.push_back(std::make_pair(std::make_pair(0x2DE0, 0x2DFF), _("Cyrillic Extended-A"))); + ranges.push_back(std::make_pair(std::make_pair(0x2E00, 0x2E7F), _("Supplemental Punctuation"))); + ranges.push_back(std::make_pair(std::make_pair(0x2E80, 0x2EFF), _("CJK Radicals Supplement"))); + ranges.push_back(std::make_pair(std::make_pair(0x2F00, 0x2FDF), _("Kangxi Radicals"))); + ranges.push_back(std::make_pair(std::make_pair(0x2FF0, 0x2FFF), _("Ideographic Description Characters"))); + ranges.push_back(std::make_pair(std::make_pair(0x3000, 0x303F), _("CJK Symbols and Punctuation"))); + ranges.push_back(std::make_pair(std::make_pair(0x3040, 0x309F), _("Hiragana"))); + ranges.push_back(std::make_pair(std::make_pair(0x30A0, 0x30FF), _("Katakana"))); + ranges.push_back(std::make_pair(std::make_pair(0x3100, 0x312F), _("Bopomofo"))); + ranges.push_back(std::make_pair(std::make_pair(0x3130, 0x318F), _("Hangul Compatibility Jamo"))); + ranges.push_back(std::make_pair(std::make_pair(0x3190, 0x319F), _("Kanbun"))); + ranges.push_back(std::make_pair(std::make_pair(0x31A0, 0x31BF), _("Bopomofo Extended"))); + ranges.push_back(std::make_pair(std::make_pair(0x31C0, 0x31EF), _("CJK Strokes"))); + ranges.push_back(std::make_pair(std::make_pair(0x31F0, 0x31FF), _("Katakana Phonetic Extensions"))); + ranges.push_back(std::make_pair(std::make_pair(0x3200, 0x32FF), _("Enclosed CJK Letters and Months"))); + ranges.push_back(std::make_pair(std::make_pair(0x3300, 0x33FF), _("CJK Compatibility"))); + ranges.push_back(std::make_pair(std::make_pair(0x3400, 0x4DBF), _("CJK Unified Ideographs Extension A"))); + ranges.push_back(std::make_pair(std::make_pair(0x4DC0, 0x4DFF), _("Yijing Hexagram Symbols"))); + ranges.push_back(std::make_pair(std::make_pair(0x4E00, 0x9FFF), _("CJK Unified Ideographs"))); + ranges.push_back(std::make_pair(std::make_pair(0xA000, 0xA48F), _("Yi Syllables"))); + ranges.push_back(std::make_pair(std::make_pair(0xA490, 0xA4CF), _("Yi Radicals"))); + ranges.push_back(std::make_pair(std::make_pair(0xA4D0, 0xA4FF), _("Lisu"))); + ranges.push_back(std::make_pair(std::make_pair(0xA500, 0xA63F), _("Vai"))); + ranges.push_back(std::make_pair(std::make_pair(0xA640, 0xA69F), _("Cyrillic Extended-B"))); + ranges.push_back(std::make_pair(std::make_pair(0xA6A0, 0xA6FF), _("Bamum"))); + ranges.push_back(std::make_pair(std::make_pair(0xA700, 0xA71F), _("Modifier Tone Letters"))); + ranges.push_back(std::make_pair(std::make_pair(0xA720, 0xA7FF), _("Latin Extended-D"))); + ranges.push_back(std::make_pair(std::make_pair(0xA800, 0xA82F), _("Syloti Nagri"))); + ranges.push_back(std::make_pair(std::make_pair(0xA830, 0xA83F), _("Common Indic Number Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0xA840, 0xA87F), _("Phags-pa"))); + ranges.push_back(std::make_pair(std::make_pair(0xA880, 0xA8DF), _("Saurashtra"))); + ranges.push_back(std::make_pair(std::make_pair(0xA8E0, 0xA8FF), _("Devanagari Extended"))); + ranges.push_back(std::make_pair(std::make_pair(0xA900, 0xA92F), _("Kayah Li"))); + ranges.push_back(std::make_pair(std::make_pair(0xA930, 0xA95F), _("Rejang"))); + ranges.push_back(std::make_pair(std::make_pair(0xA960, 0xA97F), _("Hangul Jamo Extended-A"))); + ranges.push_back(std::make_pair(std::make_pair(0xA980, 0xA9DF), _("Javanese"))); + ranges.push_back(std::make_pair(std::make_pair(0xAA00, 0xAA5F), _("Cham"))); + ranges.push_back(std::make_pair(std::make_pair(0xAA60, 0xAA7F), _("Myanmar Extended-A"))); + ranges.push_back(std::make_pair(std::make_pair(0xAA80, 0xAADF), _("Tai Viet"))); + ranges.push_back(std::make_pair(std::make_pair(0xABC0, 0xABFF), _("Meetei Mayek"))); + ranges.push_back(std::make_pair(std::make_pair(0xAC00, 0xD7AF), _("Hangul Syllables"))); + ranges.push_back(std::make_pair(std::make_pair(0xD7B0, 0xD7FF), _("Hangul Jamo Extended-B"))); + ranges.push_back(std::make_pair(std::make_pair(0xD800, 0xDB7F), _("High Surrogates"))); + ranges.push_back(std::make_pair(std::make_pair(0xDB80, 0xDBFF), _("High Private Use Surrogates"))); + ranges.push_back(std::make_pair(std::make_pair(0xDC00, 0xDFFF), _("Low Surrogates"))); + ranges.push_back(std::make_pair(std::make_pair(0xE000, 0xF8FF), _("Private Use Area"))); + ranges.push_back(std::make_pair(std::make_pair(0xF900, 0xFAFF), _("CJK Compatibility Ideographs"))); + ranges.push_back(std::make_pair(std::make_pair(0xFB00, 0xFB4F), _("Alphabetic Presentation Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0xFB50, 0xFDFF), _("Arabic Presentation Forms-A"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE00, 0xFE0F), _("Variation Selectors"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE10, 0xFE1F), _("Vertical Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE20, 0xFE2F), _("Combining Half Marks"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE30, 0xFE4F), _("CJK Compatibility Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE50, 0xFE6F), _("Small Form Variants"))); + ranges.push_back(std::make_pair(std::make_pair(0xFE70, 0xFEFF), _("Arabic Presentation Forms-B"))); + ranges.push_back(std::make_pair(std::make_pair(0xFF00, 0xFFEF), _("Halfwidth and Fullwidth Forms"))); + ranges.push_back(std::make_pair(std::make_pair(0xFFF0, 0xFFFF), _("Specials"))); + } + + return ranges; +} class GlyphColumns : public Gtk::TreeModel::ColumnRecord { @@ -173,7 +337,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : deskTrack(), iconActiveConn(), iconSelectConn(), - scriptSelectConn() + scriptSelectConn(), + rangeSelectConn() { Gtk::Table *table = new Gtk::Table(3, 1, false); _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); @@ -203,28 +368,48 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : Gtk::SHRINK, Gtk::SHRINK); scriptCombo = new Gtk::ComboBoxText(); - - std::map items = getScriptToName(); - for (std::map::iterator it = items.begin(); it != items.end(); ++it) + for (std::map::iterator it = getScriptToName().begin(); it != getScriptToName().end(); ++it) { scriptCombo->append_text(it->second); } - scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_COMMON]); // default to a smaller set + scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]); scriptSelectConn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); - table->attach( *Gtk::manage(scriptCombo), + Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0); + align->add(*Gtk::manage(scriptCombo)); + table->attach( *Gtk::manage(align), 1, 2, row, row + 1, - Gtk::SHRINK, Gtk::SHRINK); + Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); + } - label = new Gtk::Label(""); + row++; +#endif // GLIB_CHECK_VERSION(2,14,0) + +// ------------------------------- + + { + Gtk::Label *label = new Gtk::Label(_("Range: ")); table->attach( *Gtk::manage(label), - 2, 3, row, row + 1, - Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); + 0, 1, row, row + 1, + Gtk::SHRINK, Gtk::SHRINK); + + rangeCombo = new Gtk::ComboBoxText(); + for ( std::vector::iterator it = getRanges().begin(); it != getRanges().end(); ++it ) { + rangeCombo->append_text(it->second); + } + + rangeCombo->set_active_text(getRanges()[1].second); + rangeSelectConn = rangeCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + + Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0); + align->add(*Gtk::manage(rangeCombo)); + table->attach( *Gtk::manage(align), + 1, 2, row, row + 1, + Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); } row++; -#endif // GLIB_CHECK_VERSION(2,14,0) // ------------------------------- @@ -291,6 +476,7 @@ GlyphsPanel::~GlyphsPanel() { iconActiveConn.disconnect(); iconSelectConn.disconnect(); + rangeSelectConn.disconnect(); scriptSelectConn.disconnect(); desktopChangeConn.disconnect(); } @@ -366,7 +552,7 @@ void GlyphsPanel::rebuild() //double sp_font_selector_get_size (SPFontSelector *fsel); #if GLIB_CHECK_VERSION(2,14,0) - GUnicodeScript script = G_UNICODE_SCRIPT_COMMON; + GUnicodeScript script = G_UNICODE_SCRIPT_INVALID_CODE; Glib::ustring scriptName = scriptCombo->get_active_text(); std::map items = getScriptToName(); for (std::map::iterator it = items.begin(); it != items.end(); ++it) { @@ -381,8 +567,15 @@ void GlyphsPanel::rebuild() Glib::RefPtr tmp = Gtk::ListStore::create(*getColumns()); iconView->set_model(tmp); + gunichar lower = 0x0001; + gunichar upper = 0xFFFD; + int active = rangeCombo->get_active_row_number(); + if (active >= 0) { + lower = getRanges()[active].first.first; + upper = getRanges()[active].first.second; + } std::vector present; - for (gunichar ch = 1; ch < 65535; ch++) { + for (gunichar ch = lower; ch <= upper; ch++) { int glyphId = font->MapUnicodeChar(ch); if (glyphId > 0) { #if GLIB_CHECK_VERSION(2,14,0) diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index ffd5757b0..602f9b5c9 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -75,12 +75,14 @@ private: #if GLIB_CHECK_VERSION(2,14,0) Gtk::ComboBoxText *scriptCombo; #endif //GLIB_CHECK_VERSION(2,14,0) + Gtk::ComboBoxText *rangeCombo; SPFontSelector *fsel; SPDesktop *targetDesktop; DesktopTracker deskTrack; sigc::connection iconActiveConn; sigc::connection iconSelectConn; sigc::connection scriptSelectConn; + sigc::connection rangeSelectConn; sigc::connection desktopChangeConn; }; -- cgit v1.2.3 From 83f36efa18ecbf1aa71205f04ea6960dcbf49158 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 4 Apr 2010 23:43:36 +0200 Subject: Merge PDF rendering fix (bzr r9281.1.11) --- src/extension/internal/cairo-renderer.cpp | 6 +----- src/extension/internal/latex-text-renderer.cpp | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 6e4bb3b7e..52f070591 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -631,12 +631,8 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page if (ret && !pageBoundingBox) { - double high = sp_document_height(doc); - if (ctx->_vector_based_target) - high *= PT_PER_PX; - Geom::Matrix tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), - (d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); + -d.y0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); ctx->transform(&tp); } diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 28bba1beb..1fdf1d7fd 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -501,7 +501,8 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * if (!pageBoundingBox) { - push_transform( Geom::Translate( - d->min() ) ); + Geom::Translate t(-d->min()[Geom::X], d->max()[Geom::Y] - sp_document_height(doc)); + push_transform( t ); } // flip y-axis -- cgit v1.2.3 From 4bfe9e6856f66825a0bf139e9744e2bc290918ae Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 4 Apr 2010 23:45:07 +0200 Subject: Coords: fix SPDesktop::point() method (bzr r9281.1.12) --- src/desktop.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index 1953ae2a6..6690e0af1 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -724,8 +724,8 @@ SPDesktop::point() const if (p[Geom::X] >= r0[Geom::X] && p[Geom::X] <= r1[Geom::X] && - p[Geom::Y] >= r1[Geom::Y] && - p[Geom::Y] <= r0[Geom::Y]) + p[Geom::Y] >= r0[Geom::Y] && + p[Geom::Y] <= r1[Geom::Y]) { return p; } else { -- cgit v1.2.3 From 6581883407e2b12ac0926cf5eaf9a971742df20c Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 5 Apr 2010 00:16:13 +0200 Subject: Coords: fix initial cursor position in the text tool (bzr r9281.1.13) --- src/text-context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/text-context.cpp b/src/text-context.cpp index 4f89bd1e1..984876f78 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -684,7 +684,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons // Cursor height is defined by the new text object's font size; it needs to be set // articifically here, for the text object does not exist yet: double cursor_height = sp_desktop_get_font_size_tool(desktop); - sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), dtp, dtp + Geom::Point(0, cursor_height)); + sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), dtp, dtp - Geom::Point(0, cursor_height)); event_context->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type text; Enter to start new line.")); // FIXME:: this is a copy of a string from _update_cursor below, do not desync event_context->within_tolerance = false; -- cgit v1.2.3 From a03fbcd36d55eb8e79dd7fef5ee9d67365f471cf Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Mon, 5 Apr 2010 01:26:13 +0200 Subject: Coords: fix guidelines (bzr r9281.1.14) --- src/document.cpp | 2 +- src/sp-guide.cpp | 6 ++++-- src/sp-object-repr.cpp | 17 +++++++++-------- src/sp-object-repr.h | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index f137ba60d..aeafaf1f9 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -327,7 +327,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, document->base = NULL; document->name = g_strdup(name); - document->root = sp_object_repr_build_tree(document, rroot); + sp_object_repr_build_tree(document, rroot); /* fixme: Not sure about this, but lets assume ::build updates */ rroot->setAttribute("inkscape:version", Inkscape::version_string); diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index f5edf7d97..def039937 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -217,12 +217,14 @@ static void sp_guide_set(SPObject *object, unsigned int key, const gchar *value) success += sp_svg_number_read_d(strarray[1], &newy); g_strfreev (strarray); if (success == 2) { - guide->point_on_line = Geom::Point(newx, newy); + // Desktop coords fix + guide->point_on_line = Geom::Point(newx, sp_document_height(guide->document) - newy); } else if (success == 1) { // before 0.46 style guideline definition. const gchar *attr = SP_OBJECT_REPR(object)->attribute("orientation"); if (attr && !strcmp(attr, "horizontal")) { - guide->point_on_line = Geom::Point(0, newx); + // Desktop coords fix + guide->point_on_line = Geom::Point(0, sp_document_height(guide->document) - newx); } else { guide->point_on_line = Geom::Point(newx, 0); } diff --git a/src/sp-object-repr.cpp b/src/sp-object-repr.cpp index 62143e3ab..e32819746 100644 --- a/src/sp-object-repr.cpp +++ b/src/sp-object-repr.cpp @@ -91,9 +91,9 @@ static unsigned const N_NAME_TYPES = SODIPODI_TYPE + 1; static GType name_to_gtype(NameType name_type, gchar const *name); /** - * Construct an SPRoot and all its descendents from the given repr. + * Construct an SPRoot and all its descendents from the given XML representation. */ -SPObject * +void sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr) { g_assert(document != NULL); @@ -103,13 +103,14 @@ sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr) g_assert(name != NULL); GType const type = name_to_gtype(REPR_NAME, name); g_assert(g_type_is_a(type, SP_TYPE_ROOT)); - gpointer newobj = g_object_new(type, 0); - g_assert(newobj != NULL); - SPObject *const object = SP_OBJECT(newobj); - g_assert(object != NULL); - sp_object_invoke_build(object, document, repr, FALSE); - return object; + // create and assign root + SPObject *root = SP_OBJECT(g_object_new(type, 0)); + g_assert(root != NULL); + document->root = root; + + // recursively create SP tree elements + sp_object_invoke_build(root, document, repr, FALSE); } GType diff --git a/src/sp-object-repr.h b/src/sp-object-repr.h index f3a80f83c..43aead41e 100644 --- a/src/sp-object-repr.h +++ b/src/sp-object-repr.h @@ -21,7 +21,7 @@ class Node; } -SPObject *sp_object_repr_build_tree (SPDocument *document, Inkscape::XML::Node *repr); +void sp_object_repr_build_tree (SPDocument *document, Inkscape::XML::Node *repr); GType sp_repr_type_lookup (Inkscape::XML::Node *repr); -- cgit v1.2.3 From 73f71735b611f432cb972b52d3744befd0ced7e7 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 5 Apr 2010 22:33:23 -0700 Subject: Track selected text items and append as needed. (bzr r9296) --- src/ui/dialog/glyphs.cpp | 168 +++++++++++++++++++++++++++++++++++++++++------ src/ui/dialog/glyphs.h | 13 ++-- 2 files changed, 156 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 72fdf7e68..8ed502aae 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -23,12 +23,18 @@ #include #include +#include #include "glyphs.h" +#include "desktop.h" +#include "document.h" // for sp_document_done() +#include "libnrtype/font-instance.h" +#include "sp-flowtext.h" +#include "sp-text.h" #include "verbs.h" #include "widgets/font-selector.h" -#include "libnrtype/font-instance.h" +#include "text-editing.h" namespace Inkscape { namespace UI { @@ -329,16 +335,15 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : iconView(0), entry(0), label(0), + insertBtn(0), #if GLIB_CHECK_VERSION(2,14,0) scriptCombo(0), #endif // GLIB_CHECK_VERSION(2,14,0) fsel(0), targetDesktop(0), deskTrack(), - iconActiveConn(), - iconSelectConn(), - scriptSelectConn(), - rangeSelectConn() + instanceConns(), + desktopConns() { Gtk::Table *table = new Gtk::Table(3, 1, false); _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); @@ -374,7 +379,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : } scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]); - scriptSelectConn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + sigc::connection conn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + instanceConns.push_back(conn); Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0); align->add(*Gtk::manage(scriptCombo)); @@ -400,7 +406,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : } rangeCombo->set_active_text(getRanges()[1].second); - rangeSelectConn = rangeCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + sigc::connection conn = rangeCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild)); + instanceConns.push_back(conn); Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0); align->add(*Gtk::manage(rangeCombo)); @@ -419,8 +426,11 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : iconView->set_text_column(columns->name); //iconView->set_columns(16); - iconActiveConn = iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated)); - iconSelectConn = iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged)); + sigc::connection conn; + conn = iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated)); + instanceConns.push_back(conn); + conn = iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged)); + instanceConns.push_back(conn); Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow(); @@ -436,6 +446,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : Gtk::HBox *box = new Gtk::HBox(); entry = new Gtk::Entry(); + conn = entry->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::calcCanInsert)); + instanceConns.push_back(conn); entry->set_width_chars(18); box->pack_start(*Gtk::manage(entry), Gtk::PACK_SHRINK); @@ -448,12 +460,16 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : pad = new Gtk::Label(""); box->pack_start(*Gtk::manage(pad), Gtk::PACK_EXPAND_WIDGET); + insertBtn = new Gtk::Button(_("Append")); + conn = insertBtn->signal_clicked().connect(sigc::mem_fun(*this, &GlyphsPanel::insertText)); + instanceConns.push_back(conn); +#if GTK_CHECK_VERSION(2,18,0) + //gtkmm 2.18 + insertBtn->set_can_default(); +#endif + insertBtn->set_sensitive(false); - GtkWidget *applyBtn = gtk_button_new_from_stock(GTK_STOCK_APPLY); - GTK_WIDGET_SET_FLAGS(applyBtn, GTK_CAN_DEFAULT | GTK_HAS_DEFAULT); - gtk_widget_set_sensitive(applyBtn, FALSE); - - box->pack_end(*Gtk::manage(Glib::wrap(applyBtn)), Gtk::PACK_SHRINK); + box->pack_end(*Gtk::manage(insertBtn), Gtk::PACK_SHRINK); table->attach( *Gtk::manage(box), 0, 3, row, row + 1, @@ -468,17 +484,21 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : restorePanelPrefs(); // Connect this up last - desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &GlyphsPanel::setTargetDesktop) ); + conn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &GlyphsPanel::setTargetDesktop) ); + instanceConns.push_back(conn); deskTrack.connect(GTK_WIDGET(gobj())); } GlyphsPanel::~GlyphsPanel() { - iconActiveConn.disconnect(); - iconSelectConn.disconnect(); - rangeSelectConn.disconnect(); - scriptSelectConn.disconnect(); - desktopChangeConn.disconnect(); + for (std::vector::iterator it = instanceConns.begin(); it != instanceConns.end(); ++it) { + it->disconnect(); + } + instanceConns.clear(); + for (std::vector::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) { + it->disconnect(); + } + desktopConns.clear(); } @@ -491,7 +511,68 @@ void GlyphsPanel::setDesktop(SPDesktop *desktop) void GlyphsPanel::setTargetDesktop(SPDesktop *desktop) { if (targetDesktop != desktop) { + if (targetDesktop) { + for (std::vector::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) { + it->disconnect(); + } + desktopConns.clear(); + } + targetDesktop = desktop; + + if (targetDesktop && targetDesktop->selection) { + sigc::connection conn = desktop->selection->connectChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, true))); + desktopConns.push_back(conn); + + // Text selection within selected items has changed: + conn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, false))); + desktopConns.push_back(conn); + + // Must check flags, so can't call performUpdate() directly. + conn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &GlyphsPanel::selectionModifiedCB))); + desktopConns.push_back(conn); + + readSelection(true, true); + } + } +} + +void GlyphsPanel::insertText() +{ + SPItem *textItem = 0; + for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) { + if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) { + textItem = SP_ITEM(item->data); + break; + } + } + + if (textItem) { + Glib::ustring glyphs; + if (entry->get_text_length() > 0) { + glyphs = entry->get_text(); + } else { + Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items(); + if (!itemArray.empty()) { + Gtk::TreeModel::Path const & path = *itemArray.begin(); + Gtk::ListStore::iterator row = store->get_iter(path); + gunichar ch = (*row)[getColumns()->code]; + glyphs = ch; + } + } + + if (!glyphs.empty()) { + Glib::ustring combined; + gchar *str = sp_te_get_string_multiline(textItem); + if (str) { + combined = str; + g_free(str); + str = 0; + } + combined += glyphs; + sp_te_set_repr_text_multiline(textItem, combined.c_str()); + sp_document_done(targetDesktop->doc(), SP_VERB_CONTEXT_TEXT, _("Append text")); + } } } @@ -535,6 +616,7 @@ void GlyphsPanel::glyphSelectionChanged() gchar * tmp = g_strdup_printf("U+%04X %s", ch, scriptName.c_str()); label->set_text(tmp); } + calcCanInsert(); } void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*font*/, GlyphsPanel *self) @@ -544,6 +626,52 @@ void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*f } } +void GlyphsPanel::selectionModifiedCB(guint flags) +{ + bool style = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG )) != 0 ); + + bool content = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG | + SP_TEXT_CONTENT_MODIFIED_FLAG )) != 0 ); + + readSelection(style, content); +} + +void GlyphsPanel::calcCanInsert() +{ + int items = 0; + for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) { + if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) { + ++items; + } + } + + bool enable = (items == 1); + if (enable) { + enable &= (!iconView->get_selected_items().empty() + || (entry->get_text_length() > 0)); + } + + if (enable != insertBtn->is_sensitive()) { + insertBtn->set_sensitive(enable); + } +} + +void GlyphsPanel::readSelection( bool updateStyle, bool /*updateContent*/ ) +{ + calcCanInsert(); + + if (targetDesktop && updateStyle) { + //SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + + //int result_family = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTFAMILY); + //int result_style = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTSTYLE); + //int result_numbers = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + + //sp_style_unref(query); + } +} + void GlyphsPanel::rebuild() { diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index 602f9b5c9..1a01aebca 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -66,12 +66,17 @@ private: void glyphActivated(Gtk::TreeModel::Path const & path); void glyphSelectionChanged(); void setTargetDesktop(SPDesktop *desktop); + void selectionModifiedCB(guint flags); + void readSelection( bool updateStyle, bool updateContent ); + void calcCanInsert(); + void insertText(); Glib::RefPtr store; Gtk::IconView *iconView; Gtk::Entry *entry; Gtk::Label *label; + Gtk::Button *insertBtn; #if GLIB_CHECK_VERSION(2,14,0) Gtk::ComboBoxText *scriptCombo; #endif //GLIB_CHECK_VERSION(2,14,0) @@ -79,11 +84,9 @@ private: SPFontSelector *fsel; SPDesktop *targetDesktop; DesktopTracker deskTrack; - sigc::connection iconActiveConn; - sigc::connection iconSelectConn; - sigc::connection scriptSelectConn; - sigc::connection rangeSelectConn; - sigc::connection desktopChangeConn; + + std::vector instanceConns; + std::vector desktopConns; }; -- cgit v1.2.3 From d8f0652333b6e13136fb0796bd9de65a487fe786 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 6 Apr 2010 00:29:20 -0700 Subject: Fixed use of dialogs in more than one window, and tile problem with selection. Fixes bug #556233. Fixed bugs: - https://launchpad.net/bugs/556233 (bzr r9297) --- src/ui/dialog/icon-preview.cpp | 9 +++---- src/ui/dialog/tile.cpp | 60 +++++++++++++++++++++++------------------- src/ui/dialog/tile.h | 5 +--- 3 files changed, 38 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 088f63031..a210fe163 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -45,14 +45,13 @@ namespace UI { namespace Dialogs { -IconPreviewPanel& -IconPreviewPanel::getInstance() +IconPreviewPanel &IconPreviewPanel::getInstance() { - static IconPreviewPanel &instance = *new IconPreviewPanel(); + IconPreviewPanel *instance = new IconPreviewPanel(); - instance.refreshPreview(); + instance->refreshPreview(); - return instance; + return *instance; } //######################################################################### diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp index e0191c589..6be346582 100644 --- a/src/ui/dialog/tile.cpp +++ b/src/ui/dialog/tile.cpp @@ -31,6 +31,7 @@ #include "sp-item.h" #include "widgets/icon.h" #include "tile.h" +#include "desktop.h" /* * Sort items by their x co-ordinates, taking account of y (keeps rows intact) @@ -161,7 +162,7 @@ void TileDialog::Grid_Arrange () sp_document_ensure_up_to_date(sp_desktop_document(desktop)); Inkscape::Selection *selection = sp_desktop_selection (desktop); - const GSList *items = selection->itemList(); + const GSList *items = selection ? selection->itemList() : 0; cnt=0; for (; items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); @@ -193,6 +194,7 @@ void TileDialog::Grid_Arrange () // require the sorting done before we can calculate row heights etc. + g_return_if_fail(selection); const GSList *items2 = selection->itemList(); GSList *rev = g_slist_copy((GSList *) items2); GSList *sorted = NULL; @@ -373,7 +375,8 @@ void TileDialog::on_row_spinbutton_changed() updating = true; SPDesktop *desktop = getDesktop(); - Inkscape::Selection *selection = sp_desktop_selection (desktop); + Inkscape::Selection *selection = desktop ? desktop->selection : 0; + g_return_if_fail( selection ); GSList const *items = selection->itemList(); int selcount = g_slist_length((GSList *)items); @@ -398,7 +401,8 @@ void TileDialog::on_col_spinbutton_changed() // in turn, prevent listener from responding updating = true; SPDesktop *desktop = getDesktop(); - Inkscape::Selection *selection = sp_desktop_selection (desktop); + Inkscape::Selection *selection = desktop ? desktop->selection : 0; + g_return_if_fail(selection); GSList const *items = selection->itemList(); int selcount = g_slist_length((GSList *)items); @@ -560,32 +564,33 @@ void TileDialog::updateSelection() // in turn, prevent listener from responding updating = true; SPDesktop *desktop = getDesktop(); - Inkscape::Selection *selection = sp_desktop_selection (desktop); - const GSList *items = selection->itemList(); - int selcount = g_slist_length((GSList *)items); - - if (NoOfColsSpinner.get_value()>1 && NoOfRowsSpinner.get_value()>1){ - // Update the number of rows assuming number of columns wanted remains same. - double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value()); - NoOfRowsSpinner.set_value(NoOfRows); - - // if the selection has less than the number set for one row, reduce it appropriately - if (selcountsetInt("/dialogs/gridtiler/NoOfCols", NoOfCols); + Inkscape::Selection *selection = desktop ? desktop->selection : 0; + GSList const *items = selection ? selection->itemList() : 0; + + if (items) { + int selcount = g_slist_length((GSList *)items); + + if (NoOfColsSpinner.get_value() > 1 && NoOfRowsSpinner.get_value() > 1){ + // Update the number of rows assuming number of columns wanted remains same. + double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value()); + NoOfRowsSpinner.set_value(NoOfRows); + + // if the selection has less than the number set for one row, reduce it appropriately + if (selcount < NoOfColsSpinner.get_value()) { + double NoOfCols = ceil(selcount / NoOfRowsSpinner.get_value()); + NoOfColsSpinner.set_value(NoOfCols); + prefs->setInt("/dialogs/gridtiler/NoOfCols", NoOfCols); + } + } else { + double PerRow = ceil(sqrt(selcount)); + double PerCol = ceil(sqrt(selcount)); + NoOfRowsSpinner.set_value(PerRow); + NoOfColsSpinner.set_value(PerCol); + prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast(PerCol)); } - } else { - double PerRow = ceil(sqrt(selcount)); - double PerCol = ceil(sqrt(selcount)); - NoOfRowsSpinner.set_value(PerRow); - NoOfColsSpinner.set_value(PerCol); - prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast(PerCol)); - } - updating=false; - + updating = false; } @@ -632,7 +637,8 @@ TileDialog::TileDialog() SPDesktop *desktop = getDesktop(); - Inkscape::Selection *selection = sp_desktop_selection (desktop); + Inkscape::Selection *selection = desktop ? desktop->selection : 0; + g_return_if_fail( selection ); int selcount = 1; if (!selection->isEmpty()) { GSList const *items = selection->itemList(); diff --git a/src/ui/dialog/tile.h b/src/ui/dialog/tile.h index 075b2b33f..9ade64935 100644 --- a/src/ui/dialog/tile.h +++ b/src/ui/dialog/tile.h @@ -66,10 +66,7 @@ public: void VertAlign_changed(); void HorizAlign_changed(); - static TileDialog& getInstance() { - static TileDialog instance; - return instance; - } + static TileDialog& getInstance() { return *new TileDialog(); } private: TileDialog(TileDialog const &d); // no copy -- cgit v1.2.3 From 95a0c8412e84f5e0cc1d9a63fce2be75f9fa517e Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 6 Apr 2010 16:11:54 +0200 Subject: Revert the inverted coordinate system fix. 3D Boxes and guides require an XML-level backwards compatibility mechanism to fix properly, and it's too late in the 0.48 cycle to introduce it. (bzr r9298) --- src/desktop.cpp | 19 ++-- src/document.cpp | 13 ++- src/extension/internal/cairo-renderer.cpp | 6 +- src/extension/internal/grid.cpp | 18 ++-- src/extension/internal/latex-text-renderer.cpp | 3 +- src/flood-context.cpp | 4 +- src/helper/pixbuf-ops.cpp | 2 +- src/helper/png-write.cpp | 21 +++- src/knot-holder-entity.cpp | 129 ++++++++++++++----------- src/select-context.cpp | 24 ++--- src/selection-chemistry.cpp | 14 +-- src/seltrans-handles.cpp | 24 ++--- src/sp-guide.cpp | 6 +- src/sp-item.cpp | 6 +- src/sp-object-repr.cpp | 17 ++-- src/sp-object-repr.h | 2 +- src/spray-context.cpp | 6 +- src/text-context.cpp | 2 +- src/tweak-context.cpp | 8 +- src/ui/dialog/align-and-distribute.cpp | 12 +-- src/ui/tool/control-point-selection.cpp | 8 +- src/ui/tool/multi-path-manipulator.cpp | 6 +- src/ui/tool/path-manipulator.cpp | 2 +- src/ui/tool/transform-handle-set.cpp | 24 ++--- src/widgets/desktop-widget.cpp | 8 +- 25 files changed, 217 insertions(+), 167 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index 6690e0af1..52f172577 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -158,7 +158,7 @@ SPDesktop::SPDesktop() : _active( false ), _w2d(), _d2w(), - _doc2dt( Geom::identity() ), + _doc2dt( Geom::Scale(1, -1) ), grids_visible( false ) { _d2w.setIdentity(); @@ -272,6 +272,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid /* Connect event for page resize */ + _doc2dt[5] = sp_document_height (document); sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -724,8 +725,8 @@ SPDesktop::point() const if (p[Geom::X] >= r0[Geom::X] && p[Geom::X] <= r1[Geom::X] && - p[Geom::Y] >= r0[Geom::Y] && - p[Geom::Y] <= r1[Geom::Y]) + p[Geom::Y] >= r1[Geom::Y] && + p[Geom::Y] <= r0[Geom::Y]) { return p; } else { @@ -792,8 +793,8 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double int clear = FALSE; if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) { // zoom changed - set new zoom factors - _d2w = Geom::Scale(newscale); - _w2d = Geom::Scale(1/newscale); + _d2w = Geom::Scale(newscale, -newscale); + _w2d = Geom::Scale(1/newscale, 1/-newscale); sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w); clear = TRUE; signal_zoom_changed.emit(_d2w.descrim()); @@ -801,10 +802,10 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double /* Calculate top left corner (in document pixels) */ x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale; - y0 = cy - 0.5 * viewbox.dimensions()[Geom::Y] / newscale; + y1 = cy + 0.5 * viewbox.dimensions()[Geom::Y] / newscale; /* Scroll */ - sp_canvas_scroll_to (canvas, x0 * newscale - border, y0 * newscale - border, clear); + sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ sp_box3d_context_update_lines(event_context); @@ -828,7 +829,8 @@ Geom::Rect SPDesktop::get_display_area() const double const scale = _d2w[0]; - return viewbox * (1./scale); + return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale), + Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale)); } /** @@ -1543,6 +1545,7 @@ SPDesktop::onDocumentURISet (gchar const* uri) void SPDesktop::onDocumentResized (gdouble width, gdouble height) { + _doc2dt[5] = height; sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); Geom::Rect const a(Geom::Point(0, 0), Geom::Point(width, height)); SP_CTRLRECT(page)->setRectangle(a); diff --git a/src/document.cpp b/src/document.cpp index aeafaf1f9..101c54e30 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -327,7 +327,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, document->base = NULL; document->name = g_strdup(name); - sp_object_repr_build_tree(document, rroot); + document->root = sp_object_repr_build_tree(document, rroot); /* fixme: Not sure about this, but lets assume ::build updates */ rroot->setAttribute("inkscape:version", Inkscape::version_string); @@ -662,6 +662,7 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double const w = rect.width(); double const h = rect.height(); + double const old_height = sp_document_height(this); SPUnit const &px(sp_unit_get_by_id(SP_UNIT_PX)); /* in px */ @@ -695,14 +696,16 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) } Geom::Rect const rect_with_margins( - rect.min() - Geom::Point(margin_left, margin_top), - rect.max() + Geom::Point(margin_right, margin_bottom)); + rect.min() - Geom::Point(margin_left, margin_bottom), + rect.max() + Geom::Point(margin_right, margin_top)); sp_document_set_width(this, rect_with_margins.width(), &px); sp_document_set_height(this, rect_with_margins.height(), &px); - Geom::Translate const tr(-to_2geom(rect_with_margins.min())); + Geom::Translate const tr( + Geom::Point(0, old_height - rect_with_margins.height()) + - to_2geom(rect_with_margins.min())); SP_GROUP(root)->translateChildItems(tr); if(nv) { @@ -710,7 +713,7 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) nv->translateGuides(tr2); // update the viewport so the drawing appears to stay where it was - nv->scrollAllDesktops(-tr2[0], -tr2[1], false); + nv->scrollAllDesktops(-tr2[0], tr2[1], false); } } diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 52f070591..6e4bb3b7e 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -631,8 +631,12 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page if (ret && !pageBoundingBox) { + double high = sp_document_height(doc); + if (ctx->_vector_based_target) + high *= PT_PER_PX; + Geom::Matrix tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), - -d.y0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); + (d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); ctx->transform(&tp); } diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index deef367a4..d4b35b261 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -46,12 +46,13 @@ Grid::load (Inkscape::Extension::Extension */*module*/) namespace { -void build_lines(int axis, Geom::Rect bounding_area, float offset, - float spacing, SVG::PathString &path_data) +Glib::ustring build_lines(int axis, Geom::Rect bounding_area, + float offset, float spacing) { Geom::Point point_offset(0.0, 0.0); point_offset[axis] = offset; + SVG::PathString path_data; for (Geom::Point start_point = bounding_area.min(); start_point[axis] + offset <= (bounding_area.max())[axis]; start_point[axis] += spacing) { @@ -61,6 +62,8 @@ void build_lines(int axis, Geom::Rect bounding_area, float offset, path_data.moveTo(start_point + point_offset) .lineTo(end_point + point_offset); } + + return path_data; } } @@ -86,8 +89,10 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc if (bounds) { bounding_area = *bounds; } - Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], bounding_area.min()[Geom::Y]), - Geom::Point(bounding_area.max()[Geom::X], bounding_area.max()[Geom::Y])); + + gdouble doc_height = sp_document_height(document->doc()); + Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]), + Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y])); bounding_area = temprec; } @@ -98,9 +103,10 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc float offsets[2] = { module->get_param_float("xoffset"), module->get_param_float("yoffset") }; - SVG::PathString path_data; + Glib::ustring path_data(""); for ( int axis = 0 ; axis < 2 ; ++axis ) { - build_lines(axis, bounding_area, offsets[axis], spacings[axis], path_data); + path_data += build_lines(axis, bounding_area, + offsets[axis], spacings[axis]); } Inkscape::XML::Document * xml_doc = sp_document_repr_doc(document->doc()); diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 1fdf1d7fd..28bba1beb 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -501,8 +501,7 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * if (!pageBoundingBox) { - Geom::Translate t(-d->min()[Geom::X], d->max()[Geom::Y] - sp_document_height(doc)); - push_transform( t ); + push_transform( Geom::Translate( - d->min() ) ); } // flip y-axis diff --git a/src/flood-context.cpp b/src/flood-context.cpp index 910b5dd80..612ae1cfc 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -798,7 +798,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even unsigned int height = (int)ceil(screen.height() * zoom_scale * padding); Geom::Point origin(screen.min()[Geom::X], - screen.min()[Geom::Y]); + sp_document_height(document) - screen.height() - screen.min()[Geom::Y]); origin[Geom::X] = origin[Geom::X] + (screen.width() * ((1 - padding) / 2)); origin[Geom::Y] = origin[Geom::Y] + (screen.height() * ((1 - padding) / 2)); @@ -905,7 +905,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even } for (unsigned int i = 0; i < fill_points.size(); i++) { - Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, (fill_points[i][Geom::Y] / zoom_scale)) * affine; + Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, sp_document_height(document) + (fill_points[i][Geom::Y] / zoom_scale)) * affine; pw[Geom::X] = (int)MIN(width - 1, MAX(0, pw[Geom::X])); pw[Geom::Y] = (int)MIN(height - 1, MAX(0, pw[Geom::Y])); diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index c26d55b8b..3be63aa68 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -113,7 +113,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, double padding = 1.0; Geom::Point origin(screen.min()[Geom::X], - screen.min()[Geom::Y]); + sp_document_height(doc) - screen[Geom::Y].extent() - screen.min()[Geom::Y]); origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2)); origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2)); diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index 8eb9e27bf..b1c135db0 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -424,9 +424,24 @@ sp_export_png_file(SPDocument *doc, gchar const *filename, sp_document_ensure_up_to_date(doc); - /* Calculate translation */ - Geom::Point translation = Geom::Point(-area[Geom::X][0], -area[Geom::Y][0]); - + /* Calculate translation by transforming to document coordinates (flipping Y)*/ + Geom::Point translation = Geom::Point(-area[Geom::X][0], area[Geom::Y][1] - sp_document_height(doc)); + + /* This calculation is only valid when assumed that (x0,y0)= area.corner(0) and (x1,y1) = area.corner(2) + * 1) a[0] * x0 + a[2] * y1 + a[4] = 0.0 + * 2) a[1] * x0 + a[3] * y1 + a[5] = 0.0 + * 3) a[0] * x1 + a[2] * y1 + a[4] = width + * 4) a[1] * x0 + a[3] * y0 + a[5] = height + * 5) a[1] = 0.0; + * 6) a[2] = 0.0; + * + * (1,3) a[0] * x1 - a[0] * x0 = width + * a[0] = width / (x1 - x0) + * (2,4) a[3] * y0 - a[3] * y1 = height + * a[3] = height / (y0 - y1) + * (1) a[4] = -a[0] * x0 + * (2) a[5] = -a[3] * y1 + */ Geom::Matrix const affine(Geom::Translate(translation) * Geom::Scale(width / area.width(), diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 6fcb26247..2d0d5eb02 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -135,16 +135,21 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: /* TODO: this pattern manipulation is not able to handle general transformation matrices. Only matrices that are the result of a pure scale times a pure rotation. */ -Geom::Point -PatternKnotHolderEntityXY::knot_get() +static gdouble sp_pattern_extract_theta(SPPattern *pat) { - SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); + Geom::Matrix transf = pat->patternTransform; + return Geom::atan2(transf.xAxis()); +} - gdouble x = 0; - gdouble y = -pattern_height(pat); +static Geom::Point sp_pattern_extract_scale(SPPattern *pat) +{ + Geom::Matrix transf = pat->patternTransform; + return Geom::Point( transf.expansionX(), transf.expansionY() ); +} - Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; - return delta; +static Geom::Point sp_pattern_extract_trans(SPPattern const *pat) +{ + return Geom::Point(pat->patternTransform[4], pat->patternTransform[5]); } void @@ -164,23 +169,32 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori } if (state) { - Geom::Point knot_relpos(0, -pattern_height(pat)); - Geom::Point const q = p_snapped - (knot_relpos * pat->patternTransform); + Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat); sp_item_adjust_pattern(item, Geom::Matrix(Geom::Translate(q))); } item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +Geom::Point +PatternKnotHolderEntityXY::knot_get() +{ + SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); + return sp_pattern_extract_trans(pat); +} + Geom::Point PatternKnotHolderEntityAngle::knot_get() { SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - gdouble x = pattern_width(pat); - gdouble y = -pattern_height(pat); - - Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; + gdouble x = (pattern_width(pat)); + gdouble y = 0; + Geom::Point delta = Geom::Point(x,y); + Geom::Point scale = sp_pattern_extract_scale(pat); + gdouble theta = sp_pattern_extract_theta(pat); + delta = delta * Geom::Matrix(Geom::Scale(scale))*Geom::Matrix(Geom::Rotate(theta)); + delta = delta + sp_pattern_extract_trans(pat); return delta; } @@ -192,38 +206,24 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const & SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - // rotate pattern around XY knot position - Geom::Point knot_relpos(pattern_width(pat), -pattern_height(pat)); - Geom::Point xy_knot_relpos(0, -pattern_height(pat)); - Geom::Point transform_origin = xy_knot_relpos * pat->patternTransform; - - Geom::Point oldp = (knot_relpos * pat->patternTransform) - transform_origin; - Geom::Point newp = p - transform_origin; - - gdouble theta = Geom::angle_between(oldp, newp); + // get the angle from pattern 0,0 to the cursor pos + Geom::Point delta = p - sp_pattern_extract_trans(pat); + gdouble theta = atan2(delta); if ( state & GDK_CONTROL_MASK ) { theta = sp_round(theta, M_PI/snaps); } - Geom::Matrix rot = Geom::Matrix(Geom::Translate(-transform_origin)) - * Geom::Rotate(theta) - * Geom::Translate(transform_origin); - sp_item_adjust_pattern(item, rot); + // get the scale from the current transform so we can keep it. + Geom::Point scl = sp_pattern_extract_scale(pat); + Geom::Matrix rot = Geom::Matrix(Geom::Scale(scl)) * Geom::Matrix(Geom::Rotate(theta)); + Geom::Point const t = sp_pattern_extract_trans(pat); + rot[4] = t[Geom::X]; + rot[5] = t[Geom::Y]; + sp_item_adjust_pattern(item, rot, true); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -Geom::Point -PatternKnotHolderEntityScale::knot_get() -{ - SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); - - gdouble x = pattern_width(pat); - gdouble y = 0; - Geom::Point delta = Geom::Point(x,y) * pat->patternTransform; - return delta; -} - void PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { @@ -232,32 +232,49 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const & // FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used. Geom::Point p_snapped = snap_knot_position(p); - Geom::Point knot_relpos(pattern_width(pat), 0); - Geom::Point xy_knot_relpos(0, -pattern_height(pat)); - Geom::Point transform_origin = xy_knot_relpos * pat->patternTransform; - - // do the scaling in pattern coordinate space - Geom::Point oldp = knot_relpos - xy_knot_relpos; - Geom::Point newp = p_snapped * pat->patternTransform.inverse() - xy_knot_relpos; - - if (Geom::are_near(newp.length(), 0)) return; + // get angle from current transform + gdouble theta = sp_pattern_extract_theta(pat); - Geom::Scale s(1); - if (state & GDK_CONTROL_MASK) { - // uniform scaling - s = Geom::Scale(oldp * (newp.length() * oldp.length())); + // Get the new scale from the position of the knotholder + Geom::Point d = p_snapped - sp_pattern_extract_trans(pat); + gdouble pat_x = pattern_width(pat); + gdouble pat_y = pattern_height(pat); + Geom::Scale scl(1); + if ( state & GDK_CONTROL_MASK ) { + // if ctrl is pressed: use 1:1 scaling + gdouble pat_h = hypot(pat_x, pat_y); + scl = Geom::Scale(d.length() / pat_h); } else { - s = Geom::Scale(newp[Geom::X] / oldp[Geom::X], newp[Geom::Y] / oldp[Geom::Y]); + d *= Geom::Rotate(-theta); + scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y); } - Geom::Matrix scl = Geom::Matrix(Geom::Translate(-xy_knot_relpos)) - * s - * Geom::Translate(xy_knot_relpos) - * pat->patternTransform; - sp_item_adjust_pattern(item, scl, true); + Geom::Matrix rot = (Geom::Matrix)scl * Geom::Rotate(theta); + + Geom::Point const t = sp_pattern_extract_trans(pat); + rot[4] = t[Geom::X]; + rot[5] = t[Geom::Y]; + sp_item_adjust_pattern(item, rot, true); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } + +Geom::Point +PatternKnotHolderEntityScale::knot_get() +{ + SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style)); + + gdouble x = pattern_width(pat); + gdouble y = pattern_height(pat); + Geom::Point delta = Geom::Point(x,y); + Geom::Matrix a = pat->patternTransform; + a[4] = 0; + a[5] = 0; + delta = delta * a; + delta = delta + sp_pattern_extract_trans(pat); + return delta; +} + /* Local Variables: mode:c++ diff --git a/src/select-context.cpp b/src/select-context.cpp index 9035021d6..028c8634b 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -765,12 +765,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__ALT) { // alt - if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*-10); // shift - else sp_selection_move_screen(desktop, 0, mul*-1); // no shift + if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*10); // shift + else sp_selection_move_screen(desktop, 0, mul*1); // no shift } else { // no alt - if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*-10*nudge); // shift - else sp_selection_move(desktop, 0, mul*-nudge); // no shift + if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*10*nudge); // shift + else sp_selection_move(desktop, 0, mul*nudge); // no shift } ret = TRUE; } @@ -799,12 +799,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__ALT) { // alt - if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*10); // shift - else sp_selection_move_screen(desktop, 0, mul*1); // no shift + if (MOD__SHIFT) sp_selection_move_screen(desktop, 0, mul*-10); // shift + else sp_selection_move_screen(desktop, 0, mul*-1); // no shift } else { // no alt - if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*10*nudge); // shift - else sp_selection_move(desktop, 0, mul*nudge); // no shift + if (MOD__SHIFT) sp_selection_move(desktop, 0, mul*-10*nudge); // shift + else sp_selection_move(desktop, 0, mul*-nudge); // no shift } ret = TRUE; } @@ -842,9 +842,9 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) get_group0_keyval(&event->key), 0); // with any mask sp_selection_rotate_screen(selection, mul*1); } else if (MOD__CTRL) { - sp_selection_rotate(selection, -90); + sp_selection_rotate(selection, 90); } else if (snaps) { - sp_selection_rotate(selection, -180/snaps); + sp_selection_rotate(selection, 180/snaps); } ret = TRUE; break; @@ -854,9 +854,9 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) get_group0_keyval(&event->key), 0); // with any mask sp_selection_rotate_screen(selection, -1*mul); } else if (MOD__CTRL) { - sp_selection_rotate(selection, 90); + sp_selection_rotate(selection, -90); } else if (snaps) { - sp_selection_rotate(selection, 180/snaps); + sp_selection_rotate(selection, -180/snaps); } ret = TRUE; break; diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 452a4ff9d..730467ee5 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2273,8 +2273,9 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = -*c; - Geom::Matrix move = Geom::Translate(move_p); + Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - *c; + move_p[Geom::Y] = -move_p[Geom::Y]; + Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); GSList *items = g_slist_copy((GSList *) selection->itemList()); @@ -2395,7 +2396,8 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = -(r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); + Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); + move_p[Geom::Y] = -move_p[Geom::Y]; Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); GSList *items = g_slist_copy((GSList *) selection->itemList()); @@ -2746,12 +2748,12 @@ sp_selection_create_bitmap_copy(SPDesktop *desktop) Geom::Matrix t; double shift_x = bbox.x0; - double shift_y = bbox.y0; + double shift_y = bbox.y1; if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid shift_x = round(shift_x); - shift_y = round(shift_y); + shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone } - t = Geom::Translate(shift_x, shift_y) * eek.inverse(); + t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse(); // Do the export sp_export_png_file(document, filepath, diff --git a/src/seltrans-handles.cpp b/src/seltrans-handles.cpp index ba18b2a5b..95b680c5e 100644 --- a/src/seltrans-handles.cpp +++ b/src/seltrans-handles.cpp @@ -5,24 +5,24 @@ SPSelTransHandle const handles_scale[] = { //anchor cursor control action request x y - {GTK_ANCHOR_NE, GDK_TOP_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1}, - {GTK_ANCHOR_N, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1}, - {GTK_ANCHOR_NW, GDK_TOP_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1}, + {GTK_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1}, + {GTK_ANCHOR_S, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1}, + {GTK_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1}, {GTK_ANCHOR_W, GDK_RIGHT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 1, 0.5}, - {GTK_ANCHOR_SW, GDK_BOTTOM_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0}, - {GTK_ANCHOR_S, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0}, - {GTK_ANCHOR_SE, GDK_BOTTOM_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0}, + {GTK_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0}, + {GTK_ANCHOR_N, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0}, + {GTK_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0}, {GTK_ANCHOR_E, GDK_LEFT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0, 0.5} }; SPSelTransHandle const handles_rotate[] = { - {GTK_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1}, - {GTK_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1}, - {GTK_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1}, + {GTK_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1}, + {GTK_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1}, + {GTK_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1}, {GTK_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 7, sp_sel_trans_skew, sp_sel_trans_skew_request, 1, 0.5}, - {GTK_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0}, - {GTK_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0}, - {GTK_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0}, + {GTK_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0}, + {GTK_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0}, + {GTK_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0}, {GTK_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, sp_sel_trans_skew, sp_sel_trans_skew_request, 0, 0.5} }; diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index def039937..f5edf7d97 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -217,14 +217,12 @@ static void sp_guide_set(SPObject *object, unsigned int key, const gchar *value) success += sp_svg_number_read_d(strarray[1], &newy); g_strfreev (strarray); if (success == 2) { - // Desktop coords fix - guide->point_on_line = Geom::Point(newx, sp_document_height(guide->document) - newy); + guide->point_on_line = Geom::Point(newx, newy); } else if (success == 1) { // before 0.46 style guideline definition. const gchar *attr = SP_OBJECT_REPR(object)->attribute("orientation"); if (attr && !strcmp(attr, "horizontal")) { - // Desktop coords fix - guide->point_on_line = Geom::Point(0, sp_document_height(guide->document) - newx); + guide->point_on_line = Geom::Point(0, newx); } else { guide->point_on_line = Geom::Point(newx, 0); } diff --git a/src/sp-item.cpp b/src/sp-item.cpp index f60a2b27a..c4411e47d 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -1574,7 +1574,8 @@ Geom::Matrix sp_item_i2d_affine(SPItem const *item) g_assert(SP_IS_ITEM(item)); Geom::Matrix const ret( sp_item_i2doc_affine(item) - ); + * Geom::Scale(1, -1) + * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); return ret; } @@ -1587,7 +1588,8 @@ void sp_item_set_i2d_affine(SPItem *item, Geom::Matrix const &i2dt) if (SP_OBJECT_PARENT(item)) { dt2p = sp_item_i2d_affine((SPItem *) SP_OBJECT_PARENT(item)).inverse(); } else { - dt2p = ( Geom::identity() ); + dt2p = ( Geom::Translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) + * Geom::Scale(1, -1) ); } Geom::Matrix const i2p( i2dt * dt2p ); diff --git a/src/sp-object-repr.cpp b/src/sp-object-repr.cpp index e32819746..62143e3ab 100644 --- a/src/sp-object-repr.cpp +++ b/src/sp-object-repr.cpp @@ -91,9 +91,9 @@ static unsigned const N_NAME_TYPES = SODIPODI_TYPE + 1; static GType name_to_gtype(NameType name_type, gchar const *name); /** - * Construct an SPRoot and all its descendents from the given XML representation. + * Construct an SPRoot and all its descendents from the given repr. */ -void +SPObject * sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr) { g_assert(document != NULL); @@ -103,14 +103,13 @@ sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr) g_assert(name != NULL); GType const type = name_to_gtype(REPR_NAME, name); g_assert(g_type_is_a(type, SP_TYPE_ROOT)); + gpointer newobj = g_object_new(type, 0); + g_assert(newobj != NULL); + SPObject *const object = SP_OBJECT(newobj); + g_assert(object != NULL); + sp_object_invoke_build(object, document, repr, FALSE); - // create and assign root - SPObject *root = SP_OBJECT(g_object_new(type, 0)); - g_assert(root != NULL); - document->root = root; - - // recursively create SP tree elements - sp_object_invoke_build(root, document, repr, FALSE); + return object; } GType diff --git a/src/sp-object-repr.h b/src/sp-object-repr.h index 43aead41e..f3a80f83c 100644 --- a/src/sp-object-repr.h +++ b/src/sp-object-repr.h @@ -21,7 +21,7 @@ class Node; } -void sp_object_repr_build_tree (SPDocument *document, Inkscape::XML::Node *repr); +SPObject *sp_object_repr_build_tree (SPDocument *document, Inkscape::XML::Node *repr); GType sp_repr_type_lookup (Inkscape::XML::Node *repr); diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 9b9caee15..2bdac197f 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -501,7 +501,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); //Move the cursor p Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } } @@ -556,7 +556,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(_scale,_scale)); sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale)); sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); // union and duplication selection->clear(); @@ -593,7 +593,7 @@ bool sp_spray_recursive(SPDesktop *desktop, sp_spray_scale_rel(center,desktop,item_copied, Geom::Scale(scale,scale)); sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle)); Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint()); - sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y])); Inkscape::GC::release(clone); diff --git a/src/text-context.cpp b/src/text-context.cpp index 984876f78..4f89bd1e1 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -684,7 +684,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons // Cursor height is defined by the new text object's font size; it needs to be set // articifically here, for the text object does not exist yet: double cursor_height = sp_desktop_get_font_size_tool(desktop); - sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), dtp, dtp - Geom::Point(0, cursor_height)); + sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), dtp, dtp + Geom::Point(0, cursor_height)); event_context->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type text; Enter to start new line.")); // FIXME:: this is a copy of a string from _update_cursor below, do not desync event_context->within_tolerance = false; diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index a34a61f53..13299b5a4 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -448,7 +448,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * vector; - sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } } @@ -462,7 +462,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * (reverse? (a->midpoint() - p) : (p - a->midpoint())); - sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } } @@ -477,7 +477,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * Geom::Point(cos(dp)*dr, sin(dp)*dr); - sp_item_move_rel(item, Geom::Translate(move[Geom::X], move[Geom::Y])); + sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } } @@ -502,7 +502,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { - double angle = (reverse? -force : force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; + double angle = (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; sp_item_rotate_rel(item, Geom::Rotate(angle)); did = true; } diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index f27c49f61..a75a8d68d 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -252,11 +252,11 @@ ActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = { {.5, .5, 0., 0., .5, .5, 0., 0.}, {0., 1., 0., 0., 0., 1., 0., 0.}, {0., 1., 0., 0., 1., 0., 0., 0.}, - {0., 0., 1., 0., 0., 0., 0., 1.}, - {0., 0., 1., 0., 0., 0., 1., 0.}, - {0., 0., .5, .5, 0., 0., .5, .5}, + {0., 0., 0., 1., 0., 0., 1., 0.}, {0., 0., 0., 1., 0., 0., 0., 1.}, - {0., 0., 0., 1., 0., 0., 1., 0.} + {0., 0., .5, .5, 0., 0., .5, .5}, + {0., 0., 1., 0., 0., 0., 1., 0.}, + {0., 0., 1., 0., 0., 0., 0., 1.} }; BBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) : @@ -866,13 +866,13 @@ AlignAndDistribute::AlignAndDistribute() addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_TOP, _("Distribute top edges equidistantly"), - 1, 1, false, Geom::Y, 1., 0.); + 1, 1, false, Geom::Y, 0, 1); addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_CENTER, _("Distribute centers equidistantly vertically"), 1, 2, false, Geom::Y, .5, .5); addDistributeButton(INKSCAPE_ICON_DISTRIBUTE_VERTICAL_BOTTOM, _("Distribute bottom edges equidistantly"), - 1, 3, false, Geom::Y, 0., 1.); + 1, 3, false, Geom::Y, 1., 0.); //Baseline distribs addBaselineButton(INKSCAPE_ICON_DISTRIBUTE_HORIZONTAL_BASELINE, diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index c7fc8a3cc..f880d2ddf 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -545,11 +545,11 @@ bool ControlPointSelection::event(GdkEvent *event) case GDK_Up: case GDK_KP_Up: case GDK_KP_8: - return _keyboardMove(event->key, Geom::Point(0, -1)); + return _keyboardMove(event->key, Geom::Point(0, 1)); case GDK_Down: case GDK_KP_Down: case GDK_KP_2: - return _keyboardMove(event->key, Geom::Point(0, 1)); + return _keyboardMove(event->key, Geom::Point(0, -1)); case GDK_Right: case GDK_KP_Right: case GDK_KP_6: @@ -561,9 +561,9 @@ bool ControlPointSelection::event(GdkEvent *event) // rotates case GDK_bracketleft: - return _keyboardRotate(event->key, -1); - case GDK_bracketright: return _keyboardRotate(event->key, 1); + case GDK_bracketright: + return _keyboardRotate(event->key, -1); // scaling case GDK_less: diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 392518207..2025a12d7 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -470,10 +470,12 @@ bool MultiPathManipulator::event(GdkEvent *event) // single handle functions // rotation case GDK_bracketleft: - pm.rotateHandle(n, which, -1, one_pixel); + case GDK_braceleft: + pm.rotateHandle(n, which, 1, one_pixel); break; case GDK_bracketright: - pm.rotateHandle(n, which, 1, one_pixel); + case GDK_braceright: + pm.rotateHandle(n, which, -1, one_pixel); break; // adjust length case GDK_period: diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index a50be873a..66f72f379 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -1193,7 +1193,7 @@ void PathManipulator::_updateOutline() Geom::Point at = j->pointAt(0.5); Geom::Point ut = j->unitTangentAt(0.5); // rotate the point - ut *= Geom::Rotate(210.0 / 180.0 * M_PI); + ut *= Geom::Rotate(150.0 / 180.0 * M_PI); Geom::Point arrow_end = _desktop->w2d( _desktop->d2w(at) + Geom::unit_vector(_desktop->d2w(ut)) * 10.0); diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 4cbc5ed4d..1af848b96 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -34,17 +34,17 @@ namespace UI { namespace { Gtk::AnchorType corner_to_anchor(unsigned c) { switch (c % 4) { - case 0: return Gtk::ANCHOR_SE; - case 1: return Gtk::ANCHOR_SW; - case 2: return Gtk::ANCHOR_NW; - default: return Gtk::ANCHOR_NE; + case 0: return Gtk::ANCHOR_NE; + case 1: return Gtk::ANCHOR_NW; + case 2: return Gtk::ANCHOR_SW; + default: return Gtk::ANCHOR_SE; } } Gtk::AnchorType side_to_anchor(unsigned s) { switch (s % 4) { - case 0: return Gtk::ANCHOR_S; + case 0: return Gtk::ANCHOR_N; case 1: return Gtk::ANCHOR_W; - case 2: return Gtk::ANCHOR_N; + case 2: return Gtk::ANCHOR_S; default: return Gtk::ANCHOR_E; } } @@ -208,8 +208,8 @@ private: static Glib::RefPtr _corner_to_pixbuf(unsigned c) { sp_select_context_get_type(); switch (c % 2) { - case 0: return Glib::wrap(handles[0], true); - default: return Glib::wrap(handles[1], true); + case 0: return Glib::wrap(handles[1], true); + default: return Glib::wrap(handles[0], true); } } Geom::Point _sc_center; @@ -332,10 +332,10 @@ private: static Glib::RefPtr _corner_to_pixbuf(unsigned c) { sp_select_context_get_type(); switch (c % 4) { - case 0: return Glib::wrap(handles[4], true); - case 1: return Glib::wrap(handles[6], true); - case 2: return Glib::wrap(handles[8], true); - default: return Glib::wrap(handles[10], true); + case 0: return Glib::wrap(handles[10], true); + case 1: return Glib::wrap(handles[8], true); + case 2: return Glib::wrap(handles[6], true); + default: return Glib::wrap(handles[4], true); } } Geom::Point _rot_center; diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 48317aa3e..ab440595f 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1493,8 +1493,8 @@ sp_desktop_widget_update_vruler (SPDesktopWidget *dtw) NR::IRect viewbox = dtw->canvas->getViewboxIntegers(); double const scale = dtw->desktop->current_zoom(); - double s = viewbox.min()[Geom::Y] / scale - dtw->ruler_origin[Geom::Y]; - double e = viewbox.max()[Geom::Y] / scale - dtw->ruler_origin[Geom::Y]; + double s = viewbox.min()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; + double e = viewbox.max()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; gtk_ruler_set_range(GTK_RULER(dtw->vruler), s, e, GTK_RULER(dtw->vruler)->position, (e - s)); } @@ -1809,8 +1809,8 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) Geom::OptRect deskarea = Geom::unify(darea, sp_item_bbox_desktop(item)); /* Canvas region we always show unconditionally */ - Geom::Rect carea( Geom::Point(deskarea->left() * scale - 64, deskarea->top() * scale - 64), - Geom::Point(deskarea->right() * scale + 64, deskarea->bottom() * scale + 64) ); + Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64), + Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) ); Geom::Rect viewbox = dtw->canvas->getViewbox(); -- cgit v1.2.3 From 360f55458fff0b79cada7f59adf4eb710c1519fc Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 6 Apr 2010 16:47:48 +0200 Subject: Fix "show handles" button state on Ctrl+H (bzr r9299) --- src/widgets/toolbox.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 4b0d84d90..5c890333f 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -1289,6 +1289,31 @@ sp_node_toolbox_sel_modified (Inkscape::Selection *selection, guint /*flags*/, G //## Node Editing Toolbox ## //################################ +class ShowHandlesObserver + : public Inkscape::Preferences::Observer +{ +public: + ShowHandlesObserver(InkToggleAction *act) + : Inkscape::Preferences::Observer("/tools/nodes/show_handles") + , _act(act) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->addObserver(*this); + } + ~ShowHandlesObserver() { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->removeObserver(*this); + } + virtual void notify(Inkscape::Preferences::Entry const &v) { + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(_act), v.getBool()); + } + static void destroy(ShowHandlesObserver *s, InkToggleAction *) { + delete s; + } +private: + InkToggleAction *_act; +}; + static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1442,6 +1467,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_handles), desktop ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_handles", true) ); + ShowHandlesObserver *s = new ShowHandlesObserver(act); + g_object_weak_ref(G_OBJECT(act), (GWeakNotify) ShowHandlesObserver::destroy, (gpointer) s); } { -- cgit v1.2.3 From 2177dbe64b6ece6261b1d6827d202b608dd77501 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 8 Apr 2010 00:49:42 -0700 Subject: Cleanup of device internal handling and API. (bzr r9300) --- src/device-manager.cpp | 332 ++++++++++++++++++++++++++++++++++++++++++------ src/device-manager.h | 12 +- src/ui/dialog/input.cpp | 34 ++--- 3 files changed, 322 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/device-manager.cpp b/src/device-manager.cpp index 09fd7cb5f..29e15b05a 100644 --- a/src/device-manager.cpp +++ b/src/device-manager.cpp @@ -2,21 +2,33 @@ /* * Inkscape::DeviceManager - a view of input devices available. * - * Copyright 2006 Jon A. Cruz + * Copyright 2010 Jon A. Cruz * * Released under GNU GPL, read the file 'COPYING' for more information */ #include #include +#include +#include #include "device-manager.h" +#include "preferences.h" +#define noDEBUG_VERBOSE 1 static void createFakeList(); GdkDevice fakeout[5]; static GList* fakeList = 0; +static bool isValidDevice(GdkDevice *device) +{ + bool valid = true; + for (size_t i = 0; (i < G_N_ELEMENTS(fakeout)) && valid; i++) { + valid = (device != &fakeout[i]); + } + return valid; +} namespace Inkscape { @@ -33,6 +45,88 @@ static pair vals[] = { static std::map bitVals(vals, &vals[G_N_ELEMENTS(vals)]); +static const int RUNAWAY_MAX = 1000; + +static Glib::ustring getBaseDeviceName(Gdk::InputSource source) +{ + Glib::ustring name; + switch (source) { + case GDK_SOURCE_MOUSE: + name ="pointer"; + break; + case GDK_SOURCE_PEN: + name ="pen"; + break; + case GDK_SOURCE_ERASER: + name ="eraser"; + break; + case GDK_SOURCE_CURSOR: + name ="cursor"; + break; + default: + name = "tablet"; + } + return name; +} + +static std::map &getStringToAxis() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + mapping["ignore"] = Gdk::AXIS_IGNORE; + mapping["x"] = Gdk::AXIS_X; + mapping["y"] = Gdk::AXIS_Y; + mapping["pressure"] = Gdk::AXIS_PRESSURE; + mapping["xtilt"] = Gdk::AXIS_XTILT; + mapping["ytilt"] = Gdk::AXIS_YTILT; + mapping["wheel"] = Gdk::AXIS_WHEEL; + } + return mapping; +} + +std::map &getAxisToString() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + for (std::map::iterator it = getStringToAxis().begin(); it != getStringToAxis().end(); ++it) { + mapping.insert(std::make_pair(it->second, it->first)); + } + } + return mapping; +} + +static std::map &getStringToMode() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + mapping["disabled"] = Gdk::MODE_DISABLED; + mapping["screen"] = Gdk::MODE_SCREEN; + mapping["window"] = Gdk::MODE_WINDOW; + } + return mapping; +} + +std::map &getModeToString() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + for (std::map::iterator it = getStringToMode().begin(); it != getStringToMode().end(); ++it) { + mapping.insert(std::make_pair(it->second, it->first)); + } + } + return mapping; +} + + + InputDevice::InputDevice() : Glib::Object() {} @@ -41,6 +135,9 @@ InputDevice::~InputDevice() {} class InputDeviceImpl : public InputDevice { public: + InputDeviceImpl(GdkDevice* device, std::set &knownIDs); + virtual ~InputDeviceImpl() {} + virtual Glib::ustring getId() const {return id;} virtual Glib::ustring getName() const {return name;} virtual Gdk::InputSource getSource() const {return source;} @@ -55,14 +152,15 @@ public: virtual gint getLiveButtons() const {return liveButtons;} virtual void setLiveButtons(gint buttons) {liveButtons = buttons;} - - InputDeviceImpl(GdkDevice* device); - virtual ~InputDeviceImpl() {} + // internal methods not on public superclass: + virtual GdkDevice *getDevice() { return device; } private: InputDeviceImpl(InputDeviceImpl const &); // no copy void operator=(InputDeviceImpl const &); // no assign + static Glib::ustring createId(Glib::ustring const &id, Gdk::InputSource source, std::set &knownIDs); + GdkDevice* device; Glib::ustring id; Glib::ustring name; @@ -72,25 +170,25 @@ private: guint liveButtons; }; -class IdMatcher : public std::unary_function { +class IdMatcher : public std::unary_function&, bool> { public: IdMatcher(Glib::ustring const& target):target(target) {} - bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());} + bool operator ()(Glib::RefPtr& dev) {return dev && (target == dev->getId());} private: Glib::ustring const& target; }; -class LinkMatcher : public std::unary_function { +class LinkMatcher : public std::unary_function&, bool> { public: LinkMatcher(Glib::ustring const& target):target(target) {} - bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());} + bool operator ()(Glib::RefPtr& dev) {return dev && (target == dev->getLink());} private: Glib::ustring const& target; }; -InputDeviceImpl::InputDeviceImpl(GdkDevice* device) +InputDeviceImpl::InputDeviceImpl(GdkDevice* device, std::set &knownIDs) : InputDevice(), device(device), id(), @@ -100,27 +198,54 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device) liveAxes(0), liveButtons(0) { + id = createId(name, source, knownIDs); +} + + +Glib::ustring InputDeviceImpl::createId(Glib::ustring const &id, + Gdk::InputSource source, + std::set &knownIDs) +{ + // Start with only allowing printable ASCII. Check later for more refinements. + bool badName = id.empty() || !id.is_ascii(); + for (Glib::ustring::const_iterator it = id.begin(); (it != id.end()) && !badName; ++it) { + badName = *it < 0x20; + } + + Glib::ustring base; switch ( source ) { case Gdk::SOURCE_MOUSE: - id = "M:"; + base = "M:"; break; case Gdk::SOURCE_CURSOR: - id = "C:"; + base = "C:"; break; case Gdk::SOURCE_PEN: - id = "P:"; + base = "P:"; break; case Gdk::SOURCE_ERASER: - id = "E:"; + base = "E:"; break; default: - id = "?:"; + base = "?:"; } - id += name; -} + if (badName) { + base += getBaseDeviceName(source); + } else { + base += id; + } + // now ensure that all IDs become unique in a session. + int num = 1; + Glib::ustring result = base; + while ((knownIDs.find(result) != knownIDs.end()) && (num < RUNAWAY_MAX)) { + result = Glib::ustring::compose("%1%2", base, ++num); + } + knownIDs.insert(result); + return result; +} @@ -129,7 +254,12 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device) class DeviceManagerImpl : public DeviceManager { public: DeviceManagerImpl(); - virtual std::list getDevices(); + + virtual void loadConfig(); + virtual void saveConfig(); + + virtual std::list > getDevices(); + virtual sigc::signal& > signalDeviceChanged(); virtual sigc::signal& > signalAxesChanged(); virtual sigc::signal& > signalButtonsChanged(); @@ -139,8 +269,13 @@ public: virtual void addButton(Glib::ustring const & id, gint button); virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link); + virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode ); + virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use ); + virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods ); + protected: - std::list devices; + std::list > devices; + sigc::signal& > signalDeviceChangedPriv; sigc::signal& > signalAxesChangedPriv; sigc::signal& > signalButtonsChangedPriv; @@ -157,29 +292,153 @@ DeviceManagerImpl::DeviceManagerImpl() : if ( !fakeList ) { createFakeList(); } -// devList = fakeList; + //devList = fakeList; + + std::set knownIDs; for ( GList* curr = devList; curr; curr = g_list_next(curr) ) { GdkDevice* dev = reinterpret_cast(curr->data); if ( dev ) { -// g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode, -// dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys); +#if DEBUG_VERBOSE + g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode, + dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys); +#endif + + InputDeviceImpl* device = new InputDeviceImpl(dev, knownIDs); + device->reference(); + devices.push_back(Glib::RefPtr(device)); + } + } +} + +void DeviceManagerImpl::loadConfig() +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + for (std::list >::iterator it = devices.begin(); it != devices.end(); ++it) { + if ((*it)->getSource() != Gdk::SOURCE_MOUSE) { + Glib::ustring path = "/devices/" + (*it)->getId(); + + Gdk::InputMode mode = Gdk::MODE_DISABLED; + Glib::ustring val = prefs->getString(path + "/mode"); + if (getStringToMode().find(val) != getStringToMode().end()) { + mode = getStringToMode()[val]; + } + if ((*it)->getMode() != mode) { + setMode( (*it)->getId(), mode ); + } - InputDeviceImpl* device = new InputDeviceImpl(dev); - devices.push_back(device); + // + + val = prefs->getString(path + "/axes"); + if (!val.empty()) { + std::vector parts = Glib::Regex::split_simple(";", val); + for (size_t i = 0; i < parts.size(); ++i) { + Glib::ustring name = parts[i]; + if (getStringToAxis().find(name) != getStringToAxis().end()) { + Gdk::AxisUse use = getStringToAxis()[name]; + setAxisUse( (*it)->getId(), i, use ); + } + } + } + + val = prefs->getString(path + "/keys"); + if (!val.empty()) { + std::vector parts = Glib::Regex::split_simple(";", val); + for (size_t i = 0; i < parts.size(); ++i) { + Glib::ustring keyStr = parts[i]; + if (!keyStr.empty()) { + guint key = 0; + GdkModifierType mods = static_cast(0); + gtk_accelerator_parse( keyStr.c_str(), &key, &mods ); + setKey( (*it)->getId(), i, key, static_cast(mods) ); + } + } + } } } } -std::list DeviceManagerImpl::getDevices() +void DeviceManagerImpl::saveConfig() { - std::list tmp; - for ( std::list::const_iterator it = devices.begin(); it != devices.end(); ++it ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + for (std::list >::iterator it = devices.begin(); it != devices.end(); ++it) { + if ((*it)->getSource() != Gdk::SOURCE_MOUSE) { + Glib::ustring path = "/devices/" + (*it)->getId(); + + prefs->setString( path + "/mode", getModeToString()[(*it)->getMode()].c_str() ); + + Glib::ustring tmp; + for (gint i = 0; i < (*it)->getNumAxes(); ++i) { + if (i > 0) { + tmp += ";"; + } + tmp += getAxisToString()[static_cast((*it)->getDevice()->axes[i].use)]; + } + prefs->setString( path + "/axes", tmp ); + + tmp = ""; + for (gint i = 0; i < (*it)->getNumKeys(); ++i) { + if (i > 0) { + tmp += ";"; + } + tmp += gtk_accelerator_name((*it)->getDevice()->keys[i].keyval, (*it)->getDevice()->keys[i].modifiers); + } + prefs->setString( path + "/keys", tmp ); + } + } +} + +std::list > DeviceManagerImpl::getDevices() +{ + std::list > tmp; + for ( std::list >::const_iterator it = devices.begin(); it != devices.end(); ++it ) { tmp.push_back(*it); } return tmp; } +void DeviceManagerImpl::setMode( Glib::ustring const & id, Gdk::InputMode mode ) +{ + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + if ( it != devices.end() ) { + if (isValidDevice((*it)->getDevice())) { + bool success = gdk_device_set_mode((*it)->getDevice(), static_cast(mode)); + if (success) { + //(*it)->setMode(mode); + signalDeviceChangedPriv.emit(*it); + } else { + g_warning("Unable to set mode on extended input device [%s]", (*it)->getId().c_str()); + } + } + } +} + +void DeviceManagerImpl::setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use ) +{ + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + if ( it != devices.end() ) { + if (isValidDevice((*it)->getDevice())) { + gdk_device_set_axis_use((*it)->getDevice(), index, static_cast(use)); + signalDeviceChangedPriv.emit(*it); + } + } +} + +void DeviceManagerImpl::setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods ) +{ + //static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers ) + // + + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + if ( it != devices.end() ) { + if (isValidDevice((*it)->getDevice())) { + gdk_device_set_key((*it)->getDevice(), index, keyval, static_cast(mods)); + signalDeviceChangedPriv.emit(*it); + } + } +} sigc::signal& > DeviceManagerImpl::signalDeviceChanged() { @@ -204,7 +463,7 @@ sigc::signal& > DeviceManagerImpl::signalL void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis) { if ( axis >= 0 && axis < static_cast(bitVals.size()) ) { - std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { gint mask = bitVals[axis]; if ( (mask & (*it)->getLiveAxes()) == 0 ) { @@ -212,7 +471,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis) // Only signal if a new axis was added (*it)->reference(); - signalAxesChangedPriv.emit(Glib::RefPtr(*it)); + signalAxesChangedPriv.emit(*it); } } } @@ -221,7 +480,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis) void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button) { if ( button >= 0 && button < static_cast(bitVals.size()) ) { - std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { gint mask = bitVals[button]; if ( (mask & (*it)->getLiveButtons()) == 0 ) { @@ -229,7 +488,7 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button) // Only signal if a new button was added (*it)->reference(); - signalButtonsChangedPriv.emit(Glib::RefPtr(*it)); + signalButtonsChangedPriv.emit(*it); } } } @@ -237,12 +496,11 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button) void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) { - std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { - InputDeviceImpl* dev = *it; - + Glib::RefPtr dev = *it; - InputDeviceImpl* targetDev = 0; + Glib::RefPtr targetDev; if ( !link.empty() ) { // Need to be sure the target of the link exists it = std::find_if(devices.begin(), devices.end(), IdMatcher(link)); @@ -255,7 +513,7 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons if ( (link.empty() && !dev->getLink().empty()) || (targetDev && (targetDev->getLink() != id)) ) { // only muck about if they aren't already linked - std::list changedItems; + std::list > changedItems; if ( targetDev ) { // Is something else already using that link? @@ -277,9 +535,9 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons dev->setLink(link); changedItems.push_back(dev); - for ( std::list::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) { + for ( std::list >::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) { (*iter)->reference(); - signalLinkChangedPriv.emit(Glib::RefPtr(*iter)); + signalLinkChangedPriv.emit(*iter); } } } diff --git a/src/device-manager.h b/src/device-manager.h index 1bfb5120c..c32a79bfa 100644 --- a/src/device-manager.h +++ b/src/device-manager.h @@ -1,7 +1,7 @@ /* * Inkscape::DeviceManager - a view of input devices available. * - * Copyright 2006 Jon A. Cruz + * Copyright 2010 Jon A. Cruz * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -42,7 +42,11 @@ class DeviceManager : public Glib::Object { public: static DeviceManager& getManager(); - virtual std::list getDevices() = 0; + virtual void loadConfig() = 0; + virtual void saveConfig() = 0; + + virtual std::list > getDevices() = 0; + virtual sigc::signal& > signalDeviceChanged() = 0; virtual sigc::signal& > signalAxesChanged() = 0; virtual sigc::signal& > signalButtonsChanged() = 0; @@ -52,6 +56,10 @@ public: virtual void addButton(Glib::ustring const & id, gint button) = 0; virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) = 0; + virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode ) = 0; + virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use ) = 0; + virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods ) = 0; + protected: DeviceManager(); virtual ~DeviceManager(); diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index ae8594e50..555b18349 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -329,7 +329,7 @@ public: Gtk::TreeModelColumn filename; Gtk::TreeModelColumn description; Gtk::TreeModelColumn< Glib::RefPtr > thumbnail; - Gtk::TreeModelColumn device; + Gtk::TreeModelColumn > device; MyModelColumns() { add(filename); add(description); add(thumbnail); add(device); } }; @@ -640,7 +640,7 @@ InputDialogImpl::InputDialogImpl() : - std::list devList = Inkscape::DeviceManager::getManager().getDevices(); + std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); if ( !devList.empty() ) { row = *(store->append()); row[cols.description] = "Hardware"; @@ -650,8 +650,8 @@ InputDialogImpl::InputDialogImpl() : childrow[cols.description] = "Tablet"; childrow[cols.thumbnail] = tabletPix; - for ( std::list::iterator it = devList.begin(); it != devList.end(); ++it ) { - InputDevice const* dev = *it; + for ( std::list >::iterator it = devList.begin(); it != devList.end(); ++it ) { + Glib::RefPtr dev = *it; if ( dev ) { // g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->getName().c_str(), dev->getSource(), dev->getMode(), // dev->hasCursor() ? "Yes":"no", dev->getNumAxes(), dev->getNumKeys()); @@ -741,7 +741,7 @@ bool InputDialogImpl::findDevice(const Gtk::TreeModel::iterator& iter, Gtk::TreeModel::iterator* result) { bool stop = false; - const InputDevice* dev = (*iter)[cols.device]; + Glib::RefPtr dev = (*iter)[cols.device]; if ( dev && (dev->getId() == id) ) { if ( result ) { *result = iter; @@ -756,7 +756,7 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter, Gtk::TreeModel::iterator* result) { bool stop = false; - const InputDevice* dev = (*iter)[cols.device]; + Glib::RefPtr dev = (*iter)[cols.device]; if ( dev && (dev->getLink() == link) ) { if ( result ) { *result = iter; @@ -783,8 +783,8 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) // g_message("Item %s is unlinked", device->getId().c_str()); if ( deviceIter->parent() != tabletIter ) { // Not the child of the tablet. move on up - - InputDevice const *dev = (*deviceIter)[cols.device]; + + Glib::RefPtr dev = (*deviceIter)[cols.device]; Glib::ustring descr = (*deviceIter)[cols.description]; Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; @@ -808,7 +808,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) (*newGroup)[cols.description] = "Pen"; (*newGroup)[cols.thumbnail] = penPix; - InputDevice const *dev = (*deviceIter)[cols.device]; + Glib::RefPtr dev = (*deviceIter)[cols.device]; Glib::ustring descr = (*deviceIter)[cols.description]; Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; @@ -817,7 +817,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) deviceRow[cols.thumbnail] = thumb; deviceRow[cols.device] = dev; - + Gtk::TreeModel::iterator linkIter; store->foreach_iter( sigc::bind( sigc::mem_fun(*this, &InputDialogImpl::findDeviceByLink), @@ -856,15 +856,15 @@ void InputDialogImpl::linkComboChanged() { if (iter) { Gtk::TreeModel::Row row = *iter; Glib::ustring val = row[cols.description]; - InputDevice const * dev = row[cols.device]; + Glib::RefPtr dev = row[cols.device]; if ( dev ) { if ( linkCombo.get_active_row_number() == 0 ) { // It is the "None" entry DeviceManager::getManager().setLinkedTo(dev->getId(), ""); } else { Glib::ustring linkName = linkCombo.get_active_text(); - std::list devList = Inkscape::DeviceManager::getManager().getDevices(); - for ( std::list::const_iterator it = devList.begin(); it != devList.end(); ++it ) { + std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); + for ( std::list >::const_iterator it = devList.begin(); it != devList.end(); ++it ) { if ( linkName == (*it)->getName() ) { DeviceManager::getManager().setLinkedTo(dev->getId(), (*it)->getId()); break; @@ -882,7 +882,7 @@ void InputDialogImpl::resyncToSelection() { if (iter) { Gtk::TreeModel::Row row = *iter; Glib::ustring val = row[cols.description]; - InputDevice const * dev = row[cols.device]; + Glib::RefPtr dev = row[cols.device]; if ( dev ) { devDetails.set_sensitive(true); @@ -892,8 +892,8 @@ void InputDialogImpl::resyncToSelection() { linkCombo.set_active(0); if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { Glib::ustring linked = dev->getLink(); - std::list devList = Inkscape::DeviceManager::getManager().getDevices(); - for ( std::list::const_iterator it = devList.begin(); it != devList.end(); ++it ) { + std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); + for ( std::list >::const_iterator it = devList.begin(); it != devList.end(); ++it ) { if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) { linkCombo.append_text((*it)->getName().c_str()); if ( (linked.length() > 0) && (linked == (*it)->getId()) ) { @@ -964,7 +964,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) if (iter) { Gtk::TreeModel::Row row = *iter; Glib::ustring val = row[cols.description]; - InputDevice const * idev = row[cols.device]; + Glib::RefPtr idev = row[cols.device]; if ( !idev || (idev->getId() != key) ) { dev = 0; } -- cgit v1.2.3 From 7557c867cfcd841cf46935e7bf7fbee53709c150 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Thu, 8 Apr 2010 23:05:52 +0200 Subject: PDF+LaTeX: fix bug 555488, and fix bug with missing space after setting justification Fixed bugs: - https://launchpad.net/bugs/555488 (bzr r9301) --- src/extension/internal/latex-text-renderer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 28bba1beb..c6c597b7a 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -350,13 +350,13 @@ Flowing in rectangle is possible, not in arb shape. g_free(strtext); g_strfreev(splitstr); - if (!flowtext->has_internal_frame()) { - // has_internal_frame includes a check that frame is a SPRect + SPItem *frame_item = flowtext->get_frame(NULL); + if (!frame_item || !SP_IS_RECT(frame_item)) { g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text."); return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think } - SPRect *frame = SP_RECT(flowtext->get_frame(NULL)); + SPRect *frame = SP_RECT(frame_item); Geom::Rect framebox = sp_rect_get_rect(frame) * transform(); // get position and alignment @@ -365,13 +365,13 @@ Flowing in rectangle is possible, not in arb shape. gchar const *justification = ""; switch (flowtext->layout.paragraphAlignment(flowtext->layout.begin())) { case Inkscape::Text::Layout::LEFT: - justification = "\\raggedright"; + justification = "\\raggedright "; break; case Inkscape::Text::Layout::RIGHT: - justification = "\\raggedleft"; + justification = "\\raggedleft "; break; case Inkscape::Text::Layout::CENTER: - justification = "\\centering"; + justification = "\\centering "; case Inkscape::Text::Layout::FULL: default: // no need to add LaTeX code for standard justified output :) -- cgit v1.2.3 From 92ec7a0a9a6a5d5de094b6481ceb0df22edcd568 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 9 Apr 2010 22:21:31 -0700 Subject: Do not emit signals when setting values to their existing state. (bzr r9304) --- src/device-manager.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device-manager.cpp b/src/device-manager.cpp index 29e15b05a..b71cca059 100644 --- a/src/device-manager.cpp +++ b/src/device-manager.cpp @@ -403,10 +403,9 @@ void DeviceManagerImpl::setMode( Glib::ustring const & id, Gdk::InputMode mode ) { std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { - if (isValidDevice((*it)->getDevice())) { + if (isValidDevice((*it)->getDevice()) && ((*it)->getMode() != mode) ) { bool success = gdk_device_set_mode((*it)->getDevice(), static_cast(mode)); if (success) { - //(*it)->setMode(mode); signalDeviceChangedPriv.emit(*it); } else { g_warning("Unable to set mode on extended input device [%s]", (*it)->getId().c_str()); @@ -420,8 +419,14 @@ void DeviceManagerImpl::setAxisUse( Glib::ustring const & id, guint index, Gdk:: std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { if (isValidDevice((*it)->getDevice())) { - gdk_device_set_axis_use((*it)->getDevice(), index, static_cast(use)); - signalDeviceChangedPriv.emit(*it); + if (static_cast(index) <= (*it)->getNumAxes()) { + if ((*it)->getDevice()->axes[index].use != static_cast(use)) { + gdk_device_set_axis_use((*it)->getDevice(), index, static_cast(use)); + signalDeviceChangedPriv.emit(*it); + } + } else { + g_warning("Invalid device axis number %d on extended input device [%s]", index, (*it)->getId().c_str()); + } } } } -- cgit v1.2.3 From 98c1f52afb5011477a9ad164ede006414e0e32af Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 10 Apr 2010 14:51:38 +0200 Subject: fix bug 168275 by removing a ceil on document height and width in pdf/eps/ps exporter. Fixed bugs: - https://launchpad.net/bugs/168275 (bzr r9306) --- src/extension/internal/cairo-renderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 6e4bb3b7e..ebdb82a69 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -608,8 +608,8 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page NRRect d; if (pageBoundingBox) { d.x0 = d.y0 = 0; - d.x1 = ceil(sp_document_width(doc)); - d.y1 = ceil(sp_document_height(doc)); + d.x1 = sp_document_width(doc); + d.y1 = sp_document_height(doc); } else { sp_item_invoke_bbox(base, &d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX); } -- cgit v1.2.3 From 20dae7a7ce078ec4e0cd5c808c21eba4d549ddc7 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 10 Apr 2010 17:21:01 +0200 Subject: * improve boundingbox calculation: include strokecaps. * increasing boundingbox calculation precision for selection to marker, selection to pattern and fit canvas to selection (bzr r9307) --- src/selection-chemistry.cpp | 6 +- src/sp-shape.cpp | 303 ++++++++++++++++++++++++-------------------- src/splivarot.cpp | 244 +++++++++++++++++++++++++++++++++++ src/splivarot.h | 1 + 4 files changed, 414 insertions(+), 140 deletions(-) (limited to 'src') diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 730467ee5..cc153aa71 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2266,7 +2266,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } sp_document_ensure_up_to_date(doc); - Geom::OptRect r = selection->bounds(); + Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX); boost::optional c = selection->center(); if ( !r || !c ) { return; @@ -2390,7 +2390,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } sp_document_ensure_up_to_date(doc); - Geom::OptRect r = selection->bounds(); + Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX); if ( !r ) { return; } @@ -3173,7 +3173,7 @@ fit_canvas_to_selection(SPDesktop *desktop, bool with_margins) desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to fit canvas to.")); return false; } - Geom::OptRect const bbox(desktop->selection->bounds()); + Geom::OptRect const bbox(desktop->selection->bounds(SPItem::RENDERING_BBOX)); if (bbox) { doc->fitToRect(*bbox, with_margins); return true; diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index de5648137..dadcb5f57 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -50,6 +50,8 @@ #include "util/mathfns.h" // for triangle_area() +#include "splivarot.h" // for bounding box calculation + #define noSHAPE_VERBOSE static void sp_shape_class_init (SPShapeClass *klass); @@ -541,166 +543,193 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & cbbox.x1 = (*geombbox)[0][1]; cbbox.y1 = (*geombbox)[1][1]; - if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) { - - SPStyle* style=SP_OBJECT_STYLE (item); - if (!style->stroke.isNone()) { - double const scale = transform.descrim(); - if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord - double const width = MAX(0.125, style->stroke_width.computed * scale); - if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) { - cbbox.x0-=0.5*width; - cbbox.x1+=0.5*width; - cbbox.y0-=0.5*width; - cbbox.y1+=0.5*width; + switch ((SPItem::BBoxType) flags) { + case SPItem::GEOMETRIC_BBOX: { + // do nothing + break; + } + case SPItem::RENDERING_BBOX: { + // convert the stroke to a path and calculate that path's geometric bbox + SPStyle* style=SP_OBJECT_STYLE (item); + if (!style->stroke.isNone()) { + Geom::PathVector *pathv = item_outline(item); + if (pathv) { + Geom::OptRect geomstrokebbox = bounds_exact_transformed(*pathv, transform); + if (geomstrokebbox) { + NRRect strokebbox; + strokebbox.x0 = (*geomstrokebbox)[0][0]; + strokebbox.y0 = (*geomstrokebbox)[1][0]; + strokebbox.x1 = (*geomstrokebbox)[0][1]; + strokebbox.y1 = (*geomstrokebbox)[1][1]; + nr_rect_d_union (&cbbox, &cbbox, &strokebbox); + } + delete pathv; } } + break; } - - // Union with bboxes of the markers, if any - if (sp_shape_has_markers (shape)) { - /** \todo make code prettier! */ - Geom::PathVector const & pathv = shape->curve->get_pathvector(); - // START marker - for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START - if ( shape->marker[i] ) { - SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); - - if (marker_item) { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - - // total marker transform - tr = marker_item->transform * marker->c2p * tr * transform; - - // get bbox of the marker with that transform - NRRect marker_bbox; - sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); - // union it with the shape bbox - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + default: + case SPItem::APPROXIMATE_BBOX: { + SPStyle* style=SP_OBJECT_STYLE (item); + if (!style->stroke.isNone()) { + double const scale = transform.descrim(); + if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord + double const width = MAX(0.125, style->stroke_width.computed * scale); + if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) { + cbbox.x0-=0.5*width; + cbbox.x1+=0.5*width; + cbbox.y0-=0.5*width; + cbbox.y1+=0.5*width; } } } - // MID marker - for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID - SPMarker* marker = SP_MARKER (shape->marker[i]); - if ( !shape->marker[i] ) continue; - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); - if ( !marker_item ) continue; - - for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - // START position - if ( path_it != pathv.begin() - && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there - { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); - } - // MID position - if ( path_it->size_default() > 1) { - Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - while (curve_it2 != path_it->end_default()) - { - /* Put marker between curve_it1 and curve_it2. - * Loop to end_default (so including closing segment), because when a path is closed, - * there should be a midpoint marker between last segment and closing straight line segment */ - - SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); - - if (marker_item) { - Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + + // Union with bboxes of the markers, if any + if (sp_shape_has_markers (shape)) { + /** \todo make code prettier! */ + Geom::PathVector const & pathv = shape->curve->get_pathvector(); + // START marker + for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (shape->marker[i]); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + + if (marker_item) { + Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; } - ++curve_it1; - ++curve_it2; - } - } - // END position - if ( path_it != (pathv.end()-1) && !path_it->empty()) { - Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + // total marker transform + tr = marker_item->transform * marker->c2p * tr * transform; + + // get bbox of the marker with that transform + NRRect marker_bbox; + sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); + // union it with the shape bbox + nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); } } - } - // END marker - for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END - if ( shape->marker[i] ) { + // MID marker + for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID SPMarker* marker = SP_MARKER (shape->marker[i]); + if ( !shape->marker[i] ) continue; SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + if ( !marker_item ) continue; - if (marker_item) { - /* Get reference to last curve in the path. - * For moveto-only path, this returns the "closing line segment". */ - Geom::Path const &path_last = pathv.back(); - unsigned int index = path_last.size_default(); - if (index > 0) { - index--; + for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { + // START position + if ( path_it != pathv.begin() + && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there + { + Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } + tr = marker_item->transform * marker->c2p * tr * transform; + NRRect marker_bbox; + sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); + nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); } - Geom::Curve const &lastcurve = path_last[index]; + // MID position + if ( path_it->size_default() > 1) { + Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve + Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve + while (curve_it2 != path_it->end_default()) + { + /* Put marker between curve_it1 and curve_it2. + * Loop to end_default (so including closing segment), because when a path is closed, + * there should be a midpoint marker between last segment and closing straight line segment */ + + SPMarker* marker = SP_MARKER (shape->marker[i]); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + + if (marker_item) { + Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } + tr = marker_item->transform * marker->c2p * tr * transform; + NRRect marker_bbox; + sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true); + nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + } - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + ++curve_it1; + ++curve_it2; + } } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; + // END position + if ( path_it != (pathv.end()-1) && !path_it->empty()) { + Geom::Curve const &lastcurve = path_it->back_default(); + Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } + tr = marker_item->transform * marker->c2p * tr * transform; + NRRect marker_bbox; + sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true); + nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); } + } + } + // END marker + for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (shape->marker[i]); + SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + + if (marker_item) { + /* Get reference to last curve in the path. + * For moveto-only path, this returns the "closing line segment". */ + Geom::Path const &path_last = pathv.back(); + unsigned int index = path_last.size_default(); + if (index > 0) { + index--; + } + Geom::Curve const &lastcurve = path_last[index]; + + Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } - // total marker transform - tr = marker_item->transform * marker->c2p * tr * transform; + // total marker transform + tr = marker_item->transform * marker->c2p * tr * transform; - // get bbox of the marker with that transform - NRRect marker_bbox; - sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true); - // union it with the shape bbox - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + // get bbox of the marker with that transform + NRRect marker_bbox; + sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true); + // union it with the shape bbox + nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + } } } } - } - } + break; + } // end case approximate bbox type + } // end switch bboxtype // copy our bbox to the variable we're given *bbox = cbbox; diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 085dfeda0..db9f72975 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -624,6 +624,250 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix } } +static +void item_outline_add_marker( SPObject const *marker_object, Geom::Matrix marker_transform, + Geom::Scale stroke_scale, Geom::Matrix transform, + Geom::PathVector* pathv_in ) +{ + SPMarker* marker = SP_MARKER (marker_object); + SPItem* marker_item = sp_item_first_item_child(SP_OBJECT(marker_object)); + + Geom::Matrix tr(marker_transform); + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = stroke_scale * tr; + } + // total marker transform + tr = marker_item->transform * marker->c2p * tr * transform; + + Geom::PathVector* marker_pathv = item_outline(marker_item); + + if (marker_pathv) { + for (unsigned int j=0; j < marker_pathv->size(); j++) { + pathv_in->push_back((*marker_pathv)[j] * tr); + } + delete marker_pathv; + } +} + +/** + * Returns a pathvector that is the outline of the stroked item, with markers. + * item must be SPShape of SPText. + */ +Geom::PathVector* item_outline(SPItem const *item) +{ + Geom::PathVector *ret_pathv = NULL; + + if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item)) + return ret_pathv; + + // no stroke: no outline + if (!SP_OBJECT_STYLE(item) || SP_OBJECT_STYLE(item)->stroke.noneSet) { + return ret_pathv; + } + + SPCurve *curve = NULL; + if (SP_IS_SHAPE(item)) { + curve = sp_shape_get_curve(SP_SHAPE(item)); + } else if (SP_IS_TEXT(item)) { + curve = SP_TEXT(item)->getNormalizedBpath(); + } + if (curve == NULL) { + return ret_pathv; + } + + // remember old stroke style, to be set on fill + SPStyle *i_style = SP_OBJECT_STYLE(item); + + Geom::Matrix const transform(item->transform); + float const scale = transform.descrim(); + + float o_width, o_miter; + JoinType o_join; + ButtType o_butt; + { + o_width = i_style->stroke_width.computed; + if (o_width < 0.1) { + o_width = 0.1; + } + o_miter = i_style->stroke_miterlimit.value * o_width; + + switch (i_style->stroke_linejoin.computed) { + case SP_STROKE_LINEJOIN_MITER: + o_join = join_pointy; + break; + case SP_STROKE_LINEJOIN_ROUND: + o_join = join_round; + break; + default: + o_join = join_straight; + break; + } + + switch (i_style->stroke_linecap.computed) { + case SP_STROKE_LINECAP_SQUARE: + o_butt = butt_square; + break; + case SP_STROKE_LINECAP_ROUND: + o_butt = butt_round; + break; + default: + o_butt = butt_straight; + break; + } + } + + // Livarots outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly. + Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() ); + + Path *orig = new Path; + orig->LoadPathVector(pathv); + + Path *res = new Path; + res->SetBackData(false); + + if (i_style->stroke_dash.n_dash) { + // For dashed strokes, use Stroke method, because Outline can't do dashes + // However Stroke adds lots of extra nodes _or_ makes the path crooked, so consider this a temporary workaround + + orig->ConvertWithBackData(0.1); + + orig->DashPolylineFromStyle(i_style, scale, 0); + + Shape* theShape = new Shape; + orig->Stroke(theShape, false, 0.5*o_width, o_join, o_butt, + 0.5 * o_miter); + orig->Outline(res, 0.5 * o_width, o_join, o_butt, 0.5 * o_miter); + + Shape *theRes = new Shape; + + theRes->ConvertToShape(theShape, fill_positive); + + Path *originaux[1]; + originaux[0] = res; + theRes->ConvertToForme(orig, 1, originaux); + + res->Coalesce(5.0); + + delete theShape; + delete theRes; + } else { + orig->Outline(res, 0.5 * o_width, o_join, o_butt, 0.5 * o_miter); + + orig->Coalesce(0.5 * o_width); + + Shape *theShape = new Shape; + Shape *theRes = new Shape; + + res->ConvertWithBackData(1.0); + res->Fill(theShape, 0); + theRes->ConvertToShape(theShape, fill_positive); + + Path *originaux[1]; + originaux[0] = res; + theRes->ConvertToForme(orig, 1, originaux); + + delete theShape; + delete theRes; + } + + if (orig->descr_cmd.size() <= 1) { + // ca a merdÂŽ, ou bien le resultat est vide + delete res; + delete orig; + curve->unref(); + return ret_pathv; + } + + + if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether + ret_pathv = orig->MakePathVector(); + + if (SP_IS_SHAPE(item) && sp_shape_has_markers (SP_SHAPE(item))) { + SPShape *shape = SP_SHAPE(item); + + Geom::PathVector const & pathv = curve->get_pathvector(); + + // START marker + for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START + if ( SPObject *marker_obj = shape->marker[i] ) { + Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); + item_outline_add_marker( marker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + ret_pathv ); + } + } + // MID marker + for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID + SPObject *midmarker_obj = shape->marker[i]; + if (!midmarker_obj) continue; + for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { + // START position + if ( path_it != pathv.begin() + && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there + { + Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); + item_outline_add_marker( midmarker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + ret_pathv ); + } + // MID position + if (path_it->size_default() > 1) { + Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve + Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve + while (curve_it2 != path_it->end_default()) + { + /* Put marker between curve_it1 and curve_it2. + * Loop to end_default (so including closing segment), because when a path is closed, + * there should be a midpoint marker between last segment and closing straight line segment + */ + Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + item_outline_add_marker( midmarker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + ret_pathv); + + ++curve_it1; + ++curve_it2; + } + } + // END position + if ( path_it != (pathv.end()-1) && !path_it->empty()) { + Geom::Curve const &lastcurve = path_it->back_default(); + Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + item_outline_add_marker( midmarker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + ret_pathv ); + } + } + } + // END marker + for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END + if ( SPObject *marker_obj = shape->marker[i] ) { + /* Get reference to last curve in the path. + * For moveto-only path, this returns the "closing line segment". */ + Geom::Path const &path_last = pathv.back(); + unsigned int index = path_last.size_default(); + if (index > 0) { + index--; + } + Geom::Curve const &lastcurve = path_last[index]; + + Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + item_outline_add_marker( marker_obj, m, + Geom::Scale(i_style->stroke_width.computed), transform, + ret_pathv ); + } + } + } + + curve->unref(); + } + + delete res; + delete orig; + + return ret_pathv; +} + void sp_selected_path_outline(SPDesktop *desktop) { diff --git a/src/splivarot.h b/src/splivarot.h index dce31a1ad..ff9f4f577 100644 --- a/src/splivarot.h +++ b/src/splivarot.h @@ -43,6 +43,7 @@ void sp_selected_path_create_updating_offset_object_zero (SPDesktop *desktop); // outline of a curve // uses the stroke-width void sp_selected_path_outline (SPDesktop *desktop); +Geom::PathVector* item_outline(SPItem const *item); // simplifies a path (removes small segments and the like) void sp_selected_path_simplify (SPDesktop *desktop); -- cgit v1.2.3 From ebeebaa753c6780247159a9db6f05e248a59e6e7 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 10 Apr 2010 21:44:27 +0200 Subject: fix bug 166659. precisely calculate bbox when exporting to png Fixed bugs: - https://launchpad.net/bugs/166659 (bzr r9309) --- src/dialogs/export.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp index 9e8a71c35..696f38b77 100644 --- a/src/dialogs/export.cpp +++ b/src/dialogs/export.cpp @@ -780,7 +780,7 @@ sp_export_selection_modified ( Inkscape::Application */*inkscape*/, if ( SP_ACTIVE_DESKTOP ) { SPDocument *doc; doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); + Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX); if (bbox) { sp_export_set_area (base, bbox->min()[Geom::X], bbox->min()[Geom::Y], @@ -792,7 +792,7 @@ sp_export_selection_modified ( Inkscape::Application */*inkscape*/, case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { NRRect bbox; - (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox); + (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox, SPItem::RENDERING_BBOX); sp_export_set_area (base, bbox.x0, bbox.y0, bbox.x1, bbox.y1); } break; @@ -849,7 +849,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { - bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds(); + bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds(SPItem::RENDERING_BBOX); /* Only if there is a selection that we can set do we break, otherwise we fall through to the drawing */ @@ -861,7 +861,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) /** \todo * This returns wrong values if the document has a viewBox. */ - bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); + bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX); /* If the drawing is valid, then we'll use it and break otherwise we drop through to the page settings */ if (bbox) { @@ -1487,7 +1487,7 @@ sp_export_detect_size(GtkObject * base) { switch (this_test[i]) { case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { - Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(); + Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(SPItem::RENDERING_BBOX); //std::cout << "Selection " << bbox; if ( bbox && sp_export_bbox_equal(*bbox,current_bbox)) { @@ -1498,7 +1498,7 @@ sp_export_detect_size(GtkObject * base) { case SELECTION_DRAWING: { SPDocument *doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); + Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX); // std::cout << "Drawing " << bbox2; if ( bbox && sp_export_bbox_equal(*bbox,current_bbox) ) { -- cgit v1.2.3 From 959ea09c04724ff39449aab779aa7958bcfb5a9f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 11 Apr 2010 00:26:08 -0700 Subject: Correct calligraphic toggles getting out of sync with behavior. (bzr r9311) --- src/widgets/toolbox.cpp | 113 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 5c890333f..f12b2d1cb 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -670,9 +670,8 @@ static void delete_connection(GObject */*obj*/, sigc::connection *connection) { delete connection; } -static void purge_repr_listener( GObject* obj, GObject* tbl ) +static void purge_repr_listener( GObject* /*obj*/, GObject* tbl ) { - (void)obj; Inkscape::XML::Node* oldrepr = reinterpret_cast( g_object_get_data( tbl, "repr" ) ); if (oldrepr) { // remove old listener sp_repr_remove_listener_by_data(oldrepr, tbl); @@ -682,6 +681,84 @@ static void purge_repr_listener( GObject* obj, GObject* tbl ) } } +// ------------------------------------------------------ + +class PrefPusher : public Inkscape::Preferences::Observer +{ +public: + PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*) = 0, GObject *cbData = 0 ); + virtual ~PrefPusher(); + + virtual void notify(Inkscape::Preferences::Entry const &new_val); + +private: + static void toggleCB( GtkToggleAction *act, PrefPusher *self ); + + void handleToggled(); + + GtkToggleAction *act; + void (*callback)(GObject*); + GObject *cbData; + bool hold; +}; + +PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*), GObject *cbData ) : + Observer(path), + act(act), + callback(callback), + cbData(cbData), + hold(false) +{ + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggleCB), this); + hold = true; + gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path, true) ); + hold = false; + + Inkscape::Preferences::get()->addObserver(*this); +} + +PrefPusher::~PrefPusher() +{ + Inkscape::Preferences::get()->removeObserver(*this); +} + +void PrefPusher::toggleCB( GtkToggleAction * /*act*/, PrefPusher *self ) +{ + if (self) { + self->handleToggled(); + } +} + +void PrefPusher::handleToggled() +{ + if (!hold) { + hold = true; + Inkscape::Preferences::get()->setBool(observed_path, gtk_toggle_action_get_active( act )); + if (callback) { + (*callback)(cbData); + } + hold = false; + } +} + +void PrefPusher::notify(Inkscape::Preferences::Entry const &newVal) +{ + bool newBool = newVal.getBool(); + bool oldBool = gtk_toggle_action_get_active(act); + + if (!hold && (newBool != oldBool)) { + gtk_toggle_action_set_active( act, newBool ); + } +} + +static void delete_prefspusher(GtkObject * /*obj*/, PrefPusher *watcher ) +{ + delete watcher; +} + +// ------------------------------------------------------ + + GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, @@ -4840,28 +4917,13 @@ static void sp_ddc_cap_rounding_value_changed( GtkAdjustment *adj, GObject* tbl update_presets_list(tbl); } -static void sp_ddc_pressure_state_changed( GtkToggleAction *act, GObject* tbl ) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/tools/calligraphic/usepressure", gtk_toggle_action_get_active( act )); - update_presets_list(tbl); -} - -static void sp_ddc_trace_background_changed( GtkToggleAction *act, GObject* tbl ) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/tools/calligraphic/tracebackground", gtk_toggle_action_get_active( act )); - update_presets_list(tbl); -} - static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GObject* tbl ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + // TODO merge into PrefPusher GtkAction * calligraphy_angle = static_cast (g_object_get_data(tbl,"angle_action")); - prefs->setBool("/tools/calligraphic/usetilt", gtk_toggle_action_get_active( act )); - update_presets_list(tbl); - if (calligraphy_angle ) + if (calligraphy_angle ) { gtk_action_set_sensitive( calligraphy_angle, !gtk_toggle_action_get_active( act ) ); + } } @@ -5049,7 +5111,6 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) { } } - static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -5203,8 +5264,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main INKSCAPE_ICON_DRAW_TRACE_BACKGROUND, Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_trace_background_changed), holder); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/tracebackground", false) ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/tracebackground", update_presets_list, holder); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); g_object_set_data( holder, "tracebackground", act ); } @@ -5216,8 +5277,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main INKSCAPE_ICON_DRAW_USE_PRESSURE, Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_pressure_state_changed), holder); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/usepressure", true) ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usepressure", update_presets_list, holder); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); g_object_set_data( holder, "usepressure", act ); } @@ -5229,6 +5290,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main INKSCAPE_ICON_DRAW_USE_TILT, Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usetilt", update_presets_list, holder); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_tilt_state_changed), holder ); gtk_action_set_sensitive( GTK_ACTION(calligraphy_angle), !prefs->getBool("/tools/calligraphic/usetilt", true) ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/usetilt", true) ); -- cgit v1.2.3 From c0b14a0f143ab6748fa48c2e251d804708efcbb5 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 11 Apr 2010 01:51:39 -0700 Subject: Switching to new input dialog. Allows for a better UI and addresses bug #334800 and bug #196195. Fixed bugs: - https://launchpad.net/bugs/334800 - https://launchpad.net/bugs/196195 (bzr r9312) --- src/dialogs/CMakeLists.txt | 1 - src/dialogs/Makefile_insert | 2 - src/dialogs/input.cpp | 607 -------------------------------------------- src/dialogs/input.h | 31 --- src/inkscape.cpp | 4 +- src/menus-skeleton.h | 1 - src/ui/dialog/input.cpp | 518 ++++++++++++++++++++++++++----------- src/ui/dialog/input.h | 2 +- src/verbs.cpp | 6 - src/verbs.h | 1 - 10 files changed, 379 insertions(+), 794 deletions(-) delete mode 100644 src/dialogs/input.cpp delete mode 100644 src/dialogs/input.h (limited to 'src') diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt index 4e6b1ee3d..9bcb1cd5a 100644 --- a/src/dialogs/CMakeLists.txt +++ b/src/dialogs/CMakeLists.txt @@ -8,7 +8,6 @@ find.cpp guidelinedialog.cpp iconpreview.cpp in-dt-coordsys.cpp -input.cpp item-properties.cpp layer-properties.cpp layers-panel.cpp diff --git a/src/dialogs/Makefile_insert b/src/dialogs/Makefile_insert index 32a11e831..8d7d3f21d 100644 --- a/src/dialogs/Makefile_insert +++ b/src/dialogs/Makefile_insert @@ -9,8 +9,6 @@ ink_common_sources += \ dialogs/export.h \ dialogs/find.cpp \ dialogs/find.h \ - dialogs/input.cpp \ - dialogs/input.h \ dialogs/item-properties.cpp \ dialogs/item-properties.h \ dialogs/object-attributes.cpp \ diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp deleted file mode 100644 index 55e9704c3..000000000 --- a/src/dialogs/input.cpp +++ /dev/null @@ -1,607 +0,0 @@ -/** @file - * @brief Extended input devices dialog - */ -/* Authors: - * Nicklas Lindgren - * Johan Engelen - * - * Copyright (C) 2005-2006 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#include "macros.h" -#include "verbs.h" -#include "inkscape.h" -#include "interface.h" -#include "xml/repr.h" - -#include "dialogs/dialog-events.h" -#include "preferences.h" - -#define MIN_ONSCREEN_DISTANCE 50 - -static GtkWidget *dlg = NULL; -static win_data wd; - -// impossible original values to make sure they are read from prefs -static gint x = -1000, y = -1000, w = 0, h = 0; -static Glib::ustring const prefs_path = "/dialogs/input/"; - -#define noTEST_WITH_GOOD_TABLET 1 -#define noTEST_WITH_BAD_TABLET 1 - -#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET) -static int testDeviceCount = 0; -static GdkDevice* testDevices = 0; - -// Defined at the end of the file to keep debugging out of the way. -static void initTestDevices(); -#endif - -static std::list getInputDevices() -{ - std::list devices; - -#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET) - initTestDevices(); - for (int i = 0; i < testDeviceCount; i++) { - devices.push_back(&testDevices[i]); - } -#else - for (GList *ptr = gdk_devices_list(); ptr; ptr = ptr->next) { - GdkDevice *device = static_cast(ptr->data); - devices.push_back(device); - } -#endif - - return devices; -} - -// wrap these GDK calls to be able to intercept for testing. - -static bool setDeviceMode( GdkDevice *device, GdkInputMode mode ) -{ -#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET) - (void)device; - (void)mode; - bool retVal = true; // Can't let the Gdk call be called with bad data -#else - bool retVal = gdk_device_set_mode(device, mode); -#endif - return retVal; -} - -static void setDeviceAxisUse( GdkDevice *device, guint index, GdkAxisUse use ) -{ -#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET) - (void)device; - (void)index; - (void)use; -#else - gdk_device_set_axis_use(device, index, use); -#endif -} - -static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers ) -{ -#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET) - (void)device; - (void)index; - (void)keyval; - (void)modifiers; -#else - gdk_device_set_key(device, index, keyval, modifiers); -#endif -} - - -static void -sp_input_dialog_destroy (GtkObject */*object*/, gpointer /*data*/) -{ - sp_signal_disconnect_by_data (INKSCAPE, dlg); - wd.win = dlg = NULL; - wd.stop = 0; -} - -static gboolean -sp_input_dialog_delete (GtkObject */*object*/, GdkEvent */*event*/, gpointer /*data*/) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gtk_window_get_position ((GtkWindow *) dlg, &x, &y); - gtk_window_get_size ((GtkWindow *) dlg, &w, &h); - - if (x<0) x=0; - if (y<0) y=0; - - prefs->setInt(prefs_path + "x", x); - prefs->setInt(prefs_path + "y", y); - prefs->setInt(prefs_path + "w", w); - prefs->setInt(prefs_path + "h", h); - - return FALSE; // which means, go ahead and destroy it - -} - -static gchar const *axis_use_strings[GDK_AXIS_LAST] = { - "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel" -}; - -static const int RUNAWAY_MAX = 1000; - -static Glib::ustring getBaseDeviceName(GdkInputSource source) -{ - Glib::ustring name; - switch (source) { - case GDK_SOURCE_MOUSE: - name ="pointer"; - break; - case GDK_SOURCE_PEN: - name ="pen"; - break; - case GDK_SOURCE_ERASER: - name ="eraser"; - break; - case GDK_SOURCE_CURSOR: - name ="cursor"; - break; - default: - name = "tablet"; - } - return name; -} - -static Glib::ustring createSanitizedPath(GdkDevice* device, std::set &seenPaths) -{ - // LP #334800: tablet device names on Windows sometimes contain funny junk like - // \x03, \xf2, etc. Moreover this junk changes between runs. - // If the tablet name contains unprintable or non-ASCII characters, - // we use some default name. - // This might break if someone has two tablets with broken names, but it's - // not possible to do anything 100% correct then. - bool broken = false; - - if (!device->name || (*(device->name) == 0)) { - broken = true; - } else { - for (gchar const *s = device->name; *s; ++s) { - if ((*s < 0x20) || (*s >= 0x7f)) { - broken = true; - break; - } - } - } - - Glib::ustring device_path; - if (broken) { - Glib::ustring base = Glib::ustring("/devices/") + getBaseDeviceName(device->source); - int num = 1; - device_path = base; - while ((seenPaths.find(device_path) != seenPaths.end()) && (num < RUNAWAY_MAX)) { - device_path = Glib::ustring::compose("%1%2", base, ++num); - } - } else { - device_path += Glib::ustring("/devices/") + device->name; - } - - seenPaths.insert(device_path); - - return device_path; -} - -void sp_input_load_from_preferences(void) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - std::list devices = getInputDevices(); - std::set seenPaths; - for (std::list::iterator it = devices.begin(); it != devices.end(); ++it) { - GdkDevice *device = *it; - -// g_message(" s:%d m:%d hc:%d a:%d k:%d [%s]", device->source, device->mode, device->has_cursor, device->num_axes, device->num_keys, device->name); -// for (int i = 0; i < device->num_axes; i++) { -// GdkDeviceAxis &axis = device->axes[i]; -// g_message(" axis[%d] u:%d min:%f max:%f", i, axis.use, axis.min, axis.max); -// } - - Glib::ustring device_path = createSanitizedPath(device, seenPaths); -// if (device_path != (Glib::ustring("/devices/") + device->name)) { -// g_message(" re-name [%s]", device_path.c_str()); -// } - - Glib::ustring device_mode = prefs->getString(device_path + "/mode"); - - GdkInputMode mode = GDK_MODE_DISABLED; - if (device_mode == "screen") { - mode = GDK_MODE_SCREEN; - } else if (device_mode == "window") { - mode = GDK_MODE_WINDOW; - } - - if (device->mode != mode) { - setDeviceMode(device, mode); - } - - Glib::ustring::size_type pos0, pos1; - GdkAxisUse axis_use; - - //temp_ptr = repr->attribute("axes"); - Glib::ustring const axes_str = prefs->getString(device_path + "/axes"); - pos0 = pos1 = 0; - for (gint i=0; i < device->num_axes; i++) { - pos1 = axes_str.find(';', pos0); - if (pos1 == Glib::ustring::npos) { - break; // Too few axis specifications - } - - axis_use = GDK_AXIS_IGNORE; - for (gint j=0; j < GDK_AXIS_LAST; j++) { - if (!strcmp(axes_str.substr(pos0, pos1-pos0).c_str(), axis_use_strings[j])) { - axis_use = static_cast(j); - break; - } - } - setDeviceAxisUse(device, i, axis_use); - pos0 = pos1 + 1; - } - - guint keyval; - GdkModifierType modifier; - - Glib::ustring const keys_str = prefs->getString(device_path + "/keys"); - pos0 = pos1 = 0; - for (gint i=0; i < device->num_keys; i++) { - pos1 = keys_str.find(';', pos0); - if (pos1 == Glib::ustring::npos) { - break; // Too few key specifications - } - - gtk_accelerator_parse(keys_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier); - setDeviceKey(device, i, keyval, modifier); - pos0 = pos1 + 1; - } - } -} - -void sp_input_save_to_preferences(void) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - std::list devices = getInputDevices(); - std::set seenPaths; - for (std::list::iterator it = devices.begin(); it != devices.end(); ++it) { - GdkDevice *device = *it; - - Glib::ustring device_path = createSanitizedPath(device, seenPaths); - - switch (device->mode) { - default: - case GDK_MODE_DISABLED: { - prefs->setString(device_path + "/mode", "disabled"); - break; - } - case GDK_MODE_SCREEN: { - prefs->setString(device_path + "/mode", "screen"); - break; - } - case GDK_MODE_WINDOW: { - prefs->setString(device_path + "/mode", "window"); - break; - } - } - - Glib::ustring temp_attribute = ""; - for (gint i=0; i < device->num_axes; i++) { - temp_attribute += axis_use_strings[device->axes[i].use]; - temp_attribute += ";"; - } - prefs->setString(device_path + "/axes", temp_attribute); - - temp_attribute = ""; - for (gint i=0; i < device->num_keys; i++) { - temp_attribute += gtk_accelerator_name(device->keys[i].keyval, device->keys[i].modifiers); - temp_attribute += ";"; - } - prefs->setString(device_path + "/keys", temp_attribute); - } -} - -static void -sp_input_save_button (GtkObject */*object*/, gpointer /*data*/) -{ - sp_input_save_to_preferences(); -} - -void -sp_input_dialog (void) -{ - if (dlg == NULL) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - gchar title[500]; - sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_INPUT), title); - - dlg = gtk_input_dialog_new(); - - if (x == -1000 || y == -1000) { - x = prefs->getInt(prefs_path + "x", -1000); - y = prefs->getInt(prefs_path + "y", -1000); - } - - if (w ==0 || h == 0) { - w = prefs->getInt(prefs_path + "w", 0); - h = prefs->getInt(prefs_path + "h", 0); - } - -// if (x<0) x=0; -// if (y<0) y=0; - - if (w && h) { - gtk_window_resize ((GtkWindow *) dlg, w, h); - } - if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) { - gtk_window_move ((GtkWindow *) dlg, x, y); - } else { - gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); - } - - - sp_transientize (dlg); - wd.win = dlg; - wd.stop = 0; - - g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_transientize_callback), &wd); - gtk_signal_connect ( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg); - gtk_signal_connect ( GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_input_dialog_destroy), dlg); - gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_input_dialog_delete), dlg); - g_signal_connect ( G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_input_dialog_delete), dlg); - g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg); - g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg); - - // Dialog-specific stuff - gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->close_button), - "clicked", - (GtkSignalFunc)gtk_widget_destroy, - GTK_OBJECT(dlg)); - gtk_signal_connect (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->save_button), - "clicked", - (GtkSignalFunc)sp_input_save_button, NULL); - } - - gtk_window_present ((GtkWindow *) dlg); -} - -// ///////////////////////////////// -// For debugging: -// ///////////////////////////////// - - -#if defined(TEST_WITH_GOOD_TABLET) -static void initTestDevices() -{ - static bool init = false; - if (!init) { - static GdkDevice devs[5] = {}; - int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc. - - { - // Laptop trackpad - devs[i].name = g_strdup("pointer"); - devs[i].source = GDK_SOURCE_MOUSE; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Tablet stylus - devs[i].name = g_strdup("pen"); - devs[i].source = GDK_SOURCE_PEN; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Puck - devs[i].name = g_strdup("cursor"); - devs[i].source = GDK_SOURCE_CURSOR; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Back of tablet stylus - devs[i].name = g_strdup("eraser"); - devs[i].source = GDK_SOURCE_ERASER; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Main (composit) mouse device - devs[i].name = g_strdup("Core Pointer"); - devs[i].source = GDK_SOURCE_MOUSE; - devs[i].mode = GDK_MODE_SCREEN; - devs[i].has_cursor = 1; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - testDeviceCount = i; - testDevices = devs; - init = true; - } -} -#elif defined(TEST_WITH_BAD_TABLET) - -/** - * Uses the current time in seconds to change a name to be unique from one - * run of the program to the next. - */ -void perturbName(gchar *str) -{ - if (str) { - GTimeVal when = {0,0}; - g_get_current_time(&when); - gchar *tmp = g_strdup_printf("%ld", when.tv_sec); - - size_t partLen = strlen(tmp); - size_t len = strlen(str); - if (len > (partLen + 4)) { - size_t pos = (len - partLen) / 2; - for (size_t i = 0; i < partLen; i++) { - str[pos + i] = tmp[i]; - } - } - g_free(tmp); - } -} - -static void initTestDevices() -{ - static bool init = false; - if (!init) { - static GdkDevice devs[5] = {}; - int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc. - - { - // Main (composit) mouse device - devs[i].name = g_strdup("Core Pointer"); - devs[i].source = GDK_SOURCE_MOUSE; - devs[i].mode = GDK_MODE_SCREEN; - devs[i].has_cursor = 1; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Back of tablet stylus - devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\356\232\210\307\255\350\271\214\310\201\350\222\200\310\201\356\202\250\310\200\350\223\260\310\201\356\202\250\310\200"); - perturbName(devs[i].name); - devs[i].source = GDK_SOURCE_ERASER; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Tablet stylus - devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\341\221\230\307\255\343\277\214\310\202\343\230\200\310\202\331\270\310\202\343\231\260\310\202\331\270\310\202"); - perturbName(devs[i].name); - devs[i].source = GDK_SOURCE_PEN; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - { - // Tablet stylus - devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\341\221\230\307\255\343\277\214\310\202\343\230\200\310\202\331\270\310\202\343\231\260\310\202\331\270\310\202"); - perturbName(devs[i].name); - devs[i].source = GDK_SOURCE_PEN; - devs[i].mode = GDK_MODE_DISABLED; - devs[i].has_cursor = 0; - static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0}, - {GDK_AXIS_Y, 0, 0}, - {GDK_AXIS_PRESSURE, 0, 1}, - {GDK_AXIS_XTILT, -1, 1}, - {GDK_AXIS_YTILT, -1, 1}}; - devs[i].num_axes = G_N_ELEMENTS(tmp); - devs[i].axes = tmp; - devs[i].num_keys = 0; - devs[i].keys = 0; - i++; - } - - testDeviceCount = i; - testDevices = devs; - init = true; - } -} -#endif - - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/dialogs/input.h b/src/dialogs/input.h deleted file mode 100644 index 0996d06ca..000000000 --- a/src/dialogs/input.h +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - * @brief Extended input device dialog - */ -/* Author: - * Nicklas Lindgren - * - * Copyright (C) 2005 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifndef SEEN_DIALOGS_INPUT_H -#define SEEN_DIALOGS_INPUT_H - -void sp_input_load_from_preferences (void); -void sp_input_save_to_preferences (void); -void sp_input_dialog (void); - - -#endif - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/inkscape.cpp b/src/inkscape.cpp index 8506f05de..d0f9a11fc 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -49,7 +49,7 @@ using Inkscape::Extension::Internal::PrintWin32; #include "application/editor.h" #include "desktop.h" #include "desktop-handles.h" -#include "dialogs/input.h" +#include "device-manager.h" #include "document.h" #include "event-context.h" #include "extension/db.h" @@ -807,7 +807,7 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui) if (use_gui) { inkscape_load_menus(inkscape); - sp_input_load_from_preferences(); + Inkscape::DeviceManager::getManager().loadConfig(); } /* set language for user interface according setting in preferences */ diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 978b555b0..0a9aa2751 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -40,7 +40,6 @@ static char const menus_skeleton[] = " \n" " \n" " \n" -" \n" " \n" " \n" " \n" diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index 555b18349..570f00944 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -12,11 +12,15 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -28,8 +32,9 @@ #include #include -#include "ui/widget/panel.h" #include "device-manager.h" +#include "preferences.h" +#include "ui/widget/panel.h" #include "input.h" @@ -323,38 +328,87 @@ namespace Dialog { -class MyModelColumns : public Gtk::TreeModel::ColumnRecord +class DeviceModelColumns : public Gtk::TreeModel::ColumnRecord { public: - Gtk::TreeModelColumn filename; Gtk::TreeModelColumn description; Gtk::TreeModelColumn< Glib::RefPtr > thumbnail; Gtk::TreeModelColumn > device; + Gtk::TreeModelColumn mode; - MyModelColumns() { add(filename); add(description); add(thumbnail); add(device); } + DeviceModelColumns() { add(description); add(thumbnail); add(device); add(mode); } }; +static std::map &getModeToString() +{ + static std::map mapping; + if (mapping.empty()) { + mapping[Gdk::MODE_DISABLED] = _("Disabled"); + mapping[Gdk::MODE_SCREEN] = _("Screen"); + mapping[Gdk::MODE_WINDOW] = _("Window"); + } + + return mapping; +} + +static std::map &getStringToMode() +{ + static std::map mapping; + if (mapping.empty()) { + mapping[_("Disabled")] = Gdk::MODE_DISABLED; + mapping[_("Screen")] = Gdk::MODE_SCREEN; + mapping[_("Window")] = Gdk::MODE_WINDOW; + } + + return mapping; +} + + + class InputDialogImpl : public InputDialog { public: InputDialogImpl(); virtual ~InputDialogImpl() {} private: - Glib::RefPtr corePix; - Glib::RefPtr penPix; - Glib::RefPtr mousePix; - Glib::RefPtr tipPix; - Glib::RefPtr tabletPix; - Glib::RefPtr eraserPix; - Glib::RefPtr sidebuttonsPix; - - Glib::RefPtr buttonsNonePix; - Glib::RefPtr buttonsOnPix; - Glib::RefPtr buttonsOffPix; - - Glib::RefPtr axisNonePix; - Glib::RefPtr axisOnPix; - Glib::RefPtr axisOffPix; + class ConfPanel : public Gtk::VBox + { + public: + ConfPanel(); + ~ConfPanel(); + + class Blink : public Preferences::Observer + { + public: + Blink(ConfPanel &parent); + virtual ~Blink(); + virtual void notify(Preferences::Entry const &new_val); + + ConfPanel &parent; + }; + + static void commitCellModeChange(Glib::ustring const &path, Glib::ustring const &newText, Glib::RefPtr store); + static void setModeCellString(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter); + + void saveSettings(); + void useExtToggled(); + + Glib::RefPtr store; + Gtk::TreeIter tabletIter; + Gtk::TreeView tree; + Gtk::ScrolledWindow treeScroller; + Blink watcher; + Gtk::CheckButton useExt; + Gtk::Button save; + }; + + static DeviceModelColumns &getCols(); + + enum PixId {PIX_CORE, PIX_PEN, PIX_MOUSE, PIX_TIP, PIX_TABLET, PIX_ERASER, PIX_SIDEBUTTONS, + PIX_BUTTONS_NONE, PIX_BUTTONS_ON, PIX_BUTTONS_OFF, + PIX_AXIS_NONE, PIX_AXIS_ON, PIX_AXIS_OFF}; + + static Glib::RefPtr getPix(PixId id); std::map > buttonMap; std::map > > axesMap; @@ -362,7 +416,6 @@ private: GdkInputSource lastSourceSeen; Glib::ustring lastDevnameSeen; - MyModelColumns cols; Glib::RefPtr store; Gtk::TreeIter tabletIter; Gtk::TreeView tree; @@ -383,7 +436,6 @@ private: Gtk::Label keyVal; Gtk::Entry keyEntry; Gtk::Table devDetails; - Gtk::HPaned confSplitter; Gtk::Notebook topHolder; Gtk::Image testThumb; Gtk::Image testButtons[24]; @@ -391,6 +443,9 @@ private: Gtk::Table imageTable; Gtk::EventBox testDetector; + ConfPanel cfgPanel; + + static void setupTree( Glib::RefPtr store, Gtk::TreeIter &tablet ); void setupValueAndCombo( gint reported, gint actual, Gtk::Label& label, Gtk::ComboBoxText& combo ); void updateTestButtons( Glib::ustring const& key, gint hotButton ); void updateTestAxes( Glib::ustring const& key, GdkDevice* dev ); @@ -402,15 +457,51 @@ private: void handleDeviceChange(const Glib::RefPtr& device); void updateDeviceAxes(const Glib::RefPtr& device); void updateDeviceButtons(const Glib::RefPtr& device); - void updateDeviceLinks(const Glib::RefPtr& device); - - bool findDevice(const Gtk::TreeModel::iterator& iter, - Glib::ustring id, - Gtk::TreeModel::iterator* result); - bool findDeviceByLink(const Gtk::TreeModel::iterator& iter, - Glib::ustring link, - Gtk::TreeModel::iterator* result); -}; + static void updateDeviceLinks(const Glib::RefPtr& device, Gtk::TreeIter &tabletIter, Gtk::TreeView &tree); + + static bool findDevice(const Gtk::TreeModel::iterator& iter, + Glib::ustring id, + Gtk::TreeModel::iterator* result); + static bool findDeviceByLink(const Gtk::TreeModel::iterator& iter, + Glib::ustring link, + Gtk::TreeModel::iterator* result); + +}; // class InputDialogImpl + + +DeviceModelColumns &InputDialogImpl::getCols() +{ + static DeviceModelColumns cols; + return cols; +} + +Glib::RefPtr InputDialogImpl::getPix(PixId id) +{ + static std::map > mappings; + + mappings[PIX_CORE] = Gdk::Pixbuf::create_from_xpm_data(core_xpm); + mappings[PIX_PEN] = Gdk::Pixbuf::create_from_xpm_data(pen); + mappings[PIX_MOUSE] = Gdk::Pixbuf::create_from_xpm_data(mouse); + mappings[PIX_TIP] = Gdk::Pixbuf::create_from_xpm_data(tip); + mappings[PIX_TABLET] = Gdk::Pixbuf::create_from_xpm_data(tablet); + mappings[PIX_ERASER] = Gdk::Pixbuf::create_from_xpm_data(eraser); + mappings[PIX_SIDEBUTTONS] = Gdk::Pixbuf::create_from_xpm_data(sidebuttons); + + mappings[PIX_BUTTONS_NONE] = Gdk::Pixbuf::create_from_xpm_data(button_none); + mappings[PIX_BUTTONS_ON] = Gdk::Pixbuf::create_from_xpm_data(button_on); + mappings[PIX_BUTTONS_OFF] = Gdk::Pixbuf::create_from_xpm_data(button_off); + + mappings[PIX_AXIS_NONE] = Gdk::Pixbuf::create_from_xpm_data(axis_none_xpm); + mappings[PIX_AXIS_ON] = Gdk::Pixbuf::create_from_xpm_data(axis_on_xpm); + mappings[PIX_AXIS_OFF] = Gdk::Pixbuf::create_from_xpm_data(axis_off_xpm); + + Glib::RefPtr pix; + if (mappings.find(id) != mappings.end()) { + pix = mappings[id]; + } + + return pix; +} // Now that we've defined the *Impl class, we can do the method to aquire one. @@ -424,38 +515,23 @@ InputDialog &InputDialog::getInstance() InputDialogImpl::InputDialogImpl() : InputDialog(), - corePix(Gdk::Pixbuf::create_from_xpm_data(core_xpm)), - penPix(Gdk::Pixbuf::create_from_xpm_data(pen)), - mousePix(Gdk::Pixbuf::create_from_xpm_data(mouse)), - tipPix(Gdk::Pixbuf::create_from_xpm_data(tip)), - tabletPix(Gdk::Pixbuf::create_from_xpm_data(tablet)), - eraserPix(Gdk::Pixbuf::create_from_xpm_data(eraser)), - sidebuttonsPix(Gdk::Pixbuf::create_from_xpm_data(sidebuttons)), - - buttonsNonePix(Gdk::Pixbuf::create_from_xpm_data(button_none)), - buttonsOnPix(Gdk::Pixbuf::create_from_xpm_data(button_on)), - buttonsOffPix(Gdk::Pixbuf::create_from_xpm_data(button_off)), - - axisNonePix(Gdk::Pixbuf::create_from_xpm_data(axis_none_xpm)), - axisOnPix(Gdk::Pixbuf::create_from_xpm_data(axis_on_xpm)), - axisOffPix(Gdk::Pixbuf::create_from_xpm_data(axis_off_xpm)), - lastSourceSeen((GdkInputSource)-1), lastDevnameSeen(""), - cols(), - store(Gtk::TreeStore::create(cols)), + store(Gtk::TreeStore::create(getCols())), + tabletIter(), tree(store), frame2(), - testFrame("Test Area"), + testFrame(_("Test Area")), treeScroller(), detailScroller(), splitter(), split2(), linkCombo(), devDetails(12, 2), - confSplitter(), topHolder(), - imageTable(8, 7) + imageTable(8, 7), + testDetector(), + cfgPanel() { Gtk::Box *contents = _getContents(); @@ -469,14 +545,14 @@ InputDialogImpl::InputDialogImpl() : testDetector.add(imageTable); testFrame.add(testDetector); - testThumb.set(tabletPix); + testThumb.set(getPix(PIX_TABLET)); testThumb.set_padding(24, 24); imageTable.attach(testThumb, 0, 8, 0, 1, ::Gtk::EXPAND, ::Gtk::EXPAND); { guint col = 0; guint row = 1; for ( guint num = 0; num < G_N_ELEMENTS(testButtons); num++ ) { - testButtons[num].set(buttonsNonePix); + testButtons[num].set(getPix(PIX_BUTTONS_NONE)); imageTable.attach(testButtons[num], col, col + 1, row, row + 1, ::Gtk::FILL, ::Gtk::FILL); col++; if (col > 7) { @@ -487,7 +563,7 @@ InputDialogImpl::InputDialogImpl() : col = 0; for ( guint num = 0; num < G_N_ELEMENTS(testAxes); num++ ) { - testAxes[num].set(axisNonePix); + testAxes[num].set(getPix(PIX_AXIS_NONE)); imageTable.attach(testAxes[num], col * 2, (col + 1) * 2, row, row + 1, ::Gtk::FILL, ::Gtk::FILL); col++; if (col > 3) { @@ -498,18 +574,16 @@ InputDialogImpl::InputDialogImpl() : } - topHolder.append_page(confSplitter, "Configuration"); - topHolder.append_page(splitter, "Hardware"); -// confSplitter.show_all(); -// splitter.show_all(); + topHolder.append_page(cfgPanel, _("Configuration")); + topHolder.append_page(splitter, _("Hardware")); topHolder.show_all(); - topHolder.set_current_page(1); + topHolder.set_current_page(0); contents->pack_start(topHolder); int rowNum = 0; - Gtk::Label* lbl = Gtk::manage(new Gtk::Label("Name:")); + Gtk::Label* lbl = Gtk::manage(new Gtk::Label(_("Name:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -519,13 +593,13 @@ InputDialogImpl::InputDialogImpl() : rowNum++; - lbl = Gtk::manage(new Gtk::Label("Link:")); + lbl = Gtk::manage(new Gtk::Label(_("Link:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); - linkCombo.append_text("None"); - linkCombo.set_active_text("None"); + linkCombo.append_text(_("None")); + linkCombo.set_active_text(_("None")); linkCombo.set_sensitive(false); linkConnection = linkCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::linkComboChanged)); @@ -534,7 +608,7 @@ InputDialogImpl::InputDialogImpl() : ::Gtk::SHRINK); rowNum++; - lbl = Gtk::manage(new Gtk::Label("Axes count:")); + lbl = Gtk::manage(new Gtk::Label(_("Axes count:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -545,7 +619,7 @@ InputDialogImpl::InputDialogImpl() : rowNum++; /* - lbl = Gtk::manage(new Gtk::Label("Actual axes count:")); + lbl = Gtk::manage(new Gtk::Label(_("Actual axes count:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -557,7 +631,7 @@ InputDialogImpl::InputDialogImpl() : */ for ( guint barNum = 0; barNum < static_cast(G_N_ELEMENTS(axesValues)); barNum++ ) { - lbl = Gtk::manage(new Gtk::Label("axis:")); + lbl = Gtk::manage(new Gtk::Label(_("axis:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -569,7 +643,7 @@ InputDialogImpl::InputDialogImpl() : rowNum++; } - lbl = Gtk::manage(new Gtk::Label("Button count:")); + lbl = Gtk::manage(new Gtk::Label(_("Button count:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -580,7 +654,7 @@ InputDialogImpl::InputDialogImpl() : rowNum++; /* - lbl = Gtk::manage(new Gtk::Label("Actual button count:")); + lbl = Gtk::manage(new Gtk::Label(_("Actual button count:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); @@ -625,30 +699,37 @@ InputDialogImpl::InputDialogImpl() : - Gtk::TreeModel::Row row; - Gtk::TreeModel::Row childrow; - Gtk::TreeModel::Row deviceRow; - - //Add the TreeView's view columns: - tree.append_column("I", cols.thumbnail); - tree.append_column("Bar", cols.description); + tree.append_column("I", getCols().thumbnail); + tree.append_column("Bar", getCols().description); tree.set_enable_tree_lines(); tree.set_headers_visible(false); tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection)); + setupTree( store, tabletIter ); + + Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange)); + Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes)); + Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons)); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, tree)); + + tree.expand_all(); + show_all_children(); +} +void InputDialogImpl::setupTree( Glib::RefPtr store, Gtk::TreeIter &tablet ) +{ std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); if ( !devList.empty() ) { - row = *(store->append()); - row[cols.description] = "Hardware"; + Gtk::TreeModel::Row row = *(store->append()); + row[getCols().description] = _("Hardware"); - tabletIter = store->append(row.children()); - childrow = *tabletIter; - childrow[cols.description] = "Tablet"; - childrow[cols.thumbnail] = tabletPix; + tablet = store->append(row.children()); + Gtk::TreeModel::Row childrow = *tablet; + childrow[getCols().description] = _("Tablet"); + childrow[getCols().thumbnail] = getPix(PIX_TABLET); for ( std::list >::iterator it = devList.begin(); it != devList.end(); ++it ) { Glib::RefPtr dev = *it; @@ -658,25 +739,26 @@ InputDialogImpl::InputDialogImpl() : // if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { if ( dev ) { - deviceRow = *(store->append(childrow.children())); - deviceRow[cols.description] = dev->getName(); - deviceRow[cols.device] = dev; + Gtk::TreeModel::Row deviceRow = *(store->append(childrow.children())); + deviceRow[getCols().description] = dev->getName(); + deviceRow[getCols().device] = dev; + deviceRow[getCols().mode] = dev->getMode(); switch ( dev->getSource() ) { case GDK_SOURCE_MOUSE: - deviceRow[cols.thumbnail] = corePix; + deviceRow[getCols().thumbnail] = getPix(PIX_CORE); break; case GDK_SOURCE_PEN: - if (deviceRow[cols.description] == "pad") { - deviceRow[cols.thumbnail] = sidebuttonsPix; + if (deviceRow[getCols().description] == _("pad")) { + deviceRow[getCols().thumbnail] = getPix(PIX_SIDEBUTTONS); } else { - deviceRow[cols.thumbnail] = tipPix; + deviceRow[getCols().thumbnail] = getPix(PIX_TIP); } break; case GDK_SOURCE_CURSOR: - deviceRow[cols.thumbnail] = mousePix; + deviceRow[getCols().thumbnail] = getPix(PIX_MOUSE); break; case GDK_SOURCE_ERASER: - deviceRow[cols.thumbnail] = eraserPix; + deviceRow[getCols().thumbnail] = getPix(PIX_ERASER); break; default: ; // nothing @@ -689,18 +771,165 @@ InputDialogImpl::InputDialogImpl() : } else { g_warning("No devices found"); } - Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange)); - Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes)); - Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons)); - Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceLinks)); +} + + +InputDialogImpl::ConfPanel::ConfPanel() : + Gtk::VBox(), + store(Gtk::TreeStore::create(getCols())), + tabletIter(), + tree(store), + treeScroller(), + watcher(*this), + useExt(_("Use pressure-sensitive tablet (requires restart)")), + save(_("Save")) +{ + pack_start(treeScroller); + + treeScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + treeScroller.add(tree); + + class Foo : public Gtk::TreeModel::ColumnRecord { + public : + Gtk::TreeModelColumn one; + Foo() {add(one);} + }; + static Foo foo; + Glib::RefPtr poppers = Gtk::ListStore::create(foo); + poppers->reference(); + + Gtk::TreeModel::Row row = *(poppers->append()); + row[foo.one] = getModeToString()[Gdk::MODE_DISABLED]; + row = *(poppers->append()); + row[foo.one] = getModeToString()[Gdk::MODE_SCREEN]; + row = *(poppers->append()); + row[foo.one] = getModeToString()[Gdk::MODE_WINDOW]; + + Gtk::CellRendererCombo *rendr = new Gtk::CellRendererCombo(); + rendr->property_model().set_value(poppers); + rendr->property_text_column().set_value(0); + rendr->property_has_entry() = false; + + //Add the TreeView's view columns: + tree.append_column("I", getCols().thumbnail); + tree.append_column("Bar", getCols().description); + Gtk::TreeViewColumn *col = new Gtk::TreeViewColumn("X", *rendr); + if (col) { + tree.append_column(*col); + col->set_cell_data_func(*rendr, sigc::ptr_fun(setModeCellString)); + rendr->signal_edited().connect(sigc::bind(sigc::ptr_fun(commitCellModeChange), store)); + rendr->property_editable() = true; + } + + tree.set_enable_tree_lines(); + tree.set_headers_visible(false); + + setupTree( store, tabletIter ); + + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, tree)); tree.expand_all(); - show_all_children(); + + useExt.set_active(Preferences::get()->getBool("/options/useextinput/value")); + useExt.signal_toggled().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::useExtToggled)); + pack_start(useExt, Gtk::PACK_SHRINK); + + save.signal_clicked().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::saveSettings)); + Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_RIGHT, Gtk::ALIGN_TOP, 0, 0); + align->add(save); + pack_start(*Gtk::manage(align), Gtk::PACK_SHRINK); +} + +InputDialogImpl::ConfPanel::~ConfPanel() +{ +} + +void InputDialogImpl::ConfPanel::setModeCellString(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter) +{ + if (iter) { + Gtk::CellRendererCombo *combo = dynamic_cast(rndr); + if (combo) { + Glib::RefPtr dev = (*iter)[getCols().device]; + Gdk::InputMode mode = (*iter)[getCols().mode]; + if (dev && (getModeToString().find(mode) != getModeToString().end())) { + combo->property_text() = getModeToString()[mode]; + } else { + combo->property_text() = ""; + } + } + } +} + +void InputDialogImpl::ConfPanel::commitCellModeChange(Glib::ustring const &path, Glib::ustring const &newText, Glib::RefPtr store) +{ + Gtk::TreeIter iter = store->get_iter(path); + if (iter) { + Glib::RefPtr dev = (*iter)[getCols().device]; + if (dev && (getStringToMode().find(newText) != getStringToMode().end())) { + Gdk::InputMode mode = getStringToMode()[newText]; + Inkscape::DeviceManager::getManager().setMode( dev->getId(), mode ); + } + } +} + +void InputDialogImpl::ConfPanel::saveSettings() +{ + Inkscape::DeviceManager::getManager().saveConfig(); +} + +void InputDialogImpl::ConfPanel::useExtToggled() +{ + bool active = useExt.get_active(); + if (active != Preferences::get()->getBool("/options/useextinput/value")) { + Preferences::get()->setBool("/options/useextinput/value", active); + if (active) { + // As a work-around for a common problem, enable tablet toggles on the calligraphic tool. + // Covered in Launchpad bug #196195. + Preferences::get()->setBool("/tools/tweak/usepressure", true); + Preferences::get()->setBool("/tools/calligraphic/usepressure", true); + Preferences::get()->setBool("/tools/calligraphic/usetilt", true); + } + } +} + +InputDialogImpl::ConfPanel::Blink::Blink(ConfPanel &parent) : + Preferences::Observer("/options/useextinput/value"), + parent(parent) +{ + Preferences::get()->addObserver(*this); +} + +InputDialogImpl::ConfPanel::Blink::~Blink() +{ + Preferences::get()->removeObserver(*this); } -void InputDialogImpl::handleDeviceChange(const Glib::RefPtr& /*device*/) +void InputDialogImpl::ConfPanel::Blink::notify(Preferences::Entry const &new_val) +{ + parent.useExt.set_active(new_val.getBool()); +} + +void InputDialogImpl::handleDeviceChange(const Glib::RefPtr& device) { // g_message("OUCH!!!! for %p hits %s", &device, device->getId().c_str()); + std::vector > stores; + stores.push_back(store); + stores.push_back(cfgPanel.store); + + for (std::vector >::iterator it = stores.begin(); it != stores.end(); ++it) { + Gtk::TreeModel::iterator deviceIter; + (*it)->foreach_iter( sigc::bind( + sigc::ptr_fun(&InputDialogImpl::findDevice), + device->getId(), + &deviceIter) ); + if ( deviceIter ) { + Gdk::InputMode mode = device->getMode(); + Gtk::TreeModel::Row row = *deviceIter; + if (row[getCols().mode] != mode) { + row[getCols().mode] = mode; + } + } + } } void InputDialogImpl::updateDeviceAxes(const Glib::RefPtr& device) @@ -741,7 +970,7 @@ bool InputDialogImpl::findDevice(const Gtk::TreeModel::iterator& iter, Gtk::TreeModel::iterator* result) { bool stop = false; - Glib::RefPtr dev = (*iter)[cols.device]; + Glib::RefPtr dev = (*iter)[getCols().device]; if ( dev && (dev->getId() == id) ) { if ( result ) { *result = iter; @@ -756,7 +985,7 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter, Gtk::TreeModel::iterator* result) { bool stop = false; - Glib::RefPtr dev = (*iter)[cols.device]; + Glib::RefPtr dev = (*iter)[getCols().device]; if ( dev && (dev->getLink() == link) ) { if ( result ) { *result = iter; @@ -766,12 +995,14 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter, return stop; } -void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) +void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device, Gtk::TreeIter &tabletIter, Gtk::TreeView &tree) { + Glib::RefPtr store = Glib::RefPtr::cast_dynamic(tree.get_model()); + // g_message("Links!!!! for %p hits [%s] with link of [%s]", &device, device->getId().c_str(), device->getLink().c_str()); Gtk::TreeModel::iterator deviceIter; store->foreach_iter( sigc::bind( - sigc::mem_fun(*this, &InputDialogImpl::findDevice), + sigc::ptr_fun(&InputDialogImpl::findDevice), device->getId(), &deviceIter) ); @@ -784,14 +1015,15 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) if ( deviceIter->parent() != tabletIter ) { // Not the child of the tablet. move on up - Glib::RefPtr dev = (*deviceIter)[cols.device]; - Glib::ustring descr = (*deviceIter)[cols.description]; - Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; + Glib::RefPtr dev = (*deviceIter)[getCols().device]; + Glib::ustring descr = (*deviceIter)[getCols().description]; + Glib::RefPtr thumb = (*deviceIter)[getCols().thumbnail]; Gtk::TreeModel::Row deviceRow = *store->append(tabletIter->children()); - deviceRow[cols.description] = descr; - deviceRow[cols.thumbnail] = thumb; - deviceRow[cols.device] = dev; + deviceRow[getCols().description] = descr; + deviceRow[getCols().thumbnail] = thumb; + deviceRow[getCols().device] = dev; + deviceRow[getCols().mode] = dev->getMode(); Gtk::TreeModel::iterator oldParent = deviceIter->parent(); store->erase(deviceIter); @@ -805,33 +1037,35 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) // Simple case. Not already linked Gtk::TreeIter newGroup = store->append(tabletIter->children()); - (*newGroup)[cols.description] = "Pen"; - (*newGroup)[cols.thumbnail] = penPix; + (*newGroup)[getCols().description] = _("Pen"); + (*newGroup)[getCols().thumbnail] = getPix(PIX_PEN); - Glib::RefPtr dev = (*deviceIter)[cols.device]; - Glib::ustring descr = (*deviceIter)[cols.description]; - Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; + Glib::RefPtr dev = (*deviceIter)[getCols().device]; + Glib::ustring descr = (*deviceIter)[getCols().description]; + Glib::RefPtr thumb = (*deviceIter)[getCols().thumbnail]; Gtk::TreeModel::Row deviceRow = *store->append(newGroup->children()); - deviceRow[cols.description] = descr; - deviceRow[cols.thumbnail] = thumb; - deviceRow[cols.device] = dev; + deviceRow[getCols().description] = descr; + deviceRow[getCols().thumbnail] = thumb; + deviceRow[getCols().device] = dev; + deviceRow[getCols().mode] = dev->getMode(); Gtk::TreeModel::iterator linkIter; store->foreach_iter( sigc::bind( - sigc::mem_fun(*this, &InputDialogImpl::findDeviceByLink), + sigc::ptr_fun(&InputDialogImpl::findDeviceByLink), device->getId(), &linkIter) ); if ( linkIter ) { - dev = (*linkIter)[cols.device]; - descr = (*linkIter)[cols.description]; - thumb = (*linkIter)[cols.thumbnail]; + dev = (*linkIter)[getCols().device]; + descr = (*linkIter)[getCols().description]; + thumb = (*linkIter)[getCols().thumbnail]; deviceRow = *store->append(newGroup->children()); - deviceRow[cols.description] = descr; - deviceRow[cols.thumbnail] = thumb; - deviceRow[cols.device] = dev; + deviceRow[getCols().description] = descr; + deviceRow[getCols().thumbnail] = thumb; + deviceRow[getCols().device] = dev; + deviceRow[getCols().mode] = dev->getMode(); Gtk::TreeModel::iterator oldParent = linkIter->parent(); store->erase(linkIter); if ( oldParent->children().empty() ) { @@ -855,8 +1089,8 @@ void InputDialogImpl::linkComboChanged() { Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; - Glib::ustring val = row[cols.description]; - Glib::RefPtr dev = row[cols.device]; + Glib::ustring val = row[getCols().description]; + Glib::RefPtr dev = row[getCols().device]; if ( dev ) { if ( linkCombo.get_active_row_number() == 0 ) { // It is the "None" entry @@ -881,14 +1115,14 @@ void InputDialogImpl::resyncToSelection() { Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; - Glib::ustring val = row[cols.description]; - Glib::RefPtr dev = row[cols.device]; + Glib::ustring val = row[getCols().description]; + Glib::RefPtr dev = row[getCols().device]; if ( dev ) { devDetails.set_sensitive(true); linkConnection.block(); linkCombo.clear_items(); - linkCombo.append_text("None"); + linkCombo.append_text(_("None")); linkCombo.set_active(0); if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { Glib::ustring linked = dev->getLink(); @@ -908,7 +1142,7 @@ void InputDialogImpl::resyncToSelection() { linkConnection.unblock(); clear = false; - devName.set_label(row[cols.description]); + devName.set_label(row[getCols().description]); setupValueAndCombo( dev->getNumAxes(), dev->getNumAxes(), devAxesCount, axesCombo); setupValueAndCombo( dev->getNumKeys(), dev->getNumKeys(), devKeyCount, buttonCombo); } @@ -945,12 +1179,12 @@ void InputDialogImpl::updateTestButtons( Glib::ustring const& key, gint hotButto for ( gint i = 0; i < static_cast(G_N_ELEMENTS(testButtons)); i++ ) { if ( buttonMap[key].find(i) != buttonMap[key].end() ) { if ( i == hotButton ) { - testButtons[i].set(buttonsOnPix); + testButtons[i].set(getPix(PIX_BUTTONS_ON)); } else { - testButtons[i].set(buttonsOffPix); + testButtons[i].set(getPix(PIX_BUTTONS_OFF)); } } else { - testButtons[i].set(buttonsNonePix); + testButtons[i].set(getPix(PIX_BUTTONS_NONE)); } } } @@ -963,8 +1197,8 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; - Glib::ustring val = row[cols.description]; - Glib::RefPtr idev = row[cols.device]; + Glib::ustring val = row[getCols().description]; + Glib::RefPtr idev = row[getCols().device]; if ( !idev || (idev->getId() != key) ) { dev = 0; } @@ -977,13 +1211,13 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) switch ( axesMap[key][i].first ) { case 0: case 1: - testAxes[i].set(axisNonePix); + testAxes[i].set(getPix(PIX_AXIS_NONE)); if ( dev && (i < static_cast(G_N_ELEMENTS(axesValues)) ) ) { axesValues[i].set_sensitive(false); } break; case 2: - testAxes[i].set(axisOffPix); + testAxes[i].set(getPix(PIX_AXIS_OFF)); axesValues[i].set_sensitive(true); if ( dev && (i < static_cast(G_N_ELEMENTS(axesValues)) ) ) { if ( (dev->axes[i].max - dev->axes[i].min) > epsilon ) { @@ -996,7 +1230,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) } break; case 3: - testAxes[i].set(axisOnPix); + testAxes[i].set(getPix(PIX_AXIS_ON)); axesValues[i].set_sensitive(true); if ( dev && (i < static_cast(G_N_ELEMENTS(axesValues)) ) ) { if ( (dev->axes[i].max - dev->axes[i].min) > epsilon ) { @@ -1010,7 +1244,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) } } else { - testAxes[i].set(axisNonePix); + testAxes[i].set(getPix(PIX_AXIS_NONE)); } } if ( !dev ) { @@ -1180,30 +1414,30 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event) switch (source) { case GDK_SOURCE_MOUSE: { - testThumb.set(corePix); + testThumb.set(getPix(PIX_CORE)); } break; case GDK_SOURCE_CURSOR: { // g_message("flip to cursor"); - testThumb.set(mousePix); + testThumb.set(getPix(PIX_MOUSE)); } break; case GDK_SOURCE_PEN: { - if (devName == "pad") { + if (devName == _("pad")) { // g_message("flip to pad"); - testThumb.set(sidebuttonsPix); + testThumb.set(getPix(PIX_SIDEBUTTONS)); } else { // g_message("flip to pen"); - testThumb.set(tipPix); + testThumb.set(getPix(PIX_TIP)); } } break; case GDK_SOURCE_ERASER: { // g_message("flip to eraser"); - testThumb.set(eraserPix); + testThumb.set(getPix(PIX_ERASER)); } break; // default: diff --git a/src/ui/dialog/input.h b/src/ui/dialog/input.h index 38666f52c..186612af0 100644 --- a/src/ui/dialog/input.h +++ b/src/ui/dialog/input.h @@ -25,7 +25,7 @@ class InputDialog : public UI::Widget::Panel public: static InputDialog &getInstance(); - InputDialog() : UI::Widget::Panel("", "/dialogs/inputdevices2", SP_VERB_DIALOG_INPUT2) {} + InputDialog() : UI::Widget::Panel("", "/dialogs/inputdevices", SP_VERB_DIALOG_INPUT) {} virtual ~InputDialog() {} }; diff --git a/src/verbs.cpp b/src/verbs.cpp index 66b6140b4..24c17aad8 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -40,7 +40,6 @@ #include "desktop-handles.h" #include "dialogs/clonetiler.h" #include "dialogs/find.h" -#include "dialogs/input.h" #include "dialogs/item-properties.h" #include "dialogs/spellcheck.h" #include "dialogs/text-edit.h" @@ -1791,9 +1790,6 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/) } #endif*/ case SP_VERB_DIALOG_INPUT: - sp_input_dialog(); - break; - case SP_VERB_DIALOG_INPUT2: dt->_dlg_mgr->showDialog("InputDevices"); break; case SP_VERB_DIALOG_EXTENSIONEDITOR: @@ -2640,8 +2636,6 @@ Verb *Verb::_base_verbs[] = { #endif*/ new DialogVerb(SP_VERB_DIALOG_INPUT, "DialogInput", N_("_Input Devices..."), N_("Configure extended input devices, such as a graphics tablet"), INKSCAPE_ICON_DIALOG_INPUT_DEVICES), - new DialogVerb(SP_VERB_DIALOG_INPUT2, "DialogInput2", N_("_Input Devices (new)..."), - N_("Configure extended input devices, such as a graphics tablet"), INKSCAPE_ICON_DIALOG_INPUT_DEVICES), new DialogVerb(SP_VERB_DIALOG_EXTENSIONEDITOR, "org.inkscape.dialogs.extensioneditor", N_("_Extensions..."), N_("Query information about extensions"), NULL), new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."), diff --git a/src/verbs.h b/src/verbs.h index eea6042c0..36bb9f9d9 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -247,7 +247,6 @@ enum { SP_VERB_XMPP_CLIENT, #endif*/ SP_VERB_DIALOG_INPUT, - SP_VERB_DIALOG_INPUT2, SP_VERB_DIALOG_EXTENSIONEDITOR, SP_VERB_DIALOG_LAYERS, SP_VERB_DIALOG_LIVE_PATH_EFFECT, -- cgit v1.2.3 From c97ce3a84aa460c20773ef4c3fc33a4ccb55b2e3 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Sun, 11 Apr 2010 21:08:37 +0200 Subject: UI inconsistency fix (Preferences>Interface. (bzr r9314) --- src/ui/dialog/inkscape-preferences.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 00e72bd4f..51e0de710 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1131,19 +1131,19 @@ void InkscapePreferences::initPageUI() int sizeValues[] = {0, 1, 2}; _misc_small_tools.init( "/toolbox/tools/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 ); - _page_ui.add_line( false, _("Toolbox icon size"), _misc_small_tools, "", + _page_ui.add_line( false, _("Toolbox icon size:"), _misc_small_tools, "", _("Set the size for the tool icons (requires restart)"), false); _misc_small_toolbar.init( "/toolbox/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 ); - _page_ui.add_line( false, _("Control bar icon size"), _misc_small_toolbar, "", + _page_ui.add_line( false, _("Control bar icon size:"), _misc_small_toolbar, "", _("Set the size for the icons in tools' control bars to use (requires restart)"), false); _misc_small_secondary.init( "/toolbox/secondary", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 1 ); - _page_ui.add_line( false, _("Secondary toolbar icon size"), _misc_small_secondary, "", + _page_ui.add_line( false, _("Secondary toolbar icon size:"), _misc_small_secondary, "", _("Set the size for the icons in secondary toolbars to use (requires restart)"), false); - _ui_colorsliders_top.init( _("Work-around color sliders not drawing."), "/options/workarounds/colorsontop", false); + _ui_colorsliders_top.init( _("Work-around color sliders not drawing"), "/options/workarounds/colorsontop", false); _page_ui.add_line( false, "", _ui_colorsliders_top, "", _("When on, will attempt to work around bugs in certain GTK themes drawing color sliders."), true); @@ -1164,7 +1164,7 @@ void InkscapePreferences::initPageUI() _("Adjust the slider until the length of the ruler on your screen matches its real length. This information is used when zooming to 1:1, 1:2, etc., to display objects in their true sizes"), true); - _ui_partialdynamic.init( _("Enable dynamic relayout for incomplete sections."), "/options/workarounds/dynamicnotdone", false); + _ui_partialdynamic.init( _("Enable dynamic relayout for incomplete sections"), "/options/workarounds/dynamicnotdone", false); _page_ui.add_line( false, "", _ui_partialdynamic, "", _("When on, will allow dynamic layout of components that are not completely finished being refactored."), true); -- cgit v1.2.3 From 95645b92240b41fb65cddb892145eb68495087ca Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 11 Apr 2010 23:22:27 -0700 Subject: Fixed state sync for node tool booleans. Addressing bug #426032. (bzr r9316) --- src/widgets/toolbox.cpp | 808 ++++++++++++++++++++++-------------------------- 1 file changed, 378 insertions(+), 430 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index f12b2d1cb..bf1231092 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -518,20 +518,20 @@ static gchar const * ui_descr = static Glib::RefPtr create_or_fetch_actions( SPDesktop* desktop ); -void setup_snap_toolbox (GtkWidget *toolbox, SPDesktop *desktop); +static void setup_snap_toolbox(GtkWidget *toolbox, SPDesktop *desktop); -static void setup_tool_toolbox (GtkWidget *toolbox, SPDesktop *desktop); -static void update_tool_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); +static void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop); +static void update_tool_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); -static void setup_aux_toolbox (GtkWidget *toolbox, SPDesktop *desktop); -static void update_aux_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); +static void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop); +static void update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); -static void setup_commands_toolbox (GtkWidget *toolbox, SPDesktop *desktop); -static void update_commands_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); +static void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop); +static void update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); -GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick( GtkWidget *t, Inkscape::IconSize size, SPButtonType type, - Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, - Inkscape::UI::View::View *view, GtkTooltips *tt); +static GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick( GtkWidget *t, Inkscape::IconSize size, SPButtonType type, + Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, + Inkscape::UI::View::View *view, GtkTooltips *tt); class VerbAction : public Gtk::Action { public: @@ -665,7 +665,8 @@ void VerbAction::on_activate() *dropper_opacity_entry ; */ // should be made a private member once this is converted to class -static void delete_connection(GObject */*obj*/, sigc::connection *connection) { +static void delete_connection(GObject * /*obj*/, sigc::connection *connection) +{ connection->disconnect(); delete connection; } @@ -683,23 +684,52 @@ static void purge_repr_listener( GObject* /*obj*/, GObject* tbl ) // ------------------------------------------------------ +/** + * A simple mediator class that keeps UI controls matched to the preference values they set. + */ class PrefPusher : public Inkscape::Preferences::Observer { public: + /** + * Constructor for a boolean value that syncs to the supplied path. + * Initializes the widget to the current preference stored state and registers callbacks + * for widget changes and preference changes. + * + * @param act the widget to synchronize preference with. + * @param path the path to the preference the widget is synchronized with. + * @param callback function to invoke when changes are pushed. + * @param cbData data to be passed on to the callback function. + */ PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*) = 0, GObject *cbData = 0 ); + + /** + * Destructor that unregisters the preference callback. + */ virtual ~PrefPusher(); + /** + * Callback method invoked when the preference setting changes. + */ virtual void notify(Inkscape::Preferences::Entry const &new_val); private: + /** + * Callback hook invoked when the widget changes. + * + * @param act the toggle action widget that was changed. + * @param self the PrefPusher instance the callback was registered to. + */ static void toggleCB( GtkToggleAction *act, PrefPusher *self ); + /** + * Method to handle the widget change. + */ void handleToggled(); GtkToggleAction *act; void (*callback)(GObject*); GObject *cbData; - bool hold; + bool freeze; }; PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*), GObject *cbData ) : @@ -707,12 +737,12 @@ PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (* act(act), callback(callback), cbData(cbData), - hold(false) + freeze(false) { g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggleCB), this); - hold = true; + freeze = true; gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path, true) ); - hold = false; + freeze = false; Inkscape::Preferences::get()->addObserver(*this); } @@ -731,13 +761,13 @@ void PrefPusher::toggleCB( GtkToggleAction * /*act*/, PrefPusher *self ) void PrefPusher::handleToggled() { - if (!hold) { - hold = true; + if (!freeze) { + freeze = true; Inkscape::Preferences::get()->setBool(observed_path, gtk_toggle_action_get_active( act )); if (callback) { (*callback)(cbData); } - hold = false; + freeze = false; } } @@ -746,7 +776,7 @@ void PrefPusher::notify(Inkscape::Preferences::Entry const &newVal) bool newBool = newVal.getBool(); bool oldBool = gtk_toggle_action_get_active(act); - if (!hold && (newBool != oldBool)) { + if (!freeze && (newBool != oldBool)) { gtk_toggle_action_set_active( act, newBool ); } } @@ -759,19 +789,21 @@ static void delete_prefspusher(GtkObject * /*obj*/, PrefPusher *watcher ) // ------------------------------------------------------ -GtkWidget * -sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, - Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, - Inkscape::UI::View::View *view, GtkTooltips *tt) +GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, + Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, + Inkscape::UI::View::View *view, GtkTooltips *tt) { SPAction *action = verb->get_action(view); - if (!action) return NULL; + if (!action) { + return NULL; + } SPAction *doubleclick_action; - if (doubleclick_verb) + if (doubleclick_verb) { doubleclick_action = doubleclick_verb->get_action(view); - else + } else { doubleclick_action = NULL; + } /* fixme: Handle sensitive/unsensitive */ /* fixme: Implement sp_button_new_from_action */ @@ -806,7 +838,7 @@ static void trigger_sp_action( GtkAction* /*act*/, gpointer user_data ) } } -static void sp_action_action_set_sensitive (SPAction */*action*/, unsigned int sensitive, void *data) +static void sp_action_action_set_sensitive(SPAction * /*action*/, unsigned int sensitive, void *data) { if ( data ) { GtkAction* act = GTK_ACTION(data); @@ -840,7 +872,7 @@ static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::Vi return act; } -Glib::RefPtr create_or_fetch_actions( SPDesktop* desktop ) +static Glib::RefPtr create_or_fetch_actions( SPDesktop* desktop ) { Inkscape::UI::View::View *view = desktop; gint verbsToUse[] = { @@ -964,14 +996,14 @@ Glib::RefPtr create_or_fetch_actions( SPDesktop* desktop ) } -void handlebox_detached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/) +static void handlebox_detached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/) { gtk_widget_set_size_request( widget, widget->allocation.width, widget->allocation.height ); } -void handlebox_attached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/) +static void handlebox_attached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/) { gtk_widget_set_size_request( widget, -1, -1 ); } @@ -1100,14 +1132,17 @@ static EgeAdjustmentAction * create_adjustment_action( gchar const *name, * Will go away during tool refactoring. */ static InkNodeTool *get_node_tool() { - if (!SP_ACTIVE_DESKTOP) return NULL; - SPEventContext *ec = SP_ACTIVE_DESKTOP->event_context; - if (!INK_IS_NODE_TOOL(ec)) return NULL; - return static_cast(ec); + InkNodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + SPEventContext *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + } + } + return tool; } -void -sp_node_path_edit_add(void) +static void sp_node_path_edit_add(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1115,8 +1150,7 @@ sp_node_path_edit_add(void) } } -void -sp_node_path_edit_delete(void) +static void sp_node_path_edit_delete(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1125,8 +1159,7 @@ sp_node_path_edit_delete(void) } } -void -sp_node_path_edit_delete_segment(void) +static void sp_node_path_edit_delete_segment(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1134,8 +1167,7 @@ sp_node_path_edit_delete_segment(void) } } -void -sp_node_path_edit_break(void) +static void sp_node_path_edit_break(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1143,8 +1175,7 @@ sp_node_path_edit_break(void) } } -void -sp_node_path_edit_join(void) +static void sp_node_path_edit_join(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1152,8 +1183,7 @@ sp_node_path_edit_join(void) } } -void -sp_node_path_edit_join_segment(void) +static void sp_node_path_edit_join_segment(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1161,8 +1191,7 @@ sp_node_path_edit_join_segment(void) } } -void -sp_node_path_edit_toline(void) +static void sp_node_path_edit_toline(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1170,8 +1199,7 @@ sp_node_path_edit_toline(void) } } -void -sp_node_path_edit_tocurve(void) +static void sp_node_path_edit_tocurve(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1179,8 +1207,7 @@ sp_node_path_edit_tocurve(void) } } -void -sp_node_path_edit_cusp(void) +static void sp_node_path_edit_cusp(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1188,8 +1215,7 @@ sp_node_path_edit_cusp(void) } } -void -sp_node_path_edit_smooth(void) +static void sp_node_path_edit_smooth(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1197,8 +1223,7 @@ sp_node_path_edit_smooth(void) } } -void -sp_node_path_edit_symmetrical(void) +static void sp_node_path_edit_symmetrical(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1206,8 +1231,7 @@ sp_node_path_edit_symmetrical(void) } } -void -sp_node_path_edit_auto(void) +static void sp_node_path_edit_auto(void) { InkNodeTool *nt = get_node_tool(); if (nt) { @@ -1215,43 +1239,12 @@ sp_node_path_edit_auto(void) } } -static void toggle_show_transform_handles (GtkToggleAction *act, gpointer /*data*/) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool show = gtk_toggle_action_get_active( act ); - prefs->setBool("/tools/nodes/show_transform_handles", show); -} - -static void toggle_show_handles (GtkToggleAction *act, gpointer /*data*/) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool show = gtk_toggle_action_get_active( act ); - prefs->setBool("/tools/nodes/show_handles", show); -} - -static void toggle_show_helperpath (GtkToggleAction *act, gpointer /*data*/) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool show = gtk_toggle_action_get_active( act ); - prefs->setBool("/tools/nodes/show_outline", show); -} - -void sp_node_path_edit_nextLPEparam (GtkAction */*act*/, gpointer data) { +static void sp_node_path_edit_nextLPEparam(GtkAction * /*act*/, gpointer data) { sp_selection_next_patheffect_param( reinterpret_cast(data) ); } -void toggle_edit_clip (GtkToggleAction *act, gpointer /*data*/) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool edit = gtk_toggle_action_get_active( act ); - prefs->setBool("/tools/nodes/edit_clipping_paths", edit); -} - -void toggle_edit_mask (GtkToggleAction *act, gpointer /*data*/) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool edit = gtk_toggle_action_get_active( act ); - prefs->setBool("/tools/nodes/edit_masks", edit); -} - /* is called when the node selection is modified */ -static void -sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl) +static void sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl) { GtkAction* xact = GTK_ACTION( g_object_get_data( tbl, "nodes_x_action" ) ); GtkAction* yact = GTK_ACTION( g_object_get_data( tbl, "nodes_y_action" ) ); @@ -1281,17 +1274,18 @@ sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl) Geom::Coord oldy = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit); Geom::Point mid = nt->_selected_nodes->pointwiseBounds()->midpoint(); - if (oldx != mid[Geom::X]) + if (oldx != mid[Geom::X]) { gtk_adjustment_set_value(xadj, sp_pixels_get_units(mid[Geom::X], *unit)); - if (oldy != mid[Geom::Y]) + } + if (oldy != mid[Geom::Y]) { gtk_adjustment_set_value(yadj, sp_pixels_get_units(mid[Geom::Y], *unit)); + } } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void -sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d) +static void sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d) { SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1324,20 +1318,17 @@ sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void -sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_node_path_value_changed(adj, tbl, Geom::X); } -static void -sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_node_path_value_changed(adj, tbl, Geom::Y); } -void -sp_node_toolbox_sel_changed (Inkscape::Selection *selection, GObject *tbl) +static void sp_node_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl) { { GtkAction* w = GTK_ACTION( g_object_get_data( tbl, "nodes_lpeedit" ) ); @@ -1354,8 +1345,7 @@ sp_node_toolbox_sel_changed (Inkscape::Selection *selection, GObject *tbl) } } -void -sp_node_toolbox_sel_modified (Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) +static void sp_node_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) { sp_node_toolbox_sel_changed (selection, tbl); } @@ -1366,34 +1356,8 @@ sp_node_toolbox_sel_modified (Inkscape::Selection *selection, guint /*flags*/, G //## Node Editing Toolbox ## //################################ -class ShowHandlesObserver - : public Inkscape::Preferences::Observer -{ -public: - ShowHandlesObserver(InkToggleAction *act) - : Inkscape::Preferences::Observer("/tools/nodes/show_handles") - , _act(act) - { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->addObserver(*this); - } - ~ShowHandlesObserver() { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->removeObserver(*this); - } - virtual void notify(Inkscape::Preferences::Entry const &v) { - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(_act), v.getBool()); - } - static void destroy(ShowHandlesObserver *s, InkToggleAction *) { - delete s; - } -private: - InkToggleAction *_act; -}; - static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE ); tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units ); g_object_set_data( holder, "tracker", tracker ); @@ -1531,8 +1495,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions "node-transform", secondarySize ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_transform_handles), desktop ); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_transform_handles", false) ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_transform_handles"); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); } { @@ -1542,10 +1506,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions INKSCAPE_ICON_SHOW_NODE_HANDLES, secondarySize ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_handles), desktop ); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_handles", true) ); - ShowHandlesObserver *s = new ShowHandlesObserver(act); - g_object_weak_ref(G_OBJECT(act), (GWeakNotify) ShowHandlesObserver::destroy, (gpointer) s); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_handles"); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); } { @@ -1555,8 +1517,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions INKSCAPE_ICON_SHOW_PATH_OUTLINE, secondarySize ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_helperpath), desktop ); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_outline", false) ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_outline"); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); } { @@ -1577,8 +1539,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions INKSCAPE_ICON_PATH_CLIP_EDIT, secondarySize ); gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); - g_signal_connect_after( G_OBJECT(inky), "toggled", G_CALLBACK(toggle_edit_clip), desktop ); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(inky), prefs->getBool("/tools/nodes/edit_clipping_paths") ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_clipping_paths"); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); } { @@ -1588,8 +1550,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions INKSCAPE_ICON_PATH_MASK_EDIT, secondarySize ); gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); - g_signal_connect_after( G_OBJECT(inky), "toggled", G_CALLBACK(toggle_edit_mask), desktop ); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(inky), prefs->getBool("/tools/nodes/edit_masks") ); + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_masks"); + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); } /* X coord of selected node(s) */ @@ -1665,7 +1627,7 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions //## Zoom Toolbox ## //######################## -static void sp_zoom_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* /*mainActions*/, GObject* /*holder*/) +static void sp_zoom_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* /*mainActions*/, GObject* /*holder*/) { // no custom GtkAction setup needed } // end of sp_zoom_toolbox_prep() @@ -1870,8 +1832,7 @@ void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientati } } -static void -setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop) +void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop) { gchar const * descr = "" @@ -1904,8 +1865,7 @@ setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop) "/toolbox/tools/small"); } -static void -update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget */*toolbox*/ ) +void update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget * /*toolbox*/ ) { gchar const *const tname = ( eventcontext ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext)) @@ -1924,8 +1884,7 @@ update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget } } -static void -setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) +void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH ); @@ -2009,8 +1968,7 @@ setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) g_object_unref( G_OBJECT(grouper) ); } -static void -update_aux_toolbox(SPDesktop */*desktop*/, SPEventContext *eventcontext, GtkWidget *toolbox) +void update_aux_toolbox(SPDesktop * /*desktop*/, SPEventContext *eventcontext, GtkWidget *toolbox) { gchar const *tname = ( eventcontext ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext)) @@ -2026,8 +1984,7 @@ update_aux_toolbox(SPDesktop */*desktop*/, SPEventContext *eventcontext, GtkWidg } } -static void -setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop) +void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop) { gchar const * descr = "" @@ -2078,13 +2035,12 @@ setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop) "/toolbox/small" ); } -static void -update_commands_toolbox(SPDesktop */*desktop*/, SPEventContext */*eventcontext*/, GtkWidget */*toolbox*/) +void update_commands_toolbox(SPDesktop * /*desktop*/, SPEventContext * /*eventcontext*/, GtkWidget * /*toolbox*/) { } -void toggle_snap_callback (GtkToggleAction *act, gpointer data) { //data points to the toolbox - +static void toggle_snap_callback(GtkToggleAction *act, gpointer data) //data points to the toolbox +{ if (g_object_get_data(G_OBJECT(data), "freeze" )) { return; } @@ -2420,7 +2376,7 @@ Glib::ustring ToolboxFactory::getToolboxName(GtkWidget* toolbox) return name; } -void ToolboxFactory::updateSnapToolbox(SPDesktop *desktop, SPEventContext */*eventcontext*/, GtkWidget *toolbox) +void ToolboxFactory::updateSnapToolbox(SPDesktop *desktop, SPEventContext * /*eventcontext*/, GtkWidget *toolbox) { g_assert(desktop != NULL); g_assert(toolbox != NULL); @@ -2578,8 +2534,10 @@ static void sp_stb_magnitude_value_changed( GtkAdjustment *adj, GObject *dataKlu modmade = true; } } - if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, - _("Star: Change number of corners")); + if (modmade) { + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, + _("Star: Change number of corners")); + } g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -2623,8 +2581,10 @@ static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GObject *dataKl } } - if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, - _("Star: Change spoke ratio")); + if (modmade) { + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, + _("Star: Change spoke ratio")); + } g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -2702,8 +2662,10 @@ static void sp_stb_rounded_value_changed( GtkAdjustment *adj, GObject *dataKludg modmade = true; } } - if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, - _("Star: Change rounding")); + if (modmade) { + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, + _("Star: Change rounding")); + } g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -2737,15 +2699,17 @@ static void sp_stb_randomized_value_changed( GtkAdjustment *adj, GObject *dataKl modmade = true; } } - if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, - _("Star: Change randomization")); + if (modmade) { + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR, + _("Star: Change randomization")); + } g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) ); } static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, - gchar const */*old_value*/, gchar const */*new_value*/, + gchar const * /*old_value*/, gchar const * /*new_value*/, bool /*is_interactive*/, gpointer data) { GtkWidget *tbl = GTK_WIDGET(data); @@ -2850,7 +2814,7 @@ sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) } -static void sp_stb_defaults( GtkWidget */*widget*/, GObject *dataKludge ) +static void sp_stb_defaults( GtkWidget * /*widget*/, GObject *dataKludge ) { // FIXME: in this and all other _default functions, set some flag telling the value_changed // callbacks to lump all the changes for all selected objects in one undo step @@ -2888,11 +2852,13 @@ static void sp_stb_defaults( GtkWidget */*widget*/, GObject *dataKludge ) } -void -sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide) +// public: +void sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide) { GtkWidget *boxl = gtk_hbox_new(FALSE, 0); - if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1); + if (wide) { + gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1); + } GtkWidget *l = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(l), title); gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0); @@ -3065,9 +3031,8 @@ static void sp_rtb_sensitivize( GObject *tbl ) } -static void -sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name, - void (*setter)(SPRect *, gdouble)) +static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name, + void (*setter)(SPRect *, gdouble)) { SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); @@ -3110,34 +3075,29 @@ sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name, g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void -sp_rtb_rx_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_rtb_rx_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx); } -static void -sp_rtb_ry_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_rtb_ry_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry); } -static void -sp_rtb_width_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_rtb_width_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width); } -static void -sp_rtb_height_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_rtb_height_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height); } -static void -sp_rtb_defaults( GtkWidget */*widget*/, GObject *obj) +static void sp_rtb_defaults( GtkWidget * /*widget*/, GObject *obj) { GtkAdjustment *adj = 0; @@ -3153,8 +3113,8 @@ sp_rtb_defaults( GtkWidget */*widget*/, GObject *obj) sp_rtb_sensitivize( obj ); } -static void rect_tb_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const */*name*/, - gchar const */*old_value*/, gchar const */*new_value*/, +static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*name*/, + gchar const * /*old_value*/, gchar const * /*new_value*/, bool /*is_interactive*/, gpointer data) { GObject *tbl = G_OBJECT(data); @@ -3214,8 +3174,7 @@ static Inkscape::XML::NodeEventVector rect_tb_repr_events = { /** * \param selection should not be NULL. */ -static void -sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +static void sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) { int n_selected = 0; Inkscape::XML::Node *repr = NULL; @@ -3398,9 +3357,12 @@ static double box3d_normalize_angle (double a) { return angle; } -static void -box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis, - GtkAdjustment *adj, GtkAction *act, GtkToggleAction *tact) { +static void box3d_set_button_and_adjustment(Persp3D *persp, + Proj::Axis axis, + GtkAdjustment *adj, + GtkAction *act, + GtkToggleAction *tact) +{ // TODO: Take all selected perspectives into account but don't touch the state button if not all of them // have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states // are reset). @@ -3420,8 +3382,8 @@ box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis, } } -static void -box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) { +static void box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) +{ if (!persp_repr) { g_print ("No perspective given to box3d_resync_toolbar().\n"); return; @@ -3459,9 +3421,12 @@ box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) { } } -static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/, - gchar const */*old_value*/, gchar const */*new_value*/, - bool /*is_interactive*/, gpointer data) +static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr, + gchar const * /*name*/, + gchar const * /*old_value*/, + gchar const * /*new_value*/, + bool /*is_interactive*/, + gpointer data) { GtkWidget *tbl = GTK_WIDGET(data); @@ -3499,8 +3464,7 @@ static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events = */ // FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each // Change of the perspective, and not of the current selection (but how to refer to the toolbar then?) -static void -box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) { // Here the following should be done: If all selected boxes have finite VPs in a certain direction, // disable the angle entry fields for this direction (otherwise entering a value in them should only @@ -3532,8 +3496,7 @@ box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) } } -static void -box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis) +static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis) { SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" ); SPDocument *document = sp_desktop_document(desktop); @@ -3563,26 +3526,23 @@ box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis ax } -static void -box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge) +static void box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge) { box3d_angle_value_changed(adj, dataKludge, Proj::X); } -static void -box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge) +static void box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge) { box3d_angle_value_changed(adj, dataKludge, Proj::Y); } -static void -box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge) +static void box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge) { box3d_angle_value_changed(adj, dataKludge, Proj::Z); } -static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction */*box3d_angle*/, Proj::Axis axis ) +static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction * /*box3d_angle*/, Proj::Axis axis ) { // TODO: Take all selected perspectives into account std::list sel_persps = sp_desktop_selection(inkscape_active_desktop())->perspList(); @@ -3751,8 +3711,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, //## Spiral ## //######################## -static void -sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &value_name) +static void sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &value_name) { SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); @@ -3794,26 +3753,22 @@ sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &v g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void -sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_spl_tb_value_changed(adj, tbl, "revolution"); } -static void -sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_spl_tb_value_changed(adj, tbl, "expansion"); } -static void -sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GObject *tbl) { sp_spl_tb_value_changed(adj, tbl, "t0"); } -static void -sp_spl_tb_defaults(GtkWidget */*widget*/, GtkObject *obj) +static void sp_spl_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj) { GtkWidget *tbl = GTK_WIDGET(obj); @@ -3840,9 +3795,12 @@ sp_spl_tb_defaults(GtkWidget */*widget*/, GtkObject *obj) } -static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/, - gchar const */*old_value*/, gchar const */*new_value*/, - bool /*is_interactive*/, gpointer data) +static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, + gchar const * /*name*/, + gchar const * /*old_value*/, + gchar const * /*new_value*/, + bool /*is_interactive*/, + gpointer data) { GtkWidget *tbl = GTK_WIDGET(data); @@ -3876,8 +3834,7 @@ static Inkscape::XML::NodeEventVector spiral_tb_repr_events = { NULL /* order_changed */ }; -static void -sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +static void sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) { int n_selected = 0; Inkscape::XML::Node *repr = NULL; @@ -3993,8 +3950,7 @@ static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio //######################## /* This is used in generic functions below to share large portions of code between pen and pencil tool */ -static Glib::ustring const -freehand_tool_name(GObject *dataKludge) +static Glib::ustring const freehand_tool_name(GObject *dataKludge) { SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop"); return ( tools_isactive(desktop, TOOLS_FREEHAND_PEN) @@ -4089,7 +4045,7 @@ static void freehand_change_shape(EgeSelectOneAction* act, GObject *dataKludge) /** * \brief Generate the list of freehand advanced shape option entries. */ -GList * freehand_shape_dropdown_items_list() { +static GList * freehand_shape_dropdown_items_list() { GList *glist = NULL; glist = g_list_append (glist, _("None")); @@ -4101,8 +4057,8 @@ GList * freehand_shape_dropdown_items_list() { return glist; } -static void -freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil) { +static void freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil) +{ /*advanced shape options */ { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -4131,15 +4087,14 @@ freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder } } -static void sp_pen_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* mainActions, GObject* holder) +static void sp_pen_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder) { sp_add_freehand_mode_toggle(mainActions, holder, false); freehand_add_advanced_shape_options(mainActions, holder, false); } -static void -sp_pencil_tb_defaults(GtkWidget */*widget*/, GtkObject *obj) +static void sp_pencil_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj) { GtkWidget *tbl = GTK_WIDGET(obj); @@ -4155,8 +4110,7 @@ sp_pencil_tb_defaults(GtkWidget */*widget*/, GtkObject *obj) spinbutton_defocus(GTK_OBJECT(tbl)); } -static void -sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl) +static void sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl) { // quit if run by the attr_changed listener if (g_object_get_data( tbl, "freeze" )) { @@ -4247,13 +4201,13 @@ static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio //## Tweak ## //######################## -static void sp_tweak_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_tweak_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/tweak/width", adj->value * 0.01 ); } -static void sp_tweak_force_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_tweak_force_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/tweak/force", adj->value * 0.01 ); @@ -4271,48 +4225,39 @@ static void sp_tweak_mode_changed( EgeSelectOneAction *act, GObject *tbl ) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/tools/tweak/mode", mode); - GtkAction *doh = GTK_ACTION(g_object_get_data( tbl, "tweak_doh")); - GtkAction *dos = GTK_ACTION(g_object_get_data( tbl, "tweak_dos")); - GtkAction *dol = GTK_ACTION(g_object_get_data( tbl, "tweak_dol")); - GtkAction *doo = GTK_ACTION(g_object_get_data( tbl, "tweak_doo")); + static gchar const* names[] = {"tweak_doh", "tweak_dos", "tweak_dol", "tweak_doo", "tweak_channels_label"}; + bool flag = ((mode == TWEAK_MODE_COLORPAINT) || (mode == TWEAK_MODE_COLORJITTER)); + for (size_t i = 0; i < G_N_ELEMENTS(names); ++i) { + GtkAction *act = GTK_ACTION(g_object_get_data( tbl, names[i] )); + if (act) { + gtk_action_set_sensitive(act, flag); + } + } GtkAction *fid = GTK_ACTION(g_object_get_data( tbl, "tweak_fidelity")); - GtkAction *dolabel = GTK_ACTION(g_object_get_data( tbl, "tweak_channels_label")); - if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) { - if (doh) gtk_action_set_sensitive (doh, TRUE); - if (dos) gtk_action_set_sensitive (dos, TRUE); - if (dol) gtk_action_set_sensitive (dol, TRUE); - if (doo) gtk_action_set_sensitive (doo, TRUE); - if (dolabel) gtk_action_set_sensitive (dolabel, TRUE); - if (fid) gtk_action_set_sensitive (fid, FALSE); - } else { - if (doh) gtk_action_set_sensitive (doh, FALSE); - if (dos) gtk_action_set_sensitive (dos, FALSE); - if (dol) gtk_action_set_sensitive (dol, FALSE); - if (doo) gtk_action_set_sensitive (doo, FALSE); - if (dolabel) gtk_action_set_sensitive (dolabel, FALSE); - if (fid) gtk_action_set_sensitive (fid, TRUE); + if (fid) { + gtk_action_set_sensitive(fid, !flag); } } -static void sp_tweak_fidelity_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_tweak_fidelity_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/tweak/fidelity", adj->value * 0.01 ); } -static void tweak_toggle_doh (GtkToggleAction *act, gpointer /*data*/) { +static void tweak_toggle_doh(GtkToggleAction *act, gpointer /*data*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/tweak/doh", gtk_toggle_action_get_active(act)); } -static void tweak_toggle_dos (GtkToggleAction *act, gpointer /*data*/) { +static void tweak_toggle_dos(GtkToggleAction *act, gpointer /*data*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/tweak/dos", gtk_toggle_action_get_active(act)); } -static void tweak_toggle_dol (GtkToggleAction *act, gpointer /*data*/) { +static void tweak_toggle_dol(GtkToggleAction *act, gpointer /*data*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/tweak/dol", gtk_toggle_action_get_active(act)); } -static void tweak_toggle_doo (GtkToggleAction *act, gpointer /*data*/) { +static void tweak_toggle_doo(GtkToggleAction *act, gpointer /*data*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/tweak/doo", gtk_toggle_action_get_active(act)); } @@ -4477,8 +4422,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction EgeOutputAction* act = ege_output_action_new( "TweakChannelsLabel", _("Channels:"), "", 0 ); ege_output_action_set_use_markup( act, TRUE ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) + if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(act), FALSE); + } g_object_set_data( holder, "tweak_channels_label", act); } @@ -4493,8 +4439,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doh), desktop ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doh", true) ); - if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) + if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(act), FALSE); + } g_object_set_data( holder, "tweak_doh", act); } { @@ -4508,8 +4455,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dos), desktop ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dos", true) ); - if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) + if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(act), FALSE); + } g_object_set_data( holder, "tweak_dos", act ); } { @@ -4523,8 +4471,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dol), desktop ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dol", true) ); - if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) + if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(act), FALSE); + } g_object_set_data( holder, "tweak_dol", act ); } { @@ -4538,8 +4487,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doo), desktop ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doo", true) ); - if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) + if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(act), FALSE); + } g_object_set_data( holder, "tweak_doo", act ); } @@ -4556,8 +4506,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction sp_tweak_fidelity_value_changed, 0.01, 0, 100 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); - if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) + if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) { gtk_action_set_sensitive (GTK_ACTION(eact), FALSE); + } g_object_set_data( holder, "tweak_fidelity", eact ); } @@ -4581,19 +4532,19 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction //## Spray ## //######################## -static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/width", adj->value ); } -static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/mean", adj->value ); } -static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/standard_deviation", adj->value ); @@ -4605,26 +4556,26 @@ static void sp_spray_pressure_state_changed( GtkToggleAction *act, gpointer /*da prefs->setBool("/tools/spray/usepressure", gtk_toggle_action_get_active(act)); } -static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject */*tbl*/ ) +static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) { int mode = ege_select_one_action_get_active( act ); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/tools/spray/mode", mode); } -static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/population", adj->value ); } -static void sp_spray_rotation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_rotation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/rotation_variation", adj->value ); } -static void sp_spray_scale_value_changed( GtkAdjustment *adj, GObject */*tbl*/ ) +static void sp_spray_scale_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble( "/tools/spray/scale_variation", adj->value ); @@ -4802,11 +4753,12 @@ static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction //######################## //## Calligraphy ## //######################## -static void update_presets_list (GObject *tbl) +static void update_presets_list(GObject *tbl) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (g_object_get_data(tbl, "presets_blocked")) + if (g_object_get_data(tbl, "presets_blocked")) { return; + } EgeSelectOneAction *sel = static_cast(g_object_get_data(tbl, "profile_selector")); if (!sel) { @@ -4824,7 +4776,9 @@ static void update_presets_list (GObject *tbl) std::vector preset = prefs->getAllEntries(*i); for (std::vector::iterator j = preset.begin(); j != preset.end(); ++j) { Glib::ustring entry_name = j->getEntryName(); - if (entry_name == "id" || entry_name == "name") continue; + if (entry_name == "id" || entry_name == "name") { + continue; + } void *widget = g_object_get_data(tbl, entry_name.data()); if (widget) { @@ -4980,15 +4934,18 @@ static void sp_dcc_build_presets_list(GObject *tbl) update_presets_list (tbl); } -static void sp_dcc_save_profile (GtkWidget */*widget*/, GObject *tbl) +static void sp_dcc_save_profile(GtkWidget * /*widget*/, GObject *tbl) { using Inkscape::UI::Dialog::CalligraphicProfileRename; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop" ); - if (! desktop) return; + if (! desktop) { + return; + } - if (g_object_get_data(tbl, "presets_blocked")) + if (g_object_get_data(tbl, "presets_blocked")) { return; + } CalligraphicProfileRename::show(desktop); if ( !CalligraphicProfileRename::applied()) { @@ -5056,15 +5013,17 @@ static void sp_dcc_save_profile (GtkWidget */*widget*/, GObject *tbl) } -static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) { - +static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint preset_index = ege_select_one_action_get_active( act ); // This is necessary because EgeSelectOneAction spams us with GObject "changed" signal calls // even when the preset is not changed. It would be good to replace it with something more // modern. Index 0 means "No preset", so we don't do anything. - if (preset_index == 0) return; + if (preset_index == 0) { + return; + } gint save_presets_index = GPOINTER_TO_INT(g_object_get_data(tbl, "save_presets_index")); @@ -5074,8 +5033,9 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) { return; } - if (g_object_get_data(tbl, "presets_blocked")) + if (g_object_get_data(tbl, "presets_blocked")) { return; + } // preset_index is one-based so we subtract 1 std::vector presets = prefs->getAllDirs("/tools/calligraphic/preset"); @@ -5089,7 +5049,9 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) { // Shouldn't this be std::map? for (std::vector::iterator i = preset.begin(); i != preset.end(); ++i) { Glib::ustring entry_name = i->getEntryName(); - if (entry_name == "id" || entry_name == "name") continue; + if (entry_name == "id" || entry_name == "name") { + continue; + } void *widget = g_object_get_data(tbl, entry_name.data()); if (widget) { if (GTK_IS_ADJUSTMENT(widget)) { @@ -5368,10 +5330,11 @@ sp_arctb_startend_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *v SPGenericEllipse *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); - if (!strcmp(value_name, "start")) + if (!strcmp(value_name, "start")) { ge->start = (adj->value * M_PI)/ 180; - else + } else { ge->end = (adj->value * M_PI)/ 180; + } sp_genericellipse_normalize(ge); ((SPObject *)arc)->updateRepr(); @@ -5442,7 +5405,7 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) items != NULL; items = items->next) { - if (SP_IS_ARC((SPItem *) items->data)) { + if (SP_IS_ARC((SPItem *) items->data)) { Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); repr->setAttribute("sodipodi:open", NULL); SP_OBJECT((SPItem *) items->data)->updateRepr(); @@ -5473,8 +5436,8 @@ static void sp_arctb_defaults(GtkWidget *, GObject *obj) spinbutton_defocus( GTK_OBJECT(obj) ); } -static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/, - gchar const */*old_value*/, gchar const */*new_value*/, +static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * /*name*/, + gchar const * /*old_value*/, gchar const * /*new_value*/, bool /*is_interactive*/, gpointer data) { GObject *tbl = G_OBJECT(data); @@ -5675,7 +5638,8 @@ static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, //## Dropper ## //######################## -static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl ) { +static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl ) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt( "/tools/dropper/pick", gtk_toggle_action_get_active( act ) ); GtkAction* set_action = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "set_action") ); @@ -5690,7 +5654,8 @@ static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl ) { spinbutton_defocus(GTK_OBJECT(tbl)); } -static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl ) { +static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl ) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool( "/tools/dropper/setalpha", gtk_toggle_action_get_active( act ) ); spinbutton_defocus(GTK_OBJECT(tbl)); @@ -5704,7 +5669,7 @@ static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl ) { * TODO: Add queue of last 5 or so colors selected with new swatches so that * can drag and drop places. Will provide a nice mixing palette. */ -static void sp_dropper_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* mainActions, GObject* holder) +static void sp_dropper_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint pickAlpha = prefs->getInt( "/tools/dropper/pick", 1 ); @@ -5790,22 +5755,21 @@ static void sp_lpetool_mode_changed(EgeSelectOneAction *act, GObject *tbl) } } -void sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject */*tbl*/) +static void sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject * /*tbl*/) { SPEventContext *ec = selection->desktop()->event_context; - if (!SP_IS_LPETOOL_CONTEXT(ec)) - return; - - lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec)); + if (SP_IS_LPETOOL_CONTEXT(ec)) { + lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec)); + } } -void -sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl) +static void sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl) { using namespace Inkscape::LivePathEffect; SPEventContext *ec = selection->desktop()->event_context; - if (!SP_IS_LPETOOL_CONTEXT(ec)) + if (!SP_IS_LPETOOL_CONTEXT(ec)) { return; + } SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec); lpetool_delete_measuring_items(lc); @@ -5835,8 +5799,7 @@ sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl) } } -static void -lpetool_toggle_show_bbox (GtkToggleAction *act, gpointer data) { +static void lpetool_toggle_show_bbox(GtkToggleAction *act, gpointer data) { SPDesktop *desktop = static_cast(data); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -5849,11 +5812,12 @@ lpetool_toggle_show_bbox (GtkToggleAction *act, gpointer data) { } } -static void -lpetool_toggle_show_measuring_info (GtkToggleAction *act, GObject *tbl) { +static void lpetool_toggle_show_measuring_info(GtkToggleAction *act, GObject *tbl) +{ SPDesktop *desktop = static_cast(g_object_get_data(tbl, "desktop")); - if (!tools_isactive(desktop, TOOLS_LPETOOL)) + if (!tools_isactive(desktop, TOOLS_LPETOOL)) { return; + } GtkAction *unitact = static_cast(g_object_get_data(tbl, "lpetool_units_action")); SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context); @@ -5866,7 +5830,8 @@ lpetool_toggle_show_measuring_info (GtkToggleAction *act, GObject *tbl) { } } -static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl) { +static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl) +{ UnitTracker* tracker = reinterpret_cast(g_object_get_data(tbl, "tracker")); SPUnit const *unit = tracker->getActiveUnit(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -5880,8 +5845,8 @@ static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl) { } } -static void -lpetool_toggle_set_bbox (GtkToggleAction *act, gpointer data) { +static void lpetool_toggle_set_bbox(GtkToggleAction *act, gpointer data) +{ SPDesktop *desktop = static_cast(data); Inkscape::Selection *selection = desktop->selection; @@ -5907,8 +5872,7 @@ lpetool_toggle_set_bbox (GtkToggleAction *act, gpointer data) { gtk_toggle_action_set_active(act, false); } -static void -sp_line_segment_build_list(GObject *tbl) +static void sp_line_segment_build_list(GObject *tbl) { g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(TRUE)); @@ -5932,8 +5896,8 @@ sp_line_segment_build_list(GObject *tbl) g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(FALSE)); } -static void -sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) { +static void sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) +{ using namespace Inkscape::LivePathEffect; // quit if run by the attr_changed listener @@ -5955,8 +5919,8 @@ sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) { g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void -lpetool_open_lpe_dialog (GtkToggleAction *act, gpointer data) { +static void lpetool_open_lpe_dialog(GtkToggleAction *act, gpointer data) +{ SPDesktop *desktop = static_cast(data); if (tools_isactive(desktop, TOOLS_LPETOOL)) { @@ -6198,40 +6162,34 @@ static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio //## Text Toolbox ## //######################## /* -static void -sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl) +static void sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl) { //Call back for letter sizing spinbutton } -static void -sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl) +static void sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl) { //Call back for line height spinbutton } -static void -sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) +static void sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) { //Call back for horizontal kerning spinbutton } -static void -sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) +static void sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) { //Call back for vertical kerning spinbutton } -static void -sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl) +static void sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl) { //Call back for letter rotation spinbutton }*/ namespace { -void -sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *tbl) +static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection*/, GObject *tbl) { // quit if run by the _changed callbacks if (g_object_get_data(G_OBJECT(tbl), "freeze")) { @@ -6324,25 +6282,19 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject * g_object_set_data (G_OBJECT (button), "block", gpointer(1)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - else - { + } else { if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) { GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start")); g_object_set_data (G_OBJECT (button), "block", gpointer(1)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) - { + } else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) { GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle")); g_object_set_data (G_OBJECT (button), "block", gpointer(1)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) - { + } else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) { GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end")); g_object_set_data (G_OBJECT (button), "block", gpointer(1)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); @@ -6387,12 +6339,9 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject * GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical")); g_object_set_data (G_OBJECT (button1), "block", gpointer(1)); - if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB) - { + if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - } - else - { + } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE); } g_object_set_data (G_OBJECT (button), "block", gpointer(0)); @@ -6404,21 +6353,18 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject * g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -void -sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) +static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) { sp_text_toolbox_selection_changed (selection, tbl); } -void -sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl) +static void sp_text_toolbox_subselection_changed(gpointer /*tc*/, GObject *tbl) { sp_text_toolbox_selection_changed (NULL, tbl); } -void -sp_text_toolbox_family_changed (GtkComboBoxEntry *, - GObject *tbl) +static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, + GObject *tbl) { // quit if run by the _changed callbacks if (g_object_get_data(G_OBJECT(tbl), "freeze")) { @@ -6501,14 +6447,11 @@ sp_text_toolbox_family_changed (GtkComboBoxEntry *, } // If querying returned nothing, set the default style of the tool (for new texts) - if (result_fontspec == QUERY_STYLE_NOTHING) - { + 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 trough a verb - } - else - { + } else { sp_desktop_set_style (desktop, css, true, true); } @@ -6528,12 +6471,15 @@ sp_text_toolbox_family_changed (GtkComboBoxEntry *, } -void -sp_text_toolbox_anchoring_toggled (GtkRadioButton *button, - gpointer data) +static void sp_text_toolbox_anchoring_toggled(GtkRadioButton *button, + gpointer data) { - if (g_object_get_data (G_OBJECT (button), "block")) return; - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return; + if (g_object_get_data (G_OBJECT (button), "block")) { + return; + } + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + return; + } int prop = GPOINTER_TO_INT(data); SPDesktop *desktop = SP_ACTIVE_DESKTOP; @@ -6556,8 +6502,9 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button, Geom::OptRect bbox = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); - if (!bbox) + if (!bbox) { continue; + } double width = bbox->dimensions()[axis]; // If you want to align within some frame, other than the text's own bbox, calculate // the left and right (or top and bottom for tb text) slacks of the text inside that @@ -6668,11 +6615,12 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button, gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); } -void -sp_text_toolbox_style_toggled (GtkToggleButton *button, - gpointer data) +static void sp_text_toolbox_style_toggled(GtkToggleButton *button, + gpointer data) { - if (g_object_get_data (G_OBJECT (button), "block")) return; + if (g_object_get_data (G_OBJECT (button), "block")) { + return; + } SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPCSSAttr *css = sp_repr_css_attr_new (); @@ -6772,9 +6720,8 @@ sp_text_toolbox_style_toggled (GtkToggleButton *button, gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); } -void -sp_text_toolbox_orientation_toggled (GtkRadioButton *button, - gpointer data) +static void sp_text_toolbox_orientation_toggled(GtkRadioButton *button, + gpointer data) { if (g_object_get_data (G_OBJECT (button), "block")) { return; @@ -6819,21 +6766,22 @@ sp_text_toolbox_orientation_toggled (GtkRadioButton *button, gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); } -gboolean -sp_text_toolbox_family_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl) +static gboolean sp_text_toolbox_family_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject *tbl) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return FALSE; + if (!desktop) { + return FALSE; + } switch (get_group0_keyval (event)) { case GDK_KP_Enter: // chosen case GDK_Return: // unfreeze and update, which will defocus g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - sp_text_toolbox_family_changed (NULL, tbl); + sp_text_toolbox_family_changed (NULL, tbl); return TRUE; // I consumed the event break; - case GDK_Escape: + case GDK_Escape: // defocus gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); return TRUE; // I consumed the event @@ -6842,11 +6790,12 @@ sp_text_toolbox_family_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject * return FALSE; } -gboolean -sp_text_toolbox_family_list_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject */*tbl*/) +static gboolean sp_text_toolbox_family_list_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject * /*tbl*/) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return FALSE; + if (!desktop) { + return FALSE; + } switch (get_group0_keyval (event)) { case GDK_KP_Enter: @@ -6867,9 +6816,8 @@ sp_text_toolbox_family_list_keypress (GtkWidget */*w*/, GdkEventKey *event, GObj } -void -sp_text_toolbox_size_changed (GtkComboBox *cbox, - GObject *tbl) +static void sp_text_toolbox_size_changed(GtkComboBox *cbox, + GObject *tbl) { // quit if run by the _changed callbacks if (g_object_get_data(G_OBJECT(tbl), "freeze")) { @@ -6935,11 +6883,12 @@ sp_text_toolbox_size_changed (GtkComboBox *cbox, g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -gboolean -sp_text_toolbox_size_focusout (GtkWidget */*w*/, GdkEventFocus */*event*/, GObject *tbl) +static gboolean sp_text_toolbox_size_focusout(GtkWidget * /*w*/, GdkEventFocus * /*event*/, GObject *tbl) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return FALSE; + if (!desktop) { + return FALSE; + } if (!g_object_get_data (tbl, "esc-pressed")) { g_object_set_data (tbl, "enter-pressed", gpointer(1)); @@ -6951,11 +6900,12 @@ sp_text_toolbox_size_focusout (GtkWidget */*w*/, GdkEventFocus */*event*/, GObje } -gboolean -sp_text_toolbox_size_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl) +static gboolean sp_text_toolbox_size_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject *tbl) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return FALSE; + if (!desktop) { + return FALSE; + } switch (get_group0_keyval (event)) { case GDK_Escape: // defocus @@ -6979,32 +6929,29 @@ sp_text_toolbox_size_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tb // While editing font name in the entry, disable family_changed by freezing, otherwise completion // does not work! -gboolean -sp_text_toolbox_entry_focus_in (GtkWidget *entry, - GdkEventFocus */*event*/, - GObject *tbl) +static gboolean sp_text_toolbox_entry_focus_in(GtkWidget *entry, + GdkEventFocus * /*event*/, + GObject *tbl) { g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); gtk_entry_select_region (GTK_ENTRY (entry), 0, -1); // select all return FALSE; } -gboolean -sp_text_toolbox_entry_focus_out (GtkWidget *entry, - GdkEventFocus */*event*/, - GObject *tbl) +static gboolean sp_text_toolbox_entry_focus_out(GtkWidget *entry, + GdkEventFocus * /*event*/, + GObject *tbl) { g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); gtk_entry_select_region (GTK_ENTRY (entry), 0, 0); // deselect return FALSE; } -void -cell_data_func (GtkCellLayout */*cell_layout*/, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer /*data*/) +static void cell_data_func(GtkCellLayout * /*cell_layout*/, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer /*data*/) { gchar *family; gtk_tree_model_get(tree_model, iter, 0, &family, -1); @@ -7031,10 +6978,10 @@ cell_data_func (GtkCellLayout */*cell_layout*/, g_free(family_escaped); } -gboolean text_toolbox_completion_match_selected(GtkEntryCompletion */*widget*/, - GtkTreeModel *model, - GtkTreeIter *iter, - GObject *tbl) +static gboolean text_toolbox_completion_match_selected(GtkEntryCompletion * /*widget*/, + GtkTreeModel *model, + GtkTreeIter *iter, + GObject *tbl) { // We intercept this signal so as to fire family_changed at once (without it, you'd have to // press Enter again after choosing a completion) @@ -7050,8 +6997,8 @@ gboolean text_toolbox_completion_match_selected(GtkEntryCompletion */*widget*/, } -static void -cbe_add_completion (GtkComboBoxEntry *cbe, GObject *tbl){ +static void cbe_add_completion(GtkComboBoxEntry *cbe, GObject *tbl) +{ GtkEntry *entry; GtkEntryCompletion *completion; GtkTreeModel *model; @@ -7071,9 +7018,9 @@ cbe_add_completion (GtkComboBoxEntry *cbe, GObject *tbl){ g_object_unref(completion); } -void sp_text_toolbox_family_popnotify(GtkComboBox *widget, - void */*property*/, - GObject *tbl) +static void sp_text_toolbox_family_popnotify(GtkComboBox *widget, + void * /*property*/, + GObject *tbl) { // while the drop-down is open, we disable font family changing, reenabling it only when it closes @@ -7109,22 +7056,23 @@ void sp_text_toolbox_family_popnotify(GtkComboBox *widget, } // update - sp_text_toolbox_family_changed (NULL, tbl); + sp_text_toolbox_family_changed (NULL, tbl); break; } - } + } } } // regardless of whether we updated, defocus the widget SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) + if (desktop) { gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); + } //g_print("POP: notify: HIDDEN\n"); } } -GtkWidget *sp_text_toolbox_new (SPDesktop *desktop) +GtkWidget *sp_text_toolbox_new(SPDesktop *desktop) { GtkToolbar *tbl = GTK_TOOLBAR(gtk_toolbar_new()); GtkIconSize secondarySize = static_cast(ToolboxFactory::prefToSize("/toolbox/secondary", 1)); @@ -7150,7 +7098,7 @@ GtkWidget *sp_text_toolbox_new (SPDesktop *desktop) g_signal_connect (G_OBJECT (font_sel->gobj()), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl); cbe_add_completion(font_sel->gobj(), G_OBJECT(tbl)); - + gtk_toolbar_append_widget( tbl, (GtkWidget*) font_sel->gobj(), "", ""); g_object_set_data (G_OBJECT (tbl), "family-entry-combo", font_sel); @@ -7163,7 +7111,7 @@ GtkWidget *sp_text_toolbox_new (SPDesktop *desktop) g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_changed), tbl); g_signal_connect (G_OBJECT (font_sel->gobj()), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl); - g_signal_connect (G_OBJECT (font_sel->gobj()), "notify::popup-shown", + g_signal_connect (G_OBJECT (font_sel->gobj()), "notify::popup-shown", G_CALLBACK (sp_text_toolbox_family_popnotify), tbl); g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl); g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl); @@ -7352,7 +7300,7 @@ GtkWidget *sp_text_toolbox_new (SPDesktop *desktop) //## Connector ## //######################### -static void sp_connector_mode_toggled( GtkToggleAction* act, GtkObject */*tbl*/ ) +static void sp_connector_mode_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/connector/mode", @@ -7376,8 +7324,7 @@ static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl Inkscape::Selection * selection = sp_desktop_selection(desktop); SPDocument *doc = sp_desktop_document(desktop); - if (!sp_document_get_undo_sensitive(doc)) - { + if (!sp_document_get_undo_sensitive(doc)) { return; } @@ -7409,8 +7356,7 @@ static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl l = l->next; } - if (!modmade) - { + if (!modmade) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/connector/orthogonal", is_orthog); } @@ -7427,8 +7373,7 @@ static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl) Inkscape::Selection * selection = sp_desktop_selection(desktop); SPDocument *doc = sp_desktop_document(desktop); - if (!sp_document_get_undo_sensitive(doc)) - { + if (!sp_document_get_undo_sensitive(doc)) { return; } @@ -7459,8 +7404,7 @@ static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl) l = l->next; } - if (!modmade) - { + if (!modmade) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble(Glib::ustring("/tools/connector/curvature"), newValue); } @@ -7477,8 +7421,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); SPDocument *doc = sp_desktop_document(desktop); - if (!sp_document_get_undo_sensitive(doc)) - { + if (!sp_document_get_undo_sensitive(doc)) { return; } @@ -7486,7 +7429,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) if ( !repr->attribute("inkscape:connector-spacing") && ( adj->value == defaultConnSpacing )) { - // Don't need to update the repr if the attribute doesn't + // Don't need to update the repr if the attribute doesn't // exist and it is being set to the default value -- as will // happen at startup. return; @@ -7522,7 +7465,9 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) static void sp_connector_graph_layout(void) { - if (!SP_ACTIVE_DESKTOP) return; + if (!SP_ACTIVE_DESKTOP) { + return; + } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // hack for clones, see comment in align-and-distribute.cpp @@ -7536,14 +7481,14 @@ static void sp_connector_graph_layout(void) sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Arrange connector network")); } -static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GtkObject */*tbl*/ ) +static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/connector/directedlayout", gtk_toggle_action_get_active( act )); } -static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GtkObject */*tbl*/ ) +static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/connector/avoidoverlaplayout", @@ -7558,7 +7503,7 @@ static void connector_length_changed(GtkAdjustment *adj, GObject* /*tbl*/) } static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr, - gchar const *name, gchar const */*old_value*/, gchar const */*new_value*/, + gchar const *name, gchar const * /*old_value*/, gchar const * /*new_value*/, bool /*is_interactive*/, gpointer data) { GtkWidget *tbl = GTK_WIDGET(data); @@ -7585,8 +7530,9 @@ static void sp_connector_new_connection_point(GtkWidget *, GObject *tbl) SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context); - if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) + if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) { cc_create_connection_point(cc); + } } static void sp_connector_remove_connection_point(GtkWidget *, GObject *tbl) @@ -7594,8 +7540,9 @@ static void sp_connector_remove_connection_point(GtkWidget *, GObject *tbl) SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context); - if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) + if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) { cc_remove_connection_point(cc); + } } static Inkscape::XML::NodeEventVector connector_tb_repr_events = { @@ -7805,13 +7752,13 @@ static void paintbucket_channels_changed(EgeSelectOneAction* act, GObject* /*tbl flood_channels_set_channels( channels ); } -static void paintbucket_threshold_changed(GtkAdjustment *adj, GObject */*tbl*/) +static void paintbucket_threshold_changed(GtkAdjustment *adj, GObject * /*tbl*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/tools/paintbucket/threshold", (gint)adj->value); } -static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject */*tbl*/) +static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject * /*tbl*/) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/paintbucket/autogap", ege_select_one_action_get_active( act )); @@ -7827,7 +7774,7 @@ static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl) prefs->setString("/tools/paintbucket/offsetunits", sp_unit_get_abbreviation(unit)); } -static void paintbucket_defaults (GtkWidget *, GObject *tbl) +static void paintbucket_defaults(GtkWidget *, GObject *tbl) { // FIXME: make defaults settable via Inkscape Options struct KeyValue { @@ -7898,8 +7845,9 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main // Create the units menu. UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE ); Glib::ustring stored_unit = prefs->getString("/tools/paintbucket/offsetunits"); - if (!stored_unit.empty()) + if (!stored_unit.empty()) { tracker->setActiveUnit(sp_unit_get_by_abbreviation(stored_unit.data())); + } g_object_set_data( holder, "tracker", tracker ); { GtkAction* act = tracker->createAction( "PaintbucketUnitsAction", _("Units"), ("") ); -- cgit v1.2.3 From 9b6e70b38a511411f2345c88919cfe14127ab859 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 12 Apr 2010 01:09:40 -0700 Subject: Simplifying sigc::bind use. Possible fix for mac compile. Fixed bugs: - https://launchpad.net/bugs/196195 (bzr r9317) --- src/device-manager.cpp | 24 ++++++++++++------------ src/device-manager.h | 8 ++++---- src/ui/dialog/input.cpp | 26 ++++++++++++++------------ 3 files changed, 30 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/device-manager.cpp b/src/device-manager.cpp index b71cca059..62e0c2545 100644 --- a/src/device-manager.cpp +++ b/src/device-manager.cpp @@ -260,10 +260,10 @@ public: virtual std::list > getDevices(); - virtual sigc::signal& > signalDeviceChanged(); - virtual sigc::signal& > signalAxesChanged(); - virtual sigc::signal& > signalButtonsChanged(); - virtual sigc::signal& > signalLinkChanged(); + virtual sigc::signal > signalDeviceChanged(); + virtual sigc::signal > signalAxesChanged(); + virtual sigc::signal > signalButtonsChanged(); + virtual sigc::signal > signalLinkChanged(); virtual void addAxis(Glib::ustring const & id, gint axis); virtual void addButton(Glib::ustring const & id, gint button); @@ -276,10 +276,10 @@ public: protected: std::list > devices; - sigc::signal& > signalDeviceChangedPriv; - sigc::signal& > signalAxesChangedPriv; - sigc::signal& > signalButtonsChangedPriv; - sigc::signal& > signalLinkChangedPriv; + sigc::signal > signalDeviceChangedPriv; + sigc::signal > signalAxesChangedPriv; + sigc::signal > signalButtonsChangedPriv; + sigc::signal > signalLinkChangedPriv; }; @@ -445,22 +445,22 @@ void DeviceManagerImpl::setKey( Glib::ustring const & id, guint index, guint key } } -sigc::signal& > DeviceManagerImpl::signalDeviceChanged() +sigc::signal > DeviceManagerImpl::signalDeviceChanged() { return signalDeviceChangedPriv; } -sigc::signal& > DeviceManagerImpl::signalAxesChanged() +sigc::signal > DeviceManagerImpl::signalAxesChanged() { return signalAxesChangedPriv; } -sigc::signal& > DeviceManagerImpl::signalButtonsChanged() +sigc::signal > DeviceManagerImpl::signalButtonsChanged() { return signalButtonsChangedPriv; } -sigc::signal& > DeviceManagerImpl::signalLinkChanged() +sigc::signal > DeviceManagerImpl::signalLinkChanged() { return signalLinkChangedPriv; } diff --git a/src/device-manager.h b/src/device-manager.h index c32a79bfa..4aea99ac0 100644 --- a/src/device-manager.h +++ b/src/device-manager.h @@ -47,10 +47,10 @@ public: virtual std::list > getDevices() = 0; - virtual sigc::signal& > signalDeviceChanged() = 0; - virtual sigc::signal& > signalAxesChanged() = 0; - virtual sigc::signal& > signalButtonsChanged() = 0; - virtual sigc::signal& > signalLinkChanged() = 0; + virtual sigc::signal > signalDeviceChanged() = 0; + virtual sigc::signal > signalAxesChanged() = 0; + virtual sigc::signal > signalButtonsChanged() = 0; + virtual sigc::signal > signalLinkChanged() = 0; virtual void addAxis(Glib::ustring const & id, gint axis) = 0; virtual void addButton(Glib::ustring const & id, gint button) = 0; diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index 570f00944..92a54affb 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -454,10 +454,10 @@ private: bool eventSnoop(GdkEvent* event); void linkComboChanged(); void resyncToSelection(); - void handleDeviceChange(const Glib::RefPtr& device); - void updateDeviceAxes(const Glib::RefPtr& device); - void updateDeviceButtons(const Glib::RefPtr& device); - static void updateDeviceLinks(const Glib::RefPtr& device, Gtk::TreeIter &tabletIter, Gtk::TreeView &tree); + void handleDeviceChange(Glib::RefPtr device); + void updateDeviceAxes(Glib::RefPtr device); + void updateDeviceButtons(Glib::RefPtr device); + static void updateDeviceLinks(Glib::RefPtr device, Gtk::TreeIter tabletIter, Glib::RefPtr tree); static bool findDevice(const Gtk::TreeModel::iterator& iter, Glib::ustring id, @@ -713,7 +713,8 @@ InputDialogImpl::InputDialogImpl() : Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange)); Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes)); Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons)); - Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, tree)); + Glib::RefPtr treePtr(&tree); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr)); tree.expand_all(); show_all_children(); @@ -826,7 +827,8 @@ InputDialogImpl::ConfPanel::ConfPanel() : setupTree( store, tabletIter ); - Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, tree)); + Glib::RefPtr treePtr(&tree); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr)); tree.expand_all(); @@ -909,7 +911,7 @@ void InputDialogImpl::ConfPanel::Blink::notify(Preferences::Entry const &new_val parent.useExt.set_active(new_val.getBool()); } -void InputDialogImpl::handleDeviceChange(const Glib::RefPtr& device) +void InputDialogImpl::handleDeviceChange(Glib::RefPtr device) { // g_message("OUCH!!!! for %p hits %s", &device, device->getId().c_str()); std::vector > stores; @@ -932,7 +934,7 @@ void InputDialogImpl::handleDeviceChange(const Glib::RefPtr& device } } -void InputDialogImpl::updateDeviceAxes(const Glib::RefPtr& device) +void InputDialogImpl::updateDeviceAxes(Glib::RefPtr device) { gint live = device->getLiveAxes(); @@ -949,7 +951,7 @@ void InputDialogImpl::updateDeviceAxes(const Glib::RefPtr& device) updateTestAxes( device->getId(), 0 ); } -void InputDialogImpl::updateDeviceButtons(const Glib::RefPtr& device) +void InputDialogImpl::updateDeviceButtons(Glib::RefPtr device) { gint live = device->getLiveButtons(); std::set existing = buttonMap[device->getId()]; @@ -995,9 +997,9 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter, return stop; } -void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device, Gtk::TreeIter &tabletIter, Gtk::TreeView &tree) +void InputDialogImpl::updateDeviceLinks(Glib::RefPtr device, Gtk::TreeIter tabletIter, Glib::RefPtr tree) { - Glib::RefPtr store = Glib::RefPtr::cast_dynamic(tree.get_model()); + Glib::RefPtr store = Glib::RefPtr::cast_dynamic(tree->get_model()); // g_message("Links!!!! for %p hits [%s] with link of [%s]", &device, device->getId().c_str(), device->getLink().c_str()); Gtk::TreeModel::iterator deviceIter; @@ -1078,7 +1080,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device, if ( oldParent->children().empty() ) { store->erase(oldParent); } - tree.expand_row(Gtk::TreePath(newGroup), true); + tree->expand_row(Gtk::TreePath(newGroup), true); } } } -- cgit v1.2.3 From 1b36b306bc0068e94b300966a50060c07c4f428f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 12 Apr 2010 02:10:41 -0700 Subject: Leave uninitialized bools in preferences to the default 'false' value. Code should initialize those explicitly and not count on GUI widgets to do so. (bzr r9318) --- src/widgets/toolbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index bf1231092..0b690504f 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -741,7 +741,7 @@ PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (* { g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggleCB), this); freeze = true; - gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path, true) ); + gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path) ); freeze = false; Inkscape::Preferences::get()->addObserver(*this); -- cgit v1.2.3 From 99f7c8998a7f1111981f485122ce687179fa95e4 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 12 Apr 2010 02:20:43 -0700 Subject: Added defaults to node tool values that were missing from preference init. (bzr r9319) --- src/preferences-skeleton.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 297d19c10..af9b446d8 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -9,7 +9,7 @@ #define N_(x) x /* The root's "version" attribute describes the preferences file format version. - * It should only increase when a backwards-incompatible change is made, + * It should only increase when a backwards-incompatible change is made, * and special handling has to be added to the preferences class to update * obsolete versions the user might have. */ static char const preferences_skeleton[] = @@ -101,7 +101,7 @@ static char const preferences_skeleton[] = " \n" " \n" " \n" -" \n" +" \n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" -- cgit v1.2.3 From 87b64ac179100521e4a740e786df5ef24956c2dd Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 12 Apr 2010 18:41:04 -0700 Subject: Minor fix of pointer check. (bzr r9321) --- src/ege-select-one-action.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index 6de22495d..50967ecb2 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -575,7 +575,7 @@ GtkWidget* create_tool_item( GtkAction* action ) g_object_set( G_OBJECT(obj), act->private_data->iconProperty, iconId, NULL ); } - if ( act->private_data->iconProperty >= 0 ) { + if ( act->private_data->iconProperty ) { /* TODO get this string to be set instead of hardcoded */ if ( act->private_data->iconSize >= 0 ) { g_object_set( G_OBJECT(obj), "iconSize", act->private_data->iconSize, NULL ); -- cgit v1.2.3 From c99316f9975a7d8c990e1af9d7b72f95a4b0d58d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 12 Apr 2010 22:36:46 -0700 Subject: Added method to fetch currently active text. (bzr r9322) --- src/ege-select-one-action.cpp | 15 +++++++++++++++ src/ege-select-one-action.h | 8 ++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index 50967ecb2..834b06b3b 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -278,6 +278,21 @@ gint ege_select_one_action_get_active( EgeSelectOneAction* action ) return action->private_data->active; } +gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action ) +{ + GtkTreeIter iter; + gchar *str = 0; + g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); + + if ( gtk_tree_model_iter_nth_child( action->private_data->model, &iter, NULL, action->private_data->active ) ) { + gtk_tree_model_get( action->private_data->model, &iter, + action->private_data->labelColumn, &str, + -1 ); + } + + return str; +} + void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val ) { g_object_set( G_OBJECT(action), "active", val, NULL ); diff --git a/src/ege-select-one-action.h b/src/ege-select-one-action.h index d0c9d6de7..2ecf7efc5 100644 --- a/src/ege-select-one-action.h +++ b/src/ege-select-one-action.h @@ -121,6 +121,14 @@ GtkTreeModel *ege_select_one_action_get_model(EgeSelectOneAction* action ); */ gint ege_select_one_action_get_active( EgeSelectOneAction* action ); +/** + * Returns the text of the currently selected item. + * + * @param action The action to fetch the text for. + * @return the selected text. The caller is responsible to call g_free() on it when done. + */ +gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action ); + /** * Sets the currently selected item. * -- cgit v1.2.3 From 6796f5a8ea82dd5958ce869e6436e438e5aa1274 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Wed, 14 Apr 2010 00:06:56 -0700 Subject: Updated GtkAction subclass to allow "open" selections for a user to type into. (bzr r9326) --- src/ege-select-one-action.cpp | 229 +++++++++++++++++++++++++++++++++++++----- src/ege-select-one-action.h | 11 +- 2 files changed, 212 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index 834b06b3b..587555c8b 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -18,7 +18,7 @@ * * The Initial Developer of the Original Code is * Jon A. Cruz. - * Portions created by the Initial Developer are Copyright (C) 2007 + * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): @@ -64,7 +64,11 @@ static void ege_select_one_action_init( EgeSelectOneAction* action ); static void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ); static void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec ); -static void resync_active( EgeSelectOneAction* act, gint active ); +static gint find_text_index(EgeSelectOneAction *act, gchar const* text); +static void commit_pending_change(EgeSelectOneAction *act); +static void resync_active( EgeSelectOneAction* act, gint active, gboolean override ); +static void combo_entry_changed_cb( GtkEntry* widget, gpointer user_data ); +static gboolean combo_entry_focus_lost_cb( GtkWidget *widget, GdkEventFocus *event, gpointer data ); static void combo_changed_cb( GtkComboBox* widget, gpointer user_data ); static void menu_toggled_cb( GtkWidget* obj, gpointer data ); static void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data ); @@ -87,6 +91,12 @@ enum { APPEARANCE_MINIMAL, // no label, just choices in a drop-down menu }; +enum { + SELECTION_UNKNOWN = -1, + SELECTION_CLOSED = 0, + SELECTION_OPEN, +}; + struct _EgeSelectOneActionPrivate { gint active; @@ -94,11 +104,15 @@ struct _EgeSelectOneActionPrivate gint iconColumn; gint tooltipColumn; gint appearanceMode; + gint selectionMode; gint iconSize; GType radioActionType; GtkTreeModel* model; - gchar* iconProperty; - gchar* appearance; + gchar *iconProperty; + gchar *appearance; + gchar *selection; + gchar *activeText; + gchar *pendingText; }; #define EGE_SELECT_ONE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_SELECT_ONE_ACTION_TYPE, EgeSelectOneActionPrivate ) ) @@ -111,7 +125,8 @@ enum { PROP_TOOLTIP_COLUMN, PROP_ICON_PROP, PROP_ICON_SIZE, - PROP_APPEARANCE + PROP_APPEARANCE, + PROP_SELECTION }; GType ege_select_one_action_get_type( void ) @@ -169,7 +184,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "active", "Active Selection", "The index of the selected item", - 0, 20, 0, + -1, 20, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, @@ -220,6 +235,14 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) "", (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + g_object_class_install_property( objClass, + PROP_SELECTION, + g_param_spec_string( "selection", + "Selection set open or closed", + "'open' to allow edits/additions, 'closed' to disallow.", + "", + (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + signals[CHANGED] = g_signal_new( "changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST, @@ -241,11 +264,15 @@ void ege_select_one_action_init( EgeSelectOneAction* action ) action->private_data->iconColumn = -1; action->private_data->tooltipColumn = -1; action->private_data->appearanceMode = APPEARANCE_NONE; + action->private_data->selectionMode = SELECTION_CLOSED; action->private_data->radioActionType = 0; action->private_data->model = 0; action->private_data->iconProperty = g_strdup("stock-id"); action->private_data->iconSize = -1; action->private_data->appearance = 0; + action->private_data->selection = 0; + action->private_data->activeText = 0; + action->private_data->pendingText = 0; /* g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */ } @@ -284,10 +311,14 @@ gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action ) gchar *str = 0; g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); - if ( gtk_tree_model_iter_nth_child( action->private_data->model, &iter, NULL, action->private_data->active ) ) { - gtk_tree_model_get( action->private_data->model, &iter, - action->private_data->labelColumn, &str, - -1 ); + if ( action->private_data->active >= 0) { + if ( gtk_tree_model_iter_nth_child( action->private_data->model, &iter, NULL, action->private_data->active ) ) { + gtk_tree_model_get( action->private_data->model, &iter, + action->private_data->labelColumn, &str, + -1 ); + } + } else if ( (action->private_data->active == -1) && action->private_data->activeText ) { + str = g_strdup(action->private_data->activeText); } return str; @@ -347,6 +378,11 @@ void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar con g_object_set( G_OBJECT(action), "appearance", val, NULL ); } +void ege_select_one_action_set_selection( EgeSelectOneAction* action, gchar const* val ) +{ + g_object_set( G_OBJECT(action), "selection", val, NULL ); +} + void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ) { EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj ); @@ -383,6 +419,10 @@ void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* val g_value_set_string( value, action->private_data->appearance ); break; + case PROP_SELECTION: + g_value_set_string( value, action->private_data->selection ); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } @@ -400,7 +440,7 @@ void ege_select_one_action_set_property( GObject* obj, guint propId, const GValu case PROP_ACTIVE: { - resync_active( action, g_value_get_int( value ) ); + resync_active( action, g_value_get_int( value ), FALSE ); } break; @@ -458,6 +498,23 @@ void ege_select_one_action_set_property( GObject* obj, guint propId, const GValu } break; + case PROP_SELECTION: + { + gchar* tmp = action->private_data->selection; + gchar* newVal = g_value_dup_string( value ); + action->private_data->selection = newVal; + g_free( tmp ); + + if ( !action->private_data->selection || (strcmp("closed", newVal) == 0) ) { + action->private_data->selectionMode = SELECTION_CLOSED; + } else if ( strcmp("open", newVal) == 0 ) { + action->private_data->selectionMode = SELECTION_OPEN; + } else { + action->private_data->selectionMode = SELECTION_UNKNOWN; + } + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } @@ -495,6 +552,7 @@ GtkWidget* create_menu_item( GtkAction* action ) gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), index == act->private_data->active ); g_free(str); + str = 0; g_signal_connect( G_OBJECT(item), "toggled", G_CALLBACK(menu_toggled_cb), GINT_TO_POINTER(index) ); @@ -629,23 +687,32 @@ GtkWidget* create_tool_item( GtkAction* action ) gtk_container_add( GTK_CONTAINER(item), holder ); } else { + GtkCellRenderer * renderer = 0; GtkWidget* holder = gtk_hbox_new( FALSE, 4 ); - GtkWidget* normal = gtk_combo_box_new_with_model( act->private_data->model ); + GtkWidget* normal = (act->private_data->selectionMode == SELECTION_OPEN) ? + gtk_combo_box_entry_new_with_model( act->private_data->model, act->private_data->labelColumn ) : + gtk_combo_box_new_with_model( act->private_data->model ); + if ((act->private_data->selectionMode == SELECTION_OPEN)) { + GtkWidget *child = gtk_bin_get_child( GTK_BIN(normal) ); + if (GTK_IS_ENTRY(child)) { + gtk_entry_set_width_chars(GTK_ENTRY(child), 4); + g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(combo_entry_changed_cb), act ); + g_signal_connect( G_OBJECT(child), "focus-out-event", G_CALLBACK(combo_entry_focus_lost_cb), act ); + } + } else { + if ( act->private_data->iconColumn >= 0 ) { + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); - GtkCellRenderer * renderer = 0; + // "icon-name" + gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn ); + } - if ( act->private_data->iconColumn >= 0 ) { - renderer = gtk_cell_renderer_pixbuf_new(); + renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); - - // "icon-name" - gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn ); + gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn ); } - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); - gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn ); - gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active ); g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action ); @@ -664,7 +731,11 @@ GtkWidget* create_tool_item( GtkAction* action ) gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 ); - gtk_container_add( GTK_CONTAINER(item), holder ); + { + GtkWidget *align = gtk_alignment_new(0, 0.5, 0, 0); + gtk_container_add( GTK_CONTAINER(align), holder); + gtk_container_add( GTK_CONTAINER(item), align ); + } } gtk_widget_show_all( item ); @@ -687,9 +758,9 @@ void disconnect_proxy( GtkAction *action, GtkWidget *proxy ) } -void resync_active( EgeSelectOneAction* act, gint active ) +void resync_active( EgeSelectOneAction* act, gint active, gboolean override ) { - if ( act->private_data->active != active ) { + if ( override || (act->private_data->active != active) ) { act->private_data->active = active; GSList* proxies = gtk_action_get_proxies( GTK_ACTION(act) ); while ( proxies ) { @@ -698,9 +769,15 @@ void resync_active( EgeSelectOneAction* act, gint active ) GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); if ( children && children->data ) { gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); + if (!combodata && GTK_IS_ALIGNMENT(children->data)) { + GList *other = gtk_container_get_children( GTK_CONTAINER(children->data) ); + combodata = g_object_get_data( G_OBJECT(other->data), "ege-combo-box" ); + } if ( GTK_IS_COMBO_BOX(combodata) ) { GtkComboBox* combo = GTK_COMBO_BOX(combodata); - if ( gtk_combo_box_get_active(combo) != active ) { + if ((active == -1) && (GTK_IS_COMBO_BOX_ENTRY(combo))) { + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))), act->private_data->activeText); + } else if ( gtk_combo_box_get_active(combo) != active ) { gtk_combo_box_set_active( combo, active ); } } else if ( GTK_IS_HBOX(children->data) ) { @@ -747,9 +824,107 @@ void combo_changed_cb( GtkComboBox* widget, gpointer user_data ) { EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data); gint newActive = gtk_combo_box_get_active(widget); - if (newActive != act->private_data->active && newActive != -1) { + gchar *text = gtk_combo_box_get_active_text(widget); + + if (newActive == -1) { + /* indicates the user is entering text for a custom aka "open" value */ + if (act->private_data->pendingText && text && (strcmp(act->private_data->pendingText, text) == 0) ) { + /* The currently entered data matches the last seen */ + } else { + if (act->private_data->pendingText) { + g_free(act->private_data->pendingText); + } + act->private_data->pendingText = text; + text = 0; + } + } else if (newActive != act->private_data->active) { + if (act->private_data->pendingText) { + g_free(act->private_data->pendingText); + act->private_data->pendingText = 0; + } g_object_set( G_OBJECT(act), "active", newActive, NULL ); } + + if (text) { + g_free(text); + text = 0; + } +} + +gboolean combo_entry_focus_lost_cb( GtkWidget *widget, GdkEventFocus *event, gpointer data ) +{ + EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(data); + (void)widget; + (void)event; + + commit_pending_change(act); + + return FALSE; +} + +void combo_entry_changed_cb( GtkEntry* widget, gpointer user_data ) +{ + EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data); + (void)widget; + commit_pending_change(act); +} + +void commit_pending_change(EgeSelectOneAction *act) +{ + if (act->private_data->pendingText) { + if (act->private_data->activeText && (strcmp(act->private_data->pendingText, act->private_data->activeText) == 0)) { + /* Was the same value */ + g_free(act->private_data->pendingText); + act->private_data->pendingText = 0; + } else { + gint matching = find_text_index(act, act->private_data->pendingText); + + if (act->private_data->activeText) { + g_free(act->private_data->activeText); + } + act->private_data->activeText = act->private_data->pendingText; + act->private_data->pendingText = 0; + + if (matching >= 0) { + g_free(act->private_data->activeText); + act->private_data->activeText = 0; + g_object_set( G_OBJECT(act), "active", matching, NULL ); + } else if (act->private_data->active != -1) { + g_object_set( G_OBJECT(act), "active", -1, NULL ); + } else { + resync_active( act, -1, TRUE ); + } + } + } +} + +gint find_text_index(EgeSelectOneAction *act, gchar const* text) +{ + gint index = -1; + + if (text) { + GtkTreeIter iter; + gboolean valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter ); + gint curr = 0; + while ( valid && (index < 0) ) { + gchar* str = 0; + gtk_tree_model_get( act->private_data->model, &iter, + act->private_data->labelColumn, &str, + -1 ); + + if (str && (strcmp(text, str) == 0)) { + index = curr; + } + + g_free(str); + str = 0; + + curr++; + valid = gtk_tree_model_iter_next( act->private_data->model, &iter ); + } + } + + return index; } void menu_toggled_cb( GtkWidget* obj, gpointer data ) diff --git a/src/ege-select-one-action.h b/src/ege-select-one-action.h index 2ecf7efc5..16f924370 100644 --- a/src/ege-select-one-action.h +++ b/src/ege-select-one-action.h @@ -20,7 +20,7 @@ * * The Initial Developer of the Original Code is * Jon A. Cruz. - * Portions created by the Initial Developer are Copyright (C) 2007 + * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): @@ -199,6 +199,15 @@ void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint */ void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val ); +/** + * Sets to allow or disallow free entry additions to the list. + * The default is "closed" selections that do not allow additions/edits. + * This is the XForms functional 'selection' attribute: "open", "closed". + * + * @param action The action to set the tooltip column for. + * @param val The value of the selection attribute. + */ +void ege_select_one_action_set_selection( EgeSelectOneAction *action, gchar const* val ); /* bit of a work-around */ void ege_select_one_action_set_radio_action_type( EgeSelectOneAction* action, GType radioActionType ); -- cgit v1.2.3 From 29edecc65ee3fcec2320d3ad718e7f4dc3cff42a Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 14 Apr 2010 17:36:23 +0200 Subject: Changed default font from Bitstream Vera Sans to Sans. Not everyone has Bitstream Vera Sans and having a non-existant default font can cause problems. (bzr r9328) --- src/preferences-skeleton.h | 2 +- src/style.cpp | 6 +++--- src/ui/dialog/filedialogimpl-gtkmm.cpp | 8 ++++---- src/ui/widget/imageicon.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index af9b446d8..c12b8f9ba 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -112,7 +112,7 @@ static char const preferences_skeleton[] = " \n" +" style=\"fill:black;fill-opacity:1;stroke:none;font-family:Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n" " \n" " \n" " \n" diff --git a/src/style.cpp b/src/style.cpp index 19ff711da..a05cef252 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -2783,9 +2783,9 @@ sp_text_style_new() ts->refcount = 1; sp_text_style_clear(ts); - ts->font_specification.value = g_strdup("Bitstream Vera Sans"); - ts->font.value = g_strdup("Bitstream Vera Sans"); - ts->font_family.value = g_strdup("Bitstream Vera Sans"); + ts->font_specification.value = g_strdup("Sans"); + ts->font.value = g_strdup("Sans"); + ts->font_family.value = g_strdup("Sans"); return ts; } diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 916e3ec97..6f83a706f 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -271,7 +271,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName) "%d x %d\n" //# VALUES HERE "\n\n"; @@ -374,7 +374,7 @@ void SVGPreview::showNoPreview() "style=\"font-size:32.000000;font-style:normal;font-variant:normal;font-weight:bold;" "font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;" "stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" - "font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n" + "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n" "x=\"190\" y=\"240\">%s\n" //# VALUE HERE "\n\n"; @@ -471,13 +471,13 @@ void SVGPreview::showTooLarge(long fileLength) "style=\"font-size:32.000000;font-style:normal;font-variant:normal;font-weight:bold;" "font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;" "stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" - "font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n" + "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n" "x=\"170\" y=\"215\">%5.1f MB\n" //# VALUE HERE "%s\n" //# VALUE HERE "\n\n"; diff --git a/src/ui/widget/imageicon.cpp b/src/ui/widget/imageicon.cpp index 6a817e30d..71ba4428c 100644 --- a/src/ui/widget/imageicon.cpp +++ b/src/ui/widget/imageicon.cpp @@ -295,7 +295,7 @@ void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage) " Date: Wed, 14 Apr 2010 19:30:26 +0200 Subject: Fix for ImageMagick solarize extension. Fixed bugs: - https://launchpad.net/bugs/362271 (bzr r9329) --- src/extension/internal/bitmap/solarize.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/bitmap/solarize.cpp b/src/extension/internal/bitmap/solarize.cpp index 147c4f0b5..ea9ec42f3 100644 --- a/src/extension/internal/bitmap/solarize.cpp +++ b/src/extension/internal/bitmap/solarize.cpp @@ -18,7 +18,9 @@ namespace Bitmap { void Solarize::applyEffect(Magick::Image* image) { - image->solarize(_factor); + // Image Magick Quantum depth = 16 + // 655.35 = (2^16 - 1) / 100 + image->solarize(_factor * 655.35); } void -- cgit v1.2.3 From 2f984e812823d02ab0fdbf28cf33582332265524 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 14 Apr 2010 22:32:14 +0200 Subject: show more axonometric grid lines Fixed bugs: - https://launchpad.net/bugs/429776 (bzr r9331) --- src/display/canvas-axonomgrid.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index ee05cd01c..cf2883116 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -518,6 +518,9 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/) { ow = origin * affine; sw = Geom::Point(fabs(affine[0]),fabs(affine[3])); + sw *= lengthy; + + scaled = false; for(int dim = 0; dim < 2; dim++) { gint scaling_factor = empspacing; @@ -525,10 +528,9 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/) if (scaling_factor <= 1) scaling_factor = 5; - scaled = FALSE; int watchdog = 0; while ( (sw[dim] < 8.0) & (watchdog < 100) ) { - scaled = TRUE; + scaled = true; sw[dim] *= scaling_factor; // First pass, go up to the major line spacing, then // keep increasing by two. @@ -538,13 +540,13 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/) } - spacing_ylines = sw[Geom::X] * lengthy /(tan_angle[X] + tan_angle[Z]); - lyw = sw[Geom::Y] * lengthy; - lxw_x = (lengthy / tan_angle[X]) * sw[Geom::X]; - lxw_z = (lengthy / tan_angle[Z]) * sw[Geom::X]; + spacing_ylines = sw[Geom::X] /(tan_angle[X] + tan_angle[Z]); + lyw = sw[Geom::Y]; + lxw_x = sw[Geom::X] / tan_angle[X]; + lxw_z = sw[Geom::X] / tan_angle[Z]; if (empspacing == 0) { - scaled = TRUE; + scaled = true; } } -- cgit v1.2.3 From 938d3cafe87e6aba410fa5e61e85eaa9600d915a Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 Apr 2010 14:34:26 +0200 Subject: Added missing Pango Weights. (bzr r9332) --- src/libnrtype/FontInstance.cpp | 14 +++++++++++--- src/libnrtype/Layout-TNG-Output.cpp | 6 +++++- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 50dbec61d..5a9aad206 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -307,17 +307,25 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int free_res=false; } else if ( strcmp(key,"weight") == 0 ) { PangoWeight v=pango_font_description_get_weight(descr); - if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { + if ( v <= PANGO_WEIGHT_THIN ) { + res=(char*)"100"; + } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { res=(char*)"200"; } else if ( v <= PANGO_WEIGHT_LIGHT ) { res=(char*)"300"; + } else if ( v <= PANGO_WEIGHT_BOOK ) { + res=(char*)"380"; } else if ( v <= PANGO_WEIGHT_NORMAL ) { res=(char*)"normal"; + } else if ( v <= PANGO_WEIGHT_MEDIUM ) { + res=(char*)"500"; + } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) { + res=(char*)"600"; } else if ( v <= PANGO_WEIGHT_BOLD ) { res=(char*)"bold"; } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) { - res=(char*)"800"; - } else { // HEAVY + res=(char*)"800"; + } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2 res=(char*)"900"; } free_res=false; diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index d6b68ab40..d25eb039d 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -333,13 +333,17 @@ static char const *style_to_text(PangoStyle s) static char const *weight_to_text(PangoWeight w) { switch (w) { + case PANGO_WEIGHT_THIN : return "thin"; case PANGO_WEIGHT_ULTRALIGHT: return "ultralight"; case PANGO_WEIGHT_LIGHT : return "light"; - case PANGO_WEIGHT_SEMIBOLD : return "semibold"; + case PANGO_WEIGHT_BOOK : return "book"; case PANGO_WEIGHT_NORMAL : return "normalweight"; + case PANGO_WEIGHT_MEDIUM : return "medium"; + case PANGO_WEIGHT_SEMIBOLD : return "semibold"; case PANGO_WEIGHT_BOLD : return "bold"; case PANGO_WEIGHT_ULTRABOLD : return "ultrabold"; case PANGO_WEIGHT_HEAVY : return "heavy"; + case PANGO_WEIGHT_ULTRAHEAVY: return "ultraheavy"; } return "???"; } -- cgit v1.2.3 From 028561682f43c02ee5a858232e6bca00e3720ede Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 Apr 2010 15:02:48 +0200 Subject: Add word-spacing attribute. (bzr r9333) --- src/desktop-style.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index f3b1b833d..2225be5ee 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -891,16 +891,17 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) double size = 0; double letterspacing = 0; + double wordspacing = 0; double linespacing = 0; - bool linespacing_normal = false; bool letterspacing_normal = false; + bool wordspacing_normal = false; + bool linespacing_normal = false; double size_prev = 0; double letterspacing_prev = 0; + double wordspacing_prev = 0; double linespacing_prev = 0; - /// \todo FIXME: add word spacing, kerns? rotates? - int texts = 0; for (GSList const *i = objects; i != NULL; i = i->next) { @@ -925,6 +926,14 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) letterspacing_normal = false; } + if (style->word_spacing.normal) { + if (!different && (wordspacing_prev == 0 || wordspacing_prev == wordspacing)) + wordspacing_normal = true; + } else { + wordspacing += style->word_spacing.computed; /// \todo FIXME: we assume non-% units here + wordspacing_normal = false; + } + double linespacing_current; if (style->line_height.normal) { linespacing_current = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL; @@ -941,12 +950,14 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) if ((size_prev != 0 && style->font_size.computed != size_prev) || (letterspacing_prev != 0 && style->letter_spacing.computed != letterspacing_prev) || + (wordspacing_prev != 0 && style->word_spacing.computed != wordspacing_prev) || (linespacing_prev != 0 && linespacing_current != linespacing_prev)) { different = true; } size_prev = style->font_size.computed; letterspacing_prev = style->letter_spacing.computed; + wordspacing_prev = style->word_spacing.computed; linespacing_prev = linespacing_current; // FIXME: we must detect MULTIPLE_DIFFERENT for these too @@ -960,6 +971,7 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) if (texts > 1) { size /= texts; letterspacing /= texts; + wordspacing /= texts; linespacing /= texts; } @@ -969,6 +981,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) style_res->letter_spacing.normal = letterspacing_normal; style_res->letter_spacing.computed = letterspacing; + style_res->word_spacing.normal = wordspacing_normal; + style_res->word_spacing.computed = wordspacing; + style_res->line_height.normal = linespacing_normal; style_res->line_height.computed = linespacing; style_res->line_height.value = linespacing; @@ -1054,6 +1069,7 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); + // std::cout << " " << SP_OBJECT_ID (i->data) << std::endl; if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) @@ -1107,6 +1123,7 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); + // std::cout << " " << SP_OBJECT_ID (i->data) << std::endl; if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) -- cgit v1.2.3 From d064dc896c5c4d0d4454d3bcf602da0250104025 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 Apr 2010 21:00:11 +0200 Subject: First step in fixing the changing of font faces (must also update toolbox.cpp). Expands use of pango_font_decription_better_match(). (bzr r9334) --- src/libnrtype/FontFactory.cpp | 231 ++++++++++++++++++++++++++++++------------ src/libnrtype/FontFactory.h | 2 + 2 files changed, 168 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 06fb93f2d..1e4bb3285 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -421,6 +421,14 @@ Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDes return style; } +/** + Replace font family leaving style alone (if possible). + @param fontSpec the given font + @param newFamily + @return the changed fontspec, if the property can not be set return an empty string + The routine first searches for an exact match. + If no exact match found, calls FontSpecificationBestMatch(). +*/ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily) { Glib::ustring newFontSpec; @@ -431,10 +439,14 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & // what constitutes a "family" in our own UI may be different from how Pango // sees it. - // Find the PangoFontDescription associated to this fontSpec + // Find the PangoFontDescription associated with the font specification string. PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); + if (it != fontInstanceMap.end()) { + // Description found! + + // Make copy PangoFontDescription *descr = pango_font_description_copy((*it).second); // Grab the UI Family string from the descr @@ -452,46 +464,9 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & it = fontInstanceMap.find(newFontSpec); if (it == fontInstanceMap.end()) { - PangoFontDescription *newFontDescr = pango_font_description_from_string(newFontSpec.c_str()); - - PangoFontDescription *bestMatchForNewDescr = NULL; - Glib::ustring bestMatchFontDescription; - - bool setFirstFamilyMatch = false; - for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) { - - Glib::ustring currentFontSpec = (*it).first; + // Search for best match, empty string returned if not found. + newFontSpec = FontSpecificationBestMatch( newFontSpec ); - // Save some time by only looking at the right family - if (currentFontSpec.find(newFamily) != Glib::ustring::npos) { - if (!setFirstFamilyMatch) { - // This ensures that the closest match is at least within the correct - // family rather than the first font in the list - bestMatchForNewDescr = pango_font_description_copy((*it).second); - bestMatchFontDescription = currentFontSpec; - setFirstFamilyMatch = true; - } else { - // Get the font description that corresponds, and - // then see if we've found a better match - PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second); - - if (pango_font_description_better_match( - newFontDescr, bestMatchForNewDescr, possibleMatch)) { - - pango_font_description_free(bestMatchForNewDescr); - bestMatchForNewDescr = possibleMatch; - bestMatchFontDescription = currentFontSpec; - } else { - pango_font_description_free(possibleMatch); - } - } - } - } - - newFontSpec = bestMatchFontDescription; - - pango_font_description_free(newFontDescr); - pango_font_description_free(bestMatchForNewDescr); } } @@ -502,92 +477,182 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & } /** - apply style property to the given font + Apply style property to the given font @param fontSpec the given font @param turnOn true to set italic style @return the changed fontspec, if the property can not be set return an empty string + The routine first searches for an exact match to "FontFamily Italic" or + "Font Family Oblique" (turnOn is true) or "FontFamily" (turnOn is false). + If no exact match found, calls FontSpecificationBestMatch(). */ Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn) { Glib::ustring newFontSpec; - // Find the PangoFontDesecription that goes with this font specification string + // Find the PangoFontDescription associated with the font specification string. PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); if (it != fontInstanceMap.end()) { - // If we did find one, make a copy and set/unset the italic as needed + // Description found! + + // Make copy. PangoFontDescription *descr = pango_font_description_copy((*it).second); PangoStyle style; if (turnOn) { - style = PANGO_STYLE_ITALIC; + // First try Oblique, we'll try Italic later + style = PANGO_STYLE_OBLIQUE; } else { style = PANGO_STYLE_NORMAL; } + pango_font_description_set_style(descr, style); newFontSpec = ConstructFontSpecification(descr); + + bool exactMatchFound = true; if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - if(turnOn) { - // there is no PANGO_STYLE_ITALIC let's test for PANGO_STYLE_OBLIQUE - style = PANGO_STYLE_OBLIQUE; + + exactMatchFound = false; + if (turnOn) { + // Next try Italic + style = PANGO_STYLE_ITALIC; pango_font_description_set_style(descr, style); - newFontSpec = ConstructFontSpecification(descr); + exactMatchFound = true; if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - // If the new font does not have even an oblique face, don't - // allow italics to be set! - newFontSpec = Glib::ustring(""); + exactMatchFound = false; } - - } else { - // If the new font does not have an italic face, don't - // allow italics to be set! - newFontSpec = Glib::ustring(""); } } + // Search for best match, empty string returned if not found. + if( !exactMatchFound ) { + newFontSpec = FontSpecificationBestMatch( newFontSpec ); + } + pango_font_description_free(descr); } - return newFontSpec; + return newFontSpec; // Empty if not found. } /** - apply width property to the given font + Apply weight property to the given font @param fontSpec the given font @param turnOn true to set bold @return the changed fontspec, if the property can not be set return an empty string + This routine first searches for an exact match, if none found + it calls FontSpecificationBestMatch(). */ Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn) { Glib::ustring newFontSpec; - // Find the PangoFontDesecription that goes with this font specification string + // Find the PangoFontDescription associated with the font specification string. PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); if (it != fontInstanceMap.end()) { - // If we did find one, make a copy and set/unset the bold as needed + // Description found! + + // Make copy. PangoFontDescription *descr = pango_font_description_copy((*it).second); + PangoWeight weight; if (turnOn) { weight = PANGO_WEIGHT_BOLD; } else { weight = PANGO_WEIGHT_NORMAL; } + pango_font_description_set_weight(descr, weight); newFontSpec = ConstructFontSpecification(descr); + if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - // If the new font does not have a bold face, don't - // allow bold to be set! - newFontSpec = Glib::ustring(""); + // Search for best match, empty string returned if not found. + newFontSpec = FontSpecificationBestMatch( newFontSpec ); } pango_font_description_free(descr); } + return newFontSpec; // Empty if not found. +} + +/** + Use pango_font_description_better_match() to find best font match. + This handles cases like Century Schoolbook L where the "normal" + font is Century Schoolbook L Medium so just removing Italic + from the font name doesn't yield the correct name. + @param fontSpec the given font + @return the changed fontspec, if the property can not be set return an empty string +*/ +// http://library.gnome.org/devel/pango/1.28/pango-Fonts.html#pango-font-description-better-match +Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fontSpec ) +{ + + Glib::ustring newFontSpec; + + // Look for exact match + PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); + + // If there is no exact match, look for the best match. + if (it != fontInstanceMap.end()) { + + newFontSpec = fontSpec; + + } else { + + PangoFontDescription *fontDescr = pango_font_description_from_string(fontSpec.c_str()); + PangoFontDescription *bestMatchDescr = NULL; + + // Grab the UI Family string from the descr + Glib::ustring family = GetUIFamilyString(fontDescr); + Glib::ustring bestMatchDescription; + + bool setFirstFamilyMatch = false; + for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) { + + Glib::ustring currentFontSpec = (*it).first; + Glib::ustring currentFamily = GetUIFamilyString((*it).second); + + // Save some time by only looking at the right family. + // Must use family name rather than fontSpec + // (otherwise DejaVu Sans matches DejaVu Sans Mono). + if (currentFamily == family) { + if (!setFirstFamilyMatch) { + // This ensures that the closest match is at least within the correct + // family rather than the first font in the list + bestMatchDescr = pango_font_description_copy((*it).second); + bestMatchDescription = currentFontSpec; + setFirstFamilyMatch = true; + } else { + // Get the font description that corresponds, and + // then see if we've found a better match + PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second); + + if (pango_font_description_better_match( + fontDescr, bestMatchDescr, possibleMatch)) { + + pango_font_description_free(bestMatchDescr); + bestMatchDescr = possibleMatch; + bestMatchDescription = currentFontSpec; + } else { + pango_font_description_free(possibleMatch); + } + } + } + } // for + + newFontSpec = bestMatchDescription; // If NULL, then no match found + + pango_font_description_free(fontDescr); + pango_font_description_free(bestMatchDescr); + + } + return newFontSpec; } @@ -689,6 +754,7 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style) g_assert(style); if (style) { + // First try to use the font specification if it is set if (style->text->font_specification.set && style->text->font_specification.value @@ -699,7 +765,16 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style) // If that failed, try using the CSS information in the style if (!font) { + font = Face(style->text->font_family.value, font_style_to_pos(*style)); + + // That was a hatchet job... so we need to check if this font exists!! + Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font); + Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec ); + if( fontSpec != newFontSpec ) { + font->Unref(); + font = FaceFromFontSpecification( newFontSpec.c_str() ); + } } } @@ -899,12 +974,20 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos) pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL); } - if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) { + if ( apos.weight <= NR_POS_WEIGHT_THIN ) { + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN); + } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT); } else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT); + } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) { + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK); } else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL); + } else if ( apos.weight <= NR_POS_WEIGHT_MEDIUM ) { + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM); + } else if ( apos.weight <= NR_POS_WEIGHT_SEMIBOLD ) { + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD); } else if ( apos.weight <= NR_POS_WEIGHT_BOLD ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD); } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_BOLD ) { @@ -912,6 +995,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos) } else { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY); } + // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2) if ( apos.stretch <= NR_POS_STRETCH_ULTRA_CONDENSED ) { pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED); @@ -919,7 +1003,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos) pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED); } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_CONDENSED ) { pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED); - } else if ( apos.stretch <= NR_POS_WEIGHT_NORMAL ) { + } else if ( apos.stretch <= NR_POS_STRETCH_NORMAL ) { pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL); } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_EXPANDED ) { pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED); @@ -984,6 +1068,23 @@ void font_factory::AddInCache(font_instance *who) nbEnt++; } +/* + { + std::cout << " Printing out fontInstanceMap: " << std::endl; + PangoStringToDescrMap::iterator it = fontInstanceMap.begin(); + while (it != fontInstanceMap.end()) { + + PangoFontDescription *descr = pango_font_description_copy((*it).second); + + // Grab the UI Family string from the descr + Glib::ustring uiFamily = GetUIFamilyString(descr); + Glib::ustring uiStyle = GetUIStyleString(descr); + std::cout << " " << uiFamily << " " << uiStyle << std::endl; + + it++; + } + } +*/ /* Local Variables: diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index 0118c862d..632ea565f 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -102,6 +102,8 @@ public: Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn); Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn); + Glib::ustring FontSpecificationBestMatch(const Glib::ustring& fontSpec ); + // Gathers all strings needed for UI while storing pango information in // fontInstanceMap and fontStringMap void GetUIFamiliesAndStyles(FamilyToStylesMap *map); -- cgit v1.2.3 From 0d391b95f7c35914498b07ff833c5541576a0c4b Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Thu, 15 Apr 2010 21:14:51 +0200 Subject: filterUnits and primitiveUnits are now actually read/set, percentages for primitiveUnits are still problematic though (bzr r9335) --- src/display/nr-filter.cpp | 8 ++++++++ src/sp-filter.cpp | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index d0e0ec11e..3b19ff69b 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -223,6 +223,14 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb) return 0; } +void Filter::set_filter_units(SPFilterUnits unit) { + _filter_units = unit; +} + +void Filter::set_primitive_units(SPFilterUnits unit) { + _primitive_units = unit; +} + void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const { for (int i = 0 ; i < _primitive_count ; i++) { if (_primitive[i]) _primitive[i]->area_enlarge(bbox, item->ctm); diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index 7197c1ec9..4cbafe50c 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -108,7 +108,7 @@ sp_filter_init(SPFilter *filter) filter->height = 0; filter->filterUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX; - filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX; + filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE; filter->filterUnits_set = FALSE; filter->primitiveUnits_set = FALSE; @@ -204,14 +204,14 @@ sp_filter_set(SPObject *object, unsigned int key, gchar const *value) break; case SP_ATTR_PRIMITIVEUNITS: if (value) { - if (!strcmp(value, "userSpaceOnUse")) { - filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE; - } else { + if (!strcmp(value, "objectBoundingBox")) { filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX; + } else { + filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE; } filter->primitiveUnits_set = TRUE; } else { - filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX; + filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE; filter->primitiveUnits_set = FALSE; } object->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -322,11 +322,11 @@ sp_filter_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::N if ((flags & SP_OBJECT_WRITE_ALL) || filter->primitiveUnits_set) { switch (filter->primitiveUnits) { - case SP_FILTER_UNITS_USERSPACEONUSE: - repr->setAttribute("primitiveUnits", "userSpaceOnUse"); + case SP_FILTER_UNITS_OBJECTBOUNDINGBOX: + repr->setAttribute("primitiveUnits", "objectBoundingBox"); break; default: - repr->setAttribute("primitiveUnits", "objectBoundingBox"); + repr->setAttribute("primitiveUnits", "userSpaceOnUse"); break; } } @@ -446,6 +446,8 @@ void sp_filter_build_renderer(SPFilter *sp_filter, Inkscape::Filters::Filter *nr sp_filter->_renderer = nr_filter; + nr_filter->set_filter_units(sp_filter->filterUnits); + nr_filter->set_primitive_units(sp_filter->primitiveUnits); nr_filter->set_x(sp_filter->x); nr_filter->set_y(sp_filter->y); nr_filter->set_width(sp_filter->width); -- cgit v1.2.3 From fd73bb4b76a9b28d816e67b4849f1ed72b11a6dd Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 15 Apr 2010 22:25:58 +0200 Subject: Tooltips inconsistency fix in Inkscape Preferences. (bzr r9337) --- src/ui/dialog/inkscape-preferences.cpp | 76 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 51e0de710..236fc8c76 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -212,10 +212,10 @@ void InkscapePreferences::initPageScrolling() _("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false); _scroll_space.init ( _("Left mouse button pans when Space is pressed"), "/options/spacepans/value", false); _page_scrolling.add_line( false, "", _scroll_space, "", - _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator). When off, Space temporarily switches to Selector tool (default).")); + _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator); when off, Space temporarily switches to Selector tool (default)")); _wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false); _page_scrolling.add_line( false, "", _wheel_zoom, "", - _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl.")); + _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl")); } void InkscapePreferences::initPageSnapping() @@ -291,7 +291,7 @@ void InkscapePreferences::AddGradientCheckbox(DialogPage &p, Glib::ustring const void InkscapePreferences::AddConvertGuidesCheckbox(DialogPage &p, Glib::ustring const &prefs_path, bool def_value) { PrefCheckButton* cb = Gtk::manage( new PrefCheckButton); cb->init ( _("Conversion to guides uses edges instead of bounding box"), prefs_path + "/convertguides", def_value); - p.add_line( false, "", *cb, "", _("Converting an object to guides places these along the object's true edges (imitating the object's shape), not along the bounding box.")); + p.add_line( false, "", *cb, "", _("Converting an object to guides places these along the object's true edges (imitating the object's shape), not along the bounding box")); } void InkscapePreferences::AddDotSizeSpinbutton(DialogPage &p, Glib::ustring const &prefs_path, double def_value) @@ -404,10 +404,10 @@ void InkscapePreferences::initPageTools() _page_tools.add_group_header( _("Conversion to guides:")); _t_cvg_keep_objects.init ( _("Keep objects after conversion to guides"), "/tools/cvg_keep_objects", false); _page_tools.add_line( true, "", _t_cvg_keep_objects, "", - _("When converting an object to guides, don't delete the object after the conversion.")); + _("When converting an object to guides, don't delete the object after the conversion")); _t_cvg_convert_whole_groups.init ( _("Treat groups as a single object"), "/tools/cvg_convert_whole_groups", false); _page_tools.add_line( true, "", _t_cvg_convert_whole_groups, "", - _("Treat groups as a single object during conversion to guides rather than converting each child separately.")); + _("Treat groups as a single object during conversion to guides rather than converting each child separately")); _pencil_average_all_sketches.init ( _("Average all sketches"), "/tools/freehand/pencil/average_all_sketches", false); _calligrapy_use_abs_size.init ( _("Width is in absolute units"), "/tools/calligraphic/abs_width", false); @@ -442,26 +442,26 @@ void InkscapePreferences::initPageTools() AddGradientCheckbox(_page_node, "/tools/nodes", true); _page_node.add_group_header( _("Path outline")); _t_node_pathoutline_color.init(_("Path outline color"), "/tools/nodes/highlight_color", 0xff0000ff); - _page_node.add_line( false, "", _t_node_pathoutline_color, "", _("Selects the color used for showing the path outline."), false); + _page_node.add_line( false, "", _t_node_pathoutline_color, "", _("Selects the color used for showing the path outline"), false); _t_node_show_outline.init(_("Always show outline"), "/tools/nodes/show_outline", false); _page_node.add_line( true, "", _t_node_show_outline, "", _("Show outlines for all paths, not only invisible paths")); _t_node_live_outline.init(_("Update outline when dragging nodes"), "/tools/nodes/live_outline", false); - _page_node.add_line( true, "", _t_node_live_outline, "", _("Update the outline when dragging or transforming nodes. If this is off, the outline will only update when completing a drag.")); + _page_node.add_line( true, "", _t_node_live_outline, "", _("Update the outline when dragging or transforming nodes; if this is off, the outline will only update when completing a drag")); _t_node_live_objects.init(_("Update paths when dragging nodes"), "/tools/nodes/live_objects", false); - _page_node.add_line( true, "", _t_node_live_objects, "", _("Update paths when dragging or transforming nodes. If this is off, paths will only be updated when completing a drag.")); + _page_node.add_line( true, "", _t_node_live_objects, "", _("Update paths when dragging or transforming nodes; if this is off, paths will only be updated when completing a drag")); _t_node_show_path_direction.init(_("Show path direction on outlines"), "/tools/nodes/show_path_direction", false); _page_node.add_line( true, "", _t_node_show_path_direction, "", _("Visualize the direction of selected paths by drawing small arrows in the middle of each outline segment")); _t_node_pathflash_enabled.init ( _("Show temporary path outline"), "/tools/nodes/pathflash_enabled", false); - _page_node.add_line( true, "", _t_node_pathflash_enabled, "", _("When hovering over a path, briefly flash its outline.")); + _page_node.add_line( true, "", _t_node_pathflash_enabled, "", _("When hovering over a path, briefly flash its outline")); _t_node_pathflash_selected.init ( _("Show temporary outline for selected paths"), "/tools/nodes/pathflash_selected", false); _page_node.add_line( true, "", _t_node_pathflash_selected, "", _("Show temporary outline even when a path is selected for editing")); _t_node_pathflash_timeout.init("/tools/nodes/pathflash_timeout", 0, 10000.0, 100.0, 100.0, 1000.0, true, false); - _page_node.add_line( false, _("Flash time"), _t_node_pathflash_timeout, "ms", _("Specifies how long the path outline will be visible after a mouse-over (in milliseconds). Specify 0 to have the outline shown until mouse leaves the path."), false); + _page_node.add_line( false, _("Flash time"), _t_node_pathflash_timeout, "ms", _("Specifies how long the path outline will be visible after a mouse-over (in milliseconds); specify 0 to have the outline shown until mouse leaves the path"), false); _page_node.add_group_header(_("Editing preferences")); _t_node_single_node_transform_handles.init(_("Show transform handles for single nodes"), "/tools/nodes/single_node_transform_handles", false); - _page_node.add_line( true, "", _t_node_single_node_transform_handles, "", _("Show transform handles even when only a single node is selected.")); + _page_node.add_line( true, "", _t_node_single_node_transform_handles, "", _("Show transform handles even when only a single node is selected")); _t_node_delete_preserves_shape.init(_("Deleting nodes preserves shape"), "/tools/nodes/delete_preserves_shape", true); - _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape. Hold Ctrl to get the other behavior.")); + _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape. Hold Ctrl to get the other behavior")); //Tweak this->AddPage(_page_tweak, _("Tweak"), iter_tools, PREFS_PAGE_TOOLS_TWEAK); @@ -515,7 +515,7 @@ void InkscapePreferences::initPageTools() this->AddDotSizeSpinbutton(_page_pencil, "/tools/freehand/pencil", 3.0); _page_pencil.add_group_header( _("Sketch mode")); _page_pencil.add_line( true, "", _pencil_average_all_sketches, "", - _("If on, the sketch result will be the normal average of all sketches made, instead of averaging the old result with the new sketch.")); + _("If on, the sketch result will be the normal average of all sketches made, instead of averaging the old result with the new sketch")); //Pen this->AddPage(_page_pen, _("Pen"), iter_tools, PREFS_PAGE_TOOLS_PEN); @@ -648,16 +648,16 @@ void InkscapePreferences::initPageClones() _page_clones.add_group_header( _("When the original moves, its clones and linked offsets:")); _page_clones.add_line( true, "", _clone_option_parallel, "", - _("Clones are translated by the same vector as their original.")); + _("Clones are translated by the same vector as their original")); _page_clones.add_line( true, "", _clone_option_stay, "", - _("Clones preserve their positions when their original is moved.")); + _("Clones preserve their positions when their original is moved")); _page_clones.add_line( true, "", _clone_option_transform, "", - _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original.")); + _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original")); _page_clones.add_group_header( _("When the original is deleted, its clones:")); _page_clones.add_line( true, "", _clone_option_unlink, "", - _("Orphaned clones are converted to regular objects.")); + _("Orphaned clones are converted to regular objects")); _page_clones.add_line( true, "", _clone_option_delete, "", - _("Orphaned clones are deleted along with their original.")); + _("Orphaned clones are deleted along with their original")); _page_clones.add_group_header( _("When duplicating original+clones:")); @@ -781,12 +781,12 @@ void InkscapePreferences::initPageFilters() /* show infobox */ _show_filters_info_box.init( _("Show filter primitives infobox"), "/options/showfiltersinfobox/value", true); _page_filters.add_line(true, "", _show_filters_info_box, "", - _("Show icons and descriptions for the filter primitives available at the filter effects dialog.")); + _("Show icons and descriptions for the filter primitives available at the filter effects dialog")); /* threaded blur */ //related comments/widgets/functions should be renamed and option should be moved elsewhere when inkscape is fully multi-threaded _filter_multi_threaded.init("/options/threading/numthreads", 1.0, 8.0, 1.0, 2.0, 4.0, true, false); _page_filters.add_line( false, _("Number of Threads:"), _filter_multi_threaded, _("(requires restart)"), - _("Configure number of processors/threads to use with rendering of gaussian blur."), false); + _("Configure number of processors/threads to use with rendering of gaussian blur"), false); this->AddPage(_page_filters, _("Filters"), PREFS_PAGE_FILTERS); } @@ -827,13 +827,13 @@ void InkscapePreferences::initPageImportExport() _("Default bitmap resolution (in dots per inch) in the Export dialog"), false); _importexport_ocal_url.init("/options/ocalurl/str", true, g_strdup_printf("openclipart.org")); _page_importexport.add_line( false, _("Open Clip Art Library Server Name:"), _importexport_ocal_url, "", - _("The server name of the Open Clip Art Library webdav server. It's used by the Import and Export to OCAL function."), true); + _("The server name of the Open Clip Art Library webdav server; it's used by the Import and Export to OCAL function"), true); _importexport_ocal_username.init("/options/ocalusername/str", true); _page_importexport.add_line( false, _("Open Clip Art Library Username:"), _importexport_ocal_username, "", - _("The username used to log into Open Clip Art Library."), true); + _("The username used to log into Open Clip Art Library"), true); _importexport_ocal_password.init("/options/ocalpassword/str", false); _page_importexport.add_line( false, _("Open Clip Art Library Password:"), _importexport_ocal_password, "", - _("The password used to log into Open Clip Art Library."), true); + _("The password used to log into Open Clip Art Library"), true); this->AddPage(_page_importexport, _("Import/Export"), PREFS_PAGE_IMPORTEXPORT); } @@ -912,42 +912,42 @@ void InkscapePreferences::initPageCMS() _cms_from_display.init( _("Retrieve profile from display"), "/options/displayprofile/from_display", false); _page_cms.add_line( false, "", _cms_from_display, "", #ifdef GDK_WINDOWING_X11 - _("Retrieve profiles from those attached to displays via XICC."), false); + _("Retrieve profiles from those attached to displays via XICC"), false); #else - _("Retrieve profiles from those attached to displays."), false); + _("Retrieve profiles from those attached to displays"), false); #endif // GDK_WINDOWING_X11 _cms_intent.init("/options/displayprofile/intent", intentLabels, intentValues, numIntents, 0); _page_cms.add_line( false, _("Display rendering intent:"), _cms_intent, "", - _("The rendering intent to use to calibrate display output."), false); + _("The rendering intent to use to calibrate display output"), false); _page_cms.add_group_header( _("Proofing")); _cms_softproof.init( _("Simulate output on screen"), "/options/softproof/enable", false); _page_cms.add_line( false, "", _cms_softproof, "", - _("Simulates output of target device."), false); + _("Simulates output of target device"), false); _cms_gamutwarn.init( _("Mark out of gamut colors"), "/options/softproof/gamutwarn", false); _page_cms.add_line( false, "", _cms_gamutwarn, "", - _("Highlights colors that are out of gamut for the target device."), false); + _("Highlights colors that are out of gamut for the target device"), false); Glib::ustring colorStr = prefs->getString("/options/softproof/gamutcolor"); Gdk::Color tmpColor( colorStr.empty() ? "#00ff00" : colorStr); _cms_gamutcolor.set_color( tmpColor ); _page_cms.add_line( true, _("Out of gamut warning color:"), _cms_gamutcolor, "", - _("Selects the color used for out of gamut warning."), false); + _("Selects the color used for out of gamut warning"), false); _page_cms.add_line( false, _("Device profile:"), _cms_proof_profile, "", - _("The ICC profile to use to simulate device output."), false); + _("The ICC profile to use to simulate device output"), false); _cms_proof_intent.init("/options/softproof/intent", intentLabels, intentValues, numIntents, 0); _page_cms.add_line( false, _("Device rendering intent:"), _cms_proof_intent, "", - _("The rendering intent to use to calibrate display output."), false); + _("The rendering intent to use to calibrate display output"), false); _cms_proof_blackpoint.init( _("Black point compensation"), "/options/softproof/bpc", false); _page_cms.add_line( false, "", _cms_proof_blackpoint, "", - _("Enables black point compensation."), false); + _("Enables black point compensation"), false); _cms_proof_preserveblack.init( _("Preserve black"), "/options/softproof/preserveblack", false); _page_cms.add_line( false, "", _cms_proof_preserveblack, @@ -1022,7 +1022,7 @@ void InkscapePreferences::initPageGrids() _page_grids.add_group_header( _("Major grid line emphasizing")); _grids_no_emphasize_on_zoom.init( _("Don't emphasize gridlines when zoomed out"), "/options/grids/no_emphasize_when_zoomedout", false); - _page_grids.add_line( false, "", _grids_no_emphasize_on_zoom, "", _("If set and zoomed out, the gridlines will be shown in normal color instead of major grid line color."), false); + _page_grids.add_line( false, "", _grids_no_emphasize_on_zoom, "", _("If set and zoomed out, the gridlines will be shown in normal color instead of major grid line color"), false); _page_grids.add_group_header( _("Default grid settings")); @@ -1099,7 +1099,7 @@ void InkscapePreferences::initPageSVGOutput() _page_svgoutput.add_line( false, _("Numeric precision:"), _svgoutput_numericprecision, "", _("How many digits to write after the decimal dot"), false); _svgoutput_minimumexponent.init("/options/svgoutput/minimumexponent", -32.0, -1, 1.0, 2.0, -8.0, true, false); - _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero."), false); + _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero"), false); this->AddPage(_page_svgoutput, _("SVG output"), PREFS_PAGE_SVGOUTPUT); } @@ -1145,7 +1145,7 @@ void InkscapePreferences::initPageUI() _ui_colorsliders_top.init( _("Work-around color sliders not drawing"), "/options/workarounds/colorsontop", false); _page_ui.add_line( false, "", _ui_colorsliders_top, "", - _("When on, will attempt to work around bugs in certain GTK themes drawing color sliders."), true); + _("When on, will attempt to work around bugs in certain GTK themes drawing color sliders"), true); _misc_recent.init("/options/maxrecentdocuments/value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false); @@ -1166,7 +1166,7 @@ void InkscapePreferences::initPageUI() _ui_partialdynamic.init( _("Enable dynamic relayout for incomplete sections"), "/options/workarounds/dynamicnotdone", false); _page_ui.add_line( false, "", _ui_partialdynamic, "", - _("When on, will allow dynamic layout of components that are not completely finished being refactored."), true); + _("When on, will allow dynamic layout of components that are not completely finished being refactored"), true); this->AddPage(_page_ui, _("Interface"), PREFS_PAGE_UI); @@ -1177,7 +1177,7 @@ void InkscapePreferences::initPageSave() { _save_use_current_dir.init( _("Use current directory for \"Save As ...\""), "/dialogs/save_as/use_current_dir", true); _page_save.add_line( false, "", _save_use_current_dir, "", - _("When this option is on, the \"Save as...\" dialog will always open in the directory where the currently open document is. When it's off, it will open in the directory where you last saved a file using that dialog."), true); + _("When this option is on, the \"Save as...\" dialog will always open in the directory where the currently open document is; when it's off, it will open in the directory where you last saved a file using that dialog"), true); // Autosave options @@ -1348,7 +1348,7 @@ void InkscapePreferences::initPageMisc() _misc_latency_skew.init("/debug/latency/skew", 0.5, 2.0, 0.01, 0.10, 1.0, false, false); _page_misc.add_line( false, _("Latency skew:"), _misc_latency_skew, _("(requires restart)"), - _("Factor by which the event clock is skewed from the actual time (0.9766 on some systems)."), false); + _("Factor by which the event clock is skewed from the actual time (0.9766 on some systems)"), false); _misc_namedicon_delay.init( _("Pre-render named icons"), "/options/iconrender/named_nodelay", false); _page_misc.add_line( false, "", _misc_namedicon_delay, "", -- cgit v1.2.3 From d55e8b3885defb0c94237883036392e1bd2034b1 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 15 Apr 2010 22:46:49 +0200 Subject: Tooltips inconsistency fix in Inkscape Preferences.(part 2) (bzr r9338) --- src/ui/dialog/inkscape-preferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 236fc8c76..96f0a0f6e 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -461,7 +461,7 @@ void InkscapePreferences::initPageTools() _t_node_single_node_transform_handles.init(_("Show transform handles for single nodes"), "/tools/nodes/single_node_transform_handles", false); _page_node.add_line( true, "", _t_node_single_node_transform_handles, "", _("Show transform handles even when only a single node is selected")); _t_node_delete_preserves_shape.init(_("Deleting nodes preserves shape"), "/tools/nodes/delete_preserves_shape", true); - _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape. Hold Ctrl to get the other behavior")); + _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape; hold Ctrl to get the other behavior")); //Tweak this->AddPage(_page_tweak, _("Tweak"), iter_tools, PREFS_PAGE_TOOLS_TWEAK); @@ -652,7 +652,7 @@ void InkscapePreferences::initPageClones() _page_clones.add_line( true, "", _clone_option_stay, "", _("Clones preserve their positions when their original is moved")); _page_clones.add_line( true, "", _clone_option_transform, "", - _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original")); + _("Each clone moves according to the value of its transform= attribute; for example, a rotated clone will move in a different direction than its original")); _page_clones.add_group_header( _("When the original is deleted, its clones:")); _page_clones.add_line( true, "", _clone_option_unlink, "", _("Orphaned clones are converted to regular objects")); -- cgit v1.2.3 From b8170886d4e5916e800965a1924072fd219df696 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 16 Apr 2010 14:19:33 +0200 Subject: Second step in fixing changing of font faces. (bzr r9340) --- src/widgets/toolbox.cpp | 99 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 0b690504f..96695ac20 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -6189,6 +6189,12 @@ static void sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl) namespace { +/* + * This function sets up the text-tool tool-controls, setting the entry boxes + * etc. to the values from the current selection or the default if no selection. + * It is called whenever a text selection is changed, including stepping cursor + * through text. + */ static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection*/, GObject *tbl) { // quit if run by the _changed callbacks @@ -6198,28 +6204,36 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection* g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image"))); + + /* + * Query from current selection: + * Font family (font-family) + * Style (font-weight, font-style, font-stretch, font-variant, font-align) + * Numbers (font-size, letter-spacing, word-spacing, line-height, text-anchor, writing-mode) + * Font specification (Inkscape private attribute) + */ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - int result_family = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); - - int result_style = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); + int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); + int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); + int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + // Used later: + int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); - int result_numbers = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); - - gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image"))); - - // If querying returned nothing, read the style from the text tool prefs (default style for new texts) + /* + * If no text in selection (querying returned nothing), read the style from + * the /tools/text preferencess (default style for new texts). Return if + * tool bar already set to these preferences. + */ if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) { - // there are no texts in selection, read from prefs + // There are no texts in selection, read from preferences. sp_style_read_from_prefs(query, "/tools/text"); if (g_object_get_data(tbl, "text_style_from_prefs")) { - // do not reset the toolbar style from prefs if we already did it last time + // Do not reset the toolbar style from prefs if we already did it last time. sp_style_unref(query); g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); return; @@ -6229,20 +6243,28 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection* g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE)); } + /* + * If we have valid query data for text (font-family, font-specification) set toolbar accordingly. + */ if (query->text) { if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) { + + // Don't set a font family if multiple styles are selected. GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry")); gtk_entry_set_text (GTK_ENTRY (entry), ""); } else if (query->text->font_specification.value || query->text->font_family.value) { + // At the moment (April 2010), font-specification isn't set unless actually + // set on current tspan (parent look up is disabled). Gtk::ComboBoxEntry *combo = (Gtk::ComboBoxEntry *) (g_object_get_data (G_OBJECT (tbl), "family-entry-combo")); GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry")); // Get the font that corresponds Glib::ustring familyName; + // This tries to use font-specification first and then font-family. font_instance * font = font_factory::Default()->FaceFromStyle(query); if (font) { familyName = font_factory::Default()->GetUIFamilyString(font->descr); @@ -6267,7 +6289,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection* combo->set_active (iter); } - //Size + //Size (average of text selected) { GtkWidget *cbox = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "combo-box-size")); gchar *const str = g_strdup_printf("%.5g", query->font_size.computed); @@ -6391,6 +6413,12 @@ static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : ""; 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); fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); @@ -6399,6 +6427,7 @@ static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, if (!fontSpec.empty()) { + // Now we have existing font specification, replace family. Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family); if (!newFontSpec.empty()) { @@ -6630,17 +6659,20 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - int result_fontspec = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); - - //int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); - //int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); - //int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); + // font_specification will not be set unless defined explicitely on a tspan. + // This needs to be fixed. Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : ""; Glib::ustring newFontSpec = ""; 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); fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); @@ -6652,12 +6684,20 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, { case 0: { + // Bold if (!fontSpec.empty()) { newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active); if (!newFontSpec.empty()) { - // Don't even set the bold if the font didn't exist on the system - sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" ); - nochange = false; + + font_instance * font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str()); + if (font) { + gchar c[256]; + font->Attribute( "weight", c, 256); + sp_repr_css_set_property (css, "font-weight", c); + font->Unref(); + font = NULL; + nochange = false; + } } } // set or reset the button according @@ -6677,11 +6717,20 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, case 1: { + // Italic/Oblique if (!fontSpec.empty()) { newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active); if (!newFontSpec.empty()) { - // Don't even set the italic if the font didn't exist on the system - sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal"); + // Don't even set the italic/oblique if the font didn't exist on the system + if( active ) { + if( newFontSpec.find( "Italic" ) != Glib::ustring::npos ) { + sp_repr_css_set_property (css, "font-style", "italic"); + } else { + sp_repr_css_set_property (css, "font-style", "oblique"); + } + } else { + sp_repr_css_set_property (css, "font-style", "normal"); + } nochange = false; } } -- cgit v1.2.3 From 525a5287f8be5382b8286aca9001bc0d73b734df Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 16 Apr 2010 15:02:16 +0200 Subject: Spray tool: default preferences fix. Fixed bugs: - https://launchpad.net/bugs/562227 (bzr r9341) --- src/preferences-skeleton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index c12b8f9ba..73e7bd2ac 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -115,7 +115,7 @@ static char const preferences_skeleton[] = " style=\"fill:black;fill-opacity:1;stroke:none;font-family:Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" -- cgit v1.2.3 From ad3ae6b4c2b2f0a05f2f4f33c37d28d2b0d500ef Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 17 Apr 2010 15:48:56 -0700 Subject: Whitespace and brace cleanup. Minor refactoring of font_style_equal. (bzr r9345) --- src/libnrtype/FontFactory.cpp | 4 +- src/libnrtype/FontInstance.cpp | 793 +++++++++++++++++++----------------- src/libnrtype/Layout-TNG-Output.cpp | 8 +- 3 files changed, 425 insertions(+), 380 deletions(-) (limited to 'src') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 1e4bb3285..83b9bf9d1 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -1030,7 +1030,7 @@ void font_factory::UnrefFace(font_instance *who) g_free(tc); } else { loadedFaces.erase(loadedFaces.find(who->descr)); - // printf("unrefFace %p: success\n",who); + // printf("unrefFace %p: success\n",who); } } } @@ -1041,7 +1041,7 @@ void font_factory::AddInCache(font_instance *who) for (int i = 0;i < nbEnt;i++) ents[i].age *= 0.9; for (int i = 0;i < nbEnt;i++) { if ( ents[i].f == who ) { - // printf("present\n"); + // printf("present\n"); ents[i].age += 1.0; return; } diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 5a9aad206..1b02ace23 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -39,57 +39,59 @@ struct font_style_equal : public std::binary_function StyleMap; - - -size_t font_style_hash::operator()(const font_style &x) const { - int h=0,n; - n=(int)floor(100*x.stroke_width); - h*=12186; - h+=n; - n=(x.vertical)?1:0; - h*=12186; - h+=n; - if ( x.stroke_width >= 0.01 ) { - n=x.stroke_cap*10+x.stroke_join+(int)(x.stroke_miter_limit*100); - h*=12186; - h+=n; - if ( x.nbDash > 0 ) { - n=x.nbDash; - h*=12186; - h+=n; - n=(int)floor(100*x.dash_offset); - h*=12186; - h+=n; - for (int i=0;i(floor(100 * x.stroke_width)); + h *= 12186; + h += n; + n = (x.vertical) ? 1:0; + h *= 12186; + h += n; + if ( x.stroke_width >= STROKE_WIDTH_THREASHOLD ) { + n = x.stroke_cap * 10 + x.stroke_join + static_cast(x.stroke_miter_limit * 100); + h *= 12186; + h += n; + if ( x.nbDash > 0 ) { + n = x.nbDash; + h *= 12186; + h += n; + n = static_cast(floor(100 * x.dash_offset)); + h *= 12186; + h += n; + for (int i = 0; i < x.nbDash; i++) { + n = static_cast(floor(100 * x.dashes[i])); + h *= 12186; + h += n; + } + } + } + return h; } -bool font_style_equal::operator()(const font_style &a,const font_style &b) const { - for (int i=0;i<6;i++) { - if ( (int)(100*a.transform[i]) != (int)(100*b.transform[i]) ) return false; - } - if ( a.vertical && b.vertical == false ) return false; - if ( a.vertical == false && b.vertical ) return false; - if ( a.stroke_width > 0.01 && b.stroke_width <= 0.01 ) return false; - if ( a.stroke_width <= 0.01 && b.stroke_width > 0.01 ) return false; - if ( a.stroke_width <= 0.01 && b.stroke_width <= 0.01 ) return true; - - if ( a.stroke_cap != b.stroke_cap ) return false; - if ( a.stroke_join != b.stroke_join ) return false; - if ( (int)(a.stroke_miter_limit*100) != (int)(b.stroke_miter_limit*100) ) return false; - if ( a.nbDash != b.nbDash ) return false; - if ( a.nbDash <= 0 ) return true; - if ( (int)floor(100*a.dash_offset) != (int)floor(100*b.dash_offset) ) return false; - for (int i=0;i(100 * a.transform[i]) == static_cast(100 * b.transform[i]) ); + } + same &= ( a.vertical == b.vertical ) + && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) == ( b.stroke_width > STROKE_WIDTH_THREASHOLD ); + if ( same && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) ) { + same = ( a.stroke_cap == b.stroke_cap ) + && ( a.stroke_join == b.stroke_join ) + && ( static_cast(a.stroke_miter_limit * 100) == static_cast(b.stroke_miter_limit * 100) ) + && ( a.nbDash == b.nbDash ); + if ( same && ( a.nbDash > 0 ) ) { + same = ( static_cast(floor(100 * a.dash_offset)) == static_cast(floor(100 * b.dash_offset)) ); + for (int i = 0; (i < a.nbDash) && same; i++) { + same = ( static_cast(floor(100 * a.dashes[i])) == static_cast(floor(100 * b.dashes[i])) ); + } + } + } + return same; } #ifndef USE_PANGO_WIN32 @@ -97,9 +99,9 @@ bool font_style_equal::operator()(const font_style &a,const font_style &b) cons * Outline extraction */ typedef struct ft2_to_liv { - Path* theP; - double scale; - Geom::Point last; + Path* theP; + double scale; + Geom::Point last; } ft2_to_liv; // Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an @@ -116,46 +118,46 @@ typedef FT_Vector FREETYPE_VECTOR; // outline as returned by freetype -> livarot Path // see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based static int ft2_move_to(FREETYPE_VECTOR *to, void * i_user) { - ft2_to_liv* user=(ft2_to_liv*)i_user; - Geom::Point p(user->scale*to->x,user->scale*to->y); - // printf("m t=%f %f\n",p[0],p[1]); - user->theP->MoveTo(p); - user->last=p; - return 0; + ft2_to_liv* user=(ft2_to_liv*)i_user; + Geom::Point p(user->scale*to->x,user->scale*to->y); + // printf("m t=%f %f\n",p[0],p[1]); + user->theP->MoveTo(p); + user->last=p; + return 0; } static int ft2_line_to(FREETYPE_VECTOR *to, void *i_user) { - ft2_to_liv* user=(ft2_to_liv*)i_user; - Geom::Point p(user->scale*to->x,user->scale*to->y); - // printf("l t=%f %f\n",p[0],p[1]); - user->theP->LineTo(p); - user->last=p; - return 0; + ft2_to_liv* user=(ft2_to_liv*)i_user; + Geom::Point p(user->scale*to->x,user->scale*to->y); + // printf("l t=%f %f\n",p[0],p[1]); + user->theP->LineTo(p); + user->last=p; + return 0; } static int ft2_conic_to(FREETYPE_VECTOR *control, FREETYPE_VECTOR *to, void *i_user) { - ft2_to_liv* user=(ft2_to_liv*)i_user; - Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y); - // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]); - user->theP->BezierTo(p); - user->theP->IntermBezierTo(c); - user->theP->EndBezierTo(); - user->last=p; - return 0; + ft2_to_liv* user=(ft2_to_liv*)i_user; + Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y); + // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]); + user->theP->BezierTo(p); + user->theP->IntermBezierTo(c); + user->theP->EndBezierTo(); + user->last=p; + return 0; } static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user) { - ft2_to_liv* user=(ft2_to_liv*)i_user; - Geom::Point p(user->scale*to->x,user->scale*to->y), - c1(user->scale*control1->x,user->scale*control1->y), - c2(user->scale*control2->x,user->scale*control2->y); - // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]); - user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2)); - user->last=p; - return 0; + ft2_to_liv* user=(ft2_to_liv*)i_user; + Geom::Point p(user->scale*to->x,user->scale*to->y); + Geom::Point c1(user->scale*control1->x,user->scale*control1->y); + Geom::Point c2(user->scale*control2->x,user->scale*control2->y); + // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]); + user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2)); + user->last=p; + return 0; } #endif @@ -203,7 +205,7 @@ font_instance::~font_instance(void) descr = 0; } - // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch + // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch theFace = 0; for (int i=0;iUnrefFace(this); - daddy=NULL; - delete this; - } + refCount--; + //char *tc=pango_font_description_to_string(descr); + //printf("font %x %s unref'd %i\n",this,tc,refCount); + //free(tc); + if ( refCount <= 0 ) { + if ( daddy ) { + daddy->UnrefFace(this); + } + daddy=NULL; + delete this; + } } unsigned int font_instance::Name(gchar *str, unsigned int size) { - return Attribute("name", str, size); + return Attribute("name", str, size); } unsigned int font_instance::Family(gchar *str, unsigned int size) { - return Attribute("family", str, size); + return Attribute("family", str, size); } unsigned int font_instance::PSName(gchar *str, unsigned int size) { - return Attribute("psname", str, size); + return Attribute("psname", str, size); } unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size) { - if ( descr == NULL ) { - if ( size > 0 ) str[0]=0; - return 0; - } - char* res=NULL; - bool free_res=false; - - if ( strcmp(key,"name") == 0 ) { - PangoFontDescription* td=pango_font_description_copy(descr); - pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE); - res=pango_font_description_to_string (td); - pango_font_description_free(td); - free_res=true; - } else if ( strcmp(key,"psname") == 0 ) { + if ( descr == NULL ) { + if ( size > 0 ) { + str[0]=0; + } + return 0; + } + char* res=NULL; + bool free_res=false; + + if ( strcmp(key,"name") == 0 ) { + PangoFontDescription* td=pango_font_description_copy(descr); + pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE); + res=pango_font_description_to_string (td); + pango_font_description_free(td); + free_res=true; + } else if ( strcmp(key,"psname") == 0 ) { #ifndef USE_PANGO_WIN32 res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work #endif @@ -292,89 +298,97 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int (i) ? "Italic" : ((o) ? "Oblique" : "") ); free_res = true; } - } else if ( strcmp(key,"family") == 0 ) { - res=(char*)pango_font_description_get_family(descr); - free_res=false; - } else if ( strcmp(key,"style") == 0 ) { - PangoStyle v=pango_font_description_get_style(descr); - if ( v == PANGO_STYLE_ITALIC ) { - res=(char*)"italic"; - } else if ( v == PANGO_STYLE_OBLIQUE ) { - res=(char*)"oblique"; - } else { - res=(char*)"normal"; - } - free_res=false; - } else if ( strcmp(key,"weight") == 0 ) { - PangoWeight v=pango_font_description_get_weight(descr); - if ( v <= PANGO_WEIGHT_THIN ) { - res=(char*)"100"; - } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { - res=(char*)"200"; - } else if ( v <= PANGO_WEIGHT_LIGHT ) { - res=(char*)"300"; - } else if ( v <= PANGO_WEIGHT_BOOK ) { - res=(char*)"380"; - } else if ( v <= PANGO_WEIGHT_NORMAL ) { - res=(char*)"normal"; - } else if ( v <= PANGO_WEIGHT_MEDIUM ) { - res=(char*)"500"; - } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) { - res=(char*)"600"; - } else if ( v <= PANGO_WEIGHT_BOLD ) { - res=(char*)"bold"; - } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) { - res=(char*)"800"; - } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2 - res=(char*)"900"; - } - free_res=false; - } else if ( strcmp(key,"stretch") == 0 ) { - PangoStretch v=pango_font_description_get_stretch(descr); - if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) { - res=(char*)"extra-condensed"; - } else if ( v <= PANGO_STRETCH_CONDENSED ) { - res=(char*)"condensed"; - } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) { - res=(char*)"semi-condensed"; - } else if ( v <= PANGO_STRETCH_NORMAL ) { - res=(char*)"normal"; - } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) { - res=(char*)"semi-expanded"; - } else if ( v <= PANGO_STRETCH_EXPANDED ) { - res=(char*)"expanded"; - } else { - res=(char*)"extra-expanded"; - } - free_res=false; - } else if ( strcmp(key,"variant") == 0 ) { - PangoVariant v=pango_font_description_get_variant(descr); - if ( v == PANGO_VARIANT_SMALL_CAPS ) { - res=(char*)"small-caps"; - } else { - res=(char*)"normal"; - } - free_res=false; - } else { - res = NULL; - free_res=false; - } - if ( res == NULL ) { - if ( size > 0 ) str[0]=0; - return 0; - } - - if (res) { - unsigned int len=strlen(res); - unsigned int rlen=(size-1 0 ) memcpy(str,res,rlen); - if ( size > 0 ) str[rlen]=0; - } - if (free_res) free(res); - return len; - } - return 0; + } else if ( strcmp(key,"family") == 0 ) { + res=(char*)pango_font_description_get_family(descr); + free_res=false; + } else if ( strcmp(key,"style") == 0 ) { + PangoStyle v=pango_font_description_get_style(descr); + if ( v == PANGO_STYLE_ITALIC ) { + res=(char*)"italic"; + } else if ( v == PANGO_STYLE_OBLIQUE ) { + res=(char*)"oblique"; + } else { + res=(char*)"normal"; + } + free_res=false; + } else if ( strcmp(key,"weight") == 0 ) { + PangoWeight v=pango_font_description_get_weight(descr); + if ( v <= PANGO_WEIGHT_THIN ) { + res=(char*)"100"; + } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { + res=(char*)"200"; + } else if ( v <= PANGO_WEIGHT_LIGHT ) { + res=(char*)"300"; + } else if ( v <= PANGO_WEIGHT_BOOK ) { + res=(char*)"380"; + } else if ( v <= PANGO_WEIGHT_NORMAL ) { + res=(char*)"normal"; + } else if ( v <= PANGO_WEIGHT_MEDIUM ) { + res=(char*)"500"; + } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) { + res=(char*)"600"; + } else if ( v <= PANGO_WEIGHT_BOLD ) { + res=(char*)"bold"; + } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) { + res=(char*)"800"; + } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2 + res=(char*)"900"; + } + free_res=false; + } else if ( strcmp(key,"stretch") == 0 ) { + PangoStretch v=pango_font_description_get_stretch(descr); + if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) { + res=(char*)"extra-condensed"; + } else if ( v <= PANGO_STRETCH_CONDENSED ) { + res=(char*)"condensed"; + } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) { + res=(char*)"semi-condensed"; + } else if ( v <= PANGO_STRETCH_NORMAL ) { + res=(char*)"normal"; + } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) { + res=(char*)"semi-expanded"; + } else if ( v <= PANGO_STRETCH_EXPANDED ) { + res=(char*)"expanded"; + } else { + res=(char*)"extra-expanded"; + } + free_res=false; + } else if ( strcmp(key,"variant") == 0 ) { + PangoVariant v=pango_font_description_get_variant(descr); + if ( v == PANGO_VARIANT_SMALL_CAPS ) { + res=(char*)"small-caps"; + } else { + res=(char*)"normal"; + } + free_res=false; + } else { + res = NULL; + free_res=false; + } + if ( res == NULL ) { + if ( size > 0 ) { + str[0] = 0; + } + return 0; + } + + if (res) { + unsigned int len=strlen(res); + unsigned int rlen=(size-1 0 ) { + memcpy(str, res, rlen); + } + if ( size > 0 ) { + str[rlen] = 0; + } + } + if (free_res) { + free(res); + } + return len; + } + return 0; } void font_instance::InitTheFace() @@ -391,9 +405,10 @@ void font_instance::InitTheFace() SetGraphicsMode(daddy->hScreenDC, GM_COMPATIBLE); SelectObject(daddy->hScreenDC,theFace); #else - theFace=pango_ft2_font_get_face(pFont); - if ( theFace ) + theFace=pango_ft2_font_get_face(pFont); + if ( theFace ) { FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol); + } #endif } @@ -408,46 +423,52 @@ void font_instance::FreeTheFace() void font_instance::InstallFace(PangoFont* iFace) { - if ( !iFace ) - return; - pFont=iFace; + if ( !iFace ) { + return; + } + pFont=iFace; InitTheFace(); - if ( pFont && IsOutlineFont() == false ) { + if ( pFont && IsOutlineFont() == false ) { FreeTheFace(); - if ( pFont ) g_object_unref(pFont); - pFont=NULL; - } + if ( pFont ) { + g_object_unref(pFont); + } + pFont=NULL; + } } -bool font_instance::IsOutlineFont(void) +bool font_instance::IsOutlineFont(void) { - if ( pFont == NULL ) return false; + if ( pFont == NULL ) { + return false; + } InitTheFace(); #ifdef USE_PANGO_WIN32 TEXTMETRIC tm; return GetTextMetrics(daddy->hScreenDC,&tm) && tm.tmPitchAndFamily&(TMPF_TRUETYPE|TMPF_DEVICE); #else - return FT_IS_SCALABLE(theFace); + return FT_IS_SCALABLE(theFace); #endif } int font_instance::MapUnicodeChar(gunichar c) { - if ( pFont == NULL ) return 0; + int res = 0; + if ( pFont ) { #ifdef USE_PANGO_WIN32 - return pango_win32_font_get_glyph_index(pFont,c); + res = pango_win32_font_get_glyph_index(pFont, c); #else - int res=0; - theFace=pango_ft2_font_get_face(pFont); - if ( c > 0xf0000 ) { - res=CLAMP(c,0xf0000,0x1fffff)-0xf0000; - } else { - res=FT_Get_Char_Index(theFace, c); - } - return res; + theFace = pango_ft2_font_get_face(pFont); + if ( c > 0xf0000 ) { + res = CLAMP(c, 0xf0000, 0x1fffff) - 0xf0000; + } else { + res = FT_Get_Char_Index(theFace, c); + } + } #endif + return res; } @@ -461,22 +482,26 @@ static inline Geom::Point pointfx_to_nrpoint(const POINTFX &p, double scale) void font_instance::LoadGlyph(int glyph_id) { - if ( pFont == NULL ) return; + if ( pFont == NULL ) { + return; + } InitTheFace(); #ifndef USE_PANGO_WIN32 - if ( !FT_IS_SCALABLE(theFace) ) return; // bitmap font + if ( !FT_IS_SCALABLE(theFace) ) { + return; // bitmap font + } #endif - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - if ( nbGlyph >= maxGlyph ) { - maxGlyph=2*nbGlyph+1; - glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph)); - } - font_glyph n_g; - n_g.outline=NULL; + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + if ( nbGlyph >= maxGlyph ) { + maxGlyph=2*nbGlyph+1; + glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph)); + } + font_glyph n_g; + n_g.outline=NULL; n_g.pathvector=NULL; - n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0; - bool doAdd=false; + n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0; + bool doAdd=false; #ifdef USE_PANGO_WIN32 @@ -534,15 +559,15 @@ void font_instance::LoadGlyph(int glyph_id) Geom::Point this_mid=pointfx_to_nrpoint(p[0], scale); while ( p != endp ) { Geom::Point next_mid=pointfx_to_nrpoint(p[1], scale); - n_g.outline->BezierTo((next_mid+this_mid)/2); - n_g.outline->IntermBezierTo(this_mid); - n_g.outline->EndBezierTo(); + n_g.outline->BezierTo((next_mid+this_mid)/2); + n_g.outline->IntermBezierTo(this_mid); + n_g.outline->EndBezierTo(); ++p; this_mid=next_mid; } - n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale)); - n_g.outline->IntermBezierTo(this_mid); - n_g.outline->EndBezierTo(); + n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale)); + n_g.outline->IntermBezierTo(this_mid); + n_g.outline->EndBezierTo(); break; } @@ -565,73 +590,81 @@ void font_instance::LoadGlyph(int glyph_id) delete [] buffer; } #else - if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) { - // shit happened - } else { - if ( FT_HAS_HORIZONTAL(theFace) ) { - n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM); - n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM); - } else { - n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM); - } - if ( FT_HAS_VERTICAL(theFace) ) { - n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM); - n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM); - } else { - n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM); - } - if ( theFace->glyph->format == ft_glyph_format_outline ) { - FT_Outline_Funcs ft2_outline_funcs = { - ft2_move_to, - ft2_line_to, - ft2_conic_to, - ft2_cubic_to, - 0, 0 - }; - n_g.outline=new Path; - ft2_to_liv tData; - tData.theP=n_g.outline; - tData.scale=1.0/((double)theFace->units_per_EM); - tData.last=Geom::Point(0,0); - FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData); - } - doAdd=true; - } + if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) { + // shit happened + } else { + if ( FT_HAS_HORIZONTAL(theFace) ) { + n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM); + n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM); + } else { + n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM); + } + if ( FT_HAS_VERTICAL(theFace) ) { + n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM); + n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM); + } else { + n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM); + } + if ( theFace->glyph->format == ft_glyph_format_outline ) { + FT_Outline_Funcs ft2_outline_funcs = { + ft2_move_to, + ft2_line_to, + ft2_conic_to, + ft2_cubic_to, + 0, 0 + }; + n_g.outline=new Path; + ft2_to_liv tData; + tData.theP=n_g.outline; + tData.scale=1.0/((double)theFace->units_per_EM); + tData.last=Geom::Point(0,0); + FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData); + } + doAdd=true; + } #endif - if ( doAdd ) { - if ( n_g.outline ) { - n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]); + if ( doAdd ) { + if ( n_g.outline ) { + n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]); n_g.pathvector=n_g.outline->MakePathVector(); - } - glyphs[nbGlyph]=n_g; - id_to_no[glyph_id]=nbGlyph; - nbGlyph++; - } + } + glyphs[nbGlyph]=n_g; + id_to_no[glyph_id]=nbGlyph; + nbGlyph++; + } } else { } } bool font_instance::FontMetrics(double &ascent,double &descent,double &leading) { - if ( pFont == NULL ) return false; + if ( pFont == NULL ) { + return false; + } InitTheFace(); - if ( theFace == NULL ) return false; + if ( theFace == NULL ) { + return false; + } #ifdef USE_PANGO_WIN32 OUTLINETEXTMETRIC otm; - if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) return false; + if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) { + return false; + } double scale=1.0/daddy->fontSize; ascent=fabs(otm.otmAscent*scale); descent=fabs(otm.otmDescent*scale); leading=fabs(otm.otmLineGap*scale); #else - if ( theFace->units_per_EM == 0 ) return false; // bitmap font - ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM)); - descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM)); - leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM)); - leading-=ascent+descent; + if ( theFace->units_per_EM == 0 ) { + return false; // bitmap font + } + ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM)); + descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM)); + leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM)); + leading-=ascent+descent; #endif - return true; + return true; } bool font_instance::FontSlope(double &run, double &rise) @@ -639,9 +672,13 @@ bool font_instance::FontSlope(double &run, double &rise) run = 0.0; rise = 1.0; - if ( pFont == NULL ) return false; + if ( pFont == NULL ) { + return false; + } InitTheFace(); - if ( theFace == NULL ) return false; + if ( theFace == NULL ) { + return false; + } #ifdef USE_PANGO_WIN32 OUTLINETEXTMETRIC otm; @@ -649,59 +686,63 @@ bool font_instance::FontSlope(double &run, double &rise) run=otm.otmsCharSlopeRun; rise=otm.otmsCharSlopeRise; #else - if ( !FT_IS_SCALABLE(theFace) ) return false; // bitmap font + if ( !FT_IS_SCALABLE(theFace) ) { + return false; // bitmap font + } TT_HoriHeader *hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(theFace, ft_sfnt_hhea); - if (hhea == NULL) return false; + if (hhea == NULL) { + return false; + } run = hhea->caret_Slope_Run; rise = hhea->caret_Slope_Rise; #endif - return true; + return true; } Geom::OptRect font_instance::BBox(int glyph_id) { - int no=-1; - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - LoadGlyph(glyph_id); - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - // didn't load - } else { - no=id_to_no[glyph_id]; - } - } else { - no=id_to_no[glyph_id]; - } - if ( no < 0 ) { - return Geom::OptRect(); + int no = -1; + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + LoadGlyph(glyph_id); + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + // didn't load } else { - Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]); - Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]); - return Geom::Rect(rmin, rmax); + no = id_to_no[glyph_id]; } + } else { + no = id_to_no[glyph_id]; + } + if ( no < 0 ) { + return Geom::OptRect(); + } else { + Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]); + Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]); + return Geom::Rect(rmin, rmax); + } } Path* font_instance::Outline(int glyph_id,Path* copyInto) { - int no=-1; - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - LoadGlyph(glyph_id); - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - // didn't load - } else { - no=id_to_no[glyph_id]; - } - } else { - no=id_to_no[glyph_id]; - } - if ( no < 0 ) return NULL; - Path* src_o=glyphs[no].outline; - if ( copyInto ) { - copyInto->Reset(); - copyInto->Copy(src_o); - return copyInto; - } - return src_o; + int no = -1; + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + LoadGlyph(glyph_id); + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + // didn't load + } else { + no = id_to_no[glyph_id]; + } + } else { + no = id_to_no[glyph_id]; + } + if ( no < 0 ) return NULL; + Path *src_o = glyphs[no].outline; + if ( copyInto ) { + copyInto->Reset(); + copyInto->Copy(src_o); + return copyInto; + } + return src_o; } Geom::PathVector* font_instance::PathVector(int glyph_id) @@ -723,70 +764,74 @@ Geom::PathVector* font_instance::PathVector(int glyph_id) double font_instance::Advance(int glyph_id,bool vertical) { - int no=-1; - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - LoadGlyph(glyph_id); - if ( id_to_no.find(glyph_id) == id_to_no.end() ) { - // didn't load - } else { - no=id_to_no[glyph_id]; - } - } else { - no=id_to_no[glyph_id]; - } - if ( no >= 0 ) { - if ( vertical ) { - return glyphs[no].v_advance; - } else { - return glyphs[no].h_advance; - } - } - return 0; + int no = -1; + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + LoadGlyph(glyph_id); + if ( id_to_no.find(glyph_id) == id_to_no.end() ) { + // didn't load + } else { + no=id_to_no[glyph_id]; + } + } else { + no = id_to_no[glyph_id]; + } + if ( no >= 0 ) { + if ( vertical ) { + return glyphs[no].v_advance; + } else { + return glyphs[no].h_advance; + } + } + return 0; } raster_font* font_instance::RasterFont(const Geom::Matrix &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/) { - font_style nStyle; - nStyle.transform=trs; - nStyle.vertical=vertical; - nStyle.stroke_width=stroke_width; - nStyle.stroke_cap=stroke_cap; - nStyle.stroke_join=stroke_join; - nStyle.nbDash=0; - nStyle.dash_offset=0; - nStyle.dashes=NULL; - return RasterFont(nStyle); + font_style nStyle; + nStyle.transform=trs; + nStyle.vertical=vertical; + nStyle.stroke_width=stroke_width; + nStyle.stroke_cap=stroke_cap; + nStyle.stroke_join=stroke_join; + nStyle.nbDash=0; + nStyle.dash_offset=0; + nStyle.dashes=NULL; + return RasterFont(nStyle); } raster_font* font_instance::RasterFont(const font_style &inStyle) { - raster_font *res=NULL; - double *savDashes=NULL; - font_style nStyle=inStyle; + raster_font *res=NULL; + double *savDashes=NULL; + font_style nStyle=inStyle; // for some evil reason font_style doesn't have a copy ctor, so the // stuff that should be done there is done here instead (because the // raster_font ctor copies nStyle). - if ( nStyle.stroke_width > 0 && nStyle.nbDash > 0 && nStyle.dashes ) { - savDashes=nStyle.dashes; - nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double)); - memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double)); - } - StyleMap& loadedStyles = *static_cast(loadedPtr); - if ( loadedStyles.find(nStyle) == loadedStyles.end() ) { - raster_font *nR = new raster_font(nStyle); - nR->Ref(); - nR->daddy=this; - loadedStyles[nStyle]=nR; - res=nR; - if ( res ) Ref(); - } else { - res=loadedStyles[nStyle]; - res->Ref(); - if ( nStyle.dashes ) free(nStyle.dashes); // since they're not taken by a new rasterfont - } - nStyle.dashes=savDashes; - return res; + if ( (nStyle.stroke_width > 0) && (nStyle.nbDash > 0) && nStyle.dashes ) { + savDashes=nStyle.dashes; + nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double)); + memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double)); + } + StyleMap& loadedStyles = *static_cast(loadedPtr); + if ( loadedStyles.find(nStyle) == loadedStyles.end() ) { + raster_font *nR = new raster_font(nStyle); + nR->Ref(); + nR->daddy=this; + loadedStyles[nStyle]=nR; + res=nR; + if ( res ) { + Ref(); + } + } else { + res=loadedStyles[nStyle]; + res->Ref(); + if ( nStyle.dashes ) { + free(nStyle.dashes); // since they're not taken by a new rasterfont + } + } + nStyle.dashes=savDashes; + return res; } void font_instance::RemoveRasterFont(raster_font* who) diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index d25eb039d..0d2b7647d 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -117,10 +117,10 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, Geom::Matrix total_transform = glyph_matrix; total_transform *= transform; if(_glyphs[glyph_index].span(this).font) { - Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph); + Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph); if (glyph_rect) { - Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max(); - Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]); + Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max(); + Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]); tlp *= total_transform; trp *= total_transform; blp *= total_transform; @@ -133,7 +133,7 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, if ( (glyph_rect->min())[1] < bounding_box->y0 ) bounding_box->y0=(glyph_rect->min())[1]; if ( (glyph_rect->max())[1] > bounding_box->y1 ) bounding_box->y1=(glyph_rect->max())[1]; } - } + } } } -- cgit v1.2.3 From 47a999e560e80d9c71041c538d9a12dd72058ac3 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 17 Apr 2010 16:07:58 -0700 Subject: Temp build-break workaround for systems with Pango older than 1.24. (bzr r9346) --- src/libnrtype/FontFactory.cpp | 7 +++++++ src/libnrtype/FontInstance.cpp | 7 +++++++ src/libnrtype/Layout-TNG-Output.cpp | 7 +++++++ 3 files changed, 21 insertions(+) (limited to 'src') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 83b9bf9d1..067254b9e 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -22,6 +22,13 @@ #include "libnrtype/font-instance.h" #include "util/unordered-containers.h" +#if !PANGO_VERSION_CHECK(1,24,0) +#define PANGO_WEIGHT_THIN static_cast(100) +#define PANGO_WEIGHT_BOOK static_cast(380) +#define PANGO_WEIGHT_MEDIUM static_cast(500) +#define PANGO_WEIGHT_ULTRAHEAVY static_cast(1000) +#endif + typedef INK_UNORDERED_MAP FaceMapType; // need to avoid using the size field diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 1b02ace23..7b16ae9b2 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -28,6 +28,13 @@ #include "livarot/Path.h" #include "util/unordered-containers.h" +#if !PANGO_VERSION_CHECK(1,24,0) +#define PANGO_WEIGHT_THIN static_cast(100) +#define PANGO_WEIGHT_BOOK static_cast(380) +#define PANGO_WEIGHT_MEDIUM static_cast(500) +#define PANGO_WEIGHT_ULTRAHEAVY static_cast(1000) +#endif + struct font_style_hash : public std::unary_function { size_t operator()(font_style const &x) const; diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 0d2b7647d..f34b93d6e 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -24,6 +24,13 @@ #include "display/curve.h" #include <2geom/pathvector.h> +#if !PANGO_VERSION_CHECK(1,24,0) +#define PANGO_WEIGHT_THIN static_cast(100) +#define PANGO_WEIGHT_BOOK static_cast(380) +#define PANGO_WEIGHT_MEDIUM static_cast(500) +#define PANGO_WEIGHT_ULTRAHEAVY static_cast(1000) +#endif + namespace Inkscape { namespace Extension { namespace Internal { -- cgit v1.2.3 From 67df04c623f19166b7674bc39827095d71241039 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 18 Apr 2010 09:24:32 +0200 Subject: Added/Fixed Pango font weights. Included Jon's workaround for Pango older than 1.24. (bzr r9348) --- src/libnrtype/Layout-TNG-Input.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp index fb2769edc..d16c6457d 100644 --- a/src/libnrtype/Layout-TNG-Input.cpp +++ b/src/libnrtype/Layout-TNG-Input.cpp @@ -19,6 +19,13 @@ #include "sp-string.h" #include "FontFactory.h" +#if !PANGO_VERSION_CHECK(1,24,0) +#define PANGO_WEIGHT_THIN static_cast(100) +#define PANGO_WEIGHT_BOOK static_cast(380) +#define PANGO_WEIGHT_MEDIUM static_cast(500) +#define PANGO_WEIGHT_ULTRAHEAVY static_cast(1000) +#endif + namespace Inkscape { namespace Text { @@ -237,18 +244,16 @@ static const Layout::EnumConversionItem enum_convert_spstyle_style_to_pango_styl {SP_CSS_FONT_STYLE_OBLIQUE, PANGO_STYLE_OBLIQUE}}; static const Layout::EnumConversionItem enum_convert_spstyle_weight_to_pango_weight[] = { + // NB: The Pango web page calls 500 "the normal font" but both CSS2 and the Pango + // enumeration define 400 as normal. {SP_CSS_FONT_WEIGHT_NORMAL, PANGO_WEIGHT_NORMAL}, - {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_ULTRALIGHT}, + {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD}, + {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_THIN}, {SP_CSS_FONT_WEIGHT_200, PANGO_WEIGHT_ULTRALIGHT}, {SP_CSS_FONT_WEIGHT_300, PANGO_WEIGHT_LIGHT}, {SP_CSS_FONT_WEIGHT_400, PANGO_WEIGHT_NORMAL}, -#if GTK_CHECK_VERSION(2,6,0) - {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_SEMIBOLD}, -#else - {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_NORMAL}, -#endif - {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_BOLD}, - {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD}, + {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_MEDIUM}, + {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_SEMIBOLD}, {SP_CSS_FONT_WEIGHT_700, PANGO_WEIGHT_BOLD}, {SP_CSS_FONT_WEIGHT_800, PANGO_WEIGHT_ULTRABOLD}, {SP_CSS_FONT_WEIGHT_900, PANGO_WEIGHT_HEAVY}}; -- cgit v1.2.3 From a242ad41a108951669023026d39ebb6e83905785 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 18 Apr 2010 01:40:21 -0700 Subject: Correct #endif placement. Should fix win32 build. (bzr r9349) --- src/libnrtype/FontInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 7b16ae9b2..b958e899d 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -473,8 +473,8 @@ int font_instance::MapUnicodeChar(gunichar c) } else { res = FT_Get_Char_Index(theFace, c); } - } #endif + } return res; } -- cgit v1.2.3 From 754b97f48cd23a2a178a121917a3e58a609fc3c2 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Sun, 18 Apr 2010 16:17:05 +0200 Subject: Fix for bug #455302 and bug #165529, also partially fixes bounding box of various NR Arena Items as passed to filters (it used to explicitly make the bounding box larger) and makes nr-filter-displacement-map use rowstride (bzr r9350) --- src/display/nr-arena-glyphs.cpp | 8 +- src/display/nr-arena-image.cpp | 16 ++-- src/display/nr-arena-shape.cpp | 33 ++++---- src/display/nr-filter-displacement-map.cpp | 92 ++++++++++++----------- src/display/pixblock-transform.cpp | 5 ++ src/libnr/nr-compose-transform.cpp | 116 ++++++++++++++++------------- 6 files changed, 144 insertions(+), 126 deletions(-) (limited to 'src') diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index ff320bd81..33b08a91c 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -211,10 +211,10 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s } if (nr_rect_d_test_empty(bbox)) return NR_ARENA_ITEM_STATE_ALL; - item->bbox.x0 = (gint32)(bbox.x0 - 1.0); - item->bbox.y0 = (gint32)(bbox.y0 - 1.0); - item->bbox.x1 = (gint32)(bbox.x1 + 1.0); - item->bbox.y1 = (gint32)(bbox.y1 + 1.0); + item->bbox.x0 = static_cast(floor(bbox.x0)); + item->bbox.y0 = static_cast(floor(bbox.y0)); + item->bbox.x1 = static_cast(ceil (bbox.x1)); + item->bbox.y1 = static_cast(ceil (bbox.y1)); return NR_ARENA_ITEM_STATE_ALL; } diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp index f45a2da4f..493943168 100644 --- a/src/display/nr-arena-image.cpp +++ b/src/display/nr-arena-image.cpp @@ -151,10 +151,10 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned nr_rect_d_matrix_transform (&bbox, &bbox, gc->transform); - item->bbox.x0 = (int) floor (bbox.x0); - item->bbox.y0 = (int) floor (bbox.y0); - item->bbox.x1 = (int) ceil (bbox.x1); - item->bbox.y1 = (int) ceil (bbox.y1); + item->bbox.x0 = static_cast(floor(bbox.x0)); // Floor gives the coordinate in which the point resides + item->bbox.y0 = static_cast(floor(bbox.y0)); + item->bbox.x1 = static_cast(ceil (bbox.x1)); // Ceil gives the first coordinate beyond the point + item->bbox.y1 = static_cast(ceil (bbox.y1)); } else { item->bbox.x0 = (int) gc->transform[4]; item->bbox.y0 = (int) gc->transform[5]; @@ -211,13 +211,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixB } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) { - - //FIXME: The _N_N_N_ version gives a gray border around images, see bug 906376 - // This mode is only used when exporting, screen rendering always has _P_P_P_, so I decided to simply replace it for now - // Feel free to propose a better fix - - //nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); - nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); + nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); } pb->empty = FALSE; diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index e2a9e9580..a3b295a4e 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -254,12 +254,11 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g if (state & NR_ARENA_ITEM_STATE_BBOX) { if (shape->curve) { boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform); - /// \todo just write item->bbox = boundingbox if (boundingbox) { - item->bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F); - item->bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F); - item->bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F); - item->bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F); + item->bbox.x0 = static_cast(floor((*boundingbox)[0][0])); // Floor gives the coordinate in which the point resides + item->bbox.y0 = static_cast(floor((*boundingbox)[1][0])); + item->bbox.x1 = static_cast(ceil ((*boundingbox)[0][1])); // Ceil gives the first coordinate beyond the point + item->bbox.y1 = static_cast(ceil ((*boundingbox)[1][1])); } else { item->bbox = NR_RECT_L_EMPTY; } @@ -300,10 +299,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g /// \todo just write item->bbox = boundingbox if (boundingbox) { - shape->approx_bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F); - shape->approx_bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F); - shape->approx_bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F); - shape->approx_bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F); + shape->approx_bbox.x0 = static_cast(floor((*boundingbox)[0][0])); + shape->approx_bbox.y0 = static_cast(floor((*boundingbox)[1][0])); + shape->approx_bbox.x1 = static_cast(ceil ((*boundingbox)[0][1])); + shape->approx_bbox.y1 = static_cast(ceil ((*boundingbox)[1][1])); } else { shape->approx_bbox = NR_RECT_L_EMPTY; } @@ -349,10 +348,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g /// \todo just write shape->approx_bbox = boundingbox if (boundingbox) { - shape->approx_bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F); - shape->approx_bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F); - shape->approx_bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F); - shape->approx_bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F); + shape->approx_bbox.x0 = static_cast(floor((*boundingbox)[0][0])); + shape->approx_bbox.y0 = static_cast(floor((*boundingbox)[1][0])); + shape->approx_bbox.x1 = static_cast(ceil ((*boundingbox)[0][1])); + shape->approx_bbox.y1 = static_cast(ceil ((*boundingbox)[1][1])); } else { shape->approx_bbox = NR_RECT_L_EMPTY; } @@ -362,10 +361,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g return NR_ARENA_ITEM_STATE_ALL; /// \todo just write item->bbox = boundingbox - item->bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F); - item->bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F); - item->bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.0F); - item->bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.0F); + item->bbox.x0 = static_cast(floor((*boundingbox)[0][0])); + item->bbox.y0 = static_cast(floor((*boundingbox)[1][0])); + item->bbox.x1 = static_cast(ceil ((*boundingbox)[0][1])); + item->bbox.y1 = static_cast(ceil ((*boundingbox)[1][1])); item->render_opacity = TRUE; if ( shape->_fill.paint.type() == NRArenaShape::Paint::SERVER ) { diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp index 4de5e658c..a983fb840 100644 --- a/src/display/nr-filter-displacement-map.cpp +++ b/src/display/nr-filter-displacement-map.cpp @@ -43,9 +43,8 @@ struct pixel_t { static inline pixel_t pixelValue(NRPixBlock const* pb, int x, int y) { if ( x < pb->area.x0 || x >= pb->area.x1 || y < pb->area.y0 || y >= pb->area.y1 ) return pixel_t::blank(); // This assumes anything outside the defined range is (0,0,0,0) - pixel_t const* data = reinterpret_cast(NR_PIXBLOCK_PX(pb)); - int offset = (x-pb->area.x0) + (pb->area.x1-pb->area.x0)*(y-pb->area.y0); - return data[offset]; + pixel_t const* rowData = reinterpret_cast(NR_PIXBLOCK_PX(pb) + (y-pb->area.y0)*pb->rs); + return rowData[x-pb->area.x0]; } template @@ -74,18 +73,9 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) { * We might as well avoid premultiplication in this case, which still gives us a fully * transparent result, but with interpolated RGB parts. */ - /* First calculate interpolated alpha value. */ - unsigned ra = 0; - if (!PREMULTIPLIED) { - unsigned const y0 = sf*p00[3] + xf*(p01[3]-p00[3]); // range [0,a*sf] - unsigned const y1 = sf*p10[3] + xf*(p11[3]-p10[3]); - ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf] - } - pixel_t r; - if (ra == 0) { - /* Either premultiplied or the interpolated alpha value is zero, - * so do simple interpolation. */ + if (PREMULTIPLIED) { + /* Premultiplied, so do simple interpolation. */ for (unsigned i = 0; i != 4; ++i) { // y0,y1 have range [0,a*sf] unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]); @@ -95,21 +85,39 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) { r[i] = (ri + sf2h)>>(2*sfl); // range [0,a] } } else { - /* Do premultiplication ourselves. */ - for (unsigned i = 0; i != 3; ++i) { - // Premultiplied versions. Range [0,255*a]. - unsigned const c00 = p00[i]*p00[3]; - unsigned const c01 = p01[i]*p01[3]; - unsigned const c10 = p10[i]*p10[3]; - unsigned const c11 = p11[i]*p11[3]; - - // Interpolation. - unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf] - unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf] - unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf] - r[i] = (ri + ra/2) / ra; // range [0,255] + /* First calculate interpolated alpha value. */ + unsigned const y0 = sf*p00[3] + xf*((unsigned int)p01[3]-(unsigned int)p00[3]); // range [0,a*sf] + unsigned const y1 = sf*p10[3] + xf*((unsigned int)p11[3]-(unsigned int)p10[3]); + unsigned const ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf] + + if (ra==0) { + /* Fully transparent, so do simple interpolation. */ + for (unsigned i = 0; i != 3; ++i) { + // y0,y1 have range [0,255*sf] + unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]); + unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]); + + unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*sf*sf] + r[i] = (ri + sf2h)>>(2*sfl); // range [0,255] + } + r[3] = 0; + } else { + /* Do premultiplication ourselves. */ + for (unsigned i = 0; i != 3; ++i) { + // Premultiplied versions. Range [0,255*a]. + unsigned const c00 = p00[i]*p00[3]; + unsigned const c01 = p01[i]*p01[3]; + unsigned const c10 = p10[i]*p10[3]; + unsigned const c11 = p11[i]*p11[3]; + + // Interpolation. + unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf] + unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf] + unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf] + r[i] = (ri + ra/2) / ra; // range [0,255] + } + r[3] = (ra + sf2h)>>(2*sfl); // range [0,a] } - r[3] = (ra + sf2h)>>(2*sfl); // range [0,a] } return r; @@ -117,19 +125,17 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) { template static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map, int Xchannel, int Ychannel, NRPixBlock* out, double scalex, double scaley) { - pixel_t *out_data = reinterpret_cast(NR_PIXBLOCK_PX(out)); - bool Xneedsdemul = MAP_PREMULTIPLIED && Xchannel<3; bool Yneedsdemul = MAP_PREMULTIPLIED && Ychannel<3; if (!Xneedsdemul) scalex /= 255.0; if (!Yneedsdemul) scaley /= 255.0; for (int yout=out->area.y0; yout < out->area.y1; yout++){ + pixel_t const* mapRowData = reinterpret_cast(NR_PIXBLOCK_PX(map) + (yout-map->area.y0)*map->rs); + pixel_t* outRowData = reinterpret_cast(NR_PIXBLOCK_PX(out) + (yout-out->area.y0)*out->rs); for (int xout=out->area.x0; xout < out->area.x1; xout++){ - int xmap = xout; - int ymap = yout; + pixel_t const mapValue = mapRowData[xout-map->area.x0]; - pixel_t mapValue = pixelValue(map, xmap, ymap); double xtex = xout + (Xneedsdemul ? // Although the value of the pixel corresponds to the MIDDLE of the pixel, no +0.5 is needed because we're interpolating pixels anyway (so to get the actual pixel locations 0.5 would have to be subtracted again). (mapValue[3]==0?0:(scalex * (mapValue[Xchannel] - mapValue[3]*0.5) / mapValue[3])) : (scalex * (mapValue[Xchannel] - 127.5))); @@ -137,7 +143,7 @@ static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map (mapValue[3]==0?0:(scaley * (mapValue[Ychannel] - mapValue[3]*0.5) / mapValue[3])) : (scaley * (mapValue[Ychannel] - 127.5))); - out_data[(xout-out->area.x0) + (out->area.x1-out->area.x0)*(yout-out->area.y0)] = interpolatePixels(texture, xtex, ytex); + outRowData[xout-out->area.x0] = interpolatePixels(texture, xtex, ytex); } } } @@ -152,8 +158,14 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) { return 1; } - //TODO: check whether do we really need this check: - if (map->area.x1 <= map->area.x0 || map->area.y1 <= map->area.y0) return 0; //nothing to do! + NR::IRect area = units.get_pixblock_filterarea_paraller(); + int x0 = std::max(map->area.x0,area.min()[NR::X]); + int y0 = std::max(map->area.y0,area.min()[NR::Y]); + int x1 = std::min(map->area.x1,area.max()[NR::X]); + int y1 = std::min(map->area.y1,area.max()[NR::Y]); + + //TODO: check whether we really need this check: + if (x1 <= x0 || y1 <= y0) return 0; //nothing to do! if (texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { g_warning("Source images without an alpha channel are not supported by feDisplacementMap at the moment."); @@ -161,13 +173,7 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) { } NRPixBlock *out = new NRPixBlock; - - out->area.x0 = map->area.x0; - out->area.y0 = map->area.y0; - out->area.x1 = map->area.x1; - out->area.y1 = map->area.y1; - - nr_pixblock_setup_fast(out, texture->mode, out->area.x0, out->area.y0, out->area.x1, out->area.y1, true); + nr_pixblock_setup_fast(out, texture->mode, x0, y0, x1, y1, true); // convert to a suitable format bool free_map_on_exit = false; diff --git a/src/display/pixblock-transform.cpp b/src/display/pixblock-transform.cpp index 73b467d5a..af05a9b88 100644 --- a/src/display/pixblock-transform.cpp +++ b/src/display/pixblock-transform.cpp @@ -148,6 +148,11 @@ void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra nr_blit_pixblock_pixblock(from, o_from); free_from_on_exit = true; } + + if (from->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { + // TODO: Fix this... (The problem is that for interpolation non-premultiplied colors should be premultiplied...) + g_warning("transform_bicubic does not properly support non-premultiplied images"); + } // Precalculate sizes of source and destination pixblocks int from_width = from->area.x1 - from->area.x0; diff --git a/src/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp index 6e03faf2f..bc05c7b51 100644 --- a/src/libnr/nr-compose-transform.cpp +++ b/src/libnr/nr-compose-transform.cpp @@ -66,18 +66,25 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, if (alpha == 0) return; + // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow + if (xd+yd>16) { + xd = 8; + yd = 8; + } + xsize = (1 << xd); ysize = (1 << yd); size = xsize * ysize; dbits = xd + yd; + unsigned int rounding_fix = size/2; /* Set up fixed point matrix */ - FFs_x_x = (long) (d2s[0] * (1 << FBITS) + 0.5); - FFs_x_y = (long) (d2s[1] * (1 << FBITS) + 0.5); - FFs_y_x = (long) (d2s[2] * (1 << FBITS) + 0.5); - FFs_y_y = (long) (d2s[3] * (1 << FBITS) + 0.5); - FFs__x = (long) (d2s[4] * (1 << FBITS) + 0.5); - FFs__y = (long) (d2s[5] * (1 << FBITS) + 0.5); + FFs_x_x = (long) floor(d2s[0] * (1 << FBITS) + 0.5); + FFs_x_y = (long) floor(d2s[1] * (1 << FBITS) + 0.5); + FFs_y_x = (long) floor(d2s[2] * (1 << FBITS) + 0.5); + FFs_y_y = (long) floor(d2s[3] * (1 << FBITS) + 0.5); + FFs__x = (long) floor(d2s[4] * (1 << FBITS) + 0.5); + FFs__y = (long) floor(d2s[5] * (1 << FBITS) + 0.5); FFs_x_x_S = FFs_x_x >> xd; FFs_x_y_S = FFs_x_y >> xd; @@ -114,35 +121,40 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, sy = (FFsy + FF_sy_S[i]) >> FBITS; if ((sy >= 0) && (sy < sh)) { const unsigned char *s; - unsigned int ca; s = spx + sy * srs + sx * 4; - ca = NR_PREMUL_112 (s[3], alpha); - r += NR_PREMUL_121 (s[0], ca); - g += NR_PREMUL_121 (s[1], ca); - b += NR_PREMUL_121 (s[2], ca); - a += NR_NORMALIZE_21(ca); + r += NR_PREMUL_112 (s[0], s[3]); + g += NR_PREMUL_112 (s[1], s[3]); + b += NR_PREMUL_112 (s[2], s[3]); + a += s[3]; } } } - a >>= dbits; + a = (a*alpha + rounding_fix) >> dbits; + // Compare to nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P if (a != 0) { - r = r >> dbits; - g = g >> dbits; - b = b >> dbits; - if (a == 255) { - /* Transparent BG, premul src */ - d[0] = r; - d[1] = g; - d[2] = b; - d[3] = a; + r = (r + rounding_fix) >> dbits; + g = (g + rounding_fix) >> dbits; + b = (b + rounding_fix) >> dbits; + if (a == 255) { + /* Full coverage, demul src */ + d[0] = NR_NORMALIZE_21(r); + d[1] = NR_NORMALIZE_21(g); + d[2] = NR_NORMALIZE_21(b); + d[3] = NR_NORMALIZE_21(a); + } else if (d[3] == 0) { + /* Only foreground, demul src */ + d[0] = NR_DEMUL_221(r,a); + d[1] = NR_DEMUL_221(g,a); + d[2] = NR_DEMUL_221(b,a); + d[3] = NR_NORMALIZE_21(a); } else { unsigned int ca; /* Full composition */ - ca = NR_COMPOSEA_112(a, d[3]); - d[0] = NR_COMPOSENNN_111121 (r, a, d[0], d[3], ca); - d[1] = NR_COMPOSENNN_111121 (g, a, d[1], d[3], ca); - d[2] = NR_COMPOSENNN_111121 (b, a, d[2], d[3], ca); - d[3] = NR_NORMALIZE_21(ca); + ca = NR_COMPOSEA_213(a, d[3]); + d[0] = NR_COMPOSEPNN_221131 (r, a, d[0], d[3], ca); + d[1] = NR_COMPOSEPNN_221131 (g, a, d[1], d[3], ca); + d[2] = NR_COMPOSEPNN_221131 (b, a, d[2], d[3], ca); + d[3] = NR_NORMALIZE_31(ca); } } /* Advance pointers */ @@ -227,9 +239,7 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h int x, y; size = (1 << dbits); - unsigned alpha_rounding_fix = size * 255; - unsigned rgb_rounding_fix = size * (255 * 256); - if (alpha > 127) ++alpha; + unsigned int rounding_fix = size/2; d0 = px; FFsx0 = FFd2s[4]; @@ -252,32 +262,30 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h sy = (long (FFsy >> (FBITS_HP - FBITS)) + FF_S[2 * i + 1]) >> FBITS; if ((sy >= 0) && (sy < sh)) { const unsigned char *s; - unsigned int ca; s = spx + sy * srs + sx * 4; - ca = NR_PREMUL_112(s[3], alpha); - r += NR_PREMUL_123(s[0], ca); - g += NR_PREMUL_123(s[1], ca); - b += NR_PREMUL_123(s[2], ca); - a += ca; + r += NR_PREMUL_112(s[0], s[3]); + g += NR_PREMUL_112(s[1], s[3]); + b += NR_PREMUL_112(s[2], s[3]); + a += s[3]; } } } - a = (a + alpha_rounding_fix) >> (8 + dbits); + a = (a*alpha + rounding_fix) >> dbits; if (a != 0) { - r = (r + rgb_rounding_fix) >> (16 + dbits); - g = (g + rgb_rounding_fix) >> (16 + dbits); - b = (b + rgb_rounding_fix) >> (16 + dbits); + r = (r + rounding_fix) >> dbits; + g = (g + rounding_fix) >> dbits; + b = (b + rounding_fix) >> dbits; if ((a == 255) || (d[3] == 0)) { /* Transparent BG, premul src */ - d[0] = r; - d[1] = g; - d[2] = b; - d[3] = a; + d[0] = NR_NORMALIZE_21(r); + d[1] = NR_NORMALIZE_21(g); + d[2] = NR_NORMALIZE_21(b); + d[3] = NR_NORMALIZE_21(a); } else { - d[0] = NR_COMPOSEPPP_1111 (r, a, d[0]); - d[1] = NR_COMPOSEPPP_1111 (g, a, d[1]); - d[2] = NR_COMPOSEPPP_1111 (b, a, d[2]); - d[3] = NR_COMPOSEA_111(a, d[3]); + d[0] = NR_COMPOSEPPP_2211 (r, a, d[0]); + d[1] = NR_COMPOSEPPP_2211 (g, a, d[1]); + d[2] = NR_COMPOSEPPP_2211 (b, a, d[2]); + d[3] = NR_COMPOSEA_211(a, d[3]); } } /* Advance pointers */ @@ -302,11 +310,17 @@ void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, in if (alpha == 0) return; - dbits = xd + yd; + // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow + if (xd+yd>16) { + xd = 8; + yd = 8; + } + + dbits = xd + yd; for (i = 0; i < 6; i++) { - FFd2s[i] = (long) (d2s[i] * (1 << FBITS) + 0.5); - FFd2s_HP[i] = (long long) (d2s[i] * (1 << FBITS_HP) + 0.5);; + FFd2s[i] = (long) floor(d2s[i] * (1 << FBITS) + 0.5); + FFd2s_HP[i] = (long long) floor(d2s[i] * (1 << FBITS_HP) + 0.5);; } if (dbits == 0) { -- cgit v1.2.3 From 36eb7fb624e3a134c8cad002cc3906509cd2888b Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 18 Apr 2010 21:43:05 +0200 Subject: Fix bbox snapping as reported in LP bug #562205 Fixed bugs: - https://launchpad.net/bugs/562205 (bzr r9351) --- src/display/snap-indicator.cpp | 8 ++++++++ src/object-snapper.cpp | 4 ++-- src/seltrans.cpp | 20 ++------------------ src/snap-candidate.h | 1 + src/snap.cpp | 17 +++++++++++++++-- src/snapped-point.cpp | 9 +++++++++ 6 files changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 1e4ca12a8..fe5bd0371 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -55,6 +55,14 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap return; // If we haven't snapped, then it is of no use to draw a snapindicator } + if (p.getTarget() == SNAPTARGET_CONSTRAINT) { + // This is not a real snap, although moving along the constraint did affect the mouse pointer's position. + // Maybe we should only show a snap indicator when the user explicitly asked for a constraint by pressing ctrl? + // We should not show a snap indicator when stretching a selection box, which is also constrained. That would be + // too much information. + return; + } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool value = prefs->getBool("/options/snapindicator/value", true); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 7d79a5e91..a3285b406 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -151,8 +151,8 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, // This item is within snapping range, so record it as a candidate _candidates->push_back(SnapCandidateItem(item, clip_or_mask, additional_affine)); // For debugging: print the id of the candidate to the console - //SPObject *obj = (SPObject*)item; - //std::cout << "Snap candidate added: " << obj->id << std::endl; + // SPObject *obj = (SPObject*)item; + // std::cout << "Snap candidate added: " << obj->getId() << std::endl; } } } diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 7a08e0a7e..aef608420 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -999,8 +999,6 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state) m.setup(_desktop, false, _items_const); Inkscape::SnappedPoint bb, sn; - Geom::Coord bd(NR_HUGE); - Geom::Coord sd(NR_HUGE); if ((state & GDK_CONTROL_MASK) || _desktop->isToolboxButtonActive ("lock")) { // Scale is locked to a 1:1 aspect ratio, so that s[X] must be made to equal s[Y]. @@ -1017,27 +1015,17 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state) // Snap along a suitable constraint vector from the origin. bb = m.constrainedSnapScale(_bbox_points, _point, default_scale, _origin_for_bboxpoints); sn = m.constrainedSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints); - - /* Choose the smaller difference in scale. Since s[X] == s[Y] we can - ** just compare difference in s[X]. - */ - bd = bb.getSnapped() ? fabs(bb.getTransformation()[Geom::X] - default_scale[Geom::X]) : NR_HUGE; - sd = sn.getSnapped() ? fabs(sn.getTransformation()[Geom::X] - geom_scale[Geom::X]) : NR_HUGE; } else { /* Scale aspect ratio is unlocked */ bb = m.freeSnapScale(_bbox_points, _point, default_scale, _origin_for_bboxpoints); sn = m.freeSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints); - - /* Pick the snap that puts us closest to the original scale */ - bd = bb.getSnapped() ? fabs(Geom::L2(bb.getTransformation()) - Geom::L2(Geom::Point(default_scale[Geom::X], default_scale[Geom::Y]))) : NR_HUGE; - sd = sn.getSnapped() ? fabs(Geom::L2(sn.getTransformation()) - Geom::L2(Geom::Point(geom_scale[Geom::X], geom_scale[Geom::Y]))) : NR_HUGE; } if (!(bb.getSnapped() || sn.getSnapped())) { // We didn't snap at all! Don't update the handle position, just calculate the new transformation _calcAbsAffineDefault(default_scale); _desktop->snapindicator->remove_snaptarget(); - } else if (bd < sd) { + } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) { // We snapped the bbox (which is either visual or geometric) _desktop->snapindicator->set_new_snaptarget(bb); default_scale = Geom::Scale(bb.getTransformation()); @@ -1109,8 +1097,6 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom Inkscape::SnappedPoint bb, sn; g_assert(bb.getSnapped() == false); // Check initialization to catch any regression - Geom::Coord bd(NR_HUGE); - Geom::Coord sd(NR_HUGE); bool symmetrical = state & GDK_CONTROL_MASK; @@ -1119,12 +1105,10 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom if (bb.getSnapped()) { // We snapped the bbox (which is either visual or geometric) - bd = fabs(bb.getTransformation()[axis] - default_scale[axis]); default_scale[axis] = bb.getTransformation()[axis]; } if (sn.getSnapped()) { - sd = fabs(sn.getTransformation()[axis] - geom_scale[axis]); geom_scale[axis] = sn.getTransformation()[axis]; } @@ -1139,7 +1123,7 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom // We didn't snap at all! Don't update the handle position, just calculate the new transformation _calcAbsAffineDefault(default_scale); _desktop->snapindicator->remove_snaptarget(); - } else if (bd < sd) { + } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) { _desktop->snapindicator->set_new_snaptarget(bb); // Calculate the new transformation and update the handle position pt = _calcAbsAffineDefault(default_scale); diff --git a/src/snap-candidate.h b/src/snap-candidate.h index bd378bec8..a0fc3290c 100644 --- a/src/snap-candidate.h +++ b/src/snap-candidate.h @@ -55,6 +55,7 @@ public: inline Inkscape::SnapSourceType getSourceType() const {return _source_type;} inline Inkscape::SnapTargetType getTargetType() const {return _target_type;} inline long getSourceNum() const {return _source_num;} + void setSourceNum(long num) {_source_num = num;} inline Geom::OptRect const getTargetBBox() const {return _target_bbox;} private: diff --git a/src/snap.cpp b/src/snap.cpp index b8b08dad5..8704ce3bb 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -524,7 +524,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /* Quick check to see if we have any snappers that are enabled ** Also used to globally disable all snapping */ - if (someSnapperMightSnap() == false) { + if (someSnapperMightSnap() == false || points.size() == 0) { return Inkscape::SnappedPoint(pointer); } @@ -559,10 +559,11 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point g_assert(best_snapped_point.getAtIntersection() == false); - std::vector::const_iterator j = transformed_points.begin(); + std::vector::iterator j = transformed_points.begin(); // std::cout << std::endl; + bool first_free_snap = true; for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { /* Snap it */ @@ -599,6 +600,17 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); snapped_point = constrainedSnap(*j, dedicated_constraint, bbox); } else { + // If we have a collection of SnapCandidatePoints, with mixed constrained snapping and free snapping + // requirements, then freeSnap might never see the SnapCandidatePoint with source_num == 0. The freeSnap() + // method in the object snapper depends on this, because only for source-num == 0 the target nodes will + // be collected. Therefore we enforce that the first SnapCandidatePoint that is to be freeSnapped always + // has source_num == 0; + // TODO: This is a bit ugly so fix this; do we need sourcenum for anything else? if we don't then get rid + // of it and explicitely communicate to the object snapper that this is a first point + if (first_free_snap) { + (*j).setSourceNum(0); + first_free_snap = false; + } snapped_point = freeSnap(*j, bbox); } } @@ -902,6 +914,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Inkscape::SnapCandidatePoint co bool allowOffScreen) const { + /* std::cout << "Type and number of snapped constraints: " << std::endl; std::cout << " Points : " << sc.points.size() << std::endl; diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 089aa4323..508ec8f62 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -164,6 +164,15 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth } } + // When snapping to a constraint line only, which is not really a snap but merely a projection + // to the constraint line, then give this snap a very low priority. Basically, any other snap will do + if (other_one.getTarget() == SNAPTARGET_CONSTRAINT) { + dist_other += NR_HUGE/2; + } + if (getTarget() == SNAPTARGET_CONSTRAINT) { + dist_this += NR_HUGE/2; + } + // If it's closer bool c1 = dist_other < dist_this; // or, if it's for a snapper with "always snap" turned on, and the previous wasn't -- cgit v1.2.3 From 162a2b9f280921cf999c12d56f6d14496d3902c8 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 18 Apr 2010 14:58:20 -0700 Subject: Patch to fix return values. Fixes bug #530790. Fixed bugs: - https://launchpad.net/bugs/530790 (bzr r9352) --- src/libgdl/gdl-switcher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/libgdl/gdl-switcher.c b/src/libgdl/gdl-switcher.c index 28b9fe661..43768bbdf 100644 --- a/src/libgdl/gdl-switcher.c +++ b/src/libgdl/gdl-switcher.c @@ -521,7 +521,7 @@ gdl_switcher_expose (GtkWidget *widget, GdkEventExpose *event) button, event); } } - GDL_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS, expose_event, + return GDL_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS, expose_event, (widget, event), FALSE); } -- cgit v1.2.3 From af6571a3cd9ea98d92595c48e9a0d62d58d7c13b Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 19 Apr 2010 09:01:16 -0700 Subject: Added settor method for custom/non-model text (bzr r9354) --- src/ege-select-one-action.cpp | 27 ++++++++++++++++++++++++--- src/ege-select-one-action.h | 8 ++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index 587555c8b..bfbd3736a 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -324,6 +324,22 @@ gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action ) return str; } +void ege_select_one_action_set_active_text( EgeSelectOneAction* action, gchar const *text ) +{ + g_return_if_fail( IS_EGE_SELECT_ONE_ACTION(action) ); + + if (action->private_data->activeText) { + g_free( action->private_data->activeText ); + } + action->private_data->activeText = g_strdup(text); + + if (action->private_data->active != -1) { + g_object_set( G_OBJECT(action), "active", -1, NULL ); + } else { + resync_active( action, -1, TRUE ); + } +} + void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val ) { g_object_set( G_OBJECT(action), "active", val, NULL ); @@ -688,14 +704,16 @@ GtkWidget* create_tool_item( GtkAction* action ) gtk_container_add( GTK_CONTAINER(item), holder ); } else { GtkCellRenderer * renderer = 0; - GtkWidget* holder = gtk_hbox_new( FALSE, 4 ); - GtkWidget* normal = (act->private_data->selectionMode == SELECTION_OPEN) ? + GtkWidget *holder = gtk_hbox_new( FALSE, 4 ); + GtkEntry *entry = 0; + GtkWidget *normal = (act->private_data->selectionMode == SELECTION_OPEN) ? gtk_combo_box_entry_new_with_model( act->private_data->model, act->private_data->labelColumn ) : gtk_combo_box_new_with_model( act->private_data->model ); if ((act->private_data->selectionMode == SELECTION_OPEN)) { GtkWidget *child = gtk_bin_get_child( GTK_BIN(normal) ); if (GTK_IS_ENTRY(child)) { - gtk_entry_set_width_chars(GTK_ENTRY(child), 4); + entry = GTK_ENTRY(child); + gtk_entry_set_width_chars(entry, 4); g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(combo_entry_changed_cb), act ); g_signal_connect( G_OBJECT(child), "focus-out-event", G_CALLBACK(combo_entry_focus_lost_cb), act ); } @@ -714,6 +732,9 @@ GtkWidget* create_tool_item( GtkAction* action ) } gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active ); + if ( entry && (act->private_data->active == -1) ) { + gtk_entry_set_text( entry, act->private_data->activeText ); + } g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action ); diff --git a/src/ege-select-one-action.h b/src/ege-select-one-action.h index 16f924370..aa20d55a7 100644 --- a/src/ege-select-one-action.h +++ b/src/ege-select-one-action.h @@ -129,6 +129,14 @@ gint ege_select_one_action_get_active( EgeSelectOneAction* action ); */ gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action ); +/** + * Sets the text of the currently selected item. + * + * @param action The action to fetch the text for. + * @param text the text to set. + */ +void ege_select_one_action_set_active_text( EgeSelectOneAction* action, gchar const *text ); + /** * Sets the currently selected item. * -- cgit v1.2.3 From d48d6579e86f42fbd376dfe94ef36adae19d1154 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Mon, 19 Apr 2010 21:37:04 +0200 Subject: Extensions. JavaFX output fix by ycswyw. Fixed bugs: - https://launchpad.net/bugs/439270 (bzr r9355) --- src/extension/internal/javafx-out.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index ca061a63a..a4d348940 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -791,7 +791,8 @@ bool JavaFXOutput::doBody(SPDocument *doc, SPObject *obj) SPShape *shape = SP_SHAPE(item); SPCurve *curve = shape->curve; if (!curve->is_empty()) { - out(" %s(),\n", id.c_str()); + String jfxid = sanatize(id); + out(" %s(),\n", jfxid.c_str()); } } } -- cgit v1.2.3 From 0b2953e827e20137fbfbc602424adf238994a8e7 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 19 Apr 2010 23:31:36 -0700 Subject: Added completion entry for editable lists. (bzr r9356) --- src/ege-select-one-action.cpp | 46 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index bfbd3736a..9a5d22963 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -78,6 +78,8 @@ static GtkWidget* create_tool_item( GtkAction* action ); static void connect_proxy( GtkAction *action, GtkWidget *proxy ); static void disconnect_proxy( GtkAction *action, GtkWidget *proxy ); +static int scan_max_width( GtkTreeModel *model, gint labelColumn ); + static GtkActionClass* gParentClass = 0; static guint signals[LAST_SIGNAL] = {0}; static GQuark gDataName = 0; @@ -86,9 +88,9 @@ static GQuark gDataName = 0; enum { APPEARANCE_UNKNOWN = -1, APPEARANCE_NONE = 0, - APPEARANCE_FULL, // label, then all choices represented by separate buttons - APPEARANCE_COMPACT, // label, then choices in a drop-down menu - APPEARANCE_MINIMAL, // no label, just choices in a drop-down menu + APPEARANCE_FULL, /* label, then all choices represented by separate buttons */ + APPEARANCE_COMPACT, /* label, then choices in a drop-down menu */ + APPEARANCE_MINIMAL, /* no label, just choices in a drop-down menu */ }; enum { @@ -712,8 +714,20 @@ GtkWidget* create_tool_item( GtkAction* action ) if ((act->private_data->selectionMode == SELECTION_OPEN)) { GtkWidget *child = gtk_bin_get_child( GTK_BIN(normal) ); if (GTK_IS_ENTRY(child)) { + int maxUsed = scan_max_width( act->private_data->model, act->private_data->labelColumn ); + GtkEntryCompletion *complete = 0; entry = GTK_ENTRY(child); - gtk_entry_set_width_chars(entry, 4); + gtk_entry_set_width_chars(entry, maxUsed); /* replace with property */ + + complete = gtk_entry_completion_new(); + gtk_entry_completion_set_model( complete, act->private_data->model ); + gtk_entry_completion_set_text_column( complete, act->private_data->labelColumn ); + gtk_entry_completion_set_inline_completion( complete, FALSE ); + gtk_entry_completion_set_inline_selection( complete, FALSE ); + gtk_entry_completion_set_popup_completion( complete, TRUE ); + gtk_entry_completion_set_popup_set_width( complete, FALSE ); + gtk_entry_set_completion( entry, complete ); + g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(combo_entry_changed_cb), act ); g_signal_connect( G_OBJECT(child), "focus-out-event", G_CALLBACK(combo_entry_focus_lost_cb), act ); } @@ -722,7 +736,7 @@ GtkWidget* create_tool_item( GtkAction* action ) renderer = gtk_cell_renderer_pixbuf_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); - // "icon-name" + /* "icon-name" */ gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn ); } @@ -969,3 +983,25 @@ void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, g } } } + +int scan_max_width( GtkTreeModel *model, gint labelColumn ) +{ + int maxUsed = 0; + GtkTreeIter iter; + gboolean valid = gtk_tree_model_get_iter_first( model, &iter ); + while ( valid ) { + gchar* str = 0; + int count = 0; + gtk_tree_model_get( model, &iter, + labelColumn, &str, + -1 ); + count = strlen(str); + if (count > maxUsed) { + maxUsed = count; + } + g_free( str ); + + valid = gtk_tree_model_iter_next( model, &iter ); + } + return maxUsed; +} -- cgit v1.2.3 From 4a6cc1d59a19db2c1c18d67ed2cfcba17e28fb02 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 20 Apr 2010 00:24:42 -0700 Subject: Drop short limit on propery values. (bzr r9357) --- src/ege-select-one-action.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp index 9a5d22963..ebc7ea26d 100644 --- a/src/ege-select-one-action.cpp +++ b/src/ege-select-one-action.cpp @@ -186,7 +186,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "active", "Active Selection", "The index of the selected item", - -1, 20, 0, + -1, G_MAXINT, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, @@ -194,7 +194,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "label-column", "Display Column", "The column of the model that holds display strings", - 0, 20, 0, + 0, G_MAXINT, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, @@ -202,7 +202,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "icon-column", "Icon Column", "The column of the model that holds display icon name", - -1, 20, -1, + -1, G_MAXINT, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, @@ -210,7 +210,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "tooltip-column", "Tooltip Column", "The column of the model that holds tooltip strings", - -1, 20, -1, + -1, G_MAXINT, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, @@ -226,7 +226,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) g_param_spec_int( "icon-size", "Icon Size", "Target icon size", - -1, 20, -1, + -1, G_MAXINT, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, -- cgit v1.2.3 From f9866a8bb992bcf27be5db0edd132178a2089334 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Tue, 20 Apr 2010 14:13:56 +0200 Subject: Small fix for nr-compose-transform (I compared against 255 where I should have compared against 255*255). (bzr r9358) --- src/libnr/nr-compose-transform.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp index bc05c7b51..e7c286569 100644 --- a/src/libnr/nr-compose-transform.cpp +++ b/src/libnr/nr-compose-transform.cpp @@ -135,7 +135,7 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, r = (r + rounding_fix) >> dbits; g = (g + rounding_fix) >> dbits; b = (b + rounding_fix) >> dbits; - if (a == 255) { + if (a == 255*255) { /* Full coverage, demul src */ d[0] = NR_NORMALIZE_21(r); d[1] = NR_NORMALIZE_21(g); @@ -275,7 +275,7 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h r = (r + rounding_fix) >> dbits; g = (g + rounding_fix) >> dbits; b = (b + rounding_fix) >> dbits; - if ((a == 255) || (d[3] == 0)) { + if ((a == 255*255) || (d[3] == 0)) { /* Transparent BG, premul src */ d[0] = NR_NORMALIZE_21(r); d[1] = NR_NORMALIZE_21(g); -- cgit v1.2.3 From 74bd4815d7af73ed1595e3daf5c6fd40ea20336c Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 21 Apr 2010 23:40:54 +0200 Subject: Extensions. Fix Render>Grid extension (Bug #401567). Fixed bugs: - https://launchpad.net/bugs/401567 (bzr r9361) --- src/extension/internal/grid.cpp | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index d4b35b261..39bca52d8 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -46,25 +46,29 @@ Grid::load (Inkscape::Extension::Extension */*module*/) namespace { -Glib::ustring build_lines(int axis, Geom::Rect bounding_area, - float offset, float spacing) +Glib::ustring build_lines(Geom::Rect bounding_area, + float offset[], float spacing[]) { Geom::Point point_offset(0.0, 0.0); - point_offset[axis] = offset; SVG::PathString path_data; - for (Geom::Point start_point = bounding_area.min(); - start_point[axis] + offset <= (bounding_area.max())[axis]; - start_point[axis] += spacing) { - Geom::Point end_point = start_point; - end_point[1-axis] = (bounding_area.max())[1-axis]; - - path_data.moveTo(start_point + point_offset) - .lineTo(end_point + point_offset); - } - return path_data; -} + for ( int axis = 0 ; axis < 2 ; ++axis ) { + point_offset[axis] = offset[axis]; + + for (Geom::Point start_point = bounding_area.min(); + start_point[axis] + offset[axis] <= (bounding_area.max())[axis]; + start_point[axis] += spacing[axis]) { + Geom::Point end_point = start_point; + end_point[1-axis] = (bounding_area.max())[1-axis]; + + path_data.moveTo(start_point + point_offset) + .lineTo(end_point + point_offset); + } + } + // std::cout << "Path data:" << path_data.c_str() << std::endl; + return path_data; + } } @@ -104,11 +108,9 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc module->get_param_float("yoffset") }; Glib::ustring path_data(""); - for ( int axis = 0 ; axis < 2 ; ++axis ) { - path_data += build_lines(axis, bounding_area, - offsets[axis], spacings[axis]); - } + path_data = build_lines(bounding_area, + offsets, spacings); Inkscape::XML::Document * xml_doc = sp_document_repr_doc(document->doc()); Inkscape::XML::Node * current_layer = static_cast(document)->currentLayer()->repr; Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); -- cgit v1.2.3 From f5fe904a389f1ea866c783a03fdf70df466e055f Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 22 Apr 2010 22:42:03 +0200 Subject: Fix snapping regression introduced by rev. #9118 Fixed bugs: - https://launchpad.net/bugs/562205 (bzr r9364) --- src/display/curve.cpp | 13 +++++++++++-- src/display/curve.h | 2 +- src/object-snapper.cpp | 2 +- src/sp-image.cpp | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 1b54c981c..73b8dc36d 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -44,7 +44,7 @@ SPCurve::SPCurve(Geom::PathVector const& pathv) } SPCurve * -SPCurve::new_from_rect(Geom::Rect const &rect) +SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides) { SPCurve *c = new SPCurve(); @@ -54,7 +54,16 @@ SPCurve::new_from_rect(Geom::Rect const &rect) for (int i=3; i>=1; i--) { c->lineto(rect.corner(i)); } - c->closepath(); + + if (all_four_sides) { + // When _constrained_ snapping to a path, the 2geom::SimpleCrosser will be invoked which doesn't consider the closing segment. + // of a path. Consequently, in case we want to snap to for example the page border, we must provide all four sides of the + // rectangle explicitly + c->lineto(rect.corner(0)); + } else { + // ... instead of just three plus a closing segment + c->closepath(); + } return c; } diff --git a/src/display/curve.h b/src/display/curve.h index 79a385b09..fe0720195 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -27,7 +27,7 @@ public: /* Constructors */ explicit SPCurve(); explicit SPCurve(Geom::PathVector const& pathv); - static SPCurve * new_from_rect(Geom::Rect const &rect); + static SPCurve * new_from_rect(Geom::Rect const &rect, bool all_four_sides = false); virtual ~SPCurve(); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index a3285b406..77449ddc3 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -733,7 +733,7 @@ Geom::PathVector* Inkscape::ObjectSnapper::_getBorderPathv() const Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const rect) const { - SPCurve const *border_curve = SPCurve::new_from_rect(rect); + SPCurve const *border_curve = SPCurve::new_from_rect(rect, true); if (border_curve) { Geom::PathVector *dummy = new Geom::PathVector(border_curve->get_pathvector()); return dummy; diff --git a/src/sp-image.cpp b/src/sp-image.cpp index bb867e969..68bafdeab 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -1552,7 +1552,7 @@ sp_image_set_curve(SPImage *image) NRRect rect; sp_image_bbox(image, &rect, Geom::identity(), 0); Geom::Rect rect2 = to_2geom(*rect.upgrade()); - SPCurve *c = SPCurve::new_from_rect(rect2); + SPCurve *c = SPCurve::new_from_rect(rect2, true); if (image->curve) { image->curve = image->curve->unref(); -- cgit v1.2.3 From cc9182818c5ea40751c2db85af3b0346bdae7611 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 23 Apr 2010 12:59:44 +0200 Subject: Converted text toolbar to GTK toolbar. Moved Bold and Italics buttons to group font items together. Added items for line-height, word-spacing, and letter-spacing. Added ink-comboboxentry-action to wrap a GtkComboBoxEntry widget: Options: Pop-up completion menu. Use of external cell_data_func for formatting (e.g. font preview). Adjustable GtkEntry width. Display warning icon/tooltip if entry isn't in list. (bzr r9365) --- src/Makefile_insert | 2 + src/ink-comboboxentry-action.cpp | 605 +++++++++++++ src/ink-comboboxentry-action.h | 86 ++ src/widgets/toolbox.cpp | 1860 ++++++++++++++++++++------------------ 4 files changed, 1676 insertions(+), 877 deletions(-) create mode 100644 src/ink-comboboxentry-action.cpp create mode 100644 src/ink-comboboxentry-action.h (limited to 'src') diff --git a/src/Makefile_insert b/src/Makefile_insert index fbaca931e..36c9de34f 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -78,6 +78,8 @@ ink_common_sources += \ ige-mac-menu.h ige-mac-menu.c \ ink-action.cpp \ ink-action.h \ + ink-comboboxentry-action.cpp \ + ink-comboboxentry-action.h \ inkscape.cpp inkscape.h inkscape-private.h \ interface.cpp interface.h \ isinf.h \ diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp new file mode 100644 index 000000000..61d6bb9c4 --- /dev/null +++ b/src/ink-comboboxentry-action.cpp @@ -0,0 +1,605 @@ +/* + * A subclass of GtkAction that wraps a GtkComboBoxEntry. + * Features: + * Setting GtkEntryBox width in characters. + * Passing a function for formatting cells. + * Displaying a warning if text isn't in list. + * + * Author(s): + * Tavmjong Bah + * + * Copyright (C) 2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +/* + * We must provide for both a toolbar item and a menu item. + * As we don't know which widgets are used (or even constructed), + * we must keep track of things like active entry ourselves. + */ + +#include +#include + +#include +#include +#include +#include + +#include "ink-comboboxentry-action.h" + +// Must handle both tool and menu items! +static GtkWidget* create_tool_item( GtkAction* action ); +static GtkWidget* create_menu_item( GtkAction* action ); + +// Internal +static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, gchar* target_text ); + +// Callbacks +static void combo_box_changed_cb( GtkComboBoxEntry* widget, gpointer data ); +static void entry_activate_cb( GtkEntry* widget, gpointer data ); +static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data ); + +enum { + PROP_MODEL = 1, + PROP_COMBOBOX, + PROP_ENTRY, + PROP_WIDTH, + PROP_CELL_DATA_FUNC, + PROP_POPUP +}; + +enum { + CHANGED = 0, + ACTIVATED, + N_SIGNALS +}; +static guint signals[N_SIGNALS] = {0}; + +static GtkActionClass *ink_comboboxentry_action_parent_class = NULL; +static GQuark gDataName = 0; + +static void ink_comboboxentry_action_finalize (GObject *object) +{ + // Free any allocated resources. + + G_OBJECT_CLASS (ink_comboboxentry_action_parent_class)->finalize (object); +} + + +static void ink_comboboxentry_action_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION (object); + + switch(property_id) { + + case PROP_MODEL: + action->model = GTK_TREE_MODEL( g_value_get_object( value )); + break; + + case PROP_COMBOBOX: + action->combobox = GTK_COMBO_BOX_ENTRY( g_value_get_object( value )); + break; + + case PROP_ENTRY: + action->entry = GTK_ENTRY( g_value_get_object( value )); + break; + + case PROP_WIDTH: + action->width = g_value_get_int( value ); + break; + + case PROP_CELL_DATA_FUNC: + action->cell_data_func = g_value_get_pointer( value ); + break; + + case PROP_POPUP: + action->popup = g_value_get_boolean( value ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + + +static void ink_comboboxentry_action_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION (object); + + switch(property_id) { + + case PROP_MODEL: + g_value_set_object (value, action->model); + break; + + case PROP_COMBOBOX: + g_value_set_object (value, action->combobox); + break; + + case PROP_ENTRY: + g_value_set_object (value, action->entry); + break; + + case PROP_WIDTH: + g_value_set_int (value, action->width); + break; + + case PROP_CELL_DATA_FUNC: + g_value_set_pointer (value, action->cell_data_func); + break; + + case PROP_POPUP: + g_value_set_boolean (value, action->popup); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +ink_comboboxentry_action_connect_proxy (GtkAction *action, + GtkWidget *proxy) +{ + /* Override any proxy properties. */ + // if (GTK_IS_MENU_ITEM (proxy)) { + // } + + GTK_ACTION_CLASS (ink_comboboxentry_action_parent_class)->connect_proxy (action, proxy); +} + + +static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass) +{ + + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkActionClass *gtkaction_class = GTK_ACTION_CLASS (klass); + + gtkaction_class->connect_proxy = ink_comboboxentry_action_connect_proxy; + + gobject_class->finalize = ink_comboboxentry_action_finalize; + gobject_class->set_property = ink_comboboxentry_action_set_property; + gobject_class->get_property = ink_comboboxentry_action_get_property; + + gDataName = g_quark_from_string("ink_comboboxentry-action"); + + klass->parent_class.create_tool_item = create_tool_item; + klass->parent_class.create_menu_item = create_menu_item; + + ink_comboboxentry_action_parent_class = GTK_ACTION_CLASS(g_type_class_peek_parent (klass) ); + + g_object_class_install_property ( + gobject_class, + PROP_MODEL, + g_param_spec_object ("model", + "Tree Model", + "Tree Model", + GTK_TYPE_TREE_MODEL, + (GParamFlags)G_PARAM_READWRITE)); + g_object_class_install_property ( + gobject_class, + PROP_COMBOBOX, + g_param_spec_object ("combobox", + "GtkComboBoxEntry", + "GtkComboBoxEntry", + GTK_TYPE_WIDGET, + (GParamFlags)G_PARAM_READABLE)); + g_object_class_install_property ( + gobject_class, + PROP_ENTRY, + g_param_spec_object ("entry", + "GtkEntry", + "GtkEntry", + GTK_TYPE_WIDGET, + (GParamFlags)G_PARAM_READABLE)); + g_object_class_install_property ( + gobject_class, + PROP_WIDTH, + g_param_spec_int ("width", + "EntryBox width", + "EntryBox width (characters)", + -1.0, 100, -1.0, + (GParamFlags)G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, + PROP_CELL_DATA_FUNC, + g_param_spec_pointer ("cell_data_func", + "Cell Data Func", + "Cell Deta Function", + (GParamFlags)G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, + PROP_POPUP, + g_param_spec_boolean ("popup", + "Entry Popup", + "Entry Popup", + false, + (GParamFlags)G_PARAM_READWRITE)); + + // We need to know when GtkComboBoxEvent or Menu ready for reading + signals[CHANGED] = g_signal_new( "changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(Ink_ComboBoxEntry_ActionClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + // Probably not needed... originally to keep track of key-presses. + signals[ACTIVATED] = g_signal_new( "activated", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(Ink_ComboBoxEntry_ActionClass, activated), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + +static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action) +{ + action->active = -1; + action->text = NULL; + action->entry_completion = NULL; + action->popup = false; + action->warning = NULL; +} + +GType ink_comboboxentry_action_get_type () +{ + static GType ink_comboboxentry_action_type = 0; + + if (!ink_comboboxentry_action_type) { + static const GTypeInfo ink_comboboxentry_action_info = { + sizeof(Ink_ComboBoxEntry_ActionClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) ink_comboboxentry_action_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(Ink_ComboBoxEntry_Action), + 0, /* n_preallocs */ + (GInstanceInitFunc)ink_comboboxentry_action_init, /* instance_init */ + NULL /* value_table */ + }; + + ink_comboboxentry_action_type = g_type_register_static (GTK_TYPE_ACTION, + "Ink_ComboBoxEntry_Action", + &ink_comboboxentry_action_info, + (GTypeFlags)0 ); + } + + return ink_comboboxentry_action_type; +} + + +Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, + const gchar *label, + const gchar *tooltip, + const gchar *stock_id, + GtkTreeModel *model, + gint width, + void *cell_data_func ) +{ + g_return_val_if_fail (name != NULL, NULL); + + return (Ink_ComboBoxEntry_Action*)g_object_new (INK_COMBOBOXENTRY_TYPE_ACTION, + "name", name, + "label", label, + "tooltip", tooltip, + "stock-id", stock_id, + "model", model, + "width", width, + "cell_data_func", cell_data_func, + NULL); +} + +// Create a widget for a toolbar. +GtkWidget* create_tool_item( GtkAction* action ) +{ + GtkWidget* item = 0; + + if ( INK_COMBOBOXENTRY_IS_ACTION( action ) && INK_COMBOBOXENTRY_ACTION(action)->model ) { + + Ink_ComboBoxEntry_Action* ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( action ); + + item = GTK_WIDGET( gtk_tool_item_new() ); + + GtkWidget* comboBoxEntry = gtk_combo_box_entry_new_with_model( ink_comboboxentry_action->model, 0 ); + + gtk_container_add( GTK_CONTAINER(item), comboBoxEntry ); + + ink_comboboxentry_action->combobox = GTK_COMBO_BOX_ENTRY(comboBoxEntry); + + gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active ); + + g_signal_connect( G_OBJECT(comboBoxEntry), "changed", G_CALLBACK(combo_box_changed_cb), action ); + + // Optionally add formatting... + if( ink_comboboxentry_action->cell_data_func != NULL ) { + GtkCellRenderer *cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_clear( GTK_CELL_LAYOUT( comboBoxEntry ) ); + gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( comboBoxEntry ), cell, true ); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT( comboBoxEntry ), cell, + GtkCellLayoutDataFunc (ink_comboboxentry_action->cell_data_func), + NULL, NULL ); + } + + // Get reference to GtkEntry and fiddle a bit with it. + GtkWidget *child = gtk_bin_get_child( GTK_BIN(comboBoxEntry) ); + if( child && GTK_IS_ENTRY( child ) ) { + ink_comboboxentry_action->entry = GTK_ENTRY(child); + + // Change width + if( ink_comboboxentry_action->width > 0 ) { + gtk_entry_set_width_chars (GTK_ENTRY (child), ink_comboboxentry_action->width ); + } + + // Add pop-up entry completion if required + if( ink_comboboxentry_action->popup ) { + ink_comboboxentry_action_popup_enable( ink_comboboxentry_action ); + } + + // Add signal for GtkEntry to check if finished typing. + g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action ); + + } + + gtk_action_connect_proxy( GTK_ACTION( action ), item ); + + gtk_widget_show_all( item ); + + } else { + + item = ink_comboboxentry_action_parent_class->create_tool_item( action ); + + } + + return item; +} + +// Create a drop-down menu. +GtkWidget* create_menu_item( GtkAction* action ) +{ + GtkWidget* item = 0; + + item = ink_comboboxentry_action_parent_class->create_menu_item( action ); + g_warning( "ink_comboboxentry_action: create_menu_item not implemented" ); + // One can easily modify ege-select-one-action routine to implement this. + return item; +} + +// Setters/Getters --------------------------------------------------- + +GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action ) { + + return action->model; +} + +GtkComboBoxEntry *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action ) { + + return action->combobox; +} + +gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* action ) { + + gchar* text = g_strdup( action->text ); + return text; +} + +gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* ink_comboboxentry_action, gchar* text ) { + + g_free( ink_comboboxentry_action->text ); + ink_comboboxentry_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 ); + + // 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 ); + } + + // Fiddle with entry + if( ink_comboboxentry_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 ); + + // Show or hide warning + if( ink_comboboxentry_action->active == -1 && ink_comboboxentry_action->warning != NULL ) { + 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 + gtk_entry_set_icon_tooltip_text( ink_comboboxentry_action->entry, + GTK_ENTRY_ICON_SECONDARY, + ink_comboboxentry_action->warning ); + + } else { + gtk_entry_set_icon_from_icon_name( GTK_ENTRY(ink_comboboxentry_action->entry), + GTK_ENTRY_ICON_SECONDARY, + NULL ); + } + } + + // Return if active text in list + gboolean found = ( ink_comboboxentry_action->active != -1 ); + return found; +} + +void ink_comboboxentry_action_set_width( Ink_ComboBoxEntry_Action* action, gint width ) { + + action->width = width; + + // Widget may not have been created.... + if( action->entry ) { + gtk_entry_set_width_chars( GTK_ENTRY(action->entry), width ); + } +} + +void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action ) { + + action->popup = true; + + // Widget may not have been created.... + if( action->entry ) { + + // Check we don't already have a GtkEntryCompletion + if( action->entry_completion ) return; + + action->entry_completion = gtk_entry_completion_new(); + + gtk_entry_set_completion( action->entry, action->entry_completion ); + gtk_entry_completion_set_model( action->entry_completion, action->model ); + gtk_entry_completion_set_text_column( action->entry_completion, 0 ); + gtk_entry_completion_set_popup_completion( action->entry_completion, true ); + gtk_entry_completion_set_inline_completion( action->entry_completion, false ); + gtk_entry_completion_set_inline_selection( action->entry_completion, true ); + + g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action ); + + } +} + +void ink_comboboxentry_action_popup_disable( Ink_ComboBoxEntry_Action* action ) { + + action->popup = false; + + if( action->entry_completion ) { + gtk_object_destroy( GTK_OBJECT( action->entry_completion ) ); + } +} + +void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, gchar* warning ) { + + g_free( action->warning ); + action->warning = g_strdup( warning ); + + // Widget may not have been created.... + if( action->entry ) { + gtk_entry_set_icon_tooltip_text( GTK_ENTRY(action->entry), + GTK_ENTRY_ICON_SECONDARY, + action->warning ); + } +} + +// Internal --------------------------------------------------- + +// Return row of active text or -1 if not found. +gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, gchar* target_text ) { + + // Check if text in list + gint row = 0; + gboolean found = false; + GtkTreeIter iter; + gboolean valid = gtk_tree_model_get_iter_first( action->model, &iter ); + while ( valid ) { + + // Get text from list entry + gchar* text = 0; + gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0 + + // Check for match + if( strcmp( target_text, text ) == 0 ){ + found = true; + break; + } + ++row; + valid = gtk_tree_model_iter_next( action->model, &iter ); + } + + if( !found ) row = -1; + + return row; + +} + + +// Callbacks --------------------------------------------------- + +static void combo_box_changed_cb( GtkComboBoxEntry* widget, gpointer data ) { + + // Two things can happen to get here: + // An item is selected in the drop-down menu. + // Text is typed. + // We only react here if an item is selected. + + // Get action + Ink_ComboBoxEntry_Action *act = INK_COMBOBOXENTRY_ACTION( data ); + + // Check if item selected: + gint newActive = gtk_combo_box_get_active( GTK_COMBO_BOX( widget )); + if( newActive >= 0 ) { + + if( newActive != act->active ) { + act->active = newActive; + g_free( act->text ); + act->text = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget )); + + // Now let the world know + g_signal_emit( G_OBJECT(act), signals[CHANGED], 0 ); + + } + } +} + +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 ); + + // Get text + g_free( ink_comboboxentry_action->text ); + ink_comboboxentry_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 ); + + // Set active row + gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active ); + + // Now let the world know + g_signal_emit( G_OBJECT(ink_comboboxentry_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; + + if( entry) { + gchar *family = 0; + gtk_tree_model_get(model, iter, 0, &family, -1); + + // Set text in GtkEntry + gtk_entry_set_text (GTK_ENTRY (entry), family ); + + // Set text in GtkAction + g_free( ink_comboboxentry_action->text ); + ink_comboboxentry_action->text = family; + + // Get row + ink_comboboxentry_action->active = + get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text ); + + // Set active row + gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active ); + + // Now let the world know + g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 ); + + return true; + } + return false; +} + diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h new file mode 100644 index 000000000..433eb2fdc --- /dev/null +++ b/src/ink-comboboxentry-action.h @@ -0,0 +1,86 @@ +/* + * A subclass of GtkAction that wraps a GtkComboBoxEntry. + * Features: + * Setting GtkEntryBox width in characters. + * Passing a function for formatting cells. + * Displaying a warning if text isn't in list. + * + * Author(s): + * Tavmjong Bah + * + * Copyright (C) 2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_INK_COMBOBOXENTRY_ACTION +#define SEEN_INK_COMBOBOXENTRY_ACTION + +#include +#include + +#include +#include + + +#define INK_COMBOBOXENTRY_TYPE_ACTION (ink_comboboxentry_action_get_type()) +#define INK_COMBOBOXENTRY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_Action)) +#define INK_COMBOBOXENTRY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass)) +#define INK_COMBOBOXENTRY_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INK_COMBOBOXENTRY_TYPE_ACTION)) +#define INK_COMBOBOXENTRY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass)) + +typedef struct _Ink_ComboBoxEntry_ActionClass Ink_ComboBoxEntry_ActionClass; +typedef struct _Ink_ComboBoxEntry_Action Ink_ComboBoxEntry_Action; + +struct _Ink_ComboBoxEntry_ActionClass { + GtkActionClass parent_class; + + void (*changed) (Ink_ComboBoxEntry_Action* action); + void (*activated) (Ink_ComboBoxEntry_Action* action); +}; + +struct _Ink_ComboBoxEntry_Action { + GtkAction parent_instance; + + GtkTreeModel *model; + GtkComboBoxEntry *combobox; + GtkEntry *entry; + GtkEntryCompletion *entry_completion; + + gpointer cell_data_func; // drop-down menu format + + gint active; // Index of active menu item (-1 if not in list). + gchar *text; // Text of active menu item or entry box. + gint width; // Width of GtkComboBoxEntry in characters. + gboolean popup; // Do we pop-up an entry-completion dialog? + gchar *warning; // Text for warning that entry isn't in list. +}; + + +GType ink_comboboxentry_action_get_type (void); + +/** + * Creates a GtkAction subclass that wraps a GtkComboBoxEntry object. + */ +Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new ( const gchar *name, + const gchar *label, + const gchar *tooltip, + const gchar *stock_id, + GtkTreeModel *model, + gint width = -1, + gpointer cell_data_func = NULL ); + +GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action ); +GtkComboBoxEntry *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, gchar* text ); + +void ink_comboboxentry_action_set_width( Ink_ComboBoxEntry_Action* action, gint width ); + +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, gchar* warning ); + +#endif /* SEEN_INK_COMBOBOXENTRY_ACTION */ diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 96695ac20..66f77a18d 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -12,10 +12,11 @@ * Josh Andler * Jon A. Cruz * Maximilian Albert + * Tavmjong Bah * * Copyright (C) 2004 David Turner * Copyright (C) 2003 MenTaLguY - * Copyright (C) 1999-2008 authors + * Copyright (C) 1999-2010 authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -56,6 +57,7 @@ #include "../helper/unit-tracker.h" #include "icon.h" #include "../ink-action.h" +#include "../ink-comboboxentry-action.h" #include "../inkscape.h" #include "../interface.h" #include "../libnrtype/font-instance.h" @@ -105,6 +107,7 @@ #include "toolbox.h" #define ENABLE_TASK_SUPPORT 1 +//#define DEBUG_TEXT using Inkscape::UnitTracker; using Inkscape::UI::UXManager; @@ -139,11 +142,9 @@ static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop); static void sp_connector_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder); static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder); static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder); +static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder); static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder); -namespace { GtkWidget *sp_text_toolbox_new (SPDesktop *desktop); } - - #if ENABLE_TASK_SUPPORT static void fireTaskChange( EgeSelectOneAction *act, SPDesktop *dt ) { @@ -235,7 +236,7 @@ static struct { SP_VERB_CONTEXT_ERASER_PREFS, "/tools/eraser", _("TBD")}, { "SPLPEToolContext", "lpetool_toolbox", 0, sp_lpetool_toolbox_prep, "LPEToolToolbar", SP_VERB_CONTEXT_LPETOOL_PREFS, "/tools/lpetool", _("TBD")}, - { "SPTextContext", "text_toolbox", sp_text_toolbox_new, 0, 0, + { "SPTextContext", "text_toolbox", 0, sp_text_toolbox_prep, "TextToolbar", SP_VERB_INVALID, 0, 0}, { "SPDropperContext", "dropper_toolbox", 0, sp_dropper_toolbox_prep, "DropperToolbar", SP_VERB_INVALID, 0, 0}, @@ -478,6 +479,21 @@ static gchar const * ui_descr = " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " " " @@ -6161,257 +6177,109 @@ static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio //######################## //## Text Toolbox ## //######################## -/* -static void sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl) -{ - //Call back for letter sizing spinbutton -} -static void sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl) -{ - //Call back for line height spinbutton -} +// Functions for debugging: +#ifdef DEBUG_TEXT -static void sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) -{ - //Call back for horizontal kerning spinbutton -} +static void sp_print_font( SPStyle *query ) { -static void sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl) -{ - //Call back for vertical kerning spinbutton -} + bool family_set = query->text->font_family.set; + bool style_set = query->font_style.set; + bool fontspec_set = query->text->font_specification.set; -static void sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl) -{ - //Call back for letter rotation spinbutton -}*/ + std::cout << " Family set? " << family_set + << " Style set? " << style_set + << " FontSpec set? " << fontspec_set + << std::endl; + std::cout << " Family: " + << (query->text->font_family.value ? query->text->font_family.value : "No value") + << " Style: " << query->font_style.computed + << " Weight: " << query->font_weight.computed + << " FontSpec: " + << (query->text->font_specification.value ? query->text->font_specification.value : "No value") + << std::endl; +} + +static void sp_print_fontweight( SPStyle *query ) { + const gchar* names[] = {"100", "200", "300", "400", "500", "600", "700", "800", "900", + "NORMAL", "BOLD", "LIGHTER", "BOLDER", "Out of range"}; + // Missing book = 380 + int index = query->font_weight.computed; + if( index < 0 || index > 13 ) index = 13; + std::cout << " Weight: " << names[ index ] + << " (" << query->font_weight.computed << ")" << std::endl; -namespace { +} -/* - * This function sets up the text-tool tool-controls, setting the entry boxes - * etc. to the values from the current selection or the default if no selection. - * It is called whenever a text selection is changed, including stepping cursor - * through text. - */ -static void sp_text_toolbox_selection_changed(Inkscape::Selection * /*selection*/, GObject *tbl) -{ - // quit if run by the _changed callbacks - if (g_object_get_data(G_OBJECT(tbl), "freeze")) { - return; - } +static void sp_print_fontstyle( SPStyle *query ) { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + const gchar* names[] = {"NORMAL", "ITALIC", "OBLIQUE", "Out of range"}; + int index = query->font_style.computed; + if( index < 0 || index > 3 ) index = 3; + std::cout << " Style: " << names[ index ] << std::endl; - gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image"))); +} +#endif - /* - * Query from current selection: - * Font family (font-family) - * Style (font-weight, font-style, font-stretch, font-variant, font-align) - * Numbers (font-size, letter-spacing, word-spacing, line-height, text-anchor, writing-mode) - * Font specification (Inkscape private attribute) - */ - SPStyle *query = - sp_style_new (SP_ACTIVE_DOCUMENT); +// Format family drop-down menu. +static void cell_data_func(GtkCellLayout * /*cell_layout*/, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer /*data*/) +{ + gchar *family; + gtk_tree_model_get(tree_model, iter, 0, &family, -1); + gchar *const family_escaped = g_markup_escape_text(family, -1); - int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); - int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); - int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); - // Used later: - int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1); + if (show_sample) { - /* - * If no text in selection (querying returned nothing), read the style from - * the /tools/text preferencess (default style for new texts). Return if - * tool bar already set to these preferences. - */ - if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) { - // There are no texts in selection, read from preferences. + Glib::ustring sample = prefs->getString("/tools/text/font_sample"); + gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1); - sp_style_read_from_prefs(query, "/tools/text"); + std::stringstream markup; + markup << family_escaped << " " << sample_escaped << ""; + g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL); - if (g_object_get_data(tbl, "text_style_from_prefs")) { - // Do not reset the toolbar style from prefs if we already did it last time. - sp_style_unref(query); - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - return; - } - g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE)); + g_free(sample_escaped); } else { - g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE)); - } - - /* - * If we have valid query data for text (font-family, font-specification) set toolbar accordingly. - */ - if (query->text) - { - if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) { - - // Don't set a font family if multiple styles are selected. - GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry")); - gtk_entry_set_text (GTK_ENTRY (entry), ""); - - } else if (query->text->font_specification.value || query->text->font_family.value) { - - // At the moment (April 2010), font-specification isn't set unless actually - // set on current tspan (parent look up is disabled). - Gtk::ComboBoxEntry *combo = (Gtk::ComboBoxEntry *) (g_object_get_data (G_OBJECT (tbl), "family-entry-combo")); - GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry")); - - // Get the font that corresponds - Glib::ustring familyName; - - // This tries to use font-specification first and then font-family. - font_instance * font = font_factory::Default()->FaceFromStyle(query); - if (font) { - familyName = font_factory::Default()->GetUIFamilyString(font->descr); - font->Unref(); - font = NULL; - } - - gtk_entry_set_text (GTK_ENTRY (entry), familyName.c_str()); - - Gtk::TreeIter iter; - try { - Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (familyName); - Glib::RefPtr model = combo->get_model(); - iter = model->get_iter(path); - } catch (...) { - g_warning("Family name %s does not have an entry in the font lister.", familyName.c_str()); - sp_style_unref(query); - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - return; - } - - combo->set_active (iter); - } - - //Size (average of text selected) - { - GtkWidget *cbox = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "combo-box-size")); - gchar *const str = g_strdup_printf("%.5g", query->font_size.computed); - gtk_entry_set_text(GTK_ENTRY(GTK_BIN(cbox)->child), str); - g_free(str); - } - - //Anchor - if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY) - { - GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-fill")); - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } else { - if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) - { - GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start")); - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) { - GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle")); - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) { - GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end")); - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - } - - //Style - { - GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-bold")); - - gboolean active = gtk_toggle_button_get_active (button); - gboolean check = ((query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700) && (query->font_weight.computed != SP_CSS_FONT_WEIGHT_NORMAL) && (query->font_weight.computed != SP_CSS_FONT_WEIGHT_LIGHTER)); - - if (active != check) - { - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - } - - { - GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-italic")); - - gboolean active = gtk_toggle_button_get_active (button); - gboolean check = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL); - - if (active != check) - { - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } - } - - //Orientation - //locking both buttons, changing one affect all group (both) - GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-horizontal")); - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - - GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical")); - g_object_set_data (G_OBJECT (button1), "block", gpointer(1)); - - if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - } else { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE); - } - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - g_object_set_data (G_OBJECT (button1), "block", gpointer(0)); + g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL); } - sp_style_unref(query); - - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); -} - -static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) -{ - sp_text_toolbox_selection_changed (selection, tbl); + g_free(family); + g_free(family_escaped); } -static void sp_text_toolbox_subselection_changed(gpointer /*tc*/, GObject *tbl) +// Font family +static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl ) { - sp_text_toolbox_selection_changed (NULL, tbl); -} +#ifdef DEBUG_TEXT + std::cout << std::endl; + std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl; + std::cout << "sp_text_fontfamily_value_changed: " << std::endl; +#endif -static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, - GObject *tbl) -{ - // quit if run by the _changed callbacks + // 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) ); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry")); - const gchar* family = gtk_entry_get_text (GTK_ENTRY (entry)); - - //g_print ("family changed to: %s\n", family); - - SPStyle *query = - sp_style_new (SP_ACTIVE_DOCUMENT); - - int result_fontspec = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); + gchar *family = ink_comboboxentry_action_get_active_text( act ); +#ifdef DEBUG_TEXT + std::cout << " New family: " << family << std::endl; +#endif - SPCSSAttr *css = sp_repr_css_attr_new (); + // 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); - // First try to get the font spec from the stored value Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : ""; + // 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 @@ -6421,14 +6289,44 @@ static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, // Construct a new font specification if it does not yet exist font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query); - fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); - fontFromStyle->Unref(); + if( fontFromStyle ) { + fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); + fontFromStyle->Unref(); + } +#ifdef DEBUG_TEXT + std::cout << " Fontspec not defined, reconstructed from style :" << fontSpec << ":" << std::endl; + sp_print_font( query ); +#endif + } + + // And if that didn't work use default + if( fontSpec.empty() ) { + sp_style_read_from_prefs(query, "/tools/text"); +#ifdef DEBUG_TEXT + std::cout << " read style from prefs:" << std::endl; + sp_print_font( query ); +#endif + // 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 not defined, reconstructed from style :" << fontSpec << ":" << std::endl; + sp_print_font( query ); +#endif } + SPCSSAttr *css = sp_repr_css_attr_new (); if (!fontSpec.empty()) { - // Now we have existing font specification, replace family. - Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family); + // Now we have a font specification, replace family. + Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family); + +#ifdef DEBUG_TEXT + std::cout << " New FontSpec from ReplaceFontSpecificationFamily :" << newFontSpec << ":" << std::endl; +#endif if (!newFontSpec.empty()) { @@ -6465,230 +6363,157 @@ static void sp_text_toolbox_family_changed(GtkComboBoxEntry *, } } else { - // If the old font on selection (or default) was not existing on the system, + + // newFontSpec empty + // If the old font on selection (or default) does not exist on the system, + // or the new font family does not exist, // ReplaceFontSpecificationFamily does not work. In that case we fall back to blindly // setting the family reported by the family chooser. - //g_print ("fallback setting family: %s\n", family); + // g_print ("fallback setting family: %s\n", family); sp_repr_css_set_property (css, "-inkscape-font-specification", family); sp_repr_css_set_property (css, "font-family", family); + // Shoud we set other css font attributes? } - } - // If querying returned nothing, set the default style of the tool (for new texts) - if (result_fontspec == QUERY_STYLE_NOTHING) { + } // fontSpec not empty or not + + // 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 trough a verb - } else { - sp_desktop_set_style (desktop, css, true, true); + sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace through a verb + } + else + { + sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true); } sp_style_unref(query); + g_free (family); + + // Save for undo sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change font family")); sp_repr_css_attr_unref (css); - gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image"))); - // unfreeze g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); // focus to canvas - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); -} + 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; + std::cout << std::endl; +#endif +} -static void sp_text_toolbox_anchoring_toggled(GtkRadioButton *button, - gpointer data) +// Font size +static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl ) { - if (g_object_get_data (G_OBJECT (button), "block")) { + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { return; } - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + + gchar *text = ink_comboboxentry_action_get_active_text( act ); + gchar *endptr; + gdouble size = g_strtod( text, &endptr ); + if (endptr == text) { // Conversion failed, non-numeric input. + g_warning( "Conversion of size text to double failed, input: %s\n", text ); + g_free( text ); return; } - int prop = GPOINTER_TO_INT(data); + g_free( text ); + + // Set css font size. + SPCSSAttr *css = sp_repr_css_attr_new (); + Inkscape::CSSOStringStream osfs; + osfs << size << "px"; // For now always use px + sp_repr_css_set_property (css, "font-size", osfs.str().c_str()); + // Apply font size to selected objects. SPDesktop *desktop = SP_ACTIVE_DESKTOP; + sp_desktop_set_style (desktop, css, true, true); - // move the x of all texts to preserve the same bbox - Inkscape::Selection *selection = sp_desktop_selection(desktop); - for (GSList const *items = selection->itemList(); items != NULL; items = items->next) { - if (SP_IS_TEXT((SPItem *) items->data)) { - SPItem *item = SP_ITEM(items->data); + // Save for undo + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE, + _("Text: Change font size")); - unsigned writing_mode = SP_OBJECT_STYLE(item)->writing_mode.value; - // below, variable names suggest horizontal move, but we check the writing direction - // and move in the corresponding axis - int axis; - if (writing_mode == SP_CSS_WRITING_MODE_LR_TB || writing_mode == SP_CSS_WRITING_MODE_RL_TB) { - axis = NR::X; - } else { - axis = NR::Y; - } + // If no selected objects, set default. + SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); + int result_numbers = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + if (result_numbers == QUERY_STYLE_NOTHING) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->mergeStyle("/tools/text/style", css); + } + sp_style_unref(query); - Geom::OptRect bbox - = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); - if (!bbox) { - continue; - } - double width = bbox->dimensions()[axis]; - // If you want to align within some frame, other than the text's own bbox, calculate - // the left and right (or top and bottom for tb text) slacks of the text inside that - // frame (currently unused) - double left_slack = 0; - double right_slack = 0; - unsigned old_align = SP_OBJECT_STYLE(item)->text_align.value; - double move = 0; - if (old_align == SP_CSS_TEXT_ALIGN_START || old_align == SP_CSS_TEXT_ALIGN_LEFT) { - switch (prop) { - case 0: - move = -left_slack; - break; - case 1: - move = width/2 + (right_slack - left_slack)/2; - break; - case 2: - move = width + right_slack; - break; - } - } else if (old_align == SP_CSS_TEXT_ALIGN_CENTER) { - switch (prop) { - case 0: - move = -width/2 - left_slack; - break; - case 1: - move = (right_slack - left_slack)/2; - break; - case 2: - move = width/2 + right_slack; - break; - } - } else if (old_align == SP_CSS_TEXT_ALIGN_END || old_align == SP_CSS_TEXT_ALIGN_RIGHT) { - switch (prop) { - case 0: - move = -width - left_slack; - break; - case 1: - move = -width/2 + (right_slack - left_slack)/2; - break; - case 2: - move = right_slack; - break; - } - } - Geom::Point XY = SP_TEXT(item)->attributes.firstXY(); - if (axis == NR::X) { - XY = XY + Geom::Point (move, 0); - } else { - XY = XY + Geom::Point (0, move); - } - SP_TEXT(item)->attributes.setFirstXY(XY); - SP_OBJECT(item)->updateRepr(); - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - } - } - - SPCSSAttr *css = sp_repr_css_attr_new (); - switch (prop) - { - case 0: - { - sp_repr_css_set_property (css, "text-anchor", "start"); - sp_repr_css_set_property (css, "text-align", "start"); - break; - } - case 1: - { - sp_repr_css_set_property (css, "text-anchor", "middle"); - sp_repr_css_set_property (css, "text-align", "center"); - break; - } - - case 2: - { - sp_repr_css_set_property (css, "text-anchor", "end"); - sp_repr_css_set_property (css, "text-align", "end"); - break; - } - - case 3: - { - sp_repr_css_set_property (css, "text-anchor", "start"); - sp_repr_css_set_property (css, "text-align", "justify"); - break; - } - } - - SPStyle *query = - sp_style_new (SP_ACTIVE_DOCUMENT); - int result_numbers = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); - - // If querying returned nothing, read the style from the text tool prefs (default style for new texts) - if (result_numbers == QUERY_STYLE_NOTHING) - { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->mergeStyle("/tools/text/style", css); - } - - sp_style_unref(query); - - sp_desktop_set_style (desktop, css, true, true); - sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, - _("Text: Change alignment")); sp_repr_css_attr_unref (css); - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void sp_text_toolbox_style_toggled(GtkToggleButton *button, - gpointer data) +// Handles both Bold and Italic/Oblique +static void sp_text_style_changed( InkToggleAction* act, GObject *tbl ) { - if (g_object_get_data (G_OBJECT (button), "block")) { + // 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) ); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPCSSAttr *css = sp_repr_css_attr_new (); - int prop = GPOINTER_TO_INT(data); - bool active = gtk_toggle_button_get_active (button); - - SPStyle *query = - sp_style_new (SP_ACTIVE_DOCUMENT); + // Called by Bold or Italics button? + const gchar* name = gtk_action_get_name( GTK_ACTION( act ) ); + gint prop = (strcmp(name, "TextBoldAction") == 0) ? 0 : 1; + // 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); // font_specification will not be set unless defined explicitely on a tspan. - // This needs to be fixed. + // This should be fixed! Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : ""; - Glib::ustring newFontSpec = ""; if (fontSpec.empty()) { - - // Must query all to fill font-family, font-style, font-weight, font-specification + // 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); - // Construct a new font specification if it does not yet exist font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query); - fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); - fontFromStyle->Unref(); + if( fontFromStyle ) { + fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle); + fontFromStyle->Unref(); + } } - bool nochange = true; + // Now that we have the old face, find the new face. + Glib::ustring newFontSpec = ""; + SPCSSAttr *css = sp_repr_css_attr_new (); + gboolean nochange = true; + gboolean active = gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(act) ); + switch (prop) { case 0: { // Bold if (!fontSpec.empty()) { + newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active); + if (!newFontSpec.empty()) { + // Set weight if we found font. font_instance * font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str()); if (font) { gchar c[256]; @@ -6696,22 +6521,19 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, sp_repr_css_set_property (css, "font-weight", c); font->Unref(); font = NULL; - nochange = false; } + nochange = false; } } - // set or reset the button according + // Reset button if no change. + // The reset code didn't work in 0.47 and doesn't here... one must prevent an infinite loop + /* if(nochange) { - gboolean check = gtk_toggle_button_get_active (button); - - if (active != check) - { - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } + gtk_action_block_activate( GTK_ACTION(act) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active ); + gtk_action_unblock_activate( GTK_ACTION(act) ); } - + */ break; } @@ -6719,8 +6541,11 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, { // Italic/Oblique if (!fontSpec.empty()) { + newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active); + if (!newFontSpec.empty()) { + // Don't even set the italic/oblique if the font didn't exist on the system if( active ) { if( newFontSpec.find( "Italic" ) != Glib::ustring::npos ) { @@ -6734,16 +6559,15 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, nochange = false; } } + // Reset button if no change. + // The reset code didn't work in 0.47... one must prevent an infinite loop + /* if(nochange) { - gboolean check = gtk_toggle_button_get_active (button); - - if (active != check) - { - g_object_set_data (G_OBJECT (button), "block", gpointer(1)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active); - g_object_set_data (G_OBJECT (button), "block", gpointer(0)); - } + gtk_action_block_activate( GTK_ACTION(act) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active ); + gtk_action_unblock_activate( GTK_ACTION(act) ); } + */ break; } } @@ -6752,7 +6576,7 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str()); } - // If querying returned nothing, read the style from the text tool prefs (default style for new texts) + // If querying returned nothing, update default style. if (result_fontspec == QUERY_STYLE_NOTHING) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -6761,36 +6585,135 @@ static void sp_text_toolbox_style_toggled(GtkToggleButton *button, 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); sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change font style")); sp_repr_css_attr_unref (css); - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static void sp_text_toolbox_orientation_toggled(GtkRadioButton *button, - gpointer data) +static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) { - if (g_object_get_data (G_OBJECT (button), "block")) { + // 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) ); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPCSSAttr *css = sp_repr_css_attr_new (); - int prop = GPOINTER_TO_INT(data); + int mode = ege_select_one_action_get_active( act ); - switch (prop) + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/tools/text/align_mode", mode); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + + // move the x of all texts to preserve the same bbox + Inkscape::Selection *selection = sp_desktop_selection(desktop); + for (GSList const *items = selection->itemList(); items != NULL; items = items->next) { + if (SP_IS_TEXT((SPItem *) items->data)) { + SPItem *item = SP_ITEM(items->data); + + unsigned writing_mode = SP_OBJECT_STYLE(item)->writing_mode.value; + // below, variable names suggest horizontal move, but we check the writing direction + // and move in the corresponding axis + int axis; + if (writing_mode == SP_CSS_WRITING_MODE_LR_TB || writing_mode == SP_CSS_WRITING_MODE_RL_TB) { + axis = NR::X; + } else { + axis = NR::Y; + } + + Geom::OptRect bbox + = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); + if (!bbox) + continue; + double width = bbox->dimensions()[axis]; + // If you want to align within some frame, other than the text's own bbox, calculate + // the left and right (or top and bottom for tb text) slacks of the text inside that + // frame (currently unused) + double left_slack = 0; + double right_slack = 0; + unsigned old_align = SP_OBJECT_STYLE(item)->text_align.value; + double move = 0; + if (old_align == SP_CSS_TEXT_ALIGN_START || old_align == SP_CSS_TEXT_ALIGN_LEFT) { + switch (mode) { + case 0: + move = -left_slack; + break; + case 1: + move = width/2 + (right_slack - left_slack)/2; + break; + case 2: + move = width + right_slack; + break; + } + } else if (old_align == SP_CSS_TEXT_ALIGN_CENTER) { + switch (mode) { + case 0: + move = -width/2 - left_slack; + break; + case 1: + move = (right_slack - left_slack)/2; + break; + case 2: + move = width/2 + right_slack; + break; + } + } else if (old_align == SP_CSS_TEXT_ALIGN_END || old_align == SP_CSS_TEXT_ALIGN_RIGHT) { + switch (mode) { + case 0: + move = -width - left_slack; + break; + case 1: + move = -width/2 + (right_slack - left_slack)/2; + break; + case 2: + move = right_slack; + break; + } + } + Geom::Point XY = SP_TEXT(item)->attributes.firstXY(); + if (axis == NR::X) { + XY = XY + Geom::Point (move, 0); + } else { + XY = XY + Geom::Point (0, move); + } + SP_TEXT(item)->attributes.setFirstXY(XY); + SP_OBJECT(item)->updateRepr(); + SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + } + } + + SPCSSAttr *css = sp_repr_css_attr_new (); + switch (mode) { case 0: { - sp_repr_css_set_property (css, "writing-mode", "lr"); + sp_repr_css_set_property (css, "text-anchor", "start"); + sp_repr_css_set_property (css, "text-align", "start"); break; } - case 1: { - sp_repr_css_set_property (css, "writing-mode", "tb"); + sp_repr_css_set_property (css, "text-anchor", "middle"); + sp_repr_css_set_property (css, "text-align", "center"); + break; + } + + case 2: + { + sp_repr_css_set_property (css, "text-anchor", "end"); + sp_repr_css_set_property (css, "text-align", "end"); + break; + } + + case 3: + { + sp_repr_css_set_property (css, "text-anchor", "start"); + sp_repr_css_set_property (css, "text-align", "justify"); break; } } @@ -6800,549 +6723,732 @@ static void sp_text_toolbox_orientation_toggled(GtkRadioButton *button, int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); - // If querying returned nothing, read the style from the text tool prefs (default style for new texts) + // If querying returned nothing, update default style. if (result_numbers == QUERY_STYLE_NOTHING) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->mergeStyle("/tools/text/style", css); } + sp_style_unref(query); + sp_desktop_set_style (desktop, css, true, true); sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, - _("Text: Change orientation")); + _("Text: Change alignment")); sp_repr_css_attr_unref (css); gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); -} - -static gboolean sp_text_toolbox_family_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject *tbl) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { - return FALSE; - } - - switch (get_group0_keyval (event)) { - case GDK_KP_Enter: // chosen - case GDK_Return: - // unfreeze and update, which will defocus - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - sp_text_toolbox_family_changed (NULL, tbl); - return TRUE; // I consumed the event - break; - case GDK_Escape: - // defocus - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - return TRUE; // I consumed the event - break; - } - return FALSE; -} - -static gboolean sp_text_toolbox_family_list_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject * /*tbl*/) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { - return FALSE; - } - switch (get_group0_keyval (event)) { - case GDK_KP_Enter: - case GDK_Return: - case GDK_Escape: // defocus - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - return TRUE; // I consumed the event - break; - case GDK_w: - case GDK_W: - if (event->state & GDK_CONTROL_MASK) { - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - return TRUE; // I consumed the event - } - break; - } - return FALSE; + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } - -static void sp_text_toolbox_size_changed(GtkComboBox *cbox, - GObject *tbl) +static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) { - // quit if run by the _changed callbacks + // 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) ); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - - // If this is not from selecting a size in the list (in which case get_active will give the - // index of the selected item, otherwise -1) and not from user pressing Enter/Return, do not - // process this event. This fixes GTK's stupid insistence on sending an activate change every - // time any character gets typed or deleted, which made this control nearly unusable in 0.45. - if (gtk_combo_box_get_active (cbox) < 0 && !g_object_get_data (tbl, "enter-pressed")) { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - return; - } - - gdouble value = -1; - { - gchar *endptr; - gchar *const text = gtk_combo_box_get_active_text(cbox); - if (text) { - value = g_strtod(text, &endptr); - if (endptr == text) { // Conversion failed, non-numeric input. - value = -1; - } - g_free(text); - } - } - if (value <= 0) { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - return; // could not parse value - } - + // At the moment this handles only numerical values (i.e. no percent). + // Set css line height. SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream osfs; - osfs << value; - sp_repr_css_set_property (css, "font-size", osfs.str().c_str()); + osfs << adj->value*100 << "%"; + sp_repr_css_set_property (css, "line-height", osfs.str().c_str()); - SPStyle *query = - sp_style_new (SP_ACTIVE_DOCUMENT); + // Apply line-height to selected objects. + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + sp_desktop_set_style (desktop, css, true, true); + + // Save for undo + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:line-height", SP_VERB_NONE, + _("Text: Change line-height")); + + // If no selected objects, set default. + SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); - - // If querying returned nothing, read the style from the text tool prefs (default style for new texts) if (result_numbers == QUERY_STYLE_NOTHING) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->mergeStyle("/tools/text/style", css); } - sp_style_unref(query); - sp_desktop_set_style (desktop, css, true, true); - sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE, - _("Text: Change font size")); sp_repr_css_attr_unref (css); - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -static gboolean sp_text_toolbox_size_focusout(GtkWidget * /*w*/, GdkEventFocus * /*event*/, GObject *tbl) +static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { - return FALSE; - } - - if (!g_object_get_data (tbl, "esc-pressed")) { - g_object_set_data (tbl, "enter-pressed", gpointer(1)); - GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size")); - sp_text_toolbox_size_changed (cbox, tbl); - g_object_set_data (tbl, "enter-pressed", gpointer(0)); + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { + return; } - return FALSE; // I consumed the event -} + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + // At the moment this handles only numerical values (i.e. no em unit). + // Set css word-spacing + SPCSSAttr *css = sp_repr_css_attr_new (); + Inkscape::CSSOStringStream osfs; + osfs << adj->value; + sp_repr_css_set_property (css, "word-spacing", osfs.str().c_str()); + + // Apply word-spacing to selected objects. + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + sp_desktop_set_style (desktop, css, true, true); + + // Save for undo + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:word-spacing", SP_VERB_NONE, + _("Text: Change word-spacing")); + + // If no selected objects, set default. + SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); + int result_numbers = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + if (result_numbers == QUERY_STYLE_NOTHING) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->mergeStyle("/tools/text/style", css); + } + sp_style_unref(query); + + sp_repr_css_attr_unref (css); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} -static gboolean sp_text_toolbox_size_keypress(GtkWidget * /*w*/, GdkEventKey *event, GObject *tbl) +static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tbl ) { + // 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) ); + + // At the moment this handles only numerical values (i.e. no em unit). + // Set css letter-spacing + SPCSSAttr *css = sp_repr_css_attr_new (); + Inkscape::CSSOStringStream osfs; + osfs << adj->value; + sp_repr_css_set_property (css, "letter-spacing", osfs.str().c_str()); + + // Apply letter-spacing to selected objects. SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { - return FALSE; + sp_desktop_set_style (desktop, css, true, true); + + // Save for undo + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:letter-spacing", SP_VERB_NONE, + _("Text: Change letter-spacing")); + + // If no selected objects, set default. + SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); + int result_numbers = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + if (result_numbers == QUERY_STYLE_NOTHING) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->mergeStyle("/tools/text/style", css); + } + sp_style_unref(query); + + sp_repr_css_attr_unref (css); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void sp_text_orientation_mode_changed( EgeSelectOneAction *act, GObject *tbl ) +{ + // 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) ); + + int mode = ege_select_one_action_get_active( act ); - switch (get_group0_keyval (event)) { - case GDK_Escape: // defocus - g_object_set_data (tbl, "esc-pressed", gpointer(1)); - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - g_object_set_data (tbl, "esc-pressed", gpointer(0)); - return TRUE; // I consumed the event + SPCSSAttr *css = sp_repr_css_attr_new (); + switch (mode) + { + case 0: + { + sp_repr_css_set_property (css, "writing-mode", "lr"); break; - case GDK_Return: // defocus - case GDK_KP_Enter: - g_object_set_data (tbl, "enter-pressed", gpointer(1)); - GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size")); - sp_text_toolbox_size_changed (cbox, tbl); - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - g_object_set_data (tbl, "enter-pressed", gpointer(0)); - return TRUE; // I consumed the event + } + + case 1: + { + sp_repr_css_set_property (css, "writing-mode", "tb"); break; + } } - return FALSE; + + SPStyle *query = + sp_style_new (SP_ACTIVE_DOCUMENT); + int result_numbers = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + + // If querying returned nothing, update default style. + if (result_numbers == QUERY_STYLE_NOTHING) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->mergeStyle("/tools/text/style", css); + } + + sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true); + sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, + _("Text: Change orientation")); + sp_repr_css_attr_unref (css); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -// While editing font name in the entry, disable family_changed by freezing, otherwise completion -// does not work! -static gboolean sp_text_toolbox_entry_focus_in(GtkWidget *entry, - GdkEventFocus * /*event*/, - GObject *tbl) +/* + * This function sets up the text-tool tool-controls, setting the entry boxes + * etc. to the values from the current selection or the default if no selection. + * It is called whenever a text selection is changed, including stepping cursor + * through text. + */ +static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl) { +#ifdef DEBUG_TEXT + static int count = 0; + ++count; + std::cout << std::endl; + std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; + std::cout << "sp_text_toolbox_selection_changed: start " << count << std::endl; + + std::cout << " Selected items:" << std::endl; + for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList(); + items != NULL; + items = items->next) + { + const gchar* id = SP_OBJECT_ID((SPItem *) items->data); + std::cout << " " << id << std::endl; + } +#endif + + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { +#ifdef DEBUG_TEXT + std::cout << " Frozen, returning" << std::endl; + std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; + std::cout << std::endl; +#endif + return; + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); - gtk_entry_select_region (GTK_ENTRY (entry), 0, -1); // select all - return FALSE; + + /* + * Query from current selection: + * Font family (font-family) + * Style (font-weight, font-style, font-stretch, font-variant, font-align) + * Numbers (font-size, letter-spacing, word-spacing, line-height, text-anchor, writing-mode) + * Font specification (Inkscape private attribute) + */ + SPStyle *query = + sp_style_new (SP_ACTIVE_DOCUMENT); + int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); + int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); + int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + // Used later: + sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); + + /* + * If no text in selection (querying returned nothing), read the style from + * the /tools/text preferencess (default style for new texts). Return if + * tool bar already set to these preferences. + */ + if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) { + // There are no texts in selection, read from preferences. + sp_style_read_from_prefs(query, "/tools/text"); +#ifdef DEBUG_TEXT + std::cout << " read style from prefs:" << std::endl; + sp_print_font( query ); +#endif + if (g_object_get_data(tbl, "text_style_from_prefs")) { + // Do not reset the toolbar style from prefs if we already did it last time + sp_style_unref(query); + 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 << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; + std::cout << std::endl; +#endif + return; + } + + g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE)); + } else { + g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE)); + } + + // 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) + double size = query->font_size.computed; + gchar size_text[G_ASCII_DTOSTR_BUF_SIZE]; + g_ascii_dtostr (size_text, sizeof (size_text), size); + + Ink_ComboBoxEntry_Action* fontSizeAction = + INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) ); + ink_comboboxentry_action_set_active_text( fontSizeAction, size_text ); + + // Weight (Bold) + // Note: in the enumeration, normal and lighter come at the end so we must explicitly test for them. + gboolean boldSet = ((query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700) && + (query->font_weight.computed != SP_CSS_FONT_WEIGHT_NORMAL) && + (query->font_weight.computed != SP_CSS_FONT_WEIGHT_LIGHTER)); + + InkToggleAction* textBoldAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextBoldAction" ) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textBoldAction), boldSet ); + + + // Style (Italic/Oblique) + gboolean italicSet = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL); + + InkToggleAction* textItalicAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextItalicAction" ) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textItalicAction), italicSet ); + + + // Alignment + // Note: SVG 1.1 doesn't include text-align, SVG 1.2 Tiny doesn't include text-align="justify" + // text-align="justify" was a draft SVG 1.2 item (along with flowed text). + // Only flowed text can be left and right justified at the same time. + // Check if we have flowed text and disable botton. + // NEED: ege_select_one_action_set_sensitve( ) + /* + gboolean isFlow = false; + for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList(); + items != NULL; + items = items->next) { + const gchar* id = SP_OBJECT_ID((SPItem *) items->data); + std::cout << " " << id << std::endl; + if( SP_IS_FLOWTEXT(( SPItem *) items->data )) { + isFlow = true; + std::cout << " Found flowed text" << std::endl; + break; + } + } + if( isFlow ) { + // enable justify button + } else { + // disable justify button + } + */ + + int activeButton = 0; + if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY) + { + activeButton = 3; + } else { + if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) activeButton = 0; + if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) activeButton = 1; + if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) activeButton = 2; + } + EgeSelectOneAction* textAlignAction = EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextAlignAction" ) ); + ege_select_one_action_set_active( textAlignAction, activeButton ); + + + // Line height (spacing) + double height; + if (query->line_height.normal) { + height = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL; + } else { + if (query->line_height.unit == SP_CSS_UNIT_PERCENT) { + height = query->line_height.value; + } else { + height = query->line_height.computed; + } + } + + GtkAction* lineHeightAction = GTK_ACTION( g_object_get_data( tbl, "TextLineHeightAction" ) ); + GtkAdjustment *lineHeightAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( lineHeightAction )); + gtk_adjustment_set_value( lineHeightAdjustment, height ); + + + // Word spacing + double wordSpacing; + if (query->word_spacing.normal) wordSpacing = 0.0; + else wordSpacing = query->word_spacing.computed; // Assume no units (change in desktop-style.cpp) + + GtkAction* wordSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextWordSpacingAction" ) ); + GtkAdjustment *wordSpacingAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( wordSpacingAction )); + gtk_adjustment_set_value( wordSpacingAdjustment, wordSpacing ); + + + // Letter spacing + double letterSpacing; + if (query->letter_spacing.normal) letterSpacing = 0.0; + else letterSpacing = query->letter_spacing.computed; // Assume no units (change in desktop-style.cpp) + + GtkAction* letterSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextLetterSpacingAction" ) ); + GtkAdjustment *letterSpacingAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( letterSpacingAction )); + gtk_adjustment_set_value( letterSpacingAdjustment, letterSpacing ); + + + // Orientation + int activeButton2 = (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB ? 0 : 1); + + EgeSelectOneAction* textOrientationAction = + EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextOrientationAction" ) ); + ege_select_one_action_set_active( textOrientationAction, activeButton2 ); + + + } // if( query->text ) + +#ifdef DEBUG_TEXT + std::cout << " GUI: fontfamily.value: " + << (query->text->font_family.value ? query->text->font_family.value : "No value") + << std::endl; + std::cout << " GUI: font_size.computed: " << query->font_size.computed << std::endl; + std::cout << " GUI: font_weight.computed: " << query->font_weight.computed << std::endl; + std::cout << " GUI: font_style.computed: " << query->font_style.computed << std::endl; + std::cout << " GUI: text_anchor.computed: " << query->text_anchor.computed << std::endl; + std::cout << " GUI: text_align.computed: " << query->text_align.computed << std::endl; + std::cout << " GUI: line_height.computed: " << query->line_height.computed + << " line_height.value: " << query->line_height.value + << " line_height.unit: " << query->line_height.unit << std::endl; + std::cout << " GUI: word_spacing.computed: " << query->word_spacing.computed + << " word_spacing.value: " << query->word_spacing.value + << " word_spacing.unit: " << query->word_spacing.unit << std::endl; + std::cout << " GUI: letter_spacing.computed: " << query->letter_spacing.computed + << " letter_spacing.value: " << query->letter_spacing.value + << " letter_spacing.unit: " << query->letter_spacing.unit << std::endl; + std::cout << " GUI: writing_mode.computed: " << query->writing_mode.computed << std::endl; + std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; + std::cout << std::endl; +#endif + + sp_style_unref(query); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); + } -static gboolean sp_text_toolbox_entry_focus_out(GtkWidget *entry, - GdkEventFocus * /*event*/, - GObject *tbl) +static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - gtk_entry_select_region (GTK_ENTRY (entry), 0, 0); // deselect - return FALSE; + sp_text_toolbox_selection_changed (selection, tbl); } -static void cell_data_func(GtkCellLayout * /*cell_layout*/, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer /*data*/) +void +sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl) { - gchar *family; - gtk_tree_model_get(tree_model, iter, 0, &family, -1); - gchar *const family_escaped = g_markup_escape_text(family, -1); + sp_text_toolbox_selection_changed (NULL, tbl); +} +// Define all the "widgets" in the toolbar. +static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1); - if (show_sample) { + Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); - Glib::ustring sample = prefs->getString("/tools/text/font_sample"); - gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1); + // Is this used? + UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE ); + tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units ); + g_object_set_data( holder, "tracker", tracker ); - std::stringstream markup; - markup << family_escaped << " " << sample_escaped << ""; - g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL); + /* Font family */ + { + // Font list + Glib::RefPtr store = Inkscape::FontLister::get_instance()->get_font_list(); + GtkListStore* model = store->gobj(); + + Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction", + _("Font Family"), + _("Select Font Family"), + NULL, + GTK_TREE_MODEL(model), + -1, // Set width + (gpointer)cell_data_func ); // Cell layout + ink_comboboxentry_action_popup_enable( act ); // Enable entry completion + gchar *const warning = _("Font not found on system"); + ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font + g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontfamily_value_changed), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "TextFontFamilyAction", act ); + } - g_free(sample_escaped); - } else { - g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL); + /* Font size */ + { + // List of font sizes for drop-down menu + GtkListStore* model_size = gtk_list_store_new( 1, G_TYPE_STRING ); + gchar const *const sizes[] = { + "4", "6", "8", "9", "10", "11", "12", "13", "14", "16", + "18", "20", "22", "24", "28", "32", "36", "40", "48", "56", + "64", "72", "144" + }; + for( unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i ) { + GtkTreeIter iter; + gtk_list_store_append( model_size, &iter ); + gtk_list_store_set( model_size, &iter, 0, sizes[i], -1 ); + } + + Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontSizeAction", + _("Font Size"), + _("Select Font Size"), + NULL, + GTK_TREE_MODEL(model_size), + 4 ); // Width in characters + g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "TextFontSizeAction", act ); } - g_free(family); - g_free(family_escaped); -} + /* Style - Bold */ + { + InkToggleAction* act = ink_toggle_action_new( "TextBoldAction", // Name + _("Toggle Bold"), // Label + _("Toggle On/Off Bold Style"), // Tooltip + GTK_STOCK_BOLD, // Icon (inkId) + secondarySize ); // Icon size + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/bold", false) ); + g_object_set_data( holder, "TextBoldAction", act ); + } -static gboolean text_toolbox_completion_match_selected(GtkEntryCompletion * /*widget*/, - GtkTreeModel *model, - GtkTreeIter *iter, - GObject *tbl) -{ - // We intercept this signal so as to fire family_changed at once (without it, you'd have to - // press Enter again after choosing a completion) - gchar *family = 0; - gtk_tree_model_get(model, iter, 0, &family, -1); + /* Style - Italic/Oblique */ + { + InkToggleAction* act = ink_toggle_action_new( "TextItalicAction", // Name + _("Toggle Italic/Oblique"), // Label + _("Toggle On/Off Italic/Oblique Style"),// Tooltip + GTK_STOCK_ITALIC, // Icon (inkId) + secondarySize ); // Icon size + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/italic", false) ); + g_object_set_data( holder, "TextItalicAction", act ); + } - GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry")); - gtk_entry_set_text (GTK_ENTRY (entry), family); + /* Alignment */ + { + GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - sp_text_toolbox_family_changed (NULL, tbl); - return TRUE; -} - - -static void cbe_add_completion(GtkComboBoxEntry *cbe, GObject *tbl) -{ - GtkEntry *entry; - GtkEntryCompletion *completion; - GtkTreeModel *model; - - entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbe))); - completion = gtk_entry_completion_new(); - model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbe)); - gtk_entry_completion_set_model(completion, model); - gtk_entry_completion_set_text_column(completion, 0); - gtk_entry_completion_set_inline_completion(completion, FALSE); - gtk_entry_completion_set_inline_selection(completion, FALSE); - gtk_entry_completion_set_popup_completion(completion, TRUE); - gtk_entry_set_completion(entry, completion); - - g_signal_connect (G_OBJECT (completion), "match-selected", G_CALLBACK (text_toolbox_completion_match_selected), tbl); - - g_object_unref(completion); -} - -static void sp_text_toolbox_family_popnotify(GtkComboBox *widget, - void * /*property*/, - GObject *tbl) -{ - // while the drop-down is open, we disable font family changing, reenabling it only when it closes - - gboolean shown; - g_object_get (G_OBJECT(widget), "popup-shown", &shown, NULL); - if (shown) { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); - //g_print("POP: notify: SHOWN\n"); - } else { - g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - - // stupid GTK doesn't let us attach to events in the drop-down window, so we peek here to - // find out if the drop down was closed by Enter and if so, manually update (only - // necessary on Windows, on Linux it updates itself - what a mess, but we'll manage) - GdkEvent *ev = gtk_get_current_event(); - if (ev) { - //g_print ("ev type: %d\n", ev->type); - if (ev->type == GDK_KEY_PRESS) { - switch (get_group0_keyval ((GdkEventKey *) ev)) { - case GDK_KP_Enter: // chosen - case GDK_Return: - { - // make sure the chosen one is inserted into the entry - GtkComboBox *combo = GTK_COMBO_BOX (((Gtk::ComboBox *) (g_object_get_data (tbl, "family-entry-combo")))->gobj()); - GtkTreeModel *model = gtk_combo_box_get_model(combo); - GtkTreeIter iter; - gboolean has_active = gtk_combo_box_get_active_iter (combo, &iter); - if (has_active) { - gchar *family; - gtk_tree_model_get(model, &iter, 0, &family, -1); - GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry")); - gtk_entry_set_text (GTK_ENTRY (entry), family); - } - - // update - sp_text_toolbox_family_changed (NULL, tbl); - break; - } - } - } - } - - // regardless of whether we updated, defocus the widget - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); - } - //g_print("POP: notify: HIDDEN\n"); - } -} - -GtkWidget *sp_text_toolbox_new(SPDesktop *desktop) -{ - GtkToolbar *tbl = GTK_TOOLBAR(gtk_toolbar_new()); - GtkIconSize secondarySize = static_cast(ToolboxFactory::prefToSize("/toolbox/secondary", 1)); + GtkTreeIter iter; - gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas); - gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop); + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Align left"), + 1, _("Align left"), + 2, GTK_STOCK_JUSTIFY_LEFT, + -1 ); - GtkTooltips *tt = gtk_tooltips_new(); - - ////////////Family - Glib::RefPtr store = Inkscape::FontLister::get_instance()->get_font_list(); - Gtk::ComboBoxEntry *font_sel = Gtk::manage(new Gtk::ComboBoxEntry(store)); - - gtk_rc_parse_string ( - "style \"dropdown-as-list-style\"\n" - "{\n" - " GtkComboBox::appears-as-list = 1\n" - "}\n" - "widget \"*.toolbox-fontfamily-list\" style \"dropdown-as-list-style\""); - gtk_widget_set_name(GTK_WIDGET (font_sel->gobj()), "toolbox-fontfamily-list"); - gtk_tooltips_set_tip (tt, GTK_WIDGET (font_sel->gobj()), _("Select font family (Alt+X to access)"), ""); - - g_signal_connect (G_OBJECT (font_sel->gobj()), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl); - - cbe_add_completion(font_sel->gobj(), G_OBJECT(tbl)); - - gtk_toolbar_append_widget( tbl, (GtkWidget*) font_sel->gobj(), "", ""); - g_object_set_data (G_OBJECT (tbl), "family-entry-combo", font_sel); - - // expand the field a bit so as to view more of the previews in the drop-down - GtkRequisition req; - gtk_widget_size_request (GTK_WIDGET (font_sel->gobj()), &req); - gtk_widget_set_size_request (GTK_WIDGET (font_sel->gobj()), MIN(req.width + 50, 500), -1); - - GtkWidget* entry = (GtkWidget*) font_sel->get_entry()->gobj(); - g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_changed), tbl); - - g_signal_connect (G_OBJECT (font_sel->gobj()), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl); - g_signal_connect (G_OBJECT (font_sel->gobj()), "notify::popup-shown", - G_CALLBACK (sp_text_toolbox_family_popnotify), tbl); - g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl); - g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl); - g_signal_connect (G_OBJECT (entry), "focus-out-event", G_CALLBACK (sp_text_toolbox_entry_focus_out), tbl); - - gtk_object_set_data(GTK_OBJECT(entry), "altx-text", entry); - g_object_set_data (G_OBJECT (tbl), "family-entry", entry); - - GtkCellRenderer *cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_clear( GTK_CELL_LAYOUT(font_sel->gobj()) ); - gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(font_sel->gobj()) , cell , TRUE ); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(font_sel->gobj()), cell, GtkCellLayoutDataFunc (cell_data_func), NULL, NULL); - - GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, secondarySize); - GtkWidget *box = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (box), image); - gtk_toolbar_append_widget( tbl, box, "", ""); - g_object_set_data (G_OBJECT (tbl), "warning-image", box); - gtk_tooltips_set_tip (tt, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), ""); - gtk_widget_hide (GTK_WIDGET (box)); - g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box); - - ////////////Size - gchar const *const sizes[] = { - "4", "6", "8", "9", "10", "11", "12", "13", "14", - "16", "18", "20", "22", "24", "28", - "32", "36", "40", "48", "56", "64", "72", "144" - }; + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Align center"), + 1, _("Align center"), + 2, GTK_STOCK_JUSTIFY_CENTER, + -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Align right"), + 1, _("Align right"), + 2, GTK_STOCK_JUSTIFY_RIGHT, + -1 ); - GtkWidget *cbox = gtk_combo_box_entry_new_text (); - for (unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i) { - gtk_combo_box_append_text(GTK_COMBO_BOX(cbox), sizes[i]); - } - gtk_widget_set_size_request (cbox, 80, -1); - gtk_toolbar_append_widget( tbl, cbox, "", ""); - g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox); - g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl); - gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), tbl); - gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "focus-out-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_focusout), tbl); - - ////////////Text anchor - GtkWidget *group = gtk_radio_button_new (NULL); - GtkWidget *row = gtk_hbox_new (FALSE, 4); - g_object_set_data (G_OBJECT (tbl), "anchor-group", group); - - // left - GtkWidget *rbutton = group; - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "text-start", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0)); - gtk_tooltips_set_tip(tt, rbutton, _("Align left"), NULL); - - // center - rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group))); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "text-middle", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1)); - gtk_tooltips_set_tip(tt, rbutton, _("Center"), NULL); - - // right - rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group))); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "text-end", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2)); - gtk_tooltips_set_tip(tt, rbutton, _("Align right"), NULL); - - // fill - rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group))); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "text-fill", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(3)); - gtk_tooltips_set_tip(tt, rbutton, _("Justify"), NULL); - - gtk_toolbar_append_widget( tbl, row, "", ""); - - //spacer - gtk_toolbar_append_widget( tbl, gtk_vseparator_new(), "", "" ); - - ////////////Text style - row = gtk_hbox_new (FALSE, 4); - - // bold - rbutton = gtk_toggle_button_new (); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_BOLD, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - gtk_tooltips_set_tip(tt, rbutton, _("Bold"), NULL); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "style-bold", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer(0)); - - // italic - rbutton = gtk_toggle_button_new (); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_ITALIC, secondarySize)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - gtk_tooltips_set_tip(tt, rbutton, _("Italic"), NULL); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "style-italic", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer (1)); - - gtk_toolbar_append_widget( tbl, row, "", ""); - - //spacer - gtk_toolbar_append_widget( tbl, gtk_vseparator_new(), "", "" ); - - // Text orientation - group = gtk_radio_button_new (NULL); - row = gtk_hbox_new (FALSE, 4); - g_object_set_data (G_OBJECT (tbl), "orientation-group", group); - - // horizontal - rbutton = group; - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), - sp_icon_new (static_cast(secondarySize), INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_HORIZONTAL)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - gtk_tooltips_set_tip(tt, rbutton, _("Horizontal text"), NULL); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "orientation-horizontal", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer(0)); - - // vertical - rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group))); - gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (rbutton), - sp_icon_new (static_cast(secondarySize), INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_VERTICAL)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE); - gtk_tooltips_set_tip(tt, rbutton, _("Vertical text"), NULL); - - gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (tbl), "orientation-vertical", rbutton); - g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer (1)); - gtk_toolbar_append_widget( tbl, row, "", "" ); + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Justify"), + 1, _("Justify - Only flowed text"), + 2, GTK_STOCK_JUSTIFY_FILL, + -1 ); + EgeSelectOneAction* act = ege_select_one_action_new( "TextAlignAction", // Name + _("Alignment"), // Label + _("Text Alignment"), // Tooltip + NULL, // StockID + GTK_TREE_MODEL(model) ); // Model + g_object_set( act, "short_label", _("Align"), NULL ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "TextAlignAction", act ); - //watch selection - Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox"); + ege_select_one_action_set_appearance( act, "full" ); + ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE ); + g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL ); + ege_select_one_action_set_icon_column( act, 2 ); + ege_select_one_action_set_icon_size( act, secondarySize ); + ege_select_one_action_set_tooltip_column( act, 1 ); + + gint mode = prefs->getInt("/tools/text/align_mode", 0); + ege_select_one_action_set_active( act, mode ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_align_mode_changed), holder ); + } + + /* Orientation (Left to Right, Top to Bottom */ + { + GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + + GtkTreeIter iter; + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Horizontal"), + 1, _("Horizontal Text"), + 2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_HORIZONTAL, + -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("Vertical"), + 1, _("Vertical Text"), + 2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_VERTICAL, + -1 ); + + EgeSelectOneAction* act = ege_select_one_action_new( "TextOrientationAction", // Name + _("Orientation"), // Label + _("Text Orientation"), // Tooltip + NULL, // StockID + GTK_TREE_MODEL(model) ); // Model + + g_object_set( act, "short_label", _("O:"), NULL ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "TextOrientationAction", act ); + + ege_select_one_action_set_appearance( act, "full" ); + ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE ); + g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL ); + ege_select_one_action_set_icon_column( act, 2 ); + ege_select_one_action_set_icon_size( act, secondarySize ); + ege_select_one_action_set_tooltip_column( act, 1 ); + + gint mode = prefs->getInt("/tools/text/orientation", 0); + ege_select_one_action_set_active( act, mode ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_orientation_mode_changed), holder ); + } + + /* Line height */ + { + // Drop down menu + gchar const* labels[] = {_("Smaller spacing"), 0, 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, _("Larger spacing")}; + gdouble values[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1,2, 1.3, 1.4, 1.5, 2.0}; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextLineHeightAction", /* name */ + _("Line Height"), /* label */ + _("Line:"), /* short label */ + _("Spacing between lines."), /* tooltip */ + "/tools/text/lineheight", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* altx? */ + NULL, /* altx_mark? */ + 0.0, 10.0, 0.1, 1.0, /* lower, upper, step (arrow up/down), page up/down */ + labels, values, G_N_ELEMENTS(labels), /* drop down menu */ + sp_text_lineheight_value_changed, /* callback */ + 0.1, /* step (used?) */ + 2, /* digits to show */ + 1.0 /* factor (multiplies default) */ + ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); + g_object_set_data( holder, "TextLineHeightAction", eact ); + } + + /* Word spacing */ + { + // Drop down menu + gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; + gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0}; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextWordSpacingAction", /* name */ + _("Word spacing"), /* label */ + _("Word:"), /* short label */ + _("Spacing between words."), /* tooltip */ + "/tools/text/wordspacing", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* altx? */ + NULL, /* altx_mark? */ + -100.0, 100.0, 1.0, 10.0, /* lower, upper, step (arrow up/down), page up/down */ + labels, values, G_N_ELEMENTS(labels), /* drop down menu */ + sp_text_wordspacing_value_changed, /* callback */ + 0.1, /* step (used?) */ + 2, /* digits to show */ + 1.0 /* factor (multiplies default) */ + ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); + g_object_set_data( holder, "TextWordSpacingAction", eact ); + } + + /* Letter spacing */ + { + // Drop down menu + gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; + gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0}; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextLetterSpacingAction", /* name */ + _("Letter spacing"), /* label */ + _("Letter:"), /* short label */ + _("Spacing between letters."), /* tooltip */ + "/tools/text/letterspacing", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* altx? */ + NULL, /* altx_mark? */ + -100.0, 100.0, 1.0, 10.0, /* lower, upper, step (arrow up/down), page up/down */ + labels, values, G_N_ELEMENTS(labels), /* drop down menu */ + sp_text_letterspacing_value_changed, /* callback */ + 0.1, /* step (used?) */ + 2, /* digits to show */ + 1.0 /* factor (multiplies default) */ + ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); + g_object_set_data( holder, "TextLetterSpacingAction", eact ); + } + + // Is this necessary to call? Shouldn't hurt. + sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder); + + // Watch selection + Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolboxGTK"); sigc::connection *c_selection_changed = new sigc::connection (sp_desktop_selection (desktop)->connectChanged - (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl))); + (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)holder))); pool->add_connection ("selection-changed", c_selection_changed); sigc::connection *c_selection_modified = new sigc::connection (sp_desktop_selection (desktop)->connectModified - (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl))); + (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)holder))); pool->add_connection ("selection-modified", c_selection_modified); sigc::connection *c_subselection_changed = new sigc::connection (desktop->connectToolSubselectionChanged - (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl))); + (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)holder))); pool->add_connection ("tool-subselection-changed", c_subselection_changed); - Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool); - - - gtk_widget_show_all( GTK_WIDGET(tbl) ); + Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool); - return GTK_WIDGET(tbl); -} // end of sp_text_toolbox_new() + g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder ); -}// namespace +} //######################### -- cgit v1.2.3 From 6b27688f633f9be6e75b3c88ec37d9414055a674 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 23 Apr 2010 22:14:51 +0200 Subject: Minor tweaks to text toolbar. (bzr r9366) --- src/widgets/toolbox.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 66f77a18d..826fabb06 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -488,8 +488,8 @@ static gchar const * ui_descr = " " " " " " - " " " " + " " " " " " " " @@ -7351,7 +7351,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions holder, /* dataKludge */ FALSE, /* altx? */ NULL, /* altx_mark? */ - 0.0, 10.0, 0.1, 1.0, /* lower, upper, step (arrow up/down), page up/down */ + 0.0, 10.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_lineheight_value_changed, /* callback */ 0.1, /* step (used?) */ @@ -7381,7 +7381,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions holder, /* dataKludge */ FALSE, /* altx? */ NULL, /* altx_mark? */ - -100.0, 100.0, 1.0, 10.0, /* lower, upper, step (arrow up/down), page up/down */ + -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_wordspacing_value_changed, /* callback */ 0.1, /* step (used?) */ @@ -7411,7 +7411,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions holder, /* dataKludge */ FALSE, /* altx? */ NULL, /* altx_mark? */ - -100.0, 100.0, 1.0, 10.0, /* lower, upper, step (arrow up/down), page up/down */ + -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_letterspacing_value_changed, /* callback */ 0.1, /* step (used?) */ -- cgit v1.2.3