diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2016-10-14 20:24:55 +0000 |
|---|---|---|
| committer | jabiertxof <info@marker.es> | 2016-10-14 20:24:55 +0000 |
| commit | 40cd3380a76c79cd09733ae01053750cf731b674 (patch) | |
| tree | bd33ff51aa43b539a56d339776986aa28835ccab /src | |
| parent | Working with rotate widget (diff) | |
| parent | Implement copying of objects with mesh gradients. (diff) | |
| download | inkscape-40cd3380a76c79cd09733ae01053750cf731b674.tar.gz inkscape-40cd3380a76c79cd09733ae01053750cf731b674.zip | |
Update to trunk
(bzr r15142.1.12)
Diffstat (limited to 'src')
| -rw-r--r-- | src/gradient-chemistry.cpp | 140 | ||||
| -rw-r--r-- | src/sp-gradient.cpp | 16 | ||||
| -rw-r--r-- | src/sp-gradient.h | 3 | ||||
| -rw-r--r-- | src/sp-lpe-item.cpp | 11 | ||||
| -rw-r--r-- | src/sp-mesh-array.cpp | 64 | ||||
| -rw-r--r-- | src/ui/tools/mesh-tool.cpp | 89 | ||||
| -rw-r--r-- | src/widgets/fill-style.cpp | 9 | ||||
| -rw-r--r-- | src/widgets/paint-selector.cpp | 102 | ||||
| -rw-r--r-- | src/widgets/paint-selector.h | 5 | ||||
| -rw-r--r-- | src/widgets/text-toolbar.cpp | 22 |
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 */ |
