summaryrefslogtreecommitdiffstats
path: root/src/ui/shape-editor-knotholders.cpp
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2018-12-18 12:14:58 +0000
committerTavmjong Bah <tavmjong@free.fr>2018-12-18 12:14:58 +0000
commit9666f3139382451bc2a84eb9959d690f75b8250b (patch)
tree5b1a40d4a553bf7dde87c96d290ab80a80890fb1 /src/ui/shape-editor-knotholders.cpp
parentremove "Perspective path" LPE (diff)
downloadinkscape-9666f3139382451bc2a84eb9959d690f75b8250b.tar.gz
inkscape-9666f3139382451bc2a84eb9959d690f75b8250b.zip
Add ability to create SVG 2 text:
'shape-inside' (disabled for the moment) 'inline-size' (via on-screen knot)
Diffstat (limited to 'src/ui/shape-editor-knotholders.cpp')
-rw-r--r--src/ui/shape-editor-knotholders.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/ui/shape-editor-knotholders.cpp b/src/ui/shape-editor-knotholders.cpp
index 2f865504a..3e90f796c 100644
--- a/src/ui/shape-editor-knotholders.cpp
+++ b/src/ui/shape-editor-knotholders.cpp
@@ -31,6 +31,7 @@
#include "object/sp-rect.h"
#include "object/sp-spiral.h"
#include "object/sp-star.h"
+#include "object/sp-text.h"
#include "style.h"
#include "include/macros.h"
@@ -71,6 +72,12 @@ public:
~OffsetKnotHolder() override = default;;
};
+class TextKnotHolder : public KnotHolder {
+public:
+ TextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
+ ~TextKnotHolder() override = default;;
+};
+
class FlowtextKnotHolder : public KnotHolder {
public:
FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler);
@@ -116,6 +123,8 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop)
knotholder = new SpiralKnotHolder(desktop, item, nullptr);
} else if (dynamic_cast<SPOffset *>(item)) {
knotholder = new OffsetKnotHolder(desktop, item, nullptr);
+ } else if (dynamic_cast<SPText *>(item)) {
+ knotholder = new TextKnotHolder(desktop, item, nullptr);
} else {
SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item);
if (flowtext && flowtext->has_internal_frame()) {
@@ -1628,6 +1637,186 @@ OffsetKnotHolder::OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolde
add_pattern_knotholder();
}
+
+/* SPText */
+class TextKnotHolderEntityInlineSize : public KnotHolderEntity {
+public:
+ Geom::Point knot_get() const override;
+ void knot_set(Geom::Point const &p, Geom::Point const &origin, unsigned int state) override;
+ void knot_click(unsigned int state) override;
+};
+
+Geom::Point
+TextKnotHolderEntityInlineSize::knot_get() const
+{
+ SPText *text = dynamic_cast<SPText *>(item);
+ g_assert(text != nullptr);
+
+ Geom::Point p;
+
+ if (text->style->shape_inside.set) {
+ // SVG 2 'shape-inside'. We only get here if there is a rectangle shape.
+
+ Geom::OptRect frame = text->get_frame();
+ if (frame) {
+ p = (*frame).corner(2);
+ } else {
+ std::cerr << "TextKnotHolderEntityInlineSize::knot_get(): no frame!" << std::endl;
+ }
+
+ } else {
+ // 'shape-inside' or normal text.
+
+ SPStyle* style = text->style;
+
+ double inline_size = style->inline_size.computed;
+ unsigned mode = style->writing_mode.computed;
+ unsigned anchor = style->text_anchor.computed;
+ unsigned direction = style->direction.computed;
+
+ p = text->attributes.firstXY();
+
+ if (text->style->inline_size.set) {
+ // SVG 2 'inline-size'
+
+ // Keep handle at end of text line.
+ if (mode == SP_CSS_WRITING_MODE_LR_TB ||
+ mode == SP_CSS_WRITING_MODE_RL_TB) {
+ // horizontal
+ if ( (direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_START ) ||
+ (direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_END) ) {
+ p *= Geom::Translate (inline_size, 0);
+ } else if ( direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate (inline_size/2.0, 0 );
+ } else if ( direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate (-inline_size/2.0, 0 );
+ } else if ( (direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_END ) ||
+ (direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_START) ) {
+ p *= Geom::Translate (-inline_size, 0);
+ }
+ } else {
+ // vertical
+ if (anchor == SP_CSS_TEXT_ANCHOR_START) {
+ p *= Geom::Translate (0, inline_size);
+ } else if (anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate (0, inline_size/2.0);
+ } else if (anchor == SP_CSS_TEXT_ANCHOR_END) {
+ p *= Geom::Translate (0, -inline_size);
+ }
+ }
+ } else {
+ // Normal single line text.
+ Geom::OptRect bbox = text->geometricBounds(); // Check if this is best.
+ if (bbox) {
+ if (mode == SP_CSS_WRITING_MODE_LR_TB ||
+ mode == SP_CSS_WRITING_MODE_RL_TB) {
+ // horizontal
+ if ( (direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_START ) ||
+ (direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_END) ) {
+ p *= Geom::Translate ((*bbox).width(), 0);
+ } else if ( direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate ((*bbox).width()/2, 0);
+ } else if ( direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate (-(*bbox).width()/2, 0);
+ } else if ( (direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_END ) ||
+ (direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_START) ) {
+ p *= Geom::Translate (-(*bbox).width(), 0);
+ }
+ } else {
+ // vertical
+ if (anchor == SP_CSS_TEXT_ANCHOR_START) {
+ p *= Geom::Translate (0, (*bbox).height());
+ } else if (anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ p *= Geom::Translate (0, (*bbox).height()/2);
+ } else if (anchor == SP_CSS_TEXT_ANCHOR_END) {
+ p *= Geom::Translate (0, -(*bbox).height());
+ }
+ p += Geom::Point((*bbox).width(), 0); // Keep on right side
+ }
+ }
+ }
+ }
+
+ return p;
+}
+
+void
+TextKnotHolderEntityInlineSize::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
+{
+ SPText *text = dynamic_cast<SPText *>(item);
+ g_assert(text != nullptr);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ if (text->style->shape_inside.set) {
+ // Text in a shape: rectangle
+
+ Inkscape::XML::Node* rectangle = text->get_first_rectangle();
+ double x = 0.0;
+ double y = 0.0;
+ sp_repr_get_double (rectangle, "x", &x);
+ sp_repr_get_double (rectangle, "y", &y);
+ double width = s[Geom::X] - x;
+ double height = s[Geom::Y] - y;
+ sp_repr_set_svg_double (rectangle, "width", width);
+ sp_repr_set_svg_double (rectangle, "height", height);
+
+ } else {
+ // Normal or 'inline-size' text.
+
+ SPStyle* style = text->style;
+
+ unsigned mode = style->writing_mode.computed;
+ unsigned anchor = style->text_anchor.computed;
+ unsigned direction = style->direction.computed;
+
+ Geom::Point delta = s - text->attributes.firstXY();
+ double size = 0.0;
+ if (mode == SP_CSS_WRITING_MODE_LR_TB ||
+ mode == SP_CSS_WRITING_MODE_RL_TB) {
+ size = abs(delta[Geom::X]);
+ } else {
+ size = delta[Geom::Y];
+ }
+ if (anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) {
+ size *= 2.0;
+ }
+
+ text->style->inline_size.setDouble(abs(size));
+ text->style->inline_size.set = true;
+ }
+
+ text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ text->updateRepr();
+}
+
+void
+TextKnotHolderEntityInlineSize::knot_click(unsigned int state)
+{
+ SPText *text = dynamic_cast<SPText *>(item);
+ g_assert(text != nullptr);
+
+ if (state & GDK_CONTROL_MASK) {
+ text->style->inline_size.clear();
+ }
+
+ text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ text->updateRepr();
+}
+
+TextKnotHolder::TextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) :
+ KnotHolder(desktop, item, relhandler)
+{
+ TextKnotHolderEntityInlineSize *entity_inlinesize = new TextKnotHolderEntityInlineSize();
+
+ entity_inlinesize->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("Adjust the <b>inline size</b> (line length) of the text."),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity.push_back(entity_inlinesize);
+}
+
+
// TODO: this is derived from RectKnotHolderEntityWH because it used the same static function
// set_internal as the latter before KnotHolderEntity was C++ified. Check whether this also makes
// sense logically.