summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2016-10-14 20:24:55 +0000
committerjabiertxof <info@marker.es>2016-10-14 20:24:55 +0000
commit40cd3380a76c79cd09733ae01053750cf731b674 (patch)
treebd33ff51aa43b539a56d339776986aa28835ccab /src
parentWorking with rotate widget (diff)
parentImplement copying of objects with mesh gradients. (diff)
downloadinkscape-40cd3380a76c79cd09733ae01053750cf731b674.tar.gz
inkscape-40cd3380a76c79cd09733ae01053750cf731b674.zip
Update to trunk
(bzr r15142.1.12)
Diffstat (limited to 'src')
-rw-r--r--src/gradient-chemistry.cpp140
-rw-r--r--src/sp-gradient.cpp16
-rw-r--r--src/sp-gradient.h3
-rw-r--r--src/sp-lpe-item.cpp11
-rw-r--r--src/sp-mesh-array.cpp64
-rw-r--r--src/ui/tools/mesh-tool.cpp89
-rw-r--r--src/widgets/fill-style.cpp9
-rw-r--r--src/widgets/paint-selector.cpp102
-rw-r--r--src/widgets/paint-selector.h5
-rw-r--r--src/widgets/text-toolbar.cpp22
10 files changed, 284 insertions, 177 deletions
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index cf5cda180..c133bfa7c 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -76,9 +76,14 @@ std::vector<PaintTarget> const &allPaintTargets()
// "vector" is a gradient that has stops but not position coords. It can be referenced by one or
// more privates. Objects should not refer to it directly. It has no radial/linear distinction.
//
-// "private" is a gradient that has no stops but has position coords (e.g. center, radius etc for a
-// radial). It references a vector for the actual colors. Each private is only used by one
-// object. It is either linear or radial.
+// "array" is a gradient that has mesh rows and patches. It may or may not have "x" and "y" attributes.
+// An array does have spacial information so it cannot be normalized like a "vector".
+//
+// "shared" is either a "vector" or "array" that is shared between multiple objects.
+//
+// "private" is a gradient that is not shared. A private linear or radial gradient has no stops but
+// has position coords (e.g. center, radius etc for a radial); it references a "vector" for the
+// actual colors. A mesh may or may not reference an array. Each private is only used by one object.
static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *gr);
@@ -89,6 +94,7 @@ SPGradient *sp_gradient_ensure_vector_normalized(SPGradient *gr)
#endif
g_return_val_if_fail(gr != NULL, NULL);
g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL);
+ g_return_val_if_fail(!SP_IS_MESHGRADIENT(gr), NULL);
/* If we are already normalized vector, just return */
if (gr->state == SP_GRADIENT_STATE_VECTOR) return gr;
@@ -122,19 +128,19 @@ SPGradient *sp_gradient_ensure_vector_normalized(SPGradient *gr)
}
/**
- * Creates new private gradient for the given vector
+ * Creates new private gradient for the given shared gradient.
*/
-static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGradient *vector, SPGradientType type)
+static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGradient *shared, SPGradientType type)
{
#ifdef SP_GR_VERBOSE
- g_message("sp_gradient_get_private_normalized(%p, %p, %d)", document, vector, type);
+ g_message("sp_gradient_get_private_normalized(%p, %p, %d)", document, shared, type);
#endif
g_return_val_if_fail(document != NULL, NULL);
- g_return_val_if_fail(vector != NULL, NULL);
- g_return_val_if_fail(SP_IS_GRADIENT(vector), NULL);
- g_return_val_if_fail(vector->hasStops(), NULL);
+ g_return_val_if_fail(shared != NULL, NULL);
+ g_return_val_if_fail(SP_IS_GRADIENT(shared), NULL);
+ g_return_val_if_fail(shared->hasStops() || shared->hasPatches(), NULL);
SPDefs *defs = document->getDefs();
@@ -146,16 +152,14 @@ static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGr
} else if(type == SP_GRADIENT_TYPE_RADIAL) {
repr = xml_doc->createElement("svg:radialGradient");
} else {
- // Rows/patches added in sp_gradient_reset_to_userspace for new meshes.
repr = xml_doc->createElement("svg:meshgradient");
}
// privates are garbage-collectable
repr->setAttribute("inkscape:collect", "always");
- // link to vector
- // MESH FIXME: Meshes don't used vector... but meshes simulating gradient across/along path might.
- sp_gradient_repr_set_link(repr, vector);
+ // link to shared
+ sp_gradient_repr_set_link(repr, shared);
/* Append the new private gradient to defs */
defs->getRepr()->appendChild(repr);
@@ -204,21 +208,21 @@ static guint count_gradient_hrefs(SPObject *o, SPGradient *gr)
/**
- * If gr has other users, create a new private; also check if gr links to vector, relink if not
+ * If gr has other users, create a new shared; also check if gr links to shared, relink if not
*/
-static SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector,
+static SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *shared,
SPGradientType type, SPObject *o)
{
#ifdef SP_GR_VERBOSE
- g_message("sp_gradient_fork_private_if_necessary(%p, %p, %d, %p)", gr, vector, type, o);
+ g_message("sp_gradient_fork_private_if_necessary(%p, %p, %d, %p)", gr, shared, type, o);
#endif
g_return_val_if_fail(gr != NULL, NULL);
g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL);
- // Orphaned gradient, no vector with stops at the end of the line; this used to be an assert
- // but i think we should not abort on this - maybe just write a validity warning into some sort
- // of log
- if ( !vector || !vector->hasStops() ) {
+ // Orphaned gradient, no shared with stops or patches at the end of the line; this used to be
+ // an assert
+ if ( !shared || !(shared->hasStops() || shared->hasPatches()) ) {
+ std::cerr << "sp_gradient_fork_private_if_necessary: Orphaned gradient" << std::endl;
return (gr);
}
@@ -232,11 +236,11 @@ static SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradi
// Check the number of uses of the gradient within this object;
// if we are private and there are no other users,
- if (!vector->isSwatch() && (gr->hrefcount <= count_gradient_hrefs(user, gr))) {
- // check vector
- if ( gr != vector && gr->ref->getObject() != vector ) {
- /* our href is not the vector, and vector is different from gr; relink */
- sp_gradient_repr_set_link(gr->getRepr(), vector);
+ if (!shared->isSwatch() && (gr->hrefcount <= count_gradient_hrefs(user, gr))) {
+ // check shared
+ if ( gr != shared && gr->ref->getObject() != shared ) {
+ /* our href is not the shared, and shared is different from gr; relink */
+ sp_gradient_repr_set_link(gr->getRepr(), shared);
}
return gr;
}
@@ -245,35 +249,49 @@ static SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradi
SPObject *defs = doc->getDefs();
if ((gr->hasStops()) ||
+ (gr->hasPatches()) ||
(gr->state != SP_GRADIENT_STATE_UNKNOWN) ||
(gr->parent != SP_OBJECT(defs)) ||
(gr->hrefcount > 1)) {
- // we have to clone a fresh new private gradient for the given vector
+
+ // we have to clone a fresh new private gradient for the given shared
// create an empty one
- SPGradient *gr_new = sp_gradient_get_private_normalized(doc, vector, type);
+ SPGradient *gr_new = sp_gradient_get_private_normalized(doc, shared, type);
// copy all the attributes to it
Inkscape::XML::Node *repr_new = gr_new->getRepr();
Inkscape::XML::Node *repr = gr->getRepr();
repr_new->setAttribute("gradientUnits", repr->attribute("gradientUnits"));
repr_new->setAttribute("gradientTransform", repr->attribute("gradientTransform"));
- repr_new->setAttribute("spreadMethod", repr->attribute("spreadMethod"));
if (SP_IS_RADIALGRADIENT(gr)) {
repr_new->setAttribute("cx", repr->attribute("cx"));
repr_new->setAttribute("cy", repr->attribute("cy"));
repr_new->setAttribute("fx", repr->attribute("fx"));
repr_new->setAttribute("fy", repr->attribute("fy"));
- repr_new->setAttribute("r", repr->attribute("r"));
+ repr_new->setAttribute("r", repr->attribute("r" ));
+ repr_new->setAttribute("fr", repr->attribute("fr"));
+ repr_new->setAttribute("spreadMethod", repr->attribute("spreadMethod"));
} else if (SP_IS_LINEARGRADIENT(gr)) {
repr_new->setAttribute("x1", repr->attribute("x1"));
repr_new->setAttribute("y1", repr->attribute("y1"));
repr_new->setAttribute("x2", repr->attribute("x2"));
repr_new->setAttribute("y2", repr->attribute("y2"));
- } else {
- std::cerr << "sp_gradient_fork_private_if_necessary: mesh not implemented" << std::endl;
+ repr_new->setAttribute("spreadMethod", repr->attribute("spreadMethod"));
+ } else { // Mesh
+ repr_new->setAttribute("x", repr->attribute("x"));
+ repr_new->setAttribute("y", repr->attribute("y"));
+ repr_new->setAttribute("type", repr->attribute("type"));
+
+ // We probably want a completely separate mesh gradient so
+ // copy the children and unset the link to the shared.
+ for ( Inkscape::XML::Node *child = repr->firstChild() ; child ; child = child->next() ) {
+ Inkscape::XML::Node *copy = child->duplicate(doc->getReprDoc());
+ repr_new->appendChild( copy );
+ Inkscape::GC::release( copy );
+ }
+ sp_gradient_repr_set_link(repr_new, NULL);
}
-
return gr_new;
} else {
return gr;
@@ -409,6 +427,8 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item)
// IN SPMeshNodeArray::create()
//sp_repr_set_svg_double(repr, "x", bbox->min()[Geom::X]);
//sp_repr_set_svg_double(repr, "y", bbox->min()[Geom::Y]);
+
+ // We don't create a shared array gradient.
SPMeshGradient* mg = SP_MESHGRADIENT( gr );
mg->array.create( mg, item, bbox );
}
@@ -434,14 +454,14 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
return gr;
}
- // FIXME Transforming a mesh gradient is more complicated... probably need to add function to SPMeshArray.wq
- if ( gr && SP_IS_MESHGRADIENT( gr ) ) {
- return gr;
- }
-
// First, fork it if it is shared
- gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(),
- SP_IS_RADIALGRADIENT(gr) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, item);
+ if (SP_IS_LINEARGRADIENT(gr)) {
+ gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(), SP_GRADIENT_TYPE_LINEAR, item);
+ } else if (SP_IS_RADIALGRADIENT(gr)) {
+ gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(), SP_GRADIENT_TYPE_RADIAL, item);
+ } else {
+ gr = sp_gradient_fork_private_if_necessary(gr, gr->getArray(), SP_GRADIENT_TYPE_MESH, item);
+ }
if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
@@ -495,7 +515,24 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
// as to cancel it out when it's applied to the gradient during rendering
Geom::Affine point_convert = bbox2user * skew.inverse();
- if (SP_IS_RADIALGRADIENT(gr)) {
+ if (SP_IS_LINEARGRADIENT(gr)) {
+ SPLinearGradient *lg = SP_LINEARGRADIENT(gr);
+
+ Geom::Point p1_b = Geom::Point(lg->x1.computed, lg->y1.computed);
+ Geom::Point p2_b = Geom::Point(lg->x2.computed, lg->y2.computed);
+
+ Geom::Point p1_u = p1_b * point_convert;
+ Geom::Point p2_u = p2_b * point_convert;
+
+ sp_repr_set_svg_double(repr, "x1", p1_u[Geom::X]);
+ sp_repr_set_svg_double(repr, "y1", p1_u[Geom::Y]);
+ sp_repr_set_svg_double(repr, "x2", p2_u[Geom::X]);
+ sp_repr_set_svg_double(repr, "y2", p2_u[Geom::Y]);
+
+ // set the gradientUnits
+ repr->setAttribute("gradientUnits", "userSpaceOnUse");
+
+ } else if (SP_IS_RADIALGRADIENT(gr)) {
SPRadialGradient *rg = SP_RADIALGRADIENT(gr);
// original points in the bbox coords
@@ -514,23 +551,12 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
sp_repr_set_svg_double(repr, "fy", f_u[Geom::Y]);
sp_repr_set_svg_double(repr, "r", r_u);
- } else {
- SPLinearGradient *lg = SP_LINEARGRADIENT(gr);
+ // set the gradientUnits
+ repr->setAttribute("gradientUnits", "userSpaceOnUse");
- Geom::Point p1_b = Geom::Point(lg->x1.computed, lg->y1.computed);
- Geom::Point p2_b = Geom::Point(lg->x2.computed, lg->y2.computed);
-
- Geom::Point p1_u = p1_b * point_convert;
- Geom::Point p2_u = p2_b * point_convert;
-
- sp_repr_set_svg_double(repr, "x1", p1_u[Geom::X]);
- sp_repr_set_svg_double(repr, "y1", p1_u[Geom::Y]);
- sp_repr_set_svg_double(repr, "x2", p2_u[Geom::X]);
- sp_repr_set_svg_double(repr, "y2", p2_u[Geom::Y]);
+ } else {
+ std::cerr << "sp_gradient_convert_to_userspace: Conversion of mesh to userspace not implemented" << std::endl;
}
-
- // set the gradientUnits
- repr->setAttribute("gradientUnits", "userSpaceOnUse");
}
// apply the gradient to the item (may be necessary if we forked it); not recursive
@@ -1281,10 +1307,10 @@ in desktop coordinates.
*/
Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke)
{
+ SPGradient *gradient = getGradient(item, fill_or_stroke);
#ifdef SP_GR_VERBOSE
- g_message("getGradientCoords(%p, %d, %d, %d)", item, point_type, point_i, fill_or_stroke);
+ g_message("getGradientCoords(%p, %d, %d, %d, %p)", item, point_type, point_i, fill_or_stroke, gradient);
#endif
- SPGradient *gradient = getGradient(item, fill_or_stroke);
Geom::Point p (0, 0);
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 333316697..49f117a51 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -1144,15 +1144,17 @@ sp_gradient_pattern_common_setup(cairo_pattern_t *cp,
}
// add stops
- for (std::vector<SPGradientStop>::iterator i = gr->vector.stops.begin();
- i != gr->vector.stops.end(); ++i)
- {
- // multiply stop opacity by paint opacity
- cairo_pattern_add_color_stop_rgba(cp, i->offset,
- i->color.v.c[0], i->color.v.c[1], i->color.v.c[2], i->opacity * opacity);
+ if (!SP_IS_MESHGRADIENT(gr)) {
+ for (std::vector<SPGradientStop>::iterator i = gr->vector.stops.begin();
+ i != gr->vector.stops.end(); ++i)
+ {
+ // multiply stop opacity by paint opacity
+ cairo_pattern_add_color_stop_rgba(cp, i->offset,
+ i->color.v.c[0], i->color.v.c[1], i->color.v.c[2], i->opacity * opacity);
+ }
}
- // set pattern matrix
+ // set pattern transform matrix
Geom::Affine gs2user = gr->gradientTransform;
if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX && bbox) {
Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top());
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index 51ba3090c..9a0d5070f 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -172,9 +172,6 @@ public:
/** Forces array (mesh) to be built, if not present (i.e. changed) */
void ensureArray();
- /** Ensures that color array is populated */
- void ensureColors();
-
/**
* Set spread property of gradient and emit modified.
*/
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index c4247bd5a..f0b46a547 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -23,6 +23,7 @@
#include "live_effects/lpe-path_length.h"
#include "live_effects/lpeobject.h"
#include "live_effects/lpeobject-reference.h"
+#include "live_effects/lpe-measure-line.h"
#include "sp-path.h"
#include "sp-item-group.h"
@@ -122,10 +123,14 @@ void SPLPEItem::set(unsigned int key, gchar const* value) {
while ( it != this->path_effect_list->end() )
{
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
- lpeobj->get_lpe()->doOnRemove(this);
+ if (!value) {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ if (Inkscape::LivePathEffect::LPEMeasureLine * lpe = dynamic_cast<Inkscape::LivePathEffect::LPEMeasureLine *>(lpeobj->get_lpe())) {
+ lpe->doOnRemove(this);
+ }
+ }
(*it)->unlink();
- delete (*it);
+ delete *it;
it = this->path_effect_list->erase(it);
}
diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp
index c47c338de..042800fbf 100644
--- a/src/sp-mesh-array.cpp
+++ b/src/sp-mesh-array.cpp
@@ -678,11 +678,17 @@ SPMeshNodeArray& SPMeshNodeArray::operator=( const SPMeshNodeArray& rhs ) {
bool SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
mg = mg_in;
+ SPMeshGradient* mg_array = dynamic_cast<SPMeshGradient*>(mg->getArray());
+ if (!mg_array) {
+ std::cerr << "SPMeshNodeArray::read: No mesh array!" << std::endl;
+ return false;
+ }
+ // std::cout << "SPMeshNodeArray::read: " << mg_in << " array: " << mg_array << std::endl;
// Count rows and columns, if unchanged reuse array to keep draggers valid.
unsigned cols = 0;
unsigned rows = 0;
- for (auto& ro: mg->children) {
+ for (auto& ro: mg_array->children) {
if (SP_IS_MESHROW(&ro)) {
++rows;
if (rows == 1 ) {
@@ -707,7 +713,7 @@ bool SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
guint max_column = 0;
guint irow = 0; // Corresponds to top of patch being read in.
- for (auto& ro: mg->children) {
+ for (auto& ro: mg_array->children) {
if (SP_IS_MESHROW(&ro)) {
@@ -921,10 +927,16 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
using Geom::X;
using Geom::Y;
+ SPMeshGradient* mg_array = dynamic_cast<SPMeshGradient*>(mg->getArray());
+ if (!mg_array) {
+ // std::cerr << "SPMeshNodeArray::write: missing patches!" << std::endl;
+ mg_array = mg;
+ }
+
// First we must delete reprs for old mesh rows and patches.
GSList *descendant_reprs = NULL;
GSList *descendant_objects = NULL;
- for (auto& row: mg->children) {
+ for (auto& row: mg_array->children) {
descendant_reprs = g_slist_prepend (descendant_reprs, row.getRepr());
descendant_objects = g_slist_prepend (descendant_objects, &row);
for (auto& patch: row.children) {
@@ -950,8 +962,9 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
// Now we build new reprs
Inkscape::XML::Node *mesh = mg->getRepr();
+ Inkscape::XML::Node *mesh_array = mg_array->getRepr();
- SPMeshNodeArray* array = &(mg->array);
+ SPMeshNodeArray* array = &(mg_array->array);
SPMeshPatchI patch0( &(array->nodes), 0, 0 );
Geom::Point current_p = patch0.getPoint( 0, 0 ); // Side 0, point 0
@@ -966,7 +979,7 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
// Write row
Inkscape::XML::Node *row = xml_doc->createElement("svg:meshrow");
- mesh->appendChild( row ); // No attributes
+ mesh_array->appendChild( row ); // No attributes
guint columns = array->patch_columns();
for( guint j = 0; j < columns; ++j ) {
@@ -1071,42 +1084,27 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
}
/**
- Find default color based on color of first stop in "vector" gradient.
- This should be rewritten if dependence on "vector" is removed.
-*/
+ * Find default color based on colors in existing fill.
+ */
static SPColor default_color( SPItem *item ) {
- // Set initial color to the color of the object before adding the mesh.
- // This is a bit tricky as at the moment, a "vector" gradient is created
- // before reaching here, replacing the original solid color. But the first
- // stop will be that of the original object color.
SPColor color( 0.5, 0.0, 0.5 );
+
if ( item->style ) {
- SPStyle const &style = *(item->style);
- SPIPaint const &paint = ( style.fill ); // Could pick between style.fill/style.stroke
+ SPIPaint const &paint = ( item->style->fill ); // Could pick between style.fill/style.stroke
if ( paint.isColor() ) {
color = paint.value.color;
} else if ( paint.isPaintserver() ) {
- SPObject const *server = style.getFillPaintServer();
- if ( SP_IS_GRADIENT(server) ) {
- SPGradient *vector = SP_GRADIENT( server )->getVector();
- SPStop *firstStop = (vector) ?
- vector->getFirstStop() : SP_GRADIENT( server )->getFirstStop();
+ SPObject const *server = item->style->getFillPaintServer();
+ if ( SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector() ) {
+ SPStop *firstStop = SP_GRADIENT(server)->getVector()->getFirstStop();
if ( firstStop ) {
- if (firstStop->currentColor) {
- Glib::ustring str = firstStop->getStyleProperty("color", NULL);
- if( !str.empty() ) {
- guint32 rgb = sp_svg_read_color( str.c_str(), 0 );
- color = SPColor( rgb );
- }
- } else {
- color = firstStop->specified_color;
- }
+ color = firstStop->getEffectiveColor();
}
}
}
} else {
- std::cout << " SPMeshNodeArray: No style" << std::endl;
+ std::cerr << " SPMeshNodeArray: default_color(): No style" << std::endl;
}
return color;
@@ -1146,6 +1144,10 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
// return if we've already constructed the mesh.
if( !nodes.empty() ) return;
+ // Set 'gradientUnits'. Our calculations assume "userSpaceOnUse".
+ Inkscape::XML::Node *repr = mg->getRepr();
+ repr->setAttribute("gradientUnits", "userSpaceOnUse");
+
// Get default color
SPColor color = default_color( item );
@@ -1192,7 +1194,6 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
// std::cout << " start: " << start << " end: " << end << std::endl;
// IS THIS NECESSARY?
- Inkscape::XML::Node *repr = mg->getRepr();
sp_repr_set_svg_double( repr, "x", center[Geom::X] + rx * cos(start) );
sp_repr_set_svg_double( repr, "y", center[Geom::Y] + ry * sin(start) );
@@ -1262,7 +1263,6 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
gdouble s = -3.0/2.0 * M_PI_2;
- Inkscape::XML::Node *repr = mg->getRepr();
sp_repr_set_svg_double( repr, "x", center[Geom::X] + rx * cos(s) );
sp_repr_set_svg_double( repr, "y", center[Geom::Y] + ry * sin(s) );
@@ -1315,7 +1315,6 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
// std::cout << "We've got ourselves an star! Sides: " << sides << std::endl;
Geom::Point p0 = sp_star_get_xy( star, SP_STAR_POINT_KNOT1, 0 );
- Inkscape::XML::Node *repr = mg->getRepr();
sp_repr_set_svg_double( repr, "x", p0[Geom::X] );
sp_repr_set_svg_double( repr, "y", p0[Geom::Y] );
@@ -1385,7 +1384,6 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
// Generic
- Inkscape::XML::Node *repr = mg->getRepr();
sp_repr_set_svg_double(repr, "x", bbox->min()[Geom::X]);
sp_repr_set_svg_double(repr, "y", bbox->min()[Geom::Y]);
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index aac8239f3..33cdc3bda 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -38,6 +38,9 @@
#include "snap.h"
#include "sp-namedview.h"
#include "verbs.h"
+#include "sp-text.h"
+#include "sp-defs.h"
+#include "style.h"
// Gradient specific
#include "gradient-drag.h"
@@ -56,7 +59,7 @@ namespace Inkscape {
namespace UI {
namespace Tools {
-static void sp_mesh_end_drag(MeshTool &rc);
+static void sp_mesh_new_default(MeshTool &rc);
const std::string& MeshTool::getPrefsPath() {
return MeshTool::prefsPath;
@@ -471,24 +474,25 @@ bool MeshTool::root_handler(GdkEvent* event) {
// always resets selection to the single object under cursor
sp_mesh_context_split_near_point(this, selection->items().front(), this->mousepoint_doc, event->button.time);
} else {
+ sp_mesh_new_default(*this);
// Create a new gradient with default coordinates.
- auto items= selection->items();
- for(auto i=items.begin();i!=items.end();++i){
- SPItem *item = *i;
- SPGradientType new_type = SP_GRADIENT_TYPE_MESH;
- Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
-
-#ifdef DEBUG_MESH
- std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl;
-#endif
- SPGradient *vector = sp_gradient_vector_for_object(desktop->getDocument(), desktop, item, fsmode);
-
- SPGradient *priv = sp_item_set_gradient(item, vector, new_type, fsmode);
- sp_gradient_reset_to_userspace(priv, item);
- }
-
- DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH,
- _("Create default mesh"));
+// auto items= selection->items();
+// for(auto i=items.begin();i!=items.end();++i){
+// SPItem *item = *i;
+// SPGradientType new_type = SP_GRADIENT_TYPE_MESH;
+// Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
+
+// #ifdef DEBUG_MESH
+// std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl;
+// #endif
+// SPGradient *vector = sp_gradient_vector_for_object(desktop->getDocument(), desktop, item, fsmode);
+
+// SPGradient *priv = sp_item_set_gradient(item, vector, new_type, fsmode);
+// sp_gradient_reset_to_userspace(priv, item);
+// }
+
+// DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH,
+// _("Create default mesh"));
}
ret = TRUE;
@@ -663,7 +667,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
}
} else {
// Create a new mesh gradient
- sp_mesh_end_drag(*this);
+ sp_mesh_new_default(*this);
}
} else if (this->item_to_select) {
if (over_line && line) {
@@ -928,7 +932,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
}
// Creates a new mesh gradient.
-static void sp_mesh_end_drag(MeshTool &rc) {
+static void sp_mesh_new_default(MeshTool &rc) {
SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop;
Inkscape::Selection *selection = desktop->getSelection();
SPDocument *document = desktop->getDocument();
@@ -937,37 +941,42 @@ static void sp_mesh_end_drag(MeshTool &rc) {
if (!selection->isEmpty()) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int type = SP_GRADIENT_TYPE_MESH;
- Inkscape::PaintTarget fill_or_stroke = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
+ Inkscape::PaintTarget fill_or_stroke =
+ (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ?
+ Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
- SPGradient *vector;
- if (ec->item_to_select) {
- // pick color from the object where drag started
- vector = sp_gradient_vector_for_object(document, desktop, ec->item_to_select, fill_or_stroke);
- } else {
- // Starting from empty space:
- // Sort items so that the topmost comes last
- std::vector<SPItem*> items(selection->items().begin(), selection->items().end());
- sort(items.begin(),items.end(),sp_item_repr_compare_position);
- // take topmost
- vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(items.back()), fill_or_stroke);
- }
-
- // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
+// 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");
+ Inkscape::XML::Document *xml_doc = document->getReprDoc();
+ SPDefs *defs = document->getDefs();
+
auto items= selection->items();
for(auto i=items.begin();i!=items.end();++i){
//FIXME: see above
sp_repr_css_change_recursive((*i)->getRepr(), css, "style");
- sp_item_set_gradient(*i, vector, (SPGradientType) type, fill_or_stroke);
+ // Create mesh element
+ Inkscape::XML::Node *repr = xml_doc->createElement("svg:meshgradient");
- // We don't need to do anything. Mesh is already sized appropriately.
-
- (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ // privates are garbage-collectable
+ repr->setAttribute("inkscape:collect", "always");
+
+ // Attach to document
+ defs->getRepr()->appendChild(repr);
+ Inkscape::GC::release(repr);
+
+ // Get corresponding object
+ SPMeshGradient *mg = static_cast<SPMeshGradient *>(document->getObjectByRepr(repr));
+ mg->array.create(mg, *i, (*i)->visualBounds());
+
+ bool isText = SP_IS_TEXT(*i);
+ sp_style_set_property_url (*i, ((fill_or_stroke == Inkscape::FOR_FILL) ? "fill":"stroke"),
+ mg, isText);
+
+ (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG|SP_OBJECT_STYLE_MODIFIED_FLAG);
}
DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, _("Create mesh"));
diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp
index c35519b68..636d892f8 100644
--- a/src/widgets/fill-style.cpp
+++ b/src/widgets/fill-style.cpp
@@ -37,6 +37,7 @@
#include "gradient-chemistry.h"
#include "inkscape.h"
#include "sp-linear-gradient.h"
+#include "sp-mesh-gradient.h"
#include "sp-pattern.h"
#include "sp-radial-gradient.h"
#include "style.h"
@@ -295,6 +296,14 @@ void FillNStroke::performUpdate()
SPRadialGradient *rg = SP_RADIALGRADIENT(server);
psel->setGradientProperties( rg->getUnits(),
rg->getSpread() );
+#ifdef WITH_MESH
+ } else if (SP_IS_MESHGRADIENT(server)) {
+ SPGradient *array = SP_MESHGRADIENT(server)->getArray();
+ psel->setGradientMesh( array );
+
+ SPMeshGradient *mg = SP_MESHGRADIENT(server);
+ psel->setMeshProperties( mg->getUnits() );
+#endif
} else if (SP_IS_PATTERN(server)) {
SPPattern *pat = SP_PATTERN(server)->rootPattern();
psel->updatePatternList( pat );
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index ddac90730..3e9f0687d 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -78,6 +78,9 @@ static void sp_paint_selector_set_mode_multiple(SPPaintSelector *psel);
static void sp_paint_selector_set_mode_none(SPPaintSelector *psel);
static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelector::Mode mode);
static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSelector::Mode mode);
+#ifdef WITH_MESH
+static void sp_paint_selector_set_mode_mesh(SPPaintSelector *psel, SPPaintSelector::Mode mode);
+#endif
static void sp_paint_selector_set_mode_pattern(SPPaintSelector *psel, SPPaintSelector::Mode mode);
static void sp_paint_selector_set_mode_swatch(SPPaintSelector *psel, SPPaintSelector::Mode mode);
static void sp_paint_selector_set_mode_unset(SPPaintSelector *psel);
@@ -95,12 +98,14 @@ static gchar const* modeStrings[] = {
"MODE_SOLID_COLOR",
"MODE_GRADIENT_LINEAR",
"MODE_GRADIENT_RADIAL",
+#ifdef WITH_MESH
+ "MODE_GRADIENT_MESH",
+#endif
"MODE_PATTERN",
"MODE_SWATCH",
"MODE_UNSET",
".",
".",
- ".",
};
#endif
@@ -109,9 +114,6 @@ static bool isPaintModeGradient(SPPaintSelector::Mode mode)
{
bool isGrad = (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) ||
(mode == SPPaintSelector::MODE_GRADIENT_RADIAL) ||
-#ifdef WITH_MESH
- (mode == SPPaintSelector::MODE_GRADIENT_MESH) ||
-#endif
(mode == SPPaintSelector::MODE_SWATCH);
return isGrad;
@@ -386,11 +388,13 @@ void SPPaintSelector::setMode(Mode mode)
break;
case MODE_GRADIENT_LINEAR:
case MODE_GRADIENT_RADIAL:
+ sp_paint_selector_set_mode_gradient(this, mode);
+ break;
#ifdef WITH_MESH
case MODE_GRADIENT_MESH:
-#endif
- sp_paint_selector_set_mode_gradient(this, mode);
+ sp_paint_selector_set_mode_mesh(this, mode);
break;
+#endif
case MODE_PATTERN:
sp_paint_selector_set_mode_pattern(this, mode);
break;
@@ -488,17 +492,17 @@ void SPPaintSelector::setGradientRadial(SPGradient *vector)
}
#ifdef WITH_MESH
-void SPPaintSelector::setGradientMesh(SPGradient *vector)
+void SPPaintSelector::setGradientMesh(SPGradient *array)
{
#ifdef SP_PS_VERBOSE
g_print("PaintSelector set GRADIENT MESH\n");
#endif
- setMode(MODE_GRADIENT_RADIAL);
+ setMode(MODE_GRADIENT_MESH);
- SPGradientSelector *gsel = getGradientFromData(this);
+ // SPGradientSelector *gsel = getGradientFromData(this);
- gsel->setMode(SPGradientSelector::MODE_MESH);
- gsel->setVector((vector) ? vector->document : 0, vector);
+ // gsel->setMode(SPGradientSelector::MODE_GRADIENT_MESH);
+ // gsel->setVector((mesh) ? mesh->document : 0, mesh);
}
#endif
@@ -520,6 +524,25 @@ void SPPaintSelector::getGradientProperties( SPGradientUnits &units, SPGradientS
spread = gsel->getSpread();
}
+#ifdef WITH_MESH
+void SPPaintSelector::setMeshProperties( SPGradientUnits units )
+{
+ g_return_if_fail(mode == MODE_GRADIENT_MESH);
+
+ // SPGradientSelector *gsel = getGradientFromData(this);
+ // gsel->setUnits(units);
+}
+
+void SPPaintSelector::getMeshProperties( SPGradientUnits &units) const
+{
+ g_return_if_fail(mode == MODE_GRADIENT_MESH);
+
+ // SPGradientSelector *gsel = getGradientFromData(this);
+ // units = gsel->getUnits();
+}
+#endif
+
+
/**
* \post (alpha == NULL) || (*alpha in [0.0, 1.0]).
*/
@@ -730,11 +753,6 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
} else if (mode == SPPaintSelector::MODE_GRADIENT_RADIAL) {
sp_paint_selector_set_style_buttons(psel, psel->radial);
}
-#ifdef WITH_MESH
- else {
- sp_paint_selector_set_style_buttons(psel, psel->mesh);
- }
-#endif
gtk_widget_set_sensitive(psel->style, TRUE);
if ((psel->mode == SPPaintSelector::MODE_GRADIENT_LINEAR) || (psel->mode == SPPaintSelector::MODE_GRADIENT_RADIAL)) {
@@ -764,18 +782,58 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL);
gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Radial gradient</b>"));
}
-#ifdef WITH_MESH
- else {
- SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_MESH);
- gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Mesh gradient</b>"));
- }
-#endif
#ifdef SP_PS_VERBOSE
g_print("Gradient req\n");
#endif
}
+#ifdef WITH_MESH
+static void sp_paint_selector_set_mode_mesh(SPPaintSelector *psel, SPPaintSelector::Mode mode)
+{
+ if (mode == SPPaintSelector::MODE_GRADIENT_MESH) {
+ sp_paint_selector_set_style_buttons(psel, psel->mesh);
+ }
+ gtk_widget_set_sensitive(psel->style, TRUE);
+
+ GtkWidget *tbl = NULL;
+
+ if (psel->mode == SPPaintSelector::MODE_GRADIENT_MESH) {
+ /* Already have mesh selector */
+ tbl = GTK_WIDGET(g_object_get_data(G_OBJECT(psel->selector), "mesh-selector"));
+ } else {
+ sp_paint_selector_clear_frame(psel);
+
+ /* We could create a new gradient selector once adapted for meshes.
+ But for the moment we just create an empty widget. */
+ /* Create vbox */
+ tbl = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
+ gtk_box_set_homogeneous(GTK_BOX(tbl), FALSE);
+ gtk_widget_show(tbl);
+
+ {
+ auto hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
+ auto l = gtk_label_new(NULL);
+ gtk_label_set_markup(GTK_LABEL(l), _("Use the <b>Mesh tool</b> to create new and edit existing meshes. Mesh selection and copying not yet implemented."));
+ gtk_label_set_line_wrap(GTK_LABEL(l), true);
+ gtk_widget_set_size_request(l, 180, -1);
+ gtk_box_pack_start(GTK_BOX(hb), l, TRUE, TRUE, AUX_BETWEEN_BUTTON_GROUPS);
+ gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
+ }
+
+ gtk_widget_show_all(tbl);
+
+ gtk_container_add(GTK_CONTAINER(psel->frame), tbl);
+ psel->selector = tbl;
+ g_object_set_data(G_OBJECT(psel->selector), "mesh-selector", tbl);
+
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Mesh gradient</b>"));
+ }
+
+}
+#endif
+
static void
sp_paint_selector_set_style_buttons(SPPaintSelector *psel, GtkWidget *active)
{
diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h
index dde14b6a6..815a6da0b 100644
--- a/src/widgets/paint-selector.h
+++ b/src/widgets/paint-selector.h
@@ -98,13 +98,16 @@ struct SPPaintSelector {
void setGradientLinear( SPGradient *vector );
void setGradientRadial( SPGradient *vector );
#ifdef WITH_MESH
- void setGradientMesh(SPGradient *vector);
+ void setGradientMesh(SPGradient *array);
#endif
void setSwatch( SPGradient *vector );
void setGradientProperties( SPGradientUnits units, SPGradientSpread spread );
void getGradientProperties( SPGradientUnits &units, SPGradientSpread &spread ) const;
+ void setMeshProperties( SPGradientUnits units );
+ void getMeshProperties( SPGradientUnits &units ) const;
+
void pushAttrsToGradient( SPGradient *gr ) const;
SPGradient *getGradientVector();
SPPattern * getPattern();
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index 610d743a0..788ac4eb3 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -1602,7 +1602,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
_(tooltip.c_str()),
NULL,
GTK_TREE_MODEL(model_size),
- 4, // Width in characters
+ 4, // Width in characters
0, // Extra list width
NULL, // Cell layout
NULL, // Separator
@@ -1624,7 +1624,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
_("Font style"),
NULL,
GTK_TREE_MODEL(model_style),
- 12, // Width in characters
+ 12, // Width in characters
0, // Extra list width
NULL, // Cell layout
NULL, // Separator
@@ -1654,7 +1654,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
_("Toggle Subscript"), // Label
_("Toggle subscript"), // Tooltip
"text_subscript", // Icon (inkId)
- secondarySize ); // Icon size
+ secondarySize ); // Icon size
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_script_changed), holder );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/sub", false) );
@@ -1748,8 +1748,8 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
-1 );
EgeSelectOneAction* act = ege_select_one_action_new( "TextWritingModeAction", // Name
- _("Writing mode"), // Label
- _("Block progression"), // Tooltip
+ _("Writing mode"), // Label
+ _("Block progression"), // Tooltip
NULL, // Icon name
GTK_TREE_MODEL(model) ); // Model
@@ -1841,7 +1841,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextLineHeightAction", /* name */
_("Line Height"), /* label */
_("Line:"), /* short label */
- _("Spacing between baselines (times font size)"), /* tooltip */
+ _("Spacing between baselines"), /* tooltip */
"/tools/text/lineheight", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */
@@ -1880,7 +1880,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextWordSpacingAction", /* name */
_("Word spacing"), /* label */
_("Word:"), /* short label */
- _("Spacing between words (px)"), /* tooltip */
+ _("Spacing between words (px)"), /* tooltip */
"/tools/text/wordspacing", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */
@@ -1911,7 +1911,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextLetterSpacingAction", /* name */
_("Letter spacing"), /* label */
_("Letter:"), /* short label */
- _("Spacing between letters (px)"), /* tooltip */
+ _("Spacing between letters (px)"), /* tooltip */
"/tools/text/letterspacing", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */
@@ -1942,7 +1942,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextDxAction", /* name */
_("Kerning"), /* label */
_("Kern:"), /* short label */
- _("Horizontal kerning (px)"), /* tooltip */
+ _("Horizontal kerning (px)"), /* tooltip */
"/tools/text/dx", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */
@@ -1973,7 +1973,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextDyAction", /* name */
_("Vertical Shift"), /* label */
_("Vert:"), /* short label */
- _("Vertical shift (px)"), /* tooltip */
+ _("Vertical shift (px)"), /* tooltip */
"/tools/text/dy", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */
@@ -2004,7 +2004,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
"TextRotationAction", /* name */
_("Letter rotation"), /* label */
_("Rot:"), /* short label */
- _("Character rotation (degrees)"),/* tooltip */
+ _("Character rotation (degrees)"), /* tooltip */
"/tools/text/rotation", /* preferences path */
0.0, /* default */
GTK_WIDGET(desktop->canvas), /* focusTarget */