summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sp-text.cpp72
-rw-r--r--src/text-editing.cpp51
-rw-r--r--src/text-editing.h7
-rw-r--r--src/text-tag-attributes.h21
-rw-r--r--src/widgets/toolbox.cpp219
5 files changed, 366 insertions, 4 deletions
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))
@@ -973,6 +973,36 @@ sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator cons
}
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)
{
// divide increment by zoom
@@ -1012,6 +1042,25 @@ sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &star
}
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)
{
g_return_if_fail (text != NULL);
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 <utility> // std::pair
#include "libnrtype/Layout-TNG.h"
#include <libnr/nr-forward.h>
+#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 =
" <toolitem action='TextLineHeightAction' />"
" <toolitem action='TextLetterSpacingAction' />"
" <toolitem action='TextWordSpacingAction' />"
+ " <toolitem action='TextDxAction' />"
+ " <toolitem action='TextDyAction' />"
+ " <toolitem action='TextRotationAction' />"
" <separator />"
" <toolitem action='TextOrientationAction' />"
" </toolbar>"
@@ -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);