From: tavmjong-free Date: Fri, 14 May 2010 20:13:53 +0000 (+0200) Subject: Add dx (kerning), dy (vertical shifting), and rotate widgets to X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=83eb6894f3d44e525bf8f34eb70bf0b26c16a47e;p=inkscape.git Add dx (kerning), dy (vertical shifting), and rotate widgets to text toolbar along with routines needed by them. --- diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 11665b890..0f21b59d1 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -926,6 +926,50 @@ void TextTagAttributes::transform(Geom::Matrix const &matrix, double scale_x, do *it = it->computed * scale_y; } +double TextTagAttributes::getDx(unsigned index) +{ + if( attributes.dx.size() == 0 ) { + return 0.0; + } + if( index < attributes.dx.size() ) { + return attributes.dx[index].computed; + } else { + return 0.0; // attributes.dx.back().computed; + } +} + + +double TextTagAttributes::getDy(unsigned index) +{ + if( attributes.dy.size() == 0 ) { + return 0.0; + } + if( index < attributes.dy.size() ) { + return attributes.dy[index].computed; + } else { + return 0.0; // attributes.dy.back().computed; + } +} + + +void TextTagAttributes::addToDx(unsigned index, double delta) +{ + SVGLength zero_length; + zero_length = 0.0; + + if (attributes.dx.size() < index + 1) attributes.dx.resize(index + 1, zero_length); + attributes.dx[index] = attributes.dx[index].computed + delta; +} + +void TextTagAttributes::addToDy(unsigned index, double delta) +{ + SVGLength zero_length; + zero_length = 0.0; + + if (attributes.dy.size() < index + 1) attributes.dy.resize(index + 1, zero_length); + attributes.dy[index] = attributes.dy[index].computed + delta; +} + void TextTagAttributes::addToDxDy(unsigned index, Geom::Point const &adjust) { SVGLength zero_length; @@ -941,6 +985,19 @@ void TextTagAttributes::addToDxDy(unsigned index, Geom::Point const &adjust) } } +double TextTagAttributes::getRotate(unsigned index) +{ + if( attributes.rotate.size() == 0 ) { + return 0.0; + } + if( index < attributes.rotate.size() ) { + return attributes.rotate[index].computed; + } else { + return attributes.rotate.back().computed; + } +} + + void TextTagAttributes::addToRotate(unsigned index, double delta) { SVGLength zero_length; @@ -956,6 +1013,21 @@ void TextTagAttributes::addToRotate(unsigned index, double delta) } +void TextTagAttributes::setRotate(unsigned index, double angle) +{ + SVGLength zero_length; + zero_length = 0.0; + + if (attributes.rotate.size() < index + 2) { + if (attributes.rotate.empty()) + attributes.rotate.resize(index + 2, zero_length); + else + attributes.rotate.resize(index + 2, attributes.rotate.back()); + } + attributes.rotate[index] = mod360(angle); +} + + /* Local Variables: mode:c++ diff --git a/src/text-editing.cpp b/src/text-editing.cpp index e93ebdffa..372f5026d 100644 --- a/src/text-editing.cpp +++ b/src/text-editing.cpp @@ -928,7 +928,7 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) /** Returns the attributes block and the character index within that block which represents the iterator \a position. */ -static TextTagAttributes* +TextTagAttributes* text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator const &position, unsigned *char_index) { if (item == NULL || char_index == NULL || !SP_IS_TEXT(item)) @@ -972,6 +972,36 @@ sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator cons item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +void +sp_te_adjust_dx (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta) +{ + unsigned char_index; + TextTagAttributes *attributes = text_tag_attributes_at_position(item, std::min(start, end), &char_index); + if (attributes) attributes->addToDx(char_index, delta); + if (start != end) { + attributes = text_tag_attributes_at_position(item, std::max(start, end), &char_index); + if (attributes) attributes->addToDx(char_index, -delta); + } + + item->updateRepr(); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); +} + +void +sp_te_adjust_dy (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta) +{ + unsigned char_index; + TextTagAttributes *attributes = text_tag_attributes_at_position(item, std::min(start, end), &char_index); + if (attributes) attributes->addToDy(char_index, delta); + if (start != end) { + attributes = text_tag_attributes_at_position(item, std::max(start, end), &char_index); + if (attributes) attributes->addToDy(char_index, -delta); + } + + item->updateRepr(); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); +} + void sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble pixels) { @@ -1011,6 +1041,25 @@ sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &star text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +void +sp_te_set_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop */*desktop*/, gdouble degrees) +{ + unsigned char_index; + TextTagAttributes *attributes = text_tag_attributes_at_position(text, std::min(start, end), &char_index); + if (attributes == NULL) return; + + if (start != end) { + for (Inkscape::Text::Layout::iterator it = std::min(start, end) ; it != std::max(start, end) ; it.nextCharacter()) { + attributes = text_tag_attributes_at_position(text, it, &char_index); + if (attributes) attributes->setRotate(char_index, degrees); + } + } else + attributes->setRotate(char_index, degrees); + + text->updateRepr(); + text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); +} + void sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by) { diff --git a/src/text-editing.h b/src/text-editing.h index 7e845dbc9..038458ff7 100644 --- a/src/text-editing.h +++ b/src/text-editing.h @@ -17,6 +17,7 @@ #include // std::pair #include "libnrtype/Layout-TNG.h" #include +#include "text-tag-attributes.h" class SPCSSAttr; struct SPItem; @@ -50,10 +51,16 @@ gchar *sp_te_get_string_multiline(SPItem const *text); Glib::ustring sp_te_get_string_multiline(SPItem const *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end); void sp_te_set_repr_text_multiline(SPItem *text, gchar const *str); +TextTagAttributes* +text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator const &position, unsigned *char_index); + void sp_te_adjust_kerning_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, Geom::Point by); +void sp_te_adjust_dx (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta); +void sp_te_adjust_dy (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, double delta); void sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble pixels); void sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble degrees); +void sp_te_set_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble degrees); void sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by); void sp_te_adjust_linespacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by); diff --git a/src/text-tag-attributes.h b/src/text-tag-attributes.h index 7a7ba5763..197bfb73f 100644 --- a/src/text-tag-attributes.h +++ b/src/text-tag-attributes.h @@ -90,15 +90,36 @@ public: position. */ void transform(Geom::Matrix const &matrix, double scale_x, double scale_y, bool extend_zero_length = false); + /** Gets current value of dx vector at \a index. */ + double getDx(unsigned index); + + /** Gets current value of dy vector at \a index. */ + double getDy(unsigned index); + + /** Adds the given value to the dx vector at the given + \a index. The vector is extended if necessary. */ + void addToDx(unsigned index, double delta); + + /** Adds the given value to the dy vector at the given + \a index. The vector is extended if necessary. */ + void addToDy(unsigned index, double delta); + /** Adds the given values to the dx and dy vectors at the given \a index. The vectors are extended if necessary. */ void addToDxDy(unsigned index, Geom::Point const &adjust); + /** Gets current value of rotate vector at \a index. */ + double getRotate(unsigned index); + /** Adds the given value to the rotate vector at the given \a index. The vector is extended if necessary. Delta is measured in degrees, clockwise positive. */ void addToRotate(unsigned index, double delta); + /** Sets rotate vector at the given \a index. The vector is extended if + necessary. Angle is measured in degrees, clockwise positive. */ + void setRotate(unsigned index, double angle); + /** Returns the first coordinates in the x and y vectors. If either is zero length, 0.0 is used for that coordinate. */ Geom::Point firstXY() const; diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 6a5ac6ebe..4078fec06 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -85,6 +85,8 @@ #include "../sp-text.h" #include "../style.h" #include "../svg/css-ostringstream.h" +#include "../text-context.h" +#include "../text-editing.h" #include "../tools-switch.h" #include "../tweak-context.h" #include "../spray-context.h" @@ -490,6 +492,9 @@ static gchar const * ui_descr = " " " " " " + " " + " " + " " " " " " " " @@ -6869,6 +6874,82 @@ static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tb g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } + +static void sp_text_dx_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) ); + + gdouble new_dx = adj->value; + + SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); + if( tc ) { + unsigned char_index = -1; + TextTagAttributes *attributes = + text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index ); + if( attributes ) { + double old_dx = attributes->getDx( char_index ); + double delta_dx = new_dx - old_dx; + sp_te_adjust_dx( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dx ); + } + } + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void sp_text_dy_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) ); + + gdouble new_dy = adj->value; + + SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); + if( tc ) { + unsigned char_index = -1; + TextTagAttributes *attributes = + text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index ); + if( attributes ) { + double old_dy = attributes->getDy( char_index ); + double delta_dy = new_dy - old_dy; + sp_te_adjust_dy( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dy ); + } + } + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void sp_text_rotation_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) ); + + gdouble new_degrees = adj->value; + + SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); + if( tc ) { + unsigned char_index = -1; + TextTagAttributes *attributes = + text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index ); + if( attributes ) { + double old_degrees = attributes->getRotate( char_index ); + double delta_deg = new_degrees - old_degrees; + sp_te_adjust_rotation( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_deg ); + } + } + + 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 @@ -6938,6 +7019,9 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ const gchar* id = SP_OBJECT_ID((SPItem *) items->data); std::cout << " " << id << std::endl; } + Glib::ustring selected_text = sp_text_get_selected_text((SP_ACTIVE_DESKTOP)->event_context); + std::cout << " Selected text:" << std::endl; + std::cout << selected_text << std::endl; #endif // quit if run by the _changed callbacks @@ -7116,7 +7200,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ 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); @@ -7146,12 +7229,52 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ << " 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); + // Kerning (xshift), yshift, rotation. NB: These are not CSS attributes. + SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); + if( tc ) { + unsigned char_index = -1; + TextTagAttributes *attributes = + text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index ); + if( attributes ) { + + // Dx + double dx = attributes->getDx( char_index ); + GtkAction* dxAction = GTK_ACTION( g_object_get_data( tbl, "TextDxAction" )); + GtkAdjustment *dxAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( dxAction )); + gtk_adjustment_set_value( dxAdjustment, dx ); + + // Dy + double dy = attributes->getDy( char_index ); + GtkAction* dyAction = GTK_ACTION( g_object_get_data( tbl, "TextDyAction" )); + GtkAdjustment *dyAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( dyAction )); + gtk_adjustment_set_value( dyAdjustment, dy ); + + // Rotation + double rotation = attributes->getRotate( char_index ); + GtkAction* rotationAction = GTK_ACTION( g_object_get_data( tbl, "TextRotationAction" )); + GtkAdjustment *rotationAdjustment = + ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( rotationAction )); + gtk_adjustment_set_value( rotationAdjustment, rotation ); + +#ifdef DEBUG_TEXT + std::cout << " GUI: Dx: " << dx << std::endl; + std::cout << " GUI: Dy: " << dy << std::endl; + std::cout << " GUI: Rotation: " << rotation << std::endl; +#endif + } + } + +#ifdef DEBUG_TEXT + std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; + std::cout << std::endl; +#endif + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -7452,6 +7575,96 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions g_object_set_data( holder, "TextLetterSpacingAction", eact ); } + /* Character kerning (horizontal shift) */ + { + // Drop down menu + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = { -2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5 }; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextDxAction", /* name */ + _("Kerning"), /* label */ + _("Kern:"), /* short label */ + _("Kerning (horizontal shift of characters)."), /* tooltip */ + "/tools/text/dx", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* set alt-x keyboard shortcut? */ + NULL, /* altx_mark */ + -100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */ + labels, values, G_N_ELEMENTS(labels), /* drop down menu */ + sp_text_dx_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, "TextDxAction", eact ); + } + + /* Character vertical shift */ + { + // Drop down menu + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = { -2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5 }; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextDyAction", /* name */ + _("Vertical Shift"), /* label */ + _("Vert:"), /* short label */ + _("Vertical shift of characters."), /* tooltip */ + "/tools/text/dy", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* set alt-x keyboard shortcut? */ + NULL, /* altx_mark */ + -100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */ + labels, values, G_N_ELEMENTS(labels), /* drop down menu */ + sp_text_dy_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, "TextDyAction", eact ); + } + + /* Character rotation */ + { + // Drop down menu + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = { -90, -45, -30, -15, 0, 15, 30, 45, 90, 180 }; + + EgeAdjustmentAction *eact = create_adjustment_action( + "TextRotationAction", /* name */ + _("Letter rotation"), /* label */ + _("Rot:"), /* short label */ + _("Rotation of selected characters (degrees)."),/* tooltip */ + "/tools/text/letterspacing", /* path? */ + 0.0, /* default */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + NULL, /* unit selector */ + holder, /* dataKludge */ + FALSE, /* set alt-x keyboard shortcut? */ + NULL, /* altx_mark */ + -180.0, 180.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_rotation_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, "TextRotationAction", eact ); + } + // Is this necessary to call? Shouldn't hurt. sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder);