From b5be22f5bd07ff14b7eade763fb9b6f755d1cf5c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 1 Mar 2015 09:57:53 +0100 Subject: Rename to , to , to . Remove experimental smoothing types. Add new smoothing 'type' attribute with bicubic smoothing option. Per SVG WG decission at Sydney 2015 face-to-face meeting. (bzr r13956) --- src/CMakeLists.txt | 4 +- src/Makefile_insert | 2 +- src/attributes.cpp | 2 +- src/attributes.h | 2 +- src/gradient-chemistry.cpp | 22 +- src/gradient-drag.cpp | 38 ++-- src/gradient-drag.h | 4 +- src/sp-factory.cpp | 14 +- src/sp-gradient.cpp | 24 +- src/sp-gradient.h | 8 +- src/sp-mesh-array.cpp | 464 +++++---------------------------------- src/sp-mesh-array.h | 33 ++- src/sp-mesh-gradient.cpp | 299 ------------------------- src/sp-mesh-gradient.h | 43 ---- src/sp-mesh-patch.cpp | 28 +-- src/sp-mesh-patch.h | 18 +- src/sp-mesh-row.cpp | 30 +-- src/sp-mesh-row.h | 18 +- src/sp-mesh.cpp | 252 +++++++++++++++++++++ src/sp-mesh.h | 43 ++++ src/ui/tools/mesh-tool.cpp | 16 +- src/ui/widget/selected-style.cpp | 4 +- src/widgets/mesh-toolbar.cpp | 125 +++++------ src/widgets/paint-selector.cpp | 6 +- 24 files changed, 539 insertions(+), 960 deletions(-) delete mode 100644 src/sp-mesh-gradient.cpp delete mode 100644 src/sp-mesh-gradient.h create mode 100644 src/sp-mesh.cpp create mode 100644 src/sp-mesh.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b1e3931b..6659e8c0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,8 +47,8 @@ set(sp_SRC sp-lpe-item.cpp sp-marker.cpp sp-mask.cpp + sp-mesh.cpp sp-mesh-array.cpp - sp-mesh-gradient.cpp sp-mesh-patch.cpp sp-mesh-row.cpp sp-metadata.cpp @@ -134,8 +134,8 @@ set(sp_SRC sp-marker.h sp-marker-loc.h sp-mask.h + sp-mesh.h sp-mesh-array.h - sp-mesh-gradient.h sp-mesh-patch.h sp-mesh-row.h sp-metadata.h diff --git a/src/Makefile_insert b/src/Makefile_insert index 2bd457529..800752df4 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -154,8 +154,8 @@ ink_common_sources += \ sp-marker-loc.h \ sp-mask.cpp sp-mask.h \ sp-metadata.cpp sp-metadata.h \ + sp-mesh.cpp sp-mesh.h \ sp-mesh-array.cpp sp-mesh-array.h \ - sp-mesh-gradient.cpp sp-mesh-gradient.h \ sp-mesh-patch.cpp sp-mesh-patch.h \ sp-mesh-row.cpp sp-mesh-row.h \ sp-missing-glyph.cpp sp-missing-glyph.h \ diff --git a/src/attributes.cpp b/src/attributes.cpp index 0b18b80cf..3cf13d3f2 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -291,7 +291,7 @@ static SPStyleProp const props[] = { {SP_ATTR_FY, "fy"}, /* SPMeshPatch */ {SP_ATTR_TENSOR, "tensor"}, - {SP_ATTR_SMOOTH, "smooth"}, + {SP_ATTR_MESH_TYPE, "type"}, /* SPPattern */ {SP_ATTR_PATTERNUNITS, "patternUnits"}, {SP_ATTR_PATTERNCONTENTUNITS, "patternContentUnits"}, diff --git a/src/attributes.h b/src/attributes.h index 645aad00b..817819b69 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -293,7 +293,7 @@ enum SPAttributeEnum { SP_ATTR_FY, /* SPMeshPatch */ SP_ATTR_TENSOR, - SP_ATTR_SMOOTH, + SP_ATTR_MESH_TYPE, /* SPPattern */ SP_ATTR_PATTERNUNITS, SP_ATTR_PATTERNCONTENTUNITS, diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index cf75f6cf0..aecf1aa35 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -41,7 +41,7 @@ #include "sp-gradient-vector.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "sp-stop.h" #include "gradient-drag.h" #include "gradient-chemistry.h" @@ -151,7 +151,7 @@ static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGr 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"); + repr = xml_doc->createElement("svg:mesh"); } // privates are garbage-collectable @@ -413,7 +413,7 @@ 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]); - SPMeshGradient* mg = SP_MESHGRADIENT( gr ); + SPMesh* mg = SP_MESH( gr ); mg->array.create( mg, item, bbox ); } @@ -758,10 +758,10 @@ guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, break; } return 0; - } else if (SP_IS_MESHGRADIENT(gradient)) { + } else if (SP_IS_MESH(gradient)) { // Mesh gradient - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + SPMesh *mg = SP_MESH(gradient); switch (point_type) { case POINT_MG_CORNER: { @@ -859,7 +859,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint } else { // Mesh gradient - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + SPMesh *mg = SP_MESH(gradient); bool changed = false; switch (point_type) { @@ -1209,8 +1209,8 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } } - } else if (SP_IS_MESHGRADIENT(gradient)) { - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + } else if (SP_IS_MESH(gradient)) { + SPMesh *mg = SP_MESH(gradient); //Geom::Affine new_transform; //bool transform_set = false; @@ -1240,7 +1240,7 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi } if( write_repr ) { //std::cout << "Write mesh repr" << std::endl; - sp_meshgradient_repr_write( mg ); + sp_mesh_repr_write( mg ); } } @@ -1346,8 +1346,8 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_ g_warning( "Bad radial gradient handle type" ); break; } - } else if (SP_IS_MESHGRADIENT(gradient)) { - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + } else if (SP_IS_MESH(gradient)) { + SPMesh *mg = SP_MESH(gradient); switch (point_type) { case POINT_MG_CORNER: diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 154b7339b..cb2bd737f 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -43,7 +43,7 @@ #include "knot.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "sp-mesh-row.h" #include "sp-mesh-patch.h" #include "gradient-chemistry.h" @@ -414,7 +414,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler //r1_knot = false; } } - } else if (SP_IS_MESHGRADIENT(gradient)) { + } else if (SP_IS_MESH(gradient)) { // add_stop_near_point() // Find out which curve pointer is over and use that curve to determine @@ -422,7 +422,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler // This is silly as we already should know which line we are over... // but that information is not saved (sp_gradient_context_is_over_line). - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + SPMesh *mg = SP_MESH(gradient); Geom::Affine transform = Geom::Affine(mg->gradientTransform)*(Geom::Affine)item->i2dt_affine(); guint rows = mg->array.patch_rows(); @@ -550,7 +550,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler } else { - SPMeshGradient *mg = SP_MESHGRADIENT(gradient); + SPMesh *mg = SP_MESH(gradient); if( divide_row > -1 ) { mg->array.split_row( divide_row, divide_coord ); @@ -559,7 +559,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler } // Update repr - sp_meshgradient_repr_write( mg ); + sp_mesh_repr_write( mg ); mg->array.built = false; mg->ensureArray(); // How do we do this? @@ -1349,7 +1349,7 @@ GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op ) // Must be a mesh gradient SPGradient *gradient = getGradient(draggable->item, draggable->fill_or_stroke); - if ( !SP_IS_MESHGRADIENT( gradient ) ) continue; + if ( !SP_IS_MESH( gradient ) ) continue; selected_corners[ gradient ].push_back( draggable->point_i ); } @@ -1374,8 +1374,8 @@ GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op ) // Must be a mesh gradient SPGradient *gradient = getGradient(item, fill_or_stroke); - if ( !SP_IS_MESHGRADIENT( gradient ) ) continue; - SPMeshGradient *mg = SP_MESHGRADIENT( gradient ); + if ( !SP_IS_MESH( gradient ) ) continue; + SPMesh *mg = SP_MESH( gradient ); // pc_old is the old corner position in desktop coordinates, we need it in gradient coordinate. gradient = sp_gradient_convert_to_userspace (gradient, item, (fill_or_stroke == Inkscape::FOR_FILL) ? "fill" : "stroke"); @@ -1958,7 +1958,7 @@ void GrDrag::addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::Pai /** *Add draggers for the mesh gradient mg on item */ -void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke) +void GrDrag::addDraggersMesh(SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke) { std::vector< std::vector< SPMeshNode* > > nodes = mg->array.nodes; @@ -1977,7 +1977,7 @@ void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTa // Make sure we have at least one patch defined. if( mg->array.patch_rows() == 0 || mg->array.patch_columns() == 0 ) { - std::cout << "Empty Mesh Gradient, No Draggers to Add" << std::endl; + std::cout << "Empty Mesh, No Draggers to Add" << std::endl; return; } @@ -2032,7 +2032,7 @@ void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTa } default: - std::cout << "Bad Mesh Gradient draggable type" << std::endl; + std::cout << "Bad Mesh draggable type" << std::endl; break; } } @@ -2097,8 +2097,8 @@ void GrDrag::updateDraggers() addDraggersLinear( SP_LINEARGRADIENT(server), item, Inkscape::FOR_FILL ); } else if ( SP_IS_RADIALGRADIENT(server) ) { addDraggersRadial( SP_RADIALGRADIENT(server), item, Inkscape::FOR_FILL ); - } else if ( SP_IS_MESHGRADIENT(server) ) { - addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_FILL ); + } else if ( SP_IS_MESH(server) ) { + addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_FILL ); } } } @@ -2113,8 +2113,8 @@ void GrDrag::updateDraggers() addDraggersLinear( SP_LINEARGRADIENT(server), item, Inkscape::FOR_STROKE ); } else if ( SP_IS_RADIALGRADIENT(server) ) { addDraggersRadial( SP_RADIALGRADIENT(server), item, Inkscape::FOR_STROKE ); - } else if ( SP_IS_MESHGRADIENT(server) ) { - addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_STROKE ); + } else if ( SP_IS_MESH(server) ) { + addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_STROKE ); } } } @@ -2169,9 +2169,9 @@ void GrDrag::updateLines() Geom::Point center = getGradientCoords(item, POINT_RG_CENTER, 0, Inkscape::FOR_FILL); addLine(item, center, getGradientCoords(item, POINT_RG_R1, 0, Inkscape::FOR_FILL), Inkscape::FOR_FILL); addLine(item, center, getGradientCoords(item, POINT_RG_R2, 0, Inkscape::FOR_FILL), Inkscape::FOR_FILL); - } else if ( SP_IS_MESHGRADIENT(server) ) { + } else if ( SP_IS_MESH(server) ) { - SPMeshGradient *mg = SP_MESHGRADIENT(server); + SPMesh *mg = SP_MESH(server); guint rows = mg->array.patch_rows(); guint columns = mg->array.patch_columns(); @@ -2231,10 +2231,10 @@ void GrDrag::updateLines() Geom::Point center = getGradientCoords(item, POINT_RG_CENTER, 0, Inkscape::FOR_STROKE); addLine(item, center, getGradientCoords(item, POINT_RG_R1, 0, Inkscape::FOR_STROKE), Inkscape::FOR_STROKE); addLine(item, center, getGradientCoords(item, POINT_RG_R2, 0, Inkscape::FOR_STROKE), Inkscape::FOR_STROKE); - } else if ( SP_IS_MESHGRADIENT(server) ) { + } else if ( SP_IS_MESH(server) ) { // MESH FIXME: TURN ROUTINE INTO FUNCTION AND CALL FOR BOTH FILL AND STROKE. - SPMeshGradient *mg = SP_MESHGRADIENT(server); + SPMesh *mg = SP_MESH(server); guint rows = mg->array.patch_rows(); guint columns = mg->array.patch_columns(); diff --git a/src/gradient-drag.h b/src/gradient-drag.h index 964ea8093..da264b4bb 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -33,7 +33,7 @@ class SPKnot; class SPDesktop; class SPCSSAttr; class SPLinearGradient; -class SPMeshGradient; +class SPMesh; class SPItem; class SPObject; class SPRadialGradient; @@ -206,7 +206,7 @@ private: void addDraggersRadial(SPRadialGradient *rg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); void addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); - void addDraggersMesh( SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); + void addDraggersMesh( SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke); bool styleSet( const SPCSSAttr *css ); diff --git a/src/sp-factory.cpp b/src/sp-factory.cpp index 9911222e5..e48646f8d 100644 --- a/src/sp-factory.cpp +++ b/src/sp-factory.cpp @@ -36,7 +36,7 @@ #include "sp-linear-gradient.h" #include "sp-marker.h" #include "sp-mask.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "sp-mesh-patch.h" #include "sp-mesh-row.h" #include "sp-metadata.h" @@ -168,12 +168,12 @@ SPObject *SPFactory::createObject(std::string const& id) ret = new SPMarker; else if (id == "svg:mask") ret = new SPMask; - else if (id == "svg:meshGradient") - ret = new SPMeshGradient; - else if (id == "svg:meshPatch") - ret = new SPMeshPatch; - else if (id == "svg:meshRow") - ret = new SPMeshRow; + else if (id == "svg:mesh") + ret = new SPMesh; + else if (id == "svg:meshpatch") + ret = new SPMeshpatch; + else if (id == "svg:meshrow") + ret = new SPMeshrow; else if (id == "svg:metadata") ret = new SPMetadata; else if (id == "svg:missing-glyph") diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index b3e885560..854d53dc4 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -1,6 +1,6 @@ /** \file * SPGradient, SPStop, SPLinearGradient, SPRadialGradient, - * SPMeshGradient, SPMeshRow, SPMeshPatch + * SPMesh, SPMeshRow, SPMeshPatch */ /* * Authors: @@ -44,7 +44,7 @@ #include "sp-gradient-reference.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "sp-mesh-row.h" #include "sp-mesh-patch.h" #include "sp-stop.h" @@ -121,7 +121,7 @@ bool SPGradient::isEquivalent(SPGradient *that) else if ( (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) || (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) || - (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) { + (SP_IS_MESH(this) && SP_IS_MESH(that))) { if(!this->isAligned(that))break; } else { break; } // this should never happen, some unhandled type of gradient @@ -206,9 +206,9 @@ bool SPGradient::isAligned(SPGradient *that) (sg->fy.computed != tg->fy.computed) ) { break; } } else if( sg->cx._set || sg->cy._set || sg->fx._set || sg->fy._set || sg->r._set ) { break; } // some mix of set and not set // none set? assume aligned and fall through - } else if (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that)) { - SPMeshGradient *sg=SP_MESHGRADIENT(this); - SPMeshGradient *tg=SP_MESHGRADIENT(that); + } else if (SP_IS_MESH(this) && SP_IS_MESH(that)) { + SPMesh *sg=SP_MESH(this); + SPMesh *tg=SP_MESH(that); if( sg->x._set != !tg->x._set) { break; } if( sg->y._set != !tg->y._set) { break; } @@ -508,9 +508,9 @@ void SPGradient::modified(guint flags) if (flags & SP_OBJECT_CHILD_MODIFIED_FLAG) { // CPPIFY // This comparison has never worked (i. e. always evaluated to false), - // the right value would have been SP_TYPE_MESHGRADIENT + // the right value would have been SP_TYPE_MESH //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { -// if (!SP_IS_MESHGRADIENT(this)) { +// if (!SP_IS_MESH(this)) { // this->invalidateVector(); // } else { // this->invalidateArray(); @@ -522,7 +522,7 @@ void SPGradient::modified(guint flags) // CPPIFY // see above //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { -// if (!SP_IS_MESHGRADIENT(this)) { +// if (!SP_IS_MESH(this)) { // this->ensureVector(); // } else { // this->ensureArray(); @@ -1014,12 +1014,12 @@ void SPGradient::rebuildArray() { // std::cout << "SPGradient::rebuildArray()" << std::endl; - if( !SP_IS_MESHGRADIENT(this) ) { + if( !SP_IS_MESH(this) ) { g_warning( "SPGradient::rebuildArray() called for non-mesh gradient" ); return; } - array.read( SP_MESHGRADIENT( this ) ); + array.read( SP_MESH( this ) ); has_patches = false; for ( SPObject *ro = firstChild() ; ro ; ro = ro->getNext() ) { @@ -1139,7 +1139,7 @@ sp_gradient_create_preview_pattern(SPGradient *gr, double width) // CPPIFY //if( gr->get_type() != SP_GRADIENT_TYPE_MESH ) { - if (!SP_IS_MESHGRADIENT(gr)) { + if (!SP_IS_MESH(gr)) { gr->ensureVector(); pat = cairo_pattern_create_linear(0, 0, width, 0); diff --git a/src/sp-gradient.h b/src/sp-gradient.h index f80d806fc..ab45d6f08 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -39,12 +39,6 @@ enum SPGradientType { SP_GRADIENT_TYPE_MESH }; -enum SPGradientMeshType { - SP_GRADIENT_MESH_TYPE_UNKNOWN, - SP_GRADIENT_MESH_TYPE_NORMAL, - SP_GRADIENT_MESH_TYPE_CONICAL -}; - enum SPGradientState { SP_GRADIENT_STATE_UNKNOWN, SP_GRADIENT_STATE_VECTOR, @@ -216,7 +210,7 @@ sp_gradient_pattern_common_setup(cairo_pattern_t *cp, void sp_gradient_repr_write_vector(SPGradient *gr); void sp_gradient_repr_clear_vector(SPGradient *gr); -void sp_meshgradient_repr_write(SPMeshGradient *mg); +void sp_mesh_repr_write(SPMesh *mg); cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width); diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp index e2d654f2f..22bbc02c4 100644 --- a/src/sp-mesh-array.cpp +++ b/src/sp-mesh-array.cpp @@ -46,8 +46,8 @@ #include "document.h" #include "sp-root.h" +#include "sp-mesh.h" #include "sp-mesh-array.h" -#include "sp-mesh-gradient.h" #include "sp-mesh-row.h" #include "sp-mesh-patch.h" #include "sp-stop.h" @@ -574,7 +574,7 @@ void SPMeshPatchI::setOpacity( guint i, gdouble opacity ) { }; -SPMeshNodeArray::SPMeshNodeArray( SPMeshGradient *mg ) { +SPMeshNodeArray::SPMeshNodeArray( SPMesh *mg ) { read( mg ); @@ -621,7 +621,7 @@ SPMeshNodeArray& SPMeshNodeArray::operator=( const SPMeshNodeArray& rhs ) { }; -void SPMeshNodeArray::read( SPMeshGradient *mg_in ) { +void SPMeshNodeArray::read( SPMesh *mg_in ) { mg = mg_in; @@ -641,7 +641,7 @@ void SPMeshNodeArray::read( SPMeshGradient *mg_in ) { if (SP_IS_MESHPATCH(po)) { - SPMeshPatch *patch = SP_MESHPATCH(po); + SPMeshpatch *patch = SP_MESHPATCH(po); // std::cout << "SPMeshNodeArray::read: row size: " << nodes.size() << std::endl; SPMeshPatchI new_patch( &nodes, irow, icolumn ); // Adds new nodes. @@ -838,7 +838,7 @@ void SPMeshNodeArray::read( SPMeshGradient *mg_in ) { /** Write repr using our array. */ -void SPMeshNodeArray::write( SPMeshGradient *mg ) { +void SPMeshNodeArray::write( SPMesh *mg ) { // std::cout << "SPMeshNodeArray::write: entrance:" << std::endl; // print(); @@ -889,14 +889,14 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) { for( guint i = 0; i < rows; ++i ) { // Write row - Inkscape::XML::Node *row = xml_doc->createElement("svg:meshRow"); + Inkscape::XML::Node *row = xml_doc->createElement("svg:meshrow"); mesh->appendChild( row ); // No attributes guint columns = array->patch_columns(); for( guint j = 0; j < columns; ++j ) { // Write patch - Inkscape::XML::Node *patch = xml_doc->createElement("svg:meshPatch"); + Inkscape::XML::Node *patch = xml_doc->createElement("svg:meshpatch"); SPMeshPatchI patchi( &(array->nodes), i, j ); @@ -967,10 +967,10 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) { break; case 'z': case 'Z': - std::cout << "sp_meshgradient_repr_write: bad path type" << path_type << std::endl; + std::cout << "sp_mesh_repr_write: bad path type" << path_type << std::endl; break; default: - std::cout << "sp_meshgradient_repr_write: unhandled path type" << path_type << std::endl; + std::cout << "sp_mesh_repr_write: unhandled path type" << path_type << std::endl; } stop->setAttribute("path", is.str().c_str()); // std::cout << "SPMeshNodeArray::write: path: " << is.str().c_str() << std::endl; @@ -1039,7 +1039,7 @@ static SPColor default_color( SPItem *item ) { /** Create a default mesh. */ -void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox ) { +void SPMeshNodeArray::create( SPMesh *mg, SPItem *item, Geom::OptRect bbox ) { // std::cout << "SPMeshNodeArray::create: Entrance" << std::endl; @@ -1077,10 +1077,10 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb guint prows = prefs->getInt("/tools/mesh/mesh_rows", 1); guint pcols = prefs->getInt("/tools/mesh/mesh_cols", 1); - SPGradientMeshType mesh_type = - (SPGradientMeshType) prefs->getInt("/tools/mesh/mesh_type", SP_GRADIENT_MESH_TYPE_NORMAL); + SPMeshGeometry mesh_type = + (SPMeshGeometry) prefs->getInt("/tools/mesh/mesh_geometry", SP_MESH_GEOMETRY_NORMAL); - if( mesh_type == SP_GRADIENT_MESH_TYPE_CONICAL ) { + if( mesh_type == SP_MESH_GEOMETRY_CONICAL ) { // Conical gradient.. for any shape/path using geometric bounding box. @@ -1424,133 +1424,7 @@ void SPMeshNodeArray::print() { -// Find the slopes at start and end for Hermite interpolation. -// Smooth using Hermite interpolation. -// Inputs are: -// pb: color value before patch -// p0: color value start of patch -// p1: color value end of patch -// pa: color value after patch -// lb0: distance between points b and 0 -// l01: distance between points 0 and 1 -// l1a: distance between points 1 and a -// is_first: If first patch in row/column -// is_last: If last patch in row/column -// type: Type of smoothing -// Output: -// m0: slope of Hermite function at start. -// m1: slope of Hermite function at end. -void find_slopes( const double &pb, const double &p0, const double &p1, const double &pa, - const double &lb0, const double &l01, const double &l1a, - const bool &is_first, const bool &is_last, const SPMeshSmooth type, - double &m0, double &m1 ) { - - // We use Hermite interpolation. We have end points, we need tangents. - - // Try various ways of finding tangents m0, m1 - - // Default to Catmul-Rom (assumes pb and pa already calculatedd) - m0 = (p1 - pb)/2.0; - m1 = (pa - p0)/2.0; - - // Finite differences - if( lb0 > 0 && l01 > 0 ) - m0 = 0.5 * ((p0 - pb )/lb0 + (p1 - p0)/l01) * l01; - if( l01 > 0 && l1a > 0 ) - m1 = 0.5 * ((p1 - p0 )/l01 + (pa - p1)/l1a) * l01; - - bool parabolic = false; // Require end patches to be parabolic - switch (type) { - case SP_MESH_SMOOTH_SMOOTH1: - // Flat - m0 = 0.0; - m1 = 0.0; - break; - case SP_MESH_SMOOTH_SMOOTH2: - // Catmul-Rom, standard end treatment. Double first/last point. - if( is_first ) { - m0 = (p1-p0)/2.0; - } - if( is_last ) { - m1 = (p1-p0)/2.0; - } - break; - case SP_MESH_SMOOTH_SMOOTH3: - // Catmul-Rom, standard end treatment. Reflect first/last point. - if( is_first ) { - m0 = (p1-p0); - } - if( is_last ) { - m1 = (p1-p0); - } - break; - case SP_MESH_SMOOTH_SMOOTH4: - // Catmul-Rom, Parabolic ends - parabolic = true; - break; - case SP_MESH_SMOOTH_SMOOTH5: - // Catmul-Rom, Parabolic ends, no color min/max in middle of patch. - parabolic = true; - - if( (pb > p0 && p1 > p0) || - (pb < p0 && p1 < p0) ) { - // tangents flat at min/max - m0 = 0; - } else { - // https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - // ensure we don't overshoot - if( fabs(m0) > fabs(3*(p1-p0)) ) { - m0 = 3*(p1-p0); - } - if( fabs(m0) > fabs(3*(p0-pb)) * l01 / lb0 ) { - m0 = 3*(p0-pb) * l01 / lb0; - } - } - if( (p0 > p1 && pa > p1) || - (p0 < p1 && pa < p1) ) { - // tangents flat at min/max - m1 = 0; - } else { - // ensure we don't overshoot - if( fabs(m1) > fabs(3*(pa-p1) * l01 / l1a) ) { - m1 = 3*(pa-p1) * l01 / l1a; - } - if( fabs(m1) > fabs(3*(p1-p0)) ) { - m1 = 3*(p1-p0); - } - } - break; - case SP_MESH_SMOOTH_NONE: - default: - std::cerr << "find_slopes() Invalid smoothing type." << std::endl; - break; - } - - // Force end patches to be parabolic - if( parabolic ) { - if( is_first ) { - // Constraint for parabola - m0 = 2.0*(p1-p0) - m1; - if ( ((p1-p0) < 0 && m0 > 0) || ((p1-p0) > 0 && m0 < 0 ) ) { - m0 = 0; // Prevent overshooting start value; - } - } else if( is_last ) { - // Constraint for parabola - m1 = 2.0*(p1-p0) - m0; - if ( ((p1-p0) < 0 && m1 > 0) || ((p1-p0) > 0 && m1 < 0 ) ) { - m1 = 0; // Prevent overshooting end value; - } - } - } - - // std::cout << " pb: " << pb - // << " p0: " << p0 - // << " p1: " << p1 - // << " pa: " << pa - // << " m0: " << m0 - // << " m1: " << m1 << std::endl; -} - +/* double hermite( const double p0, const double p1, const double m0, const double m1, const double t ) { double t2 = t*t; double t3 = t2*t; @@ -1562,178 +1436,7 @@ double hermite( const double p0, const double p1, const double m0, const double return result; } - - -/** - Fill 'smooth' with a smoothed version of the array by subdividing each patch into smaller patches. */ -void SPMeshNodeArray::smooth( SPMeshNodeArray* smooth, SPMeshSmooth type ) { - - *smooth = *this; // Deep copy via copy assignment constructor, smooth cleared before copy - // std::cout << "SPMeshNodeArray::smooth(): " << this->patch_rows() << " " << smooth->patch_rows() << std::endl; - // std::cout << " " << smooth << " " << this << std::endl; - // Next split each patch into 8x8 smaller patches. - - // Do rows first. - - // Split each row into eight rows. - // Must do it from end so inserted rows don't mess up indexing - for( int i = smooth->patch_rows() - 1; i >= 0; --i ) { - smooth->split_row( i, unsigned(8) ); - } - - // Update color values (every third node is a corner) - for( unsigned i = 0; i < this->patch_rows(); ++i ) { // i is orignal patch index - - bool is_first_row = (i == 0); - bool is_last_row = (i == this->patch_rows() - 1 ); - //std::cout << " last row: " << smooth->patch_rows()/8 - 1 << " " << is_last_row << std::endl; - for( unsigned j = 0; j < smooth->patch_columns()+1; ++j ) { // j is smooth patch index - - // Can't use guint32 since delta can be negative - float pb[3]; // Point before patch - float p0[3]; // Point at start of patch - float p1[3]; // Point at end of patch - float pa[3]; // Point after patch - float result[3][8]; - sp_color_get_rgb_floatv( &this->nodes[ i *3 ][ j*3 ]->color, p0 ); - sp_color_get_rgb_floatv( &this->nodes[ (i+1)*3 ][ j*3 ]->color, p1 ); - - // Use linear distance to avoid calculation overhead of calculating true path length - Geom::Point *ptb = NULL; - Geom::Point *pt0 = &this->nodes[ i *3 ][ j*3 ]->p; - Geom::Point *pt1 = &this->nodes[ (i+1)*3 ][ j*3 ]->p; - Geom::Point *pta = NULL; - - double lb0 = 0.0; - double l01 = Geom::distance( *pt0, *pt1 ); - double l1a = 0.0; - - if( !is_first_row ) { - sp_color_get_rgb_floatv( &this->nodes[ (i-1)*3 ][ j*3 ]->color, pb ); - ptb = &this->nodes[ (i-1)*3 ][ j*3 ]->p; - lb0 = Geom::distance( *ptb, *pt0 ); - } else { - pb[0] = 2.0*p0[0] - p1[0]; - pb[1] = 2.0*p0[1] - p1[1]; - pb[2] = 2.0*p0[2] - p1[2]; - } - if( !is_last_row ) { - sp_color_get_rgb_floatv( &this->nodes[ (i+2)*3 ][ j*3 ]->color, pa ); - pta = &this->nodes[ (i+2)*3 ][ j*3 ]->p; - l1a = Geom::distance( *pt1, *pta ); - } else { - pa[0] = 2.0*p1[0] - p0[0]; - pa[1] = 2.0*p1[1] - p0[1]; - pa[2] = 2.0*p1[2] - p0[2]; - } - - for( unsigned n = 0; n < 3; ++n ) { // Loop over colors - - // We use Hermite interpolation. We have end points, we need tangents. - double m0 = 0; - double m1 = 0; - find_slopes( pb[n], p0[n], p1[n], pa[n], - lb0, l01, l1a, - is_first_row, is_last_row, type, m0, m1 ); - - for( unsigned k = 1; k < 8; ++k ) { - double t = k/8.0; - // Cubic Hermite (four constraints) - result[n][k] = hermite( p0[n], p1[n], m0, m1, t ); - // Clamp to allowed values - if( result[n][k] > 1.0 ) - result[n][k] = 1.0; - if( result[n][k] < 0.0 ) - result[n][k] = 0.0; - } - } - - for( unsigned k = 1; k < 8; ++k ) { - smooth->nodes[ (i*8+k)*3 ][ j*3 ]->color.set( result[0][k], result[1][k], result[2][k] ); - } - } - } - - // Split each column into eight columns. - // Must do it from end so inserted columns don't mess up indexing - for( int i = smooth->patch_columns() - 1; i >= 0; --i ) { - smooth->split_column( i, (unsigned)8 ); - } - - // Update color values (every third node is a corner) - for( unsigned i = 0; i < this->patch_columns(); ++i ) { // i is orignal patch index - - bool is_first_column = (i == 0); - bool is_last_column = (i == this->patch_columns() - 1 ); - //std::cout << " last column: " << smooth->patch_columns()/8 - 1 << " " << is_last_column << std::endl; - for( unsigned j = 0; j < smooth->patch_rows()+1; ++j ) { // j is smooth patch index - - // Can't use guint32 since delta can be negative - float pb[3]; // Point before patch - float p0[3]; // Point at start of patch - float p1[3]; // Point at end of patch - float pa[3]; // Point after patch - float result[3][8]; - sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ i *3*8 ]->color, p0 ); - sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i+1)*3*8 ]->color, p1 ); - - // Use linear distance to avoid calculation overhead of calculating true path length - Geom::Point *ptb = NULL; - Geom::Point *pt0 = &smooth->nodes[ j*3 ][ i *3*8 ]->p; - Geom::Point *pt1 = &smooth->nodes[ j*3 ][ (i+1)*3*8 ]->p; - Geom::Point *pta = NULL; - - double lb0 = 0.0; - double l01 = Geom::distance( *pt0, *pt1 ); - double l1a = 0.0; - - if( !is_first_column ) { - sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i-1)*3*8 ]->color, pb ); - ptb = &smooth->nodes[ j*3 ][ (i-1)*3*8 ]->p; - lb0 = Geom::distance( *ptb, *pt0 ); - } else { - pb[0] = 2.0*p0[0] - p1[0]; - pb[1] = 2.0*p0[1] - p1[1]; - pb[2] = 2.0*p0[2] - p1[2]; - } - if( !is_last_column ) { - sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i+2)*3*8 ]->color, pa ); - pta = &smooth->nodes[ j*3 ][ (i+2)*3*8 ]->p; - l1a = Geom::distance( *pt1, *pta ); - } else { - pa[0] = 2.0*p1[0] - p0[0]; - pa[1] = 2.0*p1[1] - p0[1]; - pa[2] = 2.0*p1[2] - p0[2]; - } - - for( unsigned n = 0; n < 3; ++n ) { // Loop over colors - - // We use Hermite interpolation. We have end points, we need tangents. - double m0 = 0; - double m1 = 0; - find_slopes( pb[n], p0[n], p1[n], pa[n], - lb0, l01, l1a, - is_first_column, is_last_column, type, m0, m1 ); - - for( unsigned k = 1; k < 8; ++k ) { - double t = k/8.0; - // Cubic Hermite (four constraints) - result[n][k] = hermite( p0[n], p1[n], m0, m1, t ); - // Clamp to allowed values - if( result[n][k] > 1.0 ) - result[n][k] = 1.0; - if( result[n][k] < 0.0 ) - result[n][k] = 0.0; - } - } - - for( unsigned k = 1; k < 8; ++k ) { - smooth->nodes[ j*3 ][ (i*8+k)*3 ]->color.set( result[0][k], result[1][k], result[2][k] ); - } - } - } -} class SPMeshSmoothCorner { @@ -1792,6 +1495,7 @@ double find_slope1( const double &p0, const double &p1, const double &p2, }; +/* // Find slope at point 0 given values at previous and next points // TO DO: TAKE DISTANCE BETWEEN POINTS INTO ACCOUNT double find_slope2( double pmm, double ppm, double pmp, double ppp, double p0 ) { @@ -1819,6 +1523,7 @@ double find_slope2( double pmm, double ppm, double pmp, double ppp, double p0 ) } return slope; } +*/ // https://en.wikipedia.org/wiki/Bicubic_interpolation void invert( const double v[16], double alpha[16] ) { @@ -1883,7 +1588,7 @@ double sum( const double alpha[16], const double& x, const double& y ) { /** Fill 'smooth' with a smoothed version of the array by subdividing each patch into smaller patches. */ -void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) { +void SPMeshNodeArray::bicubic( SPMeshNodeArray* smooth, SPMeshType type ) { *smooth = *this; // Deep copy via copy assignment constructor, smooth cleared before copy @@ -1911,40 +1616,29 @@ void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) { for( unsigned i = 0; i < d.size(); ++i ) { for( unsigned j = 0; j < d[i].size(); ++j ) { for( unsigned k = 0; k < 3; ++k ) { // Loop over colors - if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) { - // dx - if( i != 0 && i != d.size()-1 ) { - double lm = Geom::distance( d[i-1][j].p, d[i][j].p ); - double lp = Geom::distance( d[i+1][j].p, d[i][j].p ); - d[i][j].g[k][1] = find_slope1( d[i-1][j].g[k][0], d[i][j].g[k][0], d[i+1][j].g[k][0], lm, lp ); - } + // dx - // dy - if( j != 0 && j != d[i].size()-1 ) { - double lm = Geom::distance( d[i][j-1].p, d[i][j].p ); - double lp = Geom::distance( d[i][j+1].p, d[i][j].p ); - d[i][j].g[k][2] = find_slope1( d[i][j-1].g[k][0], d[i][j].g[k][0], d[i][j+1].g[k][0], lm, lp ); - } - - // dxdy if needed, need to take lengths into account - // if( i != 0 && i != d.size()-1 && j != 0 && j != d[i].size()-1 ) { - // d[i][j].g[k][3] = find_slope2( d[i-1][j-1].g[k][0], d[i+1][j-1].g[k][0], - // d[i-1][j+1].g[k][0], d[i-1][j-1].g[k][0], - // d[i][j].g[k][0] ); - // } + if( i != 0 && i != d.size()-1 ) { + double lm = Geom::distance( d[i-1][j].p, d[i][j].p ); + double lp = Geom::distance( d[i+1][j].p, d[i][j].p ); + d[i][j].g[k][1] = find_slope1( d[i-1][j].g[k][0], d[i][j].g[k][0], d[i+1][j].g[k][0], lm, lp ); + } - } else { - // Catmul-Rom - if( i != 0 && i != d.size()-1 ) { - double d2 = Geom::distance( d[i-1][j].p, d[i+1][j].p ); - d[i][j].g[k][1] = (d[i+1][j].g[k][0] - d[i-1][j].g[k][0])/d2; - } - if( j != 0 && j != d[i].size()-1 ) { - double d2 = Geom::distance( d[i][j-1].p, d[i][j+1].p ); - d[i][j].g[k][2] = (d[i][j+1].g[k][0] - d[i][j-1].g[k][0])/d2; - } + // dy + if( j != 0 && j != d[i].size()-1 ) { + double lm = Geom::distance( d[i][j-1].p, d[i][j].p ); + double lp = Geom::distance( d[i][j+1].p, d[i][j].p ); + d[i][j].g[k][2] = find_slope1( d[i][j-1].g[k][0], d[i][j].g[k][0], d[i][j+1].g[k][0], lm, lp ); } + + // dxdy if needed, need to take lengths into account + // if( i != 0 && i != d.size()-1 && j != 0 && j != d[i].size()-1 ) { + // d[i][j].g[k][3] = find_slope2( d[i-1][j-1].g[k][0], d[i+1][j-1].g[k][0], + // d[i-1][j+1].g[k][0], d[i-1][j-1].g[k][0], + // d[i][j].g[k][0] ); + // } + } } } @@ -1954,80 +1648,42 @@ void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) { // have the non-exterior derivative calculated for finding the parabola. for( unsigned j = 0; j< d[0].size(); ++j ) { for( unsigned k = 0; k < 3; ++k ) { // Loop over colors - unsigned z = d.size()-1; - if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) { - - // Parabolic - double d0 = Geom::distance( d[1][j].p, d[0 ][j].p ); - if( d0 > 0 ) { - d[0][j].g[k][1] = 2.0*(d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0 - d[1][j].g[k][1]; - } else { - d[0][j].g[k][1] = 0; - } - - double dz = Geom::distance( d[z][j].p, d[z-1][j].p ); - if( dz > 0 ) { - d[z][j].g[k][1] = 2.0*(d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz - d[z-1][j].g[k][1]; - } else { - d[z][j].g[k][1] = 0; - } + // Parabolic + double d0 = Geom::distance( d[1][j].p, d[0 ][j].p ); + if( d0 > 0 ) { + d[0][j].g[k][1] = 2.0*(d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0 - d[1][j].g[k][1]; } else { + d[0][j].g[k][1] = 0; + } - // Catmul-Rom - double d0 = Geom::distance( d[1][j].p, d[0 ][j].p ); - if( d0 > 0 ) { - d[0][j].g[k][1] = (d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0; - } else { - d[0][j].g[k][1] = 0; - } - - double dz = Geom::distance( d[z][j].p, d[z-1][j].p ); - if( dz > 0 ) { - d[z][j].g[k][1] = (d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz; - } else { - d[z][j].g[k][1] = 0; - } + unsigned z = d.size()-1; + double dz = Geom::distance( d[z][j].p, d[z-1][j].p ); + if( dz > 0 ) { + d[z][j].g[k][1] = 2.0*(d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz - d[z-1][j].g[k][1]; + } else { + d[z][j].g[k][1] = 0; } } } for( unsigned i = 0; i< d.size(); ++i ) { for( unsigned k = 0; k < 3; ++k ) { // Loop over colors - unsigned z = d[0].size()-1; - if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) { - - // Parabolic - double d0 = Geom::distance( d[i][1].p, d[i][0 ].p ); - if( d0 > 0 ) { - d[i][0].g[k][2] = 2.0*(d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0 - d[i][1].g[k][2]; - } else { - d[i][0].g[k][2] = 0; - } - double dz = Geom::distance( d[i][z].p, d[i][z-1].p ); - if( dz > 0 ) { - d[i][z].g[k][2] = 2.0*(d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz - d[i][z-1].g[k][2]; - } else { - d[i][z].g[k][2] = 0; - } - + // Parabolic + double d0 = Geom::distance( d[i][1].p, d[i][0 ].p ); + if( d0 > 0 ) { + d[i][0].g[k][2] = 2.0*(d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0 - d[i][1].g[k][2]; } else { + d[i][0].g[k][2] = 0; + } - // Catmul-Rom - double d0 = Geom::distance( d[i][1].p, d[i][0 ].p ); - if( d0 > 0 ) { - d[i][0].g[k][2] = (d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0; - } else { - d[i][0].g[k][2] = 0; - } - - double dz = Geom::distance( d[i][z].p, d[i][z-1].p ); - if( dz > 0 ) { - d[i][z].g[k][2] = (d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz; - } else { - d[i][z].g[k][2] = 0; - } + unsigned z = d[0].size()-1; + double dz = Geom::distance( d[i][z].p, d[i][z-1].p ); + if( dz > 0 ) { + d[i][z].g[k][2] = 2.0*(d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz - d[i][z-1].g[k][2]; + } else { + d[i][z].g[k][2] = 0; } } } diff --git a/src/sp-mesh-array.h b/src/sp-mesh-array.h index 19f8634f8..b078b221e 100644 --- a/src/sp-mesh-array.h +++ b/src/sp-mesh-array.h @@ -45,16 +45,14 @@ // For color picking #include "sp-item.h" -enum SPMeshSmooth { - SP_MESH_SMOOTH_NONE, - SP_MESH_SMOOTH_SMOOTH, - SP_MESH_SMOOTH_SMOOTH1, - SP_MESH_SMOOTH_SMOOTH2, - SP_MESH_SMOOTH_SMOOTH3, - SP_MESH_SMOOTH_SMOOTH4, - SP_MESH_SMOOTH_SMOOTH5, - SP_MESH_SMOOTH_SMOOTH6, - SP_MESH_SMOOTH_SMOOTH7 +enum SPMeshType { + SP_MESH_TYPE_COONS, + SP_MESH_TYPE_BICUBIC +}; + +enum SPMeshGeometry { + SP_MESH_GEOMETRY_NORMAL, + SP_MESH_GEOMETRY_CONICAL }; enum NodeType { @@ -137,14 +135,14 @@ public: void setOpacity( unsigned int i, double o ); }; -class SPMeshGradient; +class SPMesh; // An array of mesh nodes. class SPMeshNodeArray { // Should be private public: - SPMeshGradient *mg; + SPMesh *mg; std::vector< std::vector< SPMeshNode* > > nodes; public: @@ -159,22 +157,21 @@ public: friend class SPMeshPatchI; SPMeshNodeArray() { built = false; mg = NULL; drag_valid = false; }; - SPMeshNodeArray( SPMeshGradient *mg ); + SPMeshNodeArray( SPMesh *mg ); SPMeshNodeArray( const SPMeshNodeArray& rhs ); SPMeshNodeArray& operator=(const SPMeshNodeArray& rhs); ~SPMeshNodeArray() { clear(); }; bool built; - void read( SPMeshGradient *mg ); - void write( SPMeshGradient *mg ); - void create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox ); + void read( SPMesh *mg ); + void write( SPMesh *mg ); + void create( SPMesh *mg, SPItem *item, Geom::OptRect bbox ); void clear(); void print(); // Fill 'smooth' with a smoothed version by subdividing each patch. - void smooth( SPMeshNodeArray* smooth, SPMeshSmooth type); - void smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type); + void bicubic( SPMeshNodeArray* smooth, SPMeshType type); // Get size of patch unsigned int patch_rows(); diff --git a/src/sp-mesh-gradient.cpp b/src/sp-mesh-gradient.cpp deleted file mode 100644 index 3301d257c..000000000 --- a/src/sp-mesh-gradient.cpp +++ /dev/null @@ -1,299 +0,0 @@ -#include - -#include "attributes.h" -#include "display/cairo-utils.h" -#include "xml/repr.h" - -#include "sp-mesh-gradient.h" - -/* - * Mesh Gradient - */ -//#define MESH_DEBUG -SPMeshGradient::SPMeshGradient() : SPGradient(), smooth(SP_MESH_SMOOTH_NONE), smooth_set(false) { - // Start coordinate of mesh - this->x.unset(SVGLength::NONE, 0.0, 0.0); - this->y.unset(SVGLength::NONE, 0.0, 0.0); -} - -SPMeshGradient::~SPMeshGradient() { -} - -void SPMeshGradient::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPGradient::build(document, repr); - - // Start coordinate of mesh - this->readAttr( "x" ); - this->readAttr( "y" ); - - this->readAttr( "smooth" ); -} - - -void SPMeshGradient::set(unsigned key, gchar const *value) { - switch (key) { - case SP_ATTR_X: - if (!this->x.read(value)) { - this->x.unset(SVGLength::NONE, 0.0, 0.0); - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_Y: - if (!this->y.read(value)) { - this->y.unset(SVGLength::NONE, 0.0, 0.0); - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_SMOOTH: - if (value) { - if (!strcmp(value, "none")) { - this->smooth = SP_MESH_SMOOTH_NONE; - } else if (!strcmp(value, "smooth")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH; - } else if (!strcmp(value, "smooth1")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH1; - } else if (!strcmp(value, "smooth2")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH2; - } else if (!strcmp(value, "smooth3")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH3; - } else if (!strcmp(value, "smooth4")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH4; - } else if (!strcmp(value, "smooth5")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH5; - } else if (!strcmp(value, "smooth6")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH6; - } else if (!strcmp(value, "smooth7")) { - this->smooth = SP_MESH_SMOOTH_SMOOTH7; - } else { - std::cout << "SPMeshGradient::set(): invalid value " << value << std::endl; - } - this->smooth_set = TRUE; - } else { - // std::cout << "SPMeshGradient::set() No value " << std::endl; - this->smooth = SP_MESH_SMOOTH_NONE; - this->smooth_set = FALSE; - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - default: - SPGradient::set(key, value); - break; - } -} - -/** - * Write mesh gradient attributes to associated repr. - */ -Inkscape::XML::Node* SPMeshGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { -#ifdef MESH_DEBUG - std::cout << "sp_meshgradient_write() ***************************" << std::endl; -#endif - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:meshGradient"); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || this->x._set) { - sp_repr_set_svg_double(repr, "x", this->x.computed); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || this->y._set) { - sp_repr_set_svg_double(repr, "y", this->y.computed); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || this->smooth_set) { - switch (this->smooth) { - case SP_MESH_SMOOTH_SMOOTH: - repr->setAttribute("smooth", "smooth"); - break; - case SP_MESH_SMOOTH_SMOOTH1: - repr->setAttribute("smooth", "smooth1"); - break; - case SP_MESH_SMOOTH_SMOOTH2: - repr->setAttribute("smooth", "smooth2"); - break; - case SP_MESH_SMOOTH_SMOOTH3: - repr->setAttribute("smooth", "smooth3"); - break; - case SP_MESH_SMOOTH_SMOOTH4: - repr->setAttribute("smooth", "smooth4"); - break; - case SP_MESH_SMOOTH_SMOOTH5: - repr->setAttribute("smooth", "smooth5"); - break; - case SP_MESH_SMOOTH_SMOOTH6: - repr->setAttribute("smooth", "smooth6"); - break; - case SP_MESH_SMOOTH_SMOOTH7: - repr->setAttribute("smooth", "smooth7"); - break; - case SP_MESH_SMOOTH_NONE: - repr->setAttribute("smooth", "none"); - break; - default: - // Do nothing - break; - } - } - - SPGradient::write(xml_doc, repr, flags); - - return repr; -} - -void -sp_meshgradient_repr_write(SPMeshGradient *mg) -{ - mg->array.write( mg ); -} - - -cairo_pattern_t* SPMeshGradient::pattern_new(cairo_t * /*ct*/, -#if defined(MESH_DEBUG) || (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4)) - Geom::OptRect const &bbox, - double opacity -#else - Geom::OptRect const & /*bbox*/, - double /*opacity*/ -#endif - ) -{ - using Geom::X; - using Geom::Y; - -#ifdef MESH_DEBUG - std::cout << "sp_meshgradient_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl; -#endif - - this->ensureArray(); - - cairo_pattern_t *cp = NULL; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4) - SPMeshNodeArray* my_array = &array; - - if( smooth_set ) { - switch (smooth) { - case SP_MESH_SMOOTH_NONE: - // std::cout << "SPMeshGradient::pattern_new: no smoothing" << std::endl; - break; - case SP_MESH_SMOOTH_SMOOTH1: - case SP_MESH_SMOOTH_SMOOTH2: - case SP_MESH_SMOOTH_SMOOTH3: - case SP_MESH_SMOOTH_SMOOTH4: - case SP_MESH_SMOOTH_SMOOTH5: - // std::cout << "SPMeshGradient::pattern_new: calling array.smooth" << std::endl; - array.smooth( &array_smoothed, smooth ); - my_array = &array_smoothed; - break; - case SP_MESH_SMOOTH_SMOOTH: - case SP_MESH_SMOOTH_SMOOTH6: - case SP_MESH_SMOOTH_SMOOTH7: - // std::cout << "SPMeshGradient::pattern_new: calling array.smooth2" << std::endl; - array.smooth2( &array_smoothed, smooth ); - my_array = &array_smoothed; - break; - } - } - - cp = cairo_pattern_create_mesh(); - - for( unsigned int i = 0; i < my_array->patch_rows(); ++i ) { - for( unsigned int j = 0; j < my_array->patch_columns(); ++j ) { - - SPMeshPatchI patch( &(my_array->nodes), i, j ); - - cairo_mesh_pattern_begin_patch( cp ); - cairo_mesh_pattern_move_to( cp, patch.getPoint( 0, 0 )[X], patch.getPoint( 0, 0 )[Y] ); - - for( unsigned int k = 0; k < 4; ++k ) { -#ifdef DEBUG_MESH - std::cout << i << " " << j << " " - << patch.getPathType( k ) << " ("; - for( int p = 0; p < 4; ++p ) { - std::cout << patch.getPoint( k, p ); - } - std::cout << ") " - << patch.getColor( k ).toString() << std::endl; -#endif - - switch ( patch.getPathType( k ) ) { - case 'l': - case 'L': - case 'z': - case 'Z': - cairo_mesh_pattern_line_to( cp, - patch.getPoint( k, 3 )[X], - patch.getPoint( k, 3 )[Y] ); - break; - case 'c': - case 'C': - { - std::vector< Geom::Point > pts = patch.getPointsForSide( k ); - cairo_mesh_pattern_curve_to( cp, - pts[1][X], pts[1][Y], - pts[2][X], pts[2][Y], - pts[3][X], pts[3][Y] ); - break; - } - default: - // Shouldn't happen - std::cout << "sp_meshgradient_create_pattern: path error" << std::endl; - } - - if( patch.tensorIsSet(k) ) { - // Tensor point defined relative to corner. - Geom::Point t = patch.getTensorPoint(k); - cairo_mesh_pattern_set_control_point( cp, k, t[X], t[Y] ); - //std::cout << " sp_meshgradient_create_pattern: tensor " << k - // << " set to " << t << "." << std::endl; - } else { - // Geom::Point t = patch.coonsTensorPoint(k); - //std::cout << " sp_meshgradient_create_pattern: tensor " << k - // << " calculated as " << t << "." <gradientTransform; - if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top()); - gs2user *= bbox2user; - } - ink_cairo_pattern_set_matrix(cp, gs2user.inverse()); - -#else - static bool shown = false; - if( !shown ) { - std::cout << "sp_meshgradient_create_pattern: needs cairo >= 1.11.4, using " - << cairo_version_string() << std::endl; - shown = true; - } -#endif - -/* - cairo_pattern_t *cp = cairo_pattern_create_radial( - rg->fx.computed, rg->fy.computed, 0, - rg->cx.computed, rg->cy.computed, rg->r.computed); - sp_gradient_pattern_common_setup(cp, gr, bbox, opacity); -*/ - - return cp; -} diff --git a/src/sp-mesh-gradient.h b/src/sp-mesh-gradient.h deleted file mode 100644 index 343cae840..000000000 --- a/src/sp-mesh-gradient.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SP_MESH_GRADIENT_H -#define SP_MESH_GRADIENT_H - -/** \file - * SPMeshGradient: SVG implementation. - */ - -#include "svg/svg-length.h" -#include "sp-gradient.h" - -#define SP_MESHGRADIENT(obj) (dynamic_cast((SPObject*)obj)) -#define SP_IS_MESHGRADIENT(obj) (dynamic_cast((SPObject*)obj) != NULL) - -/** Mesh gradient. */ -class SPMeshGradient : public SPGradient { -public: - SPMeshGradient(); - virtual ~SPMeshGradient(); - - SVGLength x; // Upper left corner of mesh - SVGLength y; // Upper right corner of mesh - SPMeshSmooth smooth; - bool smooth_set; - virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity); - -protected: - virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual void set(unsigned key, char const *value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); -}; - -#endif /* !SP_MESH_GRADIENT_H */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/sp-mesh-patch.cpp b/src/sp-mesh-patch.cpp index e7c7c837d..834c09935 100644 --- a/src/sp-mesh-patch.cpp +++ b/src/sp-mesh-patch.cpp @@ -20,9 +20,9 @@ #include "attributes.h" #include "xml/repr.h" -SPMeshPatch* SPMeshPatch::getNextMeshPatch() +SPMeshpatch* SPMeshpatch::getNextMeshpatch() { - SPMeshPatch *result = 0; + SPMeshpatch *result = 0; for (SPObject* obj = getNext(); obj && !result; obj = obj->getNext()) { if (SP_IS_MESHPATCH(obj)) { @@ -33,19 +33,19 @@ SPMeshPatch* SPMeshPatch::getNextMeshPatch() return result; } -SPMeshPatch* SPMeshPatch::getPrevMeshPatch() +SPMeshpatch* SPMeshpatch::getPrevMeshpatch() { - SPMeshPatch *result = 0; + SPMeshpatch *result = 0; for (SPObject* obj = getPrev(); obj; obj = obj->getPrev()) { - // The closest previous SPObject that is an SPMeshPatch *should* be ourself. + // The closest previous SPObject that is an SPMeshpatch *should* be ourself. if (SP_IS_MESHPATCH(obj)) { - SPMeshPatch* meshpatch = SP_MESHPATCH(obj); + SPMeshpatch* meshpatch = SP_MESHPATCH(obj); // Sanity check to ensure we have a proper sibling structure. - if (meshpatch->getNextMeshPatch() == this) { + if (meshpatch->getNextMeshpatch() == this) { result = meshpatch; } else { - g_warning("SPMeshPatch previous/next relationship broken"); + g_warning("SPMeshpatch previous/next relationship broken"); } break; } @@ -59,14 +59,14 @@ SPMeshPatch* SPMeshPatch::getPrevMeshPatch() * Mesh Patch */ -SPMeshPatch::SPMeshPatch() : SPObject() { +SPMeshpatch::SPMeshpatch() : SPObject() { this->tensor_string = NULL; } -SPMeshPatch::~SPMeshPatch() { +SPMeshpatch::~SPMeshpatch() { } -void SPMeshPatch::build(SPDocument* doc, Inkscape::XML::Node* repr) { +void SPMeshpatch::build(SPDocument* doc, Inkscape::XML::Node* repr) { SPObject::build(doc, repr); this->readAttr( "tensor" ); @@ -76,7 +76,7 @@ void SPMeshPatch::build(SPDocument* doc, Inkscape::XML::Node* repr) { * Virtual build: set meshpatch attributes from its associated XML node. */ -void SPMeshPatch::set(unsigned int key, const gchar* value) { +void SPMeshpatch::set(unsigned int key, const gchar* value) { switch (key) { case SP_ATTR_TENSOR: { if (value) { @@ -95,9 +95,9 @@ void SPMeshPatch::set(unsigned int key, const gchar* value) { * Virtual set: set attribute to value. */ -Inkscape::XML::Node* SPMeshPatch::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { +Inkscape::XML::Node* SPMeshpatch::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:meshPatch"); + repr = xml_doc->createElement("svg:meshpatch"); } SPObject::write(xml_doc, repr, flags); diff --git a/src/sp-mesh-patch.h b/src/sp-mesh-patch.h index e57ad1699..88d6325c3 100644 --- a/src/sp-mesh-patch.h +++ b/src/sp-mesh-patch.h @@ -2,7 +2,7 @@ #define SEEN_SP_MESHPATCH_H /** \file - * SPMeshPatch: SVG implementation. + * SPMeshpatch: SVG implementation. */ /* * Authors: Tavmjong Bah @@ -15,17 +15,17 @@ #include #include "sp-object.h" -#define SP_MESHPATCH(obj) (dynamic_cast((SPObject*)obj)) -#define SP_IS_MESHPATCH(obj) (dynamic_cast((SPObject*)obj) != NULL) +#define SP_MESHPATCH(obj) (dynamic_cast((SPObject*)obj)) +#define SP_IS_MESHPATCH(obj) (dynamic_cast((SPObject*)obj) != NULL) -/** Gradient MeshPatch. */ -class SPMeshPatch : public SPObject { +/** Gradient Meshpatch. */ +class SPMeshpatch : public SPObject { public: - SPMeshPatch(); - virtual ~SPMeshPatch(); + SPMeshpatch(); + virtual ~SPMeshpatch(); - SPMeshPatch* getNextMeshPatch(); - SPMeshPatch* getPrevMeshPatch(); + SPMeshpatch* getNextMeshpatch(); + SPMeshpatch* getPrevMeshpatch(); Glib::ustring * tensor_string; //SVGLength tx[4]; // Tensor points //SVGLength ty[4]; // Tensor points diff --git a/src/sp-mesh-row.cpp b/src/sp-mesh-row.cpp index f95909b63..dd7948bdf 100644 --- a/src/sp-mesh-row.cpp +++ b/src/sp-mesh-row.cpp @@ -1,5 +1,5 @@ /** @file - * @gradient meshpatch class. + * @gradient meshrow class. */ /* Authors: * Lauris Kaplinski @@ -19,9 +19,9 @@ #include "xml/repr.h" -SPMeshRow* SPMeshRow::getNextMeshRow() +SPMeshrow* SPMeshrow::getNextMeshrow() { - SPMeshRow *result = 0; + SPMeshrow *result = 0; for (SPObject* obj = getNext(); obj && !result; obj = obj->getNext()) { if (SP_IS_MESHROW(obj)) { @@ -32,19 +32,19 @@ SPMeshRow* SPMeshRow::getNextMeshRow() return result; } -SPMeshRow* SPMeshRow::getPrevMeshRow() +SPMeshrow* SPMeshrow::getPrevMeshrow() { - SPMeshRow *result = 0; + SPMeshrow *result = 0; for (SPObject* obj = getPrev(); obj; obj = obj->getPrev()) { - // The closest previous SPObject that is an SPMeshRow *should* be ourself. + // The closest previous SPObject that is an SPMeshrow *should* be ourself. if (SP_IS_MESHROW(obj)) { - SPMeshRow* meshrow = SP_MESHROW(obj); + SPMeshrow* meshrow = SP_MESHROW(obj); // Sanity check to ensure we have a proper sibling structure. - if (meshrow->getNextMeshRow() == this) { + if (meshrow->getNextMeshrow() == this) { result = meshrow; } else { - g_warning("SPMeshRow previous/next relationship broken"); + g_warning("SPMeshrow previous/next relationship broken"); } break; } @@ -57,13 +57,13 @@ SPMeshRow* SPMeshRow::getPrevMeshRow() /* * Mesh Row */ -SPMeshRow::SPMeshRow() : SPObject() { +SPMeshrow::SPMeshrow() : SPObject() { } -SPMeshRow::~SPMeshRow() { +SPMeshrow::~SPMeshrow() { } -void SPMeshRow::build(SPDocument* doc, Inkscape::XML::Node* repr) { +void SPMeshrow::build(SPDocument* doc, Inkscape::XML::Node* repr) { SPObject::build(doc, repr); } @@ -71,16 +71,16 @@ void SPMeshRow::build(SPDocument* doc, Inkscape::XML::Node* repr) { * Virtual build: set meshrow attributes from its associated XML node. */ -void SPMeshRow::set(unsigned int /*key*/, const gchar* /*value*/) { +void SPMeshrow::set(unsigned int /*key*/, const gchar* /*value*/) { } /** * Virtual set: set attribute to value. */ -Inkscape::XML::Node* SPMeshRow::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { +Inkscape::XML::Node* SPMeshrow::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:meshRow"); + repr = xml_doc->createElement("svg:meshrow"); } SPObject::write(xml_doc, repr, flags); diff --git a/src/sp-mesh-row.h b/src/sp-mesh-row.h index 793b5a645..ffb3efa6b 100644 --- a/src/sp-mesh-row.h +++ b/src/sp-mesh-row.h @@ -2,7 +2,7 @@ #define SEEN_SP_MESHROW_H /** \file - * SPMeshRow: SVG implementation. + * SPMeshrow: SVG implementation. */ /* * Authors: Tavmjong Bah @@ -13,17 +13,17 @@ #include "sp-object.h" -#define SP_MESHROW(obj) (dynamic_cast((SPObject*)obj)) -#define SP_IS_MESHROW(obj) (dynamic_cast((SPObject*)obj) != NULL) +#define SP_MESHROW(obj) (dynamic_cast((SPObject*)obj)) +#define SP_IS_MESHROW(obj) (dynamic_cast((SPObject*)obj) != NULL) -/** Gradient MeshRow. */ -class SPMeshRow : public SPObject { +/** Gradient Meshrow. */ +class SPMeshrow : public SPObject { public: - SPMeshRow(); - virtual ~SPMeshRow(); + SPMeshrow(); + virtual ~SPMeshrow(); - SPMeshRow* getNextMeshRow(); - SPMeshRow* getPrevMeshRow(); + SPMeshrow* getNextMeshrow(); + SPMeshrow* getPrevMeshrow(); protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); diff --git a/src/sp-mesh.cpp b/src/sp-mesh.cpp new file mode 100644 index 000000000..0b1eb4509 --- /dev/null +++ b/src/sp-mesh.cpp @@ -0,0 +1,252 @@ +#include + +#include "attributes.h" +#include "display/cairo-utils.h" +#include "xml/repr.h" + +#include "sp-mesh.h" + +/* + * Mesh Gradient + */ +//#define MESH_DEBUG +SPMesh::SPMesh() : SPGradient(), type( SP_MESH_TYPE_COONS ), type_set(false) { + // Start coordinate of mesh + this->x.unset(SVGLength::NONE, 0.0, 0.0); + this->y.unset(SVGLength::NONE, 0.0, 0.0); +} + +SPMesh::~SPMesh() { +} + +void SPMesh::build(SPDocument *document, Inkscape::XML::Node *repr) { + SPGradient::build(document, repr); + + // Start coordinate of mesh + this->readAttr( "x" ); + this->readAttr( "y" ); + + this->readAttr( "type" ); +} + + +void SPMesh::set(unsigned key, gchar const *value) { + switch (key) { + case SP_ATTR_X: + if (!this->x.read(value)) { + this->x.unset(SVGLength::NONE, 0.0, 0.0); + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_Y: + if (!this->y.read(value)) { + this->y.unset(SVGLength::NONE, 0.0, 0.0); + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_MESH_TYPE: + if (value) { + if (!strcmp(value, "coons")) { + this->type = SP_MESH_TYPE_COONS; + } else if (!strcmp(value, "bicubic")) { + this->type = SP_MESH_TYPE_BICUBIC; + } else { + std::cout << "SPMesh::set(): invalid value " << value << std::endl; + } + this->type_set = TRUE; + } else { + // std::cout << "SPMesh::set() No value " << std::endl; + this->type = SP_MESH_TYPE_COONS; + this->type_set = FALSE; + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + default: + SPGradient::set(key, value); + break; + } +} + +/** + * Write mesh gradient attributes to associated repr. + */ +Inkscape::XML::Node* SPMesh::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { +#ifdef MESH_DEBUG + std::cout << "sp_mesh_write() ***************************" << std::endl; +#endif + + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("svg:mesh"); + } + + if ((flags & SP_OBJECT_WRITE_ALL) || this->x._set) { + sp_repr_set_svg_double(repr, "x", this->x.computed); + } + + if ((flags & SP_OBJECT_WRITE_ALL) || this->y._set) { + sp_repr_set_svg_double(repr, "y", this->y.computed); + } + + if ((flags & SP_OBJECT_WRITE_ALL) || this->type_set) { + switch (this->type) { + case SP_MESH_TYPE_COONS: + repr->setAttribute("type", "coons"); + break; + case SP_MESH_TYPE_BICUBIC: + repr->setAttribute("type", "bicubic"); + break; + default: + // Do nothing + break; + } + } + + SPGradient::write(xml_doc, repr, flags); + + return repr; +} + +void +sp_mesh_repr_write(SPMesh *mg) +{ + mg->array.write( mg ); +} + + +cairo_pattern_t* SPMesh::pattern_new(cairo_t * /*ct*/, +#if defined(MESH_DEBUG) || (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4)) + Geom::OptRect const &bbox, + double opacity +#else + Geom::OptRect const & /*bbox*/, + double /*opacity*/ +#endif + ) +{ + using Geom::X; + using Geom::Y; + +#ifdef MESH_DEBUG + std::cout << "sp_mesh_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl; +#endif + + this->ensureArray(); + + cairo_pattern_t *cp = NULL; + +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4) + SPMeshNodeArray* my_array = &array; + + if( type_set ) { + switch (type) { + case SP_MESH_TYPE_COONS: + // std::cout << "SPMesh::pattern_new: Coons" << std::endl; + break; + case SP_MESH_TYPE_BICUBIC: + array.bicubic( &array_smoothed, type ); + my_array = &array_smoothed; + break; + } + } + + cp = cairo_pattern_create_mesh(); + + for( unsigned int i = 0; i < my_array->patch_rows(); ++i ) { + for( unsigned int j = 0; j < my_array->patch_columns(); ++j ) { + + SPMeshPatchI patch( &(my_array->nodes), i, j ); + + cairo_mesh_pattern_begin_patch( cp ); + cairo_mesh_pattern_move_to( cp, patch.getPoint( 0, 0 )[X], patch.getPoint( 0, 0 )[Y] ); + + for( unsigned int k = 0; k < 4; ++k ) { +#ifdef DEBUG_MESH + std::cout << i << " " << j << " " + << patch.getPathType( k ) << " ("; + for( int p = 0; p < 4; ++p ) { + std::cout << patch.getPoint( k, p ); + } + std::cout << ") " + << patch.getColor( k ).toString() << std::endl; +#endif + + switch ( patch.getPathType( k ) ) { + case 'l': + case 'L': + case 'z': + case 'Z': + cairo_mesh_pattern_line_to( cp, + patch.getPoint( k, 3 )[X], + patch.getPoint( k, 3 )[Y] ); + break; + case 'c': + case 'C': + { + std::vector< Geom::Point > pts = patch.getPointsForSide( k ); + cairo_mesh_pattern_curve_to( cp, + pts[1][X], pts[1][Y], + pts[2][X], pts[2][Y], + pts[3][X], pts[3][Y] ); + break; + } + default: + // Shouldn't happen + std::cout << "sp_mesh_create_pattern: path error" << std::endl; + } + + if( patch.tensorIsSet(k) ) { + // Tensor point defined relative to corner. + Geom::Point t = patch.getTensorPoint(k); + cairo_mesh_pattern_set_control_point( cp, k, t[X], t[Y] ); + //std::cout << " sp_mesh_create_pattern: tensor " << k + // << " set to " << t << "." << std::endl; + } else { + // Geom::Point t = patch.coonsTensorPoint(k); + //std::cout << " sp_mesh_create_pattern: tensor " << k + // << " calculated as " << t << "." <gradientTransform; + if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top()); + gs2user *= bbox2user; + } + ink_cairo_pattern_set_matrix(cp, gs2user.inverse()); + +#else + static bool shown = false; + if( !shown ) { + std::cout << "sp_mesh_create_pattern: needs cairo >= 1.11.4, using " + << cairo_version_string() << std::endl; + shown = true; + } +#endif + + /* + cairo_pattern_t *cp = cairo_pattern_create_radial( + rg->fx.computed, rg->fy.computed, 0, + rg->cx.computed, rg->cy.computed, rg->r.computed); + sp_gradient_pattern_common_setup(cp, gr, bbox, opacity); + */ + + return cp; +} diff --git a/src/sp-mesh.h b/src/sp-mesh.h new file mode 100644 index 000000000..6f992d034 --- /dev/null +++ b/src/sp-mesh.h @@ -0,0 +1,43 @@ +#ifndef SP_MESH_H +#define SP_MESH_H + +/** \file + * SPMesh: SVG implementation. + */ + +#include "svg/svg-length.h" +#include "sp-gradient.h" + +#define SP_MESH(obj) (dynamic_cast((SPObject*)obj)) +#define SP_IS_MESH(obj) (dynamic_cast((SPObject*)obj) != NULL) + +/** Mesh gradient. */ +class SPMesh : public SPGradient { +public: + SPMesh(); + virtual ~SPMesh(); + + SVGLength x; // Upper left corner of mesh + SVGLength y; // Upper right corner of mesh + SPMeshType type; + bool type_set; + virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity); + +protected: + virtual void build(SPDocument *document, Inkscape::XML::Node *repr); + virtual void set(unsigned key, char const *value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); +}; + +#endif /* !SP_MESH_H */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 9527b7de8..67ed7aef1 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -48,7 +48,7 @@ // Mesh specific #include "ui/tools/mesh-tool.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "display/sp-ctrlcurve.h" using Inkscape::DocumentUndo; @@ -162,9 +162,9 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { // if (style && (style->fill.isPaintserver())) { // SPPaintServer *server = item->style->getFillPaintServer(); - // if ( SP_IS_MESHGRADIENT(server) ) { + // if ( SP_IS_MESH(server) ) { - // SPMeshGradient *mg = SP_MESHGRADIENT(server); + // SPMesh *mg = SP_MESH(server); // guint rows = 0;//mg->array.patches.size(); // for ( guint i = 0; i < rows; ++i ) { @@ -327,8 +327,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) SPDocument *doc = NULL; GrDrag *drag = rc->_grdrag; - std::map > points; - std::map items; + std::map > points; + std::map items; // Get list of selected draggers for each mesh. // For all selected draggers @@ -342,7 +342,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) if( d->point_type != POINT_MG_CORNER ) continue; // Find the gradient - SPMeshGradient *gradient = SP_MESHGRADIENT( getGradient (d->item, d->fill_or_stroke) ); + SPMesh *gradient = SP_MESH( getGradient (d->item, d->fill_or_stroke) ); // Collect points together for same gradient points[gradient].push_back( d->point_i ); @@ -351,8 +351,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) } // Loop over meshes. - for( std::map >::const_iterator iter = points.begin(); iter != points.end(); ++iter) { - SPMeshGradient *mg = SP_MESHGRADIENT( iter->first ); + for( std::map >::const_iterator iter = points.begin(); iter != points.end(); ++iter) { + SPMesh *mg = SP_MESH( iter->first ); if( iter->second.size() > 0 ) { guint noperation = 0; switch (operation) { diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 1fc67dcef..9e283fc64 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -25,8 +25,8 @@ #include "desktop-style.h" #include "sp-namedview.h" #include "sp-linear-gradient.h" -#include "sp-mesh-gradient.h" #include "sp-radial-gradient.h" +#include "sp-mesh.h" #include "sp-pattern.h" #include "ui/dialog/dialog-manager.h" #include "ui/dialog/fill-and-stroke.h" @@ -1045,7 +1045,7 @@ SelectedStyle::update() place->set_tooltip_text(__rgradient[i]); _mode[i] = SS_RGRADIENT; #ifdef WITH_MESH - } else if (SP_IS_MESHGRADIENT(server)) { + } else if (SP_IS_MESH(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(_gradient_preview_m[i]), vector); place->add(_gradient_box_m[i]); diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp index 3d549047a..bf406e632 100644 --- a/src/widgets/mesh-toolbar.cpp +++ b/src/widgets/mesh-toolbar.cpp @@ -44,7 +44,7 @@ #include "ui/tools/gradient-tool.h" #include "ui/tools/mesh-tool.h" #include "gradient-drag.h" -#include "sp-mesh-gradient.h" +#include "sp-mesh.h" #include "gradient-chemistry.h" #include "gradient-selector.h" #include "selection.h" @@ -77,15 +77,15 @@ static bool blocked = false; * Get the current selection and dragger status from the desktop */ void ms_read_selection( Inkscape::Selection *selection, - SPMeshGradient *&ms_selected, + SPMesh *&ms_selected, bool &ms_selected_multi, - SPMeshSmooth &ms_smooth, - bool &ms_smooth_multi ) + SPMeshType &ms_type, + bool &ms_type_multi ) { // Read desktop selection bool first = true; - ms_smooth = SP_MESH_SMOOTH_NONE; + ms_type = SP_MESH_TYPE_COONS; for (GSList const* i = selection->itemList(); i; i = i->next) { SPItem *item = SP_ITEM(i->data); @@ -93,10 +93,10 @@ void ms_read_selection( Inkscape::Selection *selection, if (style && (style->fill.isPaintserver())) { SPPaintServer *server = item->style->getFillPaintServer(); - if ( SP_IS_MESHGRADIENT(server) ) { + if ( SP_IS_MESH(server) ) { - SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector(); - SPMeshSmooth smooth = gradient->smooth; + SPMesh *gradient = SP_MESH(server); // ->getVector(); + SPMeshType type = gradient->type; if (gradient != ms_selected) { if (ms_selected) { @@ -105,11 +105,11 @@ void ms_read_selection( Inkscape::Selection *selection, ms_selected = gradient; } } - if( smooth != ms_smooth ) { - if (ms_smooth != SP_MESH_SMOOTH_NONE && !first) { - ms_smooth_multi = true; + if( type != ms_type ) { + if (ms_type != SP_MESH_TYPE_COONS && !first) { + ms_type_multi = true; } else { - ms_smooth = smooth; + ms_type = type; } } first = false; @@ -118,10 +118,10 @@ void ms_read_selection( Inkscape::Selection *selection, if (style && (style->stroke.isPaintserver())) { SPPaintServer *server = item->style->getStrokePaintServer(); - if ( SP_IS_MESHGRADIENT(server) ) { + if ( SP_IS_MESH(server) ) { - SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector(); - SPMeshSmooth smooth = gradient->smooth; + SPMesh *gradient = SP_MESH(server); // ->getVector(); + SPMeshType type = gradient->type; if (gradient != ms_selected) { if (ms_selected) { @@ -130,11 +130,11 @@ void ms_read_selection( Inkscape::Selection *selection, ms_selected = gradient; } } - if( smooth != ms_smooth ) { - if (ms_smooth != SP_MESH_SMOOTH_NONE && !first) { - ms_smooth_multi = true; + if( type != ms_type ) { + if (ms_type != SP_MESH_TYPE_COONS && !first) { + ms_type_multi = true; } else { - ms_smooth = smooth; + ms_type = type; } } first = false; @@ -170,18 +170,18 @@ static void ms_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe // // Hide/show handles? // } - SPMeshGradient *ms_selected = 0; - SPMeshSmooth ms_smooth = SP_MESH_SMOOTH_NONE; + SPMesh *ms_selected = 0; + SPMeshType ms_type = SP_MESH_TYPE_COONS; bool ms_selected_multi = false; - bool ms_smooth_multi = false; - ms_read_selection( selection, ms_selected, ms_selected_multi, ms_smooth, ms_smooth_multi ); - // std::cout << " smooth: " << ms_smooth << std::endl; + bool ms_type_multi = false; + ms_read_selection( selection, ms_selected, ms_selected_multi, ms_type, ms_type_multi ); + // std::cout << " type: " << ms_type << std::endl; - EgeSelectOneAction* smooth = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "mesh_select_smooth_action"); - gtk_action_set_sensitive( GTK_ACTION(smooth), (ms_selected && !ms_selected_multi) ); + EgeSelectOneAction* type = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "mesh_select_type_action"); + gtk_action_set_sensitive( GTK_ACTION(type), (ms_selected && !ms_selected_multi) ); if (ms_selected) { blocked = TRUE; - ege_select_one_action_set_active( smooth, ms_smooth ); + ege_select_one_action_set_active( type, ms_type ); blocked = FALSE; } } @@ -209,9 +209,9 @@ static void ms_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject *widg ms_tb_selection_changed(NULL, widget); } -void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient *&ms_selected) +void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMesh *&ms_selected) { - SPMeshGradient *gradient = 0; + SPMesh *gradient = 0; for (GSList const* i = selection->itemList(); i; i = i->next) { SPItem *item = SP_ITEM(i->data); // get the items gradient, not the getVector() version @@ -225,8 +225,8 @@ void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient server = item->style->getStrokePaintServer(); } - if ( SP_IS_MESHGRADIENT(server) ) { - gradient = SP_MESHGRADIENT(server); + if ( SP_IS_MESH(server) ) { + gradient = SP_MESH(server); } } @@ -240,11 +240,11 @@ void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient * Callback functions for user actions */ -static void ms_new_type_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) +static void ms_new_geometry_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gint typemode = ege_select_one_action_get_active( act ) == 0 ? SP_GRADIENT_MESH_TYPE_NORMAL : SP_GRADIENT_MESH_TYPE_CONICAL; - prefs->setInt("/tools/mesh/mesh_type", typemode); + gint geometrymode = ege_select_one_action_get_active( act ) == 0 ? SP_MESH_GEOMETRY_NORMAL : SP_MESH_GEOMETRY_CONICAL; + prefs->setInt("/tools/mesh/mesh_geometry", geometrymode); } static void ms_new_fillstroke_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) @@ -288,27 +288,27 @@ static void ms_col_changed(GtkAdjustment *adj, GObject * /*tbl*/ ) blocked = FALSE; } -static void ms_smooth_changed(EgeSelectOneAction *act, GtkWidget *widget) +static void ms_type_changed(EgeSelectOneAction *act, GtkWidget *widget) { - // std::cout << "ms_smooth_changed" << std::endl; + // std::cout << "ms_type_changed" << std::endl; if (blocked) { return; } SPDesktop *desktop = static_cast(g_object_get_data(G_OBJECT(widget), "desktop")); Inkscape::Selection *selection = desktop->getSelection(); - SPMeshGradient *gradient = 0; + SPMesh *gradient = 0; ms_get_dt_selected_gradient(selection, gradient); if (gradient) { - SPMeshSmooth smooth = (SPMeshSmooth) ege_select_one_action_get_active(act); - // std::cout << " smooth: " << smooth << std::endl; - gradient->smooth = smooth; - gradient->smooth_set = true; + SPMeshType type = (SPMeshType) ege_select_one_action_get_active(act); + // std::cout << " type: " << type << std::endl; + gradient->type = type; + gradient->type_set = true; gradient->updateRepr(); DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, - _("Set mesh smoothing")); + _("Set mesh type")); } } @@ -349,9 +349,9 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj ege_select_one_action_set_tooltip_column( act, 1 ); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gint mode = prefs->getInt("/tools/mesh/mesh_type", SP_GRADIENT_MESH_TYPE_NORMAL) != SP_GRADIENT_MESH_TYPE_NORMAL; + gint mode = prefs->getInt("/tools/mesh/mesh_geometry", SP_MESH_GEOMETRY_NORMAL) != SP_MESH_GEOMETRY_NORMAL; ege_select_one_action_set_active( act, mode ); - g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(ms_new_type_changed), holder ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(ms_new_geometry_changed), holder ); } /* New gradient on fill or stroke*/ @@ -460,51 +460,30 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj /* Warning */ { GtkAction* act = gtk_action_new( "MeshWarningAction", - _("WARNING: Mesh SVG Syntax Subject to Change, Smoothing Experimental"), NULL, NULL ); + _("WARNING: Mesh SVG Syntax Subject to Change"), NULL, NULL ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); } - /* Smoothing method */ + /* Typeing method */ { GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT ); GtkTreeIter iter; gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, C_("Smoothing", "None"), 1, SP_MESH_SMOOTH_NONE, -1 ); + gtk_list_store_set( model, &iter, 0, C_("Type", "Coons"), 1, SP_MESH_TYPE_COONS, -1 ); gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Default"), 1, SP_MESH_SMOOTH_SMOOTH, -1 ); + gtk_list_store_set( model, &iter, 0, _("Bicubic"), 1, SP_MESH_TYPE_BICUBIC, -1 ); - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth1"), 1, SP_MESH_SMOOTH_SMOOTH1, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth2"), 1, SP_MESH_SMOOTH_SMOOTH2, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth3"), 1, SP_MESH_SMOOTH_SMOOTH3, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth4"), 1, SP_MESH_SMOOTH_SMOOTH4, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth5"), 1, SP_MESH_SMOOTH_SMOOTH5, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth6"), 1, SP_MESH_SMOOTH_SMOOTH6, -1 ); - - gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, _("Smooth7"), 1, SP_MESH_SMOOTH_SMOOTH7, -1 ); - - EgeSelectOneAction* act = ege_select_one_action_new( "MeshSmoothAction", _("None"), - _("If the mesh should be smoothed across patch boundaries."), + EgeSelectOneAction* act = ege_select_one_action_new( "MeshSmoothAction", _("Coons"), + _("Coons: no smoothing. Bicubic: smoothing across patch boundaries."), NULL, GTK_TREE_MODEL(model) ); g_object_set( act, "short_label", _("Smoothing:"), NULL ); ege_select_one_action_set_appearance( act, "compact" ); gtk_action_set_sensitive( GTK_ACTION(act), FALSE ); - g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(ms_smooth_changed), holder ); + g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(ms_type_changed), holder ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); - g_object_set_data( holder, "mesh_select_smooth_action", act ); + g_object_set_data( holder, "mesh_select_type_action", act ); } } diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 6ef910f61..948c80db3 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -37,8 +37,8 @@ #include "sp-color-notebook.h" #include "sp-linear-gradient.h" -#include "sp-mesh-gradient.h" #include "sp-radial-gradient.h" +#include "sp-mesh.h" /* fixme: Move it from dialogs to here */ #include "gradient-selector.h" #include @@ -777,7 +777,7 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe } #ifdef WITH_MESH else { - SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL); + SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_MESH); gtk_label_set_markup(GTK_LABEL(psel->label), _("Mesh gradient")); } #endif @@ -1244,7 +1244,7 @@ SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, Fi } else if (SP_IS_RADIALGRADIENT(server)) { mode = MODE_GRADIENT_RADIAL; #ifdef WITH_MESH - } else if (SP_IS_MESHGRADIENT(server)) { + } else if (SP_IS_MESH(server)) { mode = MODE_GRADIENT_MESH; #endif } else if (SP_IS_PATTERN(server)) { -- cgit v1.2.3