summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/display/cairo-utils.cpp86
-rw-r--r--src/display/cairo-utils.h2
-rw-r--r--src/extension/internal/cairo-render-context.cpp6
-rw-r--r--src/gradient-chemistry.cpp34
-rw-r--r--src/gradient-drag.cpp50
-rw-r--r--src/gradient-drag.h6
-rw-r--r--src/helper/png-write.cpp77
-rw-r--r--src/helper/png-write.h6
-rw-r--r--src/live_effects/lpe-mirror_symmetry.cpp39
-rw-r--r--src/live_effects/lpe-mirror_symmetry.h1
-rw-r--r--src/live_effects/lpe-perspective-envelope.cpp4
-rw-r--r--src/main-cmdlineact.cpp117
-rw-r--r--src/main-cmdlineact.h12
-rw-r--r--src/sp-factory.cpp27
-rw-r--r--src/sp-gradient.cpp106
-rw-r--r--src/sp-gradient.h2
-rw-r--r--src/sp-item.cpp5
-rw-r--r--src/sp-mesh-array.cpp123
-rw-r--r--src/sp-mesh-array.h21
-rw-r--r--src/sp-mesh-gradient.cpp (renamed from src/sp-mesh.cpp)70
-rw-r--r--src/sp-mesh-gradient.h43
-rw-r--r--src/sp-mesh-patch.cpp31
-rw-r--r--src/sp-mesh-patch.h11
-rw-r--r--src/sp-mesh-row.cpp31
-rw-r--r--src/sp-mesh-row.h11
-rw-r--r--src/sp-mesh.h43
-rw-r--r--src/sp-object.cpp129
-rw-r--r--src/sp-object.h2
-rw-r--r--src/sp-rect.cpp36
-rw-r--r--src/sp-stop.cpp1
-rw-r--r--src/ui/dialog/align-and-distribute.cpp4
-rw-r--r--src/ui/dialog/export.cpp62
-rw-r--r--src/ui/dialog/export.h14
-rw-r--r--src/ui/dialog/xml-tree.cpp3
-rw-r--r--src/ui/tools/gradient-tool.cpp1
-rw-r--r--src/ui/tools/mesh-tool.cpp35
-rw-r--r--src/ui/widget/selected-style.cpp4
-rw-r--r--src/widgets/mesh-toolbar.cpp24
-rw-r--r--src/widgets/paint-selector.cpp4
40 files changed, 916 insertions, 371 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9928f9694..3c4f28aa8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -44,9 +44,9 @@ set(sp_SRC
sp-marker.cpp
sp-mask.cpp
sp-mesh-array.cpp
+ sp-mesh-gradient.cpp
sp-mesh-patch.cpp
sp-mesh-row.cpp
- sp-mesh.cpp
sp-metadata.cpp
sp-missing-glyph.cpp
sp-namedview.cpp
@@ -134,9 +134,9 @@ set(sp_SRC
sp-marker.h
sp-mask.h
sp-mesh-array.h
+ sp-mesh-gradient.h
sp-mesh-patch.h
sp-mesh-row.h
- sp-mesh.h
sp-metadata.h
sp-missing-glyph.h
sp-namedview.h
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 24a75de4c..a7625f4a1 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -13,6 +13,7 @@
#endif
#include "display/cairo-utils.h"
+#include <arpa/inet.h>
#include <stdexcept>
#include <glib/gstdio.h>
@@ -1321,6 +1322,91 @@ guint32 argb32_from_rgba(guint32 in)
return px;
}
+
+/**
+ * Converts a pixbuf to a PNG data structure.
+ * For 8-but RGBA png, this is like copying.
+ *
+ */
+const guchar* pixbuf_to_png(guchar const**rows, guchar* px, int num_rows, int num_cols, int stride, int color_type, int bit_depth)
+{
+ int n_fields = 1 + (color_type&2) + (color_type&4)/4;
+ const guchar* new_data = (const guchar*)malloc((n_fields * bit_depth * num_rows * num_cols)/8 + 64);
+ char* ptr = (char*) new_data;
+ int pad=0; //used when we write image data smaller than one byte (for instance in black and white images where 1px = 1bit)
+ for(int row = 0; row < num_rows; ++row){
+ rows[row] = (const guchar*)ptr;
+ for(int col = 0; col < num_cols; ++col){
+ guint32 *pixel = reinterpret_cast<guint32*>(px + row*stride)+col;
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ //this part should probably be rewritten as (a tested, working) big endian, using htons() and ntohs()
+ guint64 a = (*pixel & 0xff000000) >> 24;
+ guint64 b = (*pixel & 0x00ff0000) >> 16;
+ guint64 g = (*pixel & 0x0000ff00) >> 8;
+ guint64 r = (*pixel & 0x000000ff);
+
+ //one of possible rgb to greyscale formulas. This one is called "luminance, "luminosity" or "luma"
+ guint16 gray = (guint16)((guint32)((0.2126*(r<<24) + 0.7152*(g<<24) + 0.0722*(b<<24)))>>16);
+
+ if (!pad) *((guint64*)ptr)=0;
+ if (color_type & 2) { //RGB
+ // for 8bit->16bit transition, I take the FF -> FFFF convention (multiplication by 0x101).
+ // If you prefer FF -> FF00 (multiplication by 0x100), remove the <<8, <<24, <<40 and <<56
+ if (color_type & 4) { //RGBA
+ if (bit_depth==8)
+ *((guint32*)ptr) = *pixel;
+ else
+ *((guint64*)ptr) = (guint64)((a<<56)+(a<<48)+(b<<40)+(b<<32)+(g<<24)+(g<<16)+(r<<8)+(r));
+ }
+ else{ //no alpha
+ if(bit_depth==8)
+ *((guint32*)ptr) = ((*pixel)<<8)>>8;
+ else
+ *((guint64*)ptr) = (guint64)((b<<40)+(b<<32)+(g<<24)+(g<<16)+(r<<8)+r);
+ }
+ } else { //Grayscale
+ if(bit_depth==16)
+ *(guint16*)ptr= ((gray & 0xff00)>>8) + ((gray &0x00ff)<<8);
+ else *((guint16*)ptr) += guint16(((gray >> (16-bit_depth))<<pad) ); //note the "+="
+
+ if(color_type & 4) { //Alpha channel
+ if (bit_depth == 16)
+ *((guint32*)(ptr+2)) = a + (a<<8);
+ else
+ *((guint32*)(ptr)) += guint32((a << 8) >> (16 - bit_depth))<<(bit_depth + pad);
+ }
+ }
+
+#else
+ // I don't have any access to a big-endian machine to test this. It should still work with default export settings.
+ guint64 r = (*pixel & 0xff000000) >> 24;
+ guint64 g = (*pixel & 0x00ff0000) >> 16;
+ guint64 b = (*pixel & 0x0000ff00) >> 8;
+ guint64 a = (*pixel & 0x000000ff);
+ guint32 gray = (guint32)(0.2126*(r<<24) + 0.7152*(g<<24) + 0.0722*(b<<24));
+ if(color_type & 2){
+ if(bit_depth==8)*ptr = *pixel; else *ptr = (guint64)((r<<56)+(g<<40)+(b<<24)+(a<<8));
+ } else {
+ *((guint32*)ptr) += guint32(gray>>pad);
+ if(color_type & 4) *((guint32*)ptr) += guint32((a>>pad)>> bit_depth);
+ }
+#endif
+ pad+=bit_depth*n_fields;
+ ptr+=(pad/8);
+ pad%=8;
+ }
+ if(pad){pad=0;ptr++;}//align bytes on rows
+ }
+ return new_data;
+}
+
+
+
+
+
+
+
+
/*
Local Variables:
mode:c++
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 2a7e460e8..72087471d 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -178,6 +178,8 @@ void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs);
G_GNUC_CONST guint32 argb32_from_pixbuf(guint32 in);
G_GNUC_CONST guint32 pixbuf_from_argb32(guint32 in);
+const guchar* pixbuf_to_png(guchar const**rows, guchar* px, int nrows, int ncols, int stride, int color_type, int bit_depth);
+
/** Convert a pixel in 0xRRGGBBAA format to Cairo ARGB32 format. */
G_GNUC_CONST guint32 argb32_from_rgba(guint32 in);
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 1310bb343..e65752c84 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -42,7 +42,7 @@
#include "sp-hatch.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-pattern.h"
#include "sp-mask.h"
#include "sp-clippath.h"
@@ -1257,8 +1257,8 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
sp_color_get_rgb_floatv(&rg->vector.stops[i].color, rgb);
cairo_pattern_add_color_stop_rgba(pattern, rg->vector.stops[i].offset, rgb[0], rgb[1], rgb[2], rg->vector.stops[i].opacity * alpha);
}
- } else if (SP_IS_MESH (paintserver)) {
- SPMesh *mg = SP_MESH(paintserver);
+ } else if (SP_IS_MESHGRADIENT (paintserver)) {
+ SPMeshGradient *mg = SP_MESHGRADIENT(paintserver);
pattern = mg->pattern_new(_cr, pbox, 1.0);
} else if (SP_IS_PATTERN (paintserver)) {
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 4521d72fd..061fadbaa 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -39,7 +39,7 @@
#include "sp-gradient-reference.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-stop.h"
#include "gradient-drag.h"
#include "gradient-chemistry.h"
@@ -147,7 +147,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:mesh");
+ repr = xml_doc->createElement("svg:meshgradient");
}
// privates are garbage-collectable
@@ -271,7 +271,7 @@ static SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradi
repr_new->setAttribute("x2", repr->attribute("x2"));
repr_new->setAttribute("y2", repr->attribute("y2"));
} else {
- std::cout << "sp_gradient_fork_private_if_necessary: mesh not implemented" << std::endl;
+ std::cerr << "sp_gradient_fork_private_if_necessary: mesh not implemented" << std::endl;
}
return gr_new;
@@ -409,7 +409,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]);
- SPMesh* mg = SP_MESH( gr );
+ SPMeshGradient* mg = SP_MESHGRADIENT( gr );
mg->array.create( mg, item, bbox );
}
@@ -754,10 +754,10 @@ guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type,
break;
}
return 0;
- } else if (SP_IS_MESH(gradient)) {
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
// Mesh gradient
- SPMesh *mg = SP_MESH(gradient);
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
switch (point_type) {
case POINT_MG_CORNER: {
@@ -855,12 +855,13 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint
} else {
// Mesh gradient
- SPMesh *mg = SP_MESH(gradient);
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
bool changed = false;
switch (point_type) {
case POINT_MG_CORNER: {
+ // Update mesh array (which is not updated automatically when stop is changed?)
gchar const* color_str = sp_repr_css_property( stop, "stop-color", NULL );
if( color_str ) {
SPColor color( 0 );
@@ -880,9 +881,14 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint
mg->array.corners[ point_i ]->opacity = opacity;
changed = true;
}
+ // Update stop
if( changed ) {
- gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
- mg->array.write( mg );
+ SPStop *stopi = mg->array.corners[ point_i ]->stop;
+ if (stopi) {
+ sp_repr_css_change(stopi->getRepr(), stop, "style");
+ } else {
+ std::cerr << "sp_item_gradient_stop_set_style: null stopi" << std::endl;
+ }
}
break;
}
@@ -1205,8 +1211,8 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
}
- } else if (SP_IS_MESH(gradient)) {
- SPMesh *mg = SP_MESH(gradient);
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
//Geom::Affine new_transform;
//bool transform_set = false;
@@ -1236,7 +1242,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_mesh_repr_write( mg );
+ mg->array.write( mg );
}
}
@@ -1342,8 +1348,8 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
g_warning( "Bad radial gradient handle type" );
break;
}
- } else if (SP_IS_MESH(gradient)) {
- SPMesh *mg = SP_MESH(gradient);
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
switch (point_type) {
case POINT_MG_CORNER:
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index d50a67490..fc75054a0 100644
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
@@ -40,7 +40,7 @@
#include "knot.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "gradient-chemistry.h"
#include "gradient-drag.h"
#include "sp-stop.h"
@@ -407,7 +407,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
//r1_knot = false;
}
}
- } else if (SP_IS_MESH(gradient)) {
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
// add_stop_near_point()
// Find out which curve pointer is over and use that curve to determine
@@ -415,7 +415,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).
- SPMesh *mg = SP_MESH(gradient);
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
Geom::Affine transform = Geom::Affine(mg->gradientTransform)*(Geom::Affine)item->i2dt_affine();
guint rows = mg->array.patch_rows();
@@ -543,7 +543,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
} else {
- SPMesh *mg = SP_MESH(gradient);
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
if( divide_row > -1 ) {
mg->array.split_row( divide_row, divide_coord );
@@ -552,7 +552,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
}
// Update repr
- sp_mesh_repr_write( mg );
+ mg->array.write( mg );
mg->array.built = false;
mg->ensureArray();
// How do we do this?
@@ -901,7 +901,7 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui
dragger->point = p;
dragger->fireDraggables (false, scale_radial);
dragger->updateDependencies(false);
- dragger->updateHandles( p_old, MG_NODE_NO_SCALE );
+ dragger->moveMeshHandles( p_old, MG_NODE_NO_SCALE );
}
}
@@ -1076,7 +1076,7 @@ static void gr_knot_ungrabbed_handler(SPKnot *knot, unsigned int state, gpointer
} else {
dragger->fireDraggables (true);
}
- dragger->updateHandles( dragger->point_original, MG_NODE_NO_SCALE );
+ dragger->moveMeshHandles( dragger->point_original, MG_NODE_NO_SCALE );
for (std::set<GrDragger *>::const_iterator it = dragger->parent->selected.begin(); it != dragger->parent->selected.end() ; ++it ) {
if (*it == dragger)
@@ -1306,9 +1306,8 @@ bool GrDragger::mayMerge(GrDraggable *da2)
* Ooops, needs to be reimplemented.
*/
void
-GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op )
+GrDragger::moveMeshHandles ( Geom::Point pc_old, MeshNodeOperation op )
{
-
// This routine might more properly be in mesh-context.cpp but moving knots is
// handled here rather than there.
@@ -1342,7 +1341,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_MESH( gradient ) ) continue;
+ if ( !SP_IS_MESHGRADIENT( gradient ) ) continue;
selected_corners[ gradient ].push_back( draggable->point_i );
}
@@ -1368,8 +1367,8 @@ GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op )
// Must be a mesh gradient
SPGradient *gradient = getGradient(item, fill_or_stroke);
- if ( !SP_IS_MESH( gradient ) ) continue;
- SPMesh *mg = SP_MESH( gradient );
+ if ( !SP_IS_MESHGRADIENT( gradient ) ) continue;
+ SPMeshGradient *mg = SP_MESHGRADIENT( 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");
@@ -1947,8 +1946,9 @@ void GrDrag::addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::Pai
/**
*Add draggers for the mesh gradient mg on item
*/
-void GrDrag::addDraggersMesh(SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke)
+void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke)
{
+ mg->ensureArray();
std::vector< std::vector< SPMeshNode* > > nodes = mg->array.nodes;
// Show/hide mesh on fill/stroke. This doesn't work at the moment... and prevents node color updating.
@@ -1966,7 +1966,7 @@ void GrDrag::addDraggersMesh(SPMesh *mg, SPItem *item, Inkscape::PaintTarget fil
// Make sure we have at least one patch defined.
if( mg->array.patch_rows() == 0 || mg->array.patch_columns() == 0 ) {
- std::cout << "Empty Mesh, No Draggers to Add" << std::endl;
+ std::cerr << "Empty Mesh, No Draggers to Add" << std::endl;
return;
}
@@ -2021,14 +2021,14 @@ void GrDrag::addDraggersMesh(SPMesh *mg, SPItem *item, Inkscape::PaintTarget fil
}
default:
- std::cout << "Bad Mesh draggable type" << std::endl;
+ std::cerr << "Bad Mesh draggable type" << std::endl;
break;
}
}
}
}
- mg->array.drag_valid = true;
+ mg->array.draggers_valid = true;
}
/**
@@ -2083,8 +2083,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_MESH(server) ) {
- addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_FILL );
+ } else if ( SP_IS_MESHGRADIENT(server) ) {
+ addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_FILL );
}
}
}
@@ -2099,8 +2099,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_MESH(server) ) {
- addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_STROKE );
+ } else if ( SP_IS_MESHGRADIENT(server) ) {
+ addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_STROKE );
}
}
}
@@ -2154,9 +2154,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_MESH(server) ) {
+ } else if ( SP_IS_MESHGRADIENT(server) ) {
- SPMesh *mg = SP_MESH(server);
+ SPMeshGradient *mg = SP_MESHGRADIENT(server);
guint rows = mg->array.patch_rows();
guint columns = mg->array.patch_columns();
@@ -2216,10 +2216,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_MESH(server) ) {
+ } else if ( SP_IS_MESHGRADIENT(server) ) {
// MESH FIXME: TURN ROUTINE INTO FUNCTION AND CALL FOR BOTH FILL AND STROKE.
- SPMesh *mg = SP_MESH(server);
+ SPMeshGradient *mg = SP_MESHGRADIENT(server);
guint rows = mg->array.patch_rows();
guint columns = mg->array.patch_columns();
@@ -2351,7 +2351,7 @@ void GrDrag::selected_move(double x, double y, bool write_repr, bool scale_radia
d->knot->moveto(d->point);
d->fireDraggables (write_repr, scale_radial);
- d->updateHandles( p_old, MG_NODE_NO_SCALE );
+ d->moveMeshHandles( p_old, MG_NODE_NO_SCALE );
d->updateDependencies(write_repr);
}
}
diff --git a/src/gradient-drag.h b/src/gradient-drag.h
index b07f748a7..cf0a35c89 100644
--- a/src/gradient-drag.h
+++ b/src/gradient-drag.h
@@ -34,7 +34,7 @@ class SPKnot;
class SPDesktop;
class SPCSSAttr;
class SPLinearGradient;
-class SPMesh;
+class SPMeshGradient;
class SPItem;
class SPObject;
class SPRadialGradient;
@@ -105,7 +105,7 @@ struct GrDragger {
void updateDependencies(bool write_repr);
/* Update handles/tensors when mesh corner moved */
- void updateHandles( Geom::Point pc_old, MeshNodeOperation op );
+ void moveMeshHandles( Geom::Point pc_old, MeshNodeOperation op );
bool mayMerge(GrDragger *other);
bool mayMerge(GrDraggable *da2);
@@ -209,7 +209,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( SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
+ void addDraggersMesh( SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
bool styleSet( const SPCSSAttr *css );
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 682aee9b2..2433e2777 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -123,8 +123,8 @@ void PngTextList::add(gchar const* key, gchar const* text)
static bool
sp_png_write_rgba_striped(SPDocument *doc,
gchar const *filename, unsigned long int width, unsigned long int height, double xdpi, double ydpi,
- int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data),
- void *data)
+ int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth),
+ void *data, bool interlace, int color_type, int bit_depth, int zlib)
{
g_return_val_if_fail(filename != NULL, false);
g_return_val_if_fail(data != NULL, false);
@@ -184,22 +184,28 @@ sp_png_write_rgba_striped(SPDocument *doc,
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
+
+ png_set_compression_level(png_ptr, zlib);
+
png_set_IHDR(png_ptr, info_ptr,
width,
height,
- 8, /* bit_depth */
- PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE,
+ bit_depth,
+ color_type,
+ interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
- /* otherwise, if we are dealing with a color image then */
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- /* if the image has an alpha channel then */
- sig_bit.alpha = 8;
- png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ if ((color_type&2) && bit_depth == 16) {
+ // otherwise, if we are dealing with a color image then
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ // if the image has an alpha channel then
+ if (color_type&4)
+ sig_bit.alpha = 8;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ }
PngTextList textList;
@@ -248,7 +254,10 @@ sp_png_write_rgba_striped(SPDocument *doc,
/* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
/* note that if sRGB is present the cHRM chunk must be ignored
* on read and must be written in accordance with the sRGB profile */
- png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 + 0.5), unsigned(ydpi / 0.0254 + 0.5), PNG_RESOLUTION_METER);
+ if(xdpi < 0.0254 ) xdpi = 0.0255;
+ if(ydpi < 0.0254 ) ydpi = 0.0255;
+
+ png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 ), unsigned(ydpi / 0.0254 ), PNG_RESOLUTION_METER);
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
@@ -271,15 +280,18 @@ sp_png_write_rgba_striped(SPDocument *doc,
*/
png_bytep* row_pointers = new png_bytep[ebp->sheight];
-
- r = 0;
- while (r < static_cast<png_uint_32>(height)) {
- void *to_free;
- int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data);
- if (!n) break;
- png_write_rows(png_ptr, row_pointers, n);
- g_free(to_free);
- r += n;
+ int number_of_passes = interlace ? png_set_interlace_handling(png_ptr) : 1;
+
+ for(int i=0;i<number_of_passes; ++i){
+ r = 0;
+ while (r < static_cast<png_uint_32>(height)) {
+ void *to_free;
+ int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data, color_type, bit_depth);
+ if (!n) break;
+ png_write_rows(png_ptr, row_pointers, n);
+ g_free(to_free);
+ r += n;
+ }
}
delete[] row_pointers;
@@ -308,7 +320,7 @@ sp_png_write_rgba_striped(SPDocument *doc,
*
*/
static int
-sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data)
+sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth)
{
struct SPEBP *ebp = (struct SPEBP *) data;
@@ -343,15 +355,14 @@ sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, v
ebp->drawing->render(dc, bbox);
cairo_surface_destroy(s);
- *to_free = px;
-
// PNG stores data as unpremultiplied big-endian RGBA, which means
// it's identical to the GdkPixbuf format.
convert_pixels_argb32_to_pixbuf(px, ebp->width, num_rows, stride);
-
- for (int r = 0; r < num_rows; r++) {
- rows[r] = px + r * stride;
- }
+
+ // If a custom bit depth or color type is asked, then convert rgb to grayscale, etc.
+ const guchar* new_data = pixbuf_to_png(rows, px, num_rows, ebp->width, stride, color_type, bit_depth);
+ *to_free = (void*) new_data;
+ free(px);
return num_rows;
}
@@ -385,10 +396,10 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned int (*status) (float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib)
{
return sp_export_png_file(doc, filename, Geom::Rect(Geom::Point(x0,y0),Geom::Point(x1,y1)),
- width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only);
+ width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only, interlace, color_type, bit_depth, zlib);
}
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
@@ -397,7 +408,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned (*status)(float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib)
{
g_return_val_if_fail(doc != NULL, EXPORT_ERROR);
g_return_val_if_fail(filename != NULL, EXPORT_ERROR);
@@ -468,7 +479,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
ebp.px = g_try_new(guchar, 4 * ebp.sheight * width);
if (ebp.px) {
- write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp);
+ write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp, interlace, color_type, bit_depth, zlib);
g_free(ebp.px);
}
diff --git a/src/helper/png-write.h b/src/helper/png-write.h
index 2657fb635..e47f01743 100644
--- a/src/helper/png-write.h
+++ b/src/helper/png-write.h
@@ -34,12 +34,14 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
double x0, double y0, double x1, double y1,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>(),
+ bool interlace = false, int color_type = 6, int bit_depth = 8, int zlib = 6);
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
Geom::Rect const &area,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>(),
+ bool interlace = false, int color_type = 6, int bit_depth = 8, int zlib = 6);
#endif // SEEN_SP_PNG_WRITE_H
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp
index a7459faed..4deb29d8f 100644
--- a/src/live_effects/lpe-mirror_symmetry.cpp
+++ b/src/live_effects/lpe-mirror_symmetry.cpp
@@ -25,11 +25,11 @@ namespace Inkscape {
namespace LivePathEffect {
static const Util::EnumData<ModeType> ModeTypeData[MT_END] = {
- { MT_V, N_("Vertical Page Center"), "Vertical Page Center, use select tool to move item instead line" },
- { MT_H, N_("Horizontal Page Center"), "Horizontal Page Center, use select tool to move item instead line" },
- { MT_FREE, N_("Free from reflection line"), "Free from path" },
- { MT_X, N_("X from middle knot"), "X from middle knot" },
- { MT_Y, N_("Y from middle knot"), "Y from middle knot" }
+ { MT_V, N_("Vertical Page Center"), "vertical" },
+ { MT_H, N_("Horizontal Page Center"), "horizontal" },
+ { MT_FREE, N_("Free from reflection line"), "free" },
+ { MT_X, N_("X from middle knot"), "X" },
+ { MT_Y, N_("Y from middle knot"), "Y" }
};
static const Util::EnumDataConverter<ModeType>
MTConverter(ModeTypeData, MT_END);
@@ -87,7 +87,7 @@ void
LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem)
{
using namespace Geom;
-
+ original_bbox(lpeitem);
Point point_a(boundingbox_X.max(), boundingbox_Y.min());
Point point_b(boundingbox_X.max(), boundingbox_Y.max());
Point point_c(boundingbox_X.max(), boundingbox_Y.middle());
@@ -145,6 +145,18 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem)
}
void
+LPEMirrorSymmetry::transform_multiply(Geom::Affine const& postmul, bool set)
+{
+ center_point *= postmul;
+ previous_center = center_point;
+ // cycle through all parameters. Most parameters will not need transformation, but path and point params do.
+ for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) {
+ Parameter * param = *it;
+ param->param_transform_multiply(postmul, set);
+ }
+}
+
+void
LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem)
{
using namespace Geom;
@@ -178,10 +190,13 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
Geom::Translate m1(point_a[0], point_a[1]);
double hyp = Geom::distance(point_a, point_b);
- double c = (point_b[0] - point_a[0]) / hyp; // cos(alpha)
- double s = (point_b[1] - point_a[1]) / hyp; // sin(alpha)
-
- Geom::Affine m2(c, -s, s, c, 0.0, 0.0);
+ double cos = 0;
+ double sin = 0;
+ if (hyp > 0) {
+ cos = (point_b[0] - point_a[0]) / hyp;
+ sin = (point_b[1] - point_a[1]) / hyp;
+ }
+ Geom::Affine m2(cos, -sin, sin, cos, 0.0, 0.0);
Geom::Scale sca(1.0, -1.0);
Geom::Affine m = m1.inverse() * m2;
@@ -292,8 +307,8 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
}
if (!fuse_paths || discard_orig_path) {
- for (int i = 0; i < static_cast<int>(path_in.size()); ++i) {
- path_out.push_back(path_in[i] * m);
+ for (size_t i = 0; i < original_pathv.size(); ++i) {
+ path_out.push_back(original_pathv[i] * m);
}
}
diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h
index 9e5b4d628..7ec4029e0 100644
--- a/src/live_effects/lpe-mirror_symmetry.h
+++ b/src/live_effects/lpe-mirror_symmetry.h
@@ -46,6 +46,7 @@ public:
virtual ~LPEMirrorSymmetry();
virtual void doOnApply (SPLPEItem const* lpeitem);
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+ virtual void transform_multiply(Geom::Affine const& postmul, bool set);
virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
/* the knotholder entity classes must be declared friends */
friend class MS::KnotHolderEntityCenterMirrorSymmetry;
diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp
index 8a6a95f2e..6a6b59519 100644
--- a/src/live_effects/lpe-perspective-envelope.cpp
+++ b/src/live_effects/lpe-perspective-envelope.cpp
@@ -31,8 +31,8 @@ enum DeformationType {
};
static const Util::EnumData<unsigned> DeformationTypeData[] = {
- {DEFORMATION_PERSPECTIVE , N_("Perspective"), "Perspective"},
- {DEFORMATION_ENVELOPE , N_("Envelope deformation"), "Envelope deformation"}
+ {DEFORMATION_PERSPECTIVE , N_("Perspective"), "perspective"},
+ {DEFORMATION_ENVELOPE , N_("Envelope deformation"), "envelope_deformation"}
};
static const Util::EnumDataConverter<unsigned> DeformationTypeConverter(DeformationTypeData, sizeof(DeformationTypeData)/sizeof(*DeformationTypeData));
diff --git a/src/main-cmdlineact.cpp b/src/main-cmdlineact.cpp
index c1b756ad5..a23c036a0 100644
--- a/src/main-cmdlineact.cpp
+++ b/src/main-cmdlineact.cpp
@@ -23,74 +23,81 @@ namespace Inkscape {
std::list <CmdLineAction *> CmdLineAction::_list;
-CmdLineAction::CmdLineAction (bool isVerb, gchar const * arg) : _isVerb(isVerb), _arg(NULL) {
- if (arg != NULL) {
- _arg = g_strdup(arg);
- }
+CmdLineAction::CmdLineAction(bool isVerb, gchar const *arg) : _isVerb(isVerb), _arg(NULL)
+{
+ if (arg != NULL) {
+ _arg = g_strdup(arg);
+ }
- _list.insert(_list.end(), this);
+ _list.insert(_list.end(), this);
- return;
+ return;
}
-CmdLineAction::~CmdLineAction () {
- if (_arg != NULL) {
- g_free(_arg);
- }
+CmdLineAction::~CmdLineAction()
+{
+ if (_arg != NULL) {
+ g_free(_arg);
+ }
}
void
-CmdLineAction::doIt (ActionContext const & context) {
- //printf("Doing: %s\n", _arg);
- if (_isVerb) {
- Inkscape::Verb * verb = Inkscape::Verb::getbyid(_arg);
- if (verb == NULL) {
- printf(_("Unable to find verb ID '%s' specified on the command line.\n"), _arg);
- return;
- }
- SPAction * action = verb->get_action(context);
- sp_action_perform(action, NULL);
- } else {
- if (context.getDocument() == NULL || context.getSelection() == NULL) { return; }
-
- SPDocument * doc = context.getDocument();
- SPObject * obj = doc->getObjectById(_arg);
- if (obj == NULL) {
- printf(_("Unable to find node ID: '%s'\n"), _arg);
- return;
- }
-
- Inkscape::Selection * selection = context.getSelection();
- selection->add(obj);
- }
- return;
+CmdLineAction::doIt(ActionContext const &context)
+{
+ //printf("Doing: %s\n", _arg);
+ if (_isVerb) {
+ Inkscape::Verb *verb = Inkscape::Verb::getbyid(_arg);
+ if (verb == NULL) {
+ printf(_("Unable to find verb ID '%s' specified on the command line.\n"), _arg);
+ return;
+ }
+ SPAction *action = verb->get_action(context);
+ sp_action_perform(action, NULL);
+ } else {
+ if (context.getDocument() == NULL || context.getSelection() == NULL) {
+ return;
+ }
+
+ SPDocument *doc = context.getDocument();
+ SPObject *obj = doc->getObjectById(_arg);
+ if (obj == NULL) {
+ printf(_("Unable to find node ID: '%s'\n"), _arg);
+ return;
+ }
+
+ Inkscape::Selection *selection = context.getSelection();
+ selection->add(obj);
+ }
+ return;
}
bool
-CmdLineAction::doList (ActionContext const & context) {
- bool hasActions = !_list.empty();
- for (std::list<CmdLineAction *>::iterator i = _list.begin();
- i != _list.end(); ++i) {
- CmdLineAction * entry = *i;
- entry->doIt(context);
- }
- return hasActions;
+CmdLineAction::doList(ActionContext const &context)
+{
+ bool hasActions = !_list.empty();
+ for (std::list<CmdLineAction *>::iterator i = _list.begin();
+ i != _list.end(); ++i) {
+ CmdLineAction *entry = *i;
+ entry->doIt(context);
+ }
+ return hasActions;
}
bool
-CmdLineAction::idle (void) {
- std::list<SPDesktop *> desktops;
- INKSCAPE.get_all_desktops(desktops);
-
- // We're going to assume one desktop per document, because no one
- // should have had time to make more at this point.
- for (std::list<SPDesktop *>::iterator i = desktops.begin();
- i != desktops.end(); ++i) {
- SPDesktop * desktop = *i;
- //Inkscape::UI::View::View * view = dynamic_cast<Inkscape::UI::View::View *>(desktop);
- doList(ActionContext(desktop));
- }
- return false;
+CmdLineAction::idle(void)
+{
+ std::list<SPDesktop *> desktops;
+ INKSCAPE.get_all_desktops(desktops);
+
+ // We're going to assume one desktop per document, because no one
+ // should have had time to make more at this point.
+ for (std::list<SPDesktop *>::iterator i = desktops.begin();
+ i != desktops.end(); ++i) {
+ SPDesktop *desktop = *i;
+ //Inkscape::UI::View::View * view = dynamic_cast<Inkscape::UI::View::View *>(desktop);
+ doList(ActionContext(desktop));
+ }
+ return false;
}
} // Inkscape
diff --git a/src/main-cmdlineact.h b/src/main-cmdlineact.h
index b8ec4403b..171313401 100644
--- a/src/main-cmdlineact.h
+++ b/src/main-cmdlineact.h
@@ -21,18 +21,18 @@ class ActionContext;
class CmdLineAction {
bool _isVerb;
- char * _arg;
+ char *_arg;
static std::list <CmdLineAction *> _list;
public:
- CmdLineAction (bool isVerb, char const * arg);
- virtual ~CmdLineAction ();
+ CmdLineAction(bool isVerb, char const *arg);
+ virtual ~CmdLineAction();
- void doIt (ActionContext const & context);
+ void doIt(ActionContext const &context);
/** Return true if any actions were performed */
- static bool doList (ActionContext const & context);
- static bool idle (void);
+ static bool doList(ActionContext const &context);
+ static bool idle(void);
};
} // Inkscape
diff --git a/src/sp-factory.cpp b/src/sp-factory.cpp
index 62af684a2..f98291378 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.h"
+#include "sp-mesh-gradient.h"
#include "sp-mesh-patch.h"
#include "sp-mesh-row.h"
#include "sp-metadata.h"
@@ -154,8 +154,12 @@ SPObject *SPFactory::createObject(std::string const& id)
ret = new SPGuide;
else if (id == "svg:hatch")
ret = new SPHatch;
- else if (id == "svg:hatchPath")
+ else if (id == "svg:hatchpath")
ret = new SPHatchPath;
+ else if (id == "svg:hatchPath") {
+ std::cerr << "Warning: <hatchPath> has been renamed <hatchpath>" << std::endl;
+ ret = new SPHatchPath;
+ }
else if (id == "svg:image")
ret = new SPImage;
else if (id == "svg:g")
@@ -168,8 +172,17 @@ SPObject *SPFactory::createObject(std::string const& id)
ret = new SPMarker;
else if (id == "svg:mask")
ret = new SPMask;
- else if (id == "svg:mesh")
- ret = new SPMesh;
+ else if (id == "svg:mesh") { // SVG 2 old
+ ret = new SPMeshGradient;
+ std::cerr << "Warning: <mesh> has been renamed <meshgradient>." << std::endl;
+ std::cerr << "Warning: <mesh> has been repurposed as a shape that tightly wraps a <meshgradient>." << std::endl;
+ }
+ else if (id == "svg:meshGradient") { // SVG 2 old
+ ret = new SPMeshGradient;
+ std::cerr << "Warning: <meshGradient> has been renamed <meshgradient>" << std::endl;
+ }
+ else if (id == "svg:meshgradient") // SVG 2
+ ret = new SPMeshGradient;
else if (id == "svg:meshpatch")
ret = new SPMeshpatch;
else if (id == "svg:meshrow")
@@ -198,7 +211,11 @@ SPObject *SPFactory::createObject(std::string const& id)
ret = new SPRoot;
else if (id == "svg:script")
ret = new SPScript;
- else if (id == "svg:solidColor")
+ else if (id == "svg:solidColor") {
+ ret = new SPSolidColor;
+ std::cerr << "Warning: <solidColor> has been renamed <solidcolor>" << std::endl;
+ }
+ else if (id == "svg:solidcolor")
ret = new SPSolidColor;
else if (id == "spiral")
ret = new SPSpiral;
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index f24e25ab1..d3e38485b 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -1,6 +1,6 @@
/** \file
* SPGradient, SPStop, SPLinearGradient, SPRadialGradient,
- * SPMesh, SPMeshRow, SPMeshPatch
+ * SPMeshGradient, SPMeshRow, SPMeshPatch
*/
/*
* Authors:
@@ -22,6 +22,7 @@
*/
#define noSP_GRADIENT_VERBOSE
+//#define OBJECT_TRACE
#include <cstring>
#include <string>
@@ -43,7 +44,7 @@
#include "sp-gradient-reference.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-mesh-row.h"
#include "sp-stop.h"
@@ -114,7 +115,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_MESH(this) && SP_IS_MESH(that))) {
+ (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
if(!this->isAligned(that))break;
}
else { break; } // this should never happen, some unhandled type of gradient
@@ -199,9 +200,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_MESH(this) && SP_IS_MESH(that)) {
- SPMesh *sg=SP_MESH(this);
- SPMesh *tg=SP_MESH(that);
+ } else if (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that)) {
+ SPMeshGradient *sg=SP_MESHGRADIENT(this);
+ SPMeshGradient *tg=SP_MESHGRADIENT(that);
if( sg->x._set != !tg->x._set) { break; }
if( sg->y._set != !tg->y._set) { break; }
@@ -228,7 +229,7 @@ SPGradient::SPGradient() : SPPaintServer(), units(),
state(2),
vector() {
- this->has_patches = 0;
+ this->has_patches = 0;
this->ref = new SPGradientReference(this);
this->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(SPGradient::gradientRefChanged), this));
@@ -318,6 +319,12 @@ void SPGradient::release()
*/
void SPGradient::set(unsigned key, gchar const *value)
{
+#ifdef OBJECT_TRACE
+ std::stringstream temp;
+ temp << "SPGradient::set: " << key << " " << (value?value:"null");
+ objectTrace( temp.str() );
+#endif
+
switch (key) {
case SP_ATTR_GRADIENTUNITS:
if (value) {
@@ -409,6 +416,10 @@ void SPGradient::set(unsigned key, gchar const *value)
SPPaintServer::set(key, value);
break;
}
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPGradient::set", false );
+#endif
}
/**
@@ -498,29 +509,24 @@ void SPGradient::remove_child(Inkscape::XML::Node *child)
*/
void SPGradient::modified(guint flags)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPGradient::modified" );
+#endif
+
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_MESH
- //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) {
-// if (!SP_IS_MESH(this)) {
-// this->invalidateVector();
-// } else {
-// this->invalidateArray();
-// }
- this->invalidateVector();
+ if (SP_IS_MESHGRADIENT(this)) {
+ this->invalidateArray();
+ } else {
+ this->invalidateVector();
+ }
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
- // CPPIFY
- // see above
- //if( this->get_type() != SP_GRADIENT_TYPE_MESH ) {
-// if (!SP_IS_MESH(this)) {
-// this->ensureVector();
-// } else {
-// this->ensureArray();
-// }
- this->ensureVector();
+ if (SP_IS_MESHGRADIENT(this)) {
+ this->ensureArray();
+ } else {
+ this->ensureVector();
+ }
}
if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
@@ -546,6 +552,10 @@ void SPGradient::modified(guint flags)
sp_object_unref(child);
}
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPGradient::modified", false );
+#endif
}
SPStop* SPGradient::getFirstStop()
@@ -576,6 +586,10 @@ int SPGradient::getStopCount() const
*/
Inkscape::XML::Node *SPGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPGradient::write" );
+#endif
+
SPPaintServer::write(xml_doc, repr, flags);
if (flags & SP_OBJECT_WRITE_BUILD) {
@@ -646,6 +660,9 @@ Inkscape::XML::Node *SPGradient::write(Inkscape::XML::Document *xml_doc, Inkscap
repr->setAttribute( "osb:paint", 0 );
}
+#ifdef OBJECT_TRACE
+ objectTrace( "SPGradient::write", false );
+#endif
return repr;
}
@@ -898,7 +915,7 @@ bool SPGradient::invalidateArray()
if (array.built) {
array.built = false;
- array.clear();
+ // array.clear();
ret = true;
}
@@ -1008,39 +1025,12 @@ void SPGradient::rebuildArray()
{
// std::cout << "SPGradient::rebuildArray()" << std::endl;
- if( !SP_IS_MESH(this) ) {
+ if( !SP_IS_MESHGRADIENT(this) ) {
g_warning( "SPGradient::rebuildArray() called for non-mesh gradient" );
return;
}
- array.read( SP_MESH( this ) );
-
- has_patches = false;
- for (auto& ro: children) {
- if (SP_IS_MESHROW(&ro)) {
- has_patches = true;
- // std::cout << " Has Patches" << std::endl;
- break;
- }
- }
-
- // MESH_FIXME: TO PROPERLY COPY
- SPGradient *reffed = ref->getObject();
- if ( !hasPatches() && reffed ) {
- std::cout << "SPGradient::rebuildArray(): reffed array NOT IMPLEMENTED!!!" << std::endl;
- /* Copy array from referenced gradient */
- array.built = true; // Prevent infinite recursion.
- reffed->ensureArray();
- // if (!reffed->array.nodes.empty()) {
- // array.built = reffed->array.built;
- // for( uint i = 0; i < reffed->array.nodes.size(); ++i ) {
- // array.nodes[i].assign(reffed->array.nodes[i].begin(), reffed->array.nodes[i].end());
-
- // // FILL ME
- // }
- // return;
- // }
- }
+ array.read( SP_MESHGRADIENT( this ) );
}
Geom::Affine
@@ -1131,9 +1121,7 @@ sp_gradient_create_preview_pattern(SPGradient *gr, double width)
{
cairo_pattern_t *pat = NULL;
- // CPPIFY
- //if( gr->get_type() != SP_GRADIENT_TYPE_MESH ) {
- if (!SP_IS_MESH(gr)) {
+ if (!SP_IS_MESHGRADIENT(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 ab45d6f08..7348bb5ca 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -210,8 +210,6 @@ 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_mesh_repr_write(SPMesh *mg);
-
cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width);
/** Transforms to/from gradient position space in given environment */
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index e03b715c0..d161562fd 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -59,6 +59,7 @@
#define noSP_ITEM_DEBUG_IDLE
+//#define OBJECT_TRACE
static SPItemView* sp_item_view_list_remove(SPItemView *list,
SPItemView *view);
@@ -691,6 +692,10 @@ void SPItem::update(SPCtx* ctx, guint flags) {
void SPItem::modified(unsigned int /*flags*/)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPItem::modified" );
+ objectTrace( "SPItem::modified", false );
+#endif
}
Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp
index 0dd89ac96..c47c338de 100644
--- a/src/sp-mesh-array.cpp
+++ b/src/sp-mesh-array.cpp
@@ -46,7 +46,7 @@
#include "document.h"
#include "sp-root.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-mesh-array.h"
#include "sp-mesh-row.h"
#include "sp-mesh-patch.h"
@@ -574,7 +574,60 @@ void SPMeshPatchI::setOpacity( guint i, gdouble opacity ) {
};
-SPMeshNodeArray::SPMeshNodeArray( SPMesh *mg ) {
+/**
+ Return stop pointer for corner of patch.
+*/
+SPStop* SPMeshPatchI::getStopPtr( guint i ) {
+
+ assert( i < 4 );
+
+ SPStop* stop = nullptr;
+ switch ( i ) {
+ case 0:
+ stop = (*nodes)[ row ][ col ]->stop;
+ break;
+ case 1:
+ stop = (*nodes)[ row ][ col+3 ]->stop;
+ break;
+ case 2:
+ stop = (*nodes)[ row+3 ][ col+3 ]->stop;
+ break;
+ case 3:
+ stop = (*nodes)[ row+3 ][ col ]->stop;
+ break;
+ }
+
+ return stop;
+};
+
+
+/**
+ Set stop pointer for corner of patch.
+*/
+void SPMeshPatchI::setStopPtr( guint i, SPStop* stop ) {
+
+ assert( i < 4 );
+
+ switch ( i ) {
+ case 0:
+ (*nodes)[ row ][ col ]->stop = stop;
+ break;
+ case 1:
+ (*nodes)[ row ][ col+3 ]->stop = stop;
+ break;
+ case 2:
+ (*nodes)[ row+3 ][ col+3 ]->stop = stop;
+ break;
+ case 3:
+ (*nodes)[ row+3 ][ col ]->stop = stop;
+ break;
+
+ }
+
+};
+
+
+SPMeshNodeArray::SPMeshNodeArray( SPMeshGradient *mg ) {
read( mg );
@@ -586,7 +639,7 @@ SPMeshNodeArray::SPMeshNodeArray( const SPMeshNodeArray& rhs ) {
built = false;
mg = NULL;
- drag_valid = false;
+ draggers_valid = false;
nodes = rhs.nodes; // This only copies the pointers but it does size the vector of vectors.
@@ -607,7 +660,7 @@ SPMeshNodeArray& SPMeshNodeArray::operator=( const SPMeshNodeArray& rhs ) {
built = false;
mg = NULL;
- drag_valid = false;
+ draggers_valid = false;
nodes = rhs.nodes; // This only copies the pointers but it does size the vector of vectors.
@@ -620,12 +673,34 @@ SPMeshNodeArray& SPMeshNodeArray::operator=( const SPMeshNodeArray& rhs ) {
return *this;
};
-
-void SPMeshNodeArray::read( SPMesh *mg_in ) {
+// Fill array with data from mesh objects.
+// Returns true of array's dimensions unchanged.
+bool SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
mg = mg_in;
- clear();
+ // Count rows and columns, if unchanged reuse array to keep draggers valid.
+ unsigned cols = 0;
+ unsigned rows = 0;
+ for (auto& ro: mg->children) {
+ if (SP_IS_MESHROW(&ro)) {
+ ++rows;
+ if (rows == 1 ) {
+ for (auto& po: ro.children) {
+ if (SP_IS_MESHPATCH(&po)) {
+ ++cols;
+ }
+ }
+ }
+ }
+ }
+ bool same_size = true;
+ if (cols != patch_columns() || rows != patch_rows() ) {
+ // Draggers will be invalidated.
+ same_size = false;
+ clear();
+ draggers_valid = false;
+ }
Geom::Point current_p( mg->x.computed, mg->y.computed );
// std::cout << "SPMeshNodeArray::read: p: " << current_p << std::endl;
@@ -701,7 +776,7 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
dp = Geom::Point( x, y );
new_patch.setPoint( istop, 3, current_p + dp );
} else {
- std::cout << "Failed to read l" << std::endl;
+ std::cerr << "Failed to read l" << std::endl;
}
}
// To facilitate some side operations, set handles to 1/3 and
@@ -723,7 +798,7 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
p = Geom::Point( x, y );
new_patch.setPoint( istop, 3, p );
} else {
- std::cout << "Failed to read L" << std::endl;
+ std::cerr << "Failed to read L" << std::endl;
}
}
// To facilitate some side operations, set handles to 1/3 and
@@ -743,7 +818,7 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
p += current_p;
new_patch.setPoint( istop, i, p );
} else {
- std::cout << "Failed to read c: " << i << std::endl;
+ std::cerr << "Failed to read c: " << i << std::endl;
}
}
break;
@@ -756,13 +831,13 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
p = Geom::Point( x, y );
new_patch.setPoint( istop, i, p );
} else {
- std::cout << "Failed to read C: " << i << std::endl;
+ std::cerr << "Failed to read C: " << i << std::endl;
}
}
break;
default:
// should not reach
- std::cout << "Path Error: unhandled path type: " << path_type << std::endl;
+ std::cerr << "Path Error: unhandled path type: " << path_type << std::endl;
}
current_p = new_patch.getPoint( istop, 3 );
@@ -774,6 +849,7 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
double opacity = stop->opacity;
new_patch.setColor( istop, color );
new_patch.setOpacity( istop, opacity );
+ new_patch.setStopPtr( istop, stop );
}
}
@@ -797,7 +873,7 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
if( !os.fail() ) {
new_patch.setTensorPoint( i, new_patch.getPoint( i, 0 ) + Geom::Point( x, y ) );
} else {
- std::cout << "Failed to read p: " << i << std::endl;
+ std::cerr << "Failed to read p: " << i << std::endl;
break;
}
}
@@ -830,15 +906,15 @@ void SPMeshNodeArray::read( SPMesh *mg_in ) {
// std::cout << "SPMeshNodeArray::Read: result:" << std::endl;
// print();
- drag_valid = false;
built = true;
+ return same_size;
};
/**
Write repr using our array.
*/
-void SPMeshNodeArray::write( SPMesh *mg ) {
+void SPMeshNodeArray::write( SPMeshGradient *mg ) {
// std::cout << "SPMeshNodeArray::write: entrance:" << std::endl;
// print();
@@ -967,10 +1043,10 @@ void SPMeshNodeArray::write( SPMesh *mg ) {
break;
case 'z':
case 'Z':
- std::cout << "sp_mesh_repr_write: bad path type" << path_type << std::endl;
+ std::cout << "SPMeshNodeArray::write(): bad path type" << path_type << std::endl;
break;
default:
- std::cout << "sp_mesh_repr_write: unhandled path type" << path_type << std::endl;
+ std::cout << "SPMeshNodeArray::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 +1115,7 @@ static SPColor default_color( SPItem *item ) {
/**
Create a default mesh.
*/
-void SPMeshNodeArray::create( SPMesh *mg, SPItem *item, Geom::OptRect bbox ) {
+void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox ) {
// std::cout << "SPMeshNodeArray::create: Entrance" << std::endl;
@@ -1415,6 +1491,7 @@ void SPMeshNodeArray::print() {
<< " Node edge: " << nodes[i][j]->node_edge
<< " Set: " << nodes[i][j]->set
<< " Path type: " << nodes[i][j]->path_type
+ << " Stop: " << nodes[i][j]->stop
<< std::endl;
} else {
std::cout << "Error: missing mesh node." << std::endl;
@@ -1776,7 +1853,9 @@ guint SPMeshNodeArray::patch_rows() {
Number of patch columns.
*/
guint SPMeshNodeArray::patch_columns() {
-
+ if (nodes.empty()) {
+ return 0;
+ }
return nodes[0].size()/3;
}
@@ -2345,7 +2424,11 @@ guint SPMeshNodeArray::color_pick( std::vector<guint> icorners, SPItem* item ) {
*/
void SPMeshNodeArray::update_handles( guint corner, std::vector< guint > /*selected*/, Geom::Point p_old, MeshNodeOperation /*op*/ )
{
- assert( drag_valid );
+ if (!draggers_valid) {
+ std::cerr << "SPMeshNodeArray::update_handles: Draggers not valid!" << std::endl;
+ return;
+ }
+ // assert( draggers_valid );
// std::cout << "SPMeshNodeArray::update_handles: "
// << " corner: " << corner
diff --git a/src/sp-mesh-array.h b/src/sp-mesh-array.h
index b078b221e..49ee88e53 100644
--- a/src/sp-mesh-array.h
+++ b/src/sp-mesh-array.h
@@ -85,6 +85,7 @@ enum MeshNodeOperation {
MG_NODE_SCALE_HANDLE
};
+class SPStop;
class SPMeshNode {
public:
@@ -95,6 +96,7 @@ public:
draggable = -1;
path_type = 'u';
opacity = 0.0;
+ stop = nullptr;
}
NodeType node_type;
unsigned int node_edge;
@@ -104,6 +106,7 @@ public:
char path_type;
SPColor color;
double opacity;
+ SPStop *stop; // Stop corresponding to node.
};
@@ -133,21 +136,23 @@ public:
void setColor( unsigned int i, SPColor c );
double getOpacity( unsigned int i );
void setOpacity( unsigned int i, double o );
+ SPStop* getStopPtr( unsigned int i );
+ void setStopPtr( unsigned int i, SPStop* );
};
-class SPMesh;
+class SPMeshGradient;
// An array of mesh nodes.
class SPMeshNodeArray {
// Should be private
public:
- SPMesh *mg;
+ SPMeshGradient *mg;
std::vector< std::vector< SPMeshNode* > > nodes;
public:
// Draggables to nodes
- bool drag_valid;
+ bool draggers_valid;
std::vector< SPMeshNode* > corners;
std::vector< SPMeshNode* > handles;
std::vector< SPMeshNode* > tensors;
@@ -156,17 +161,17 @@ public:
friend class SPMeshPatchI;
- SPMeshNodeArray() { built = false; mg = NULL; drag_valid = false; };
- SPMeshNodeArray( SPMesh *mg );
+ SPMeshNodeArray() { built = false; mg = NULL; draggers_valid = false; };
+ SPMeshNodeArray( SPMeshGradient *mg );
SPMeshNodeArray( const SPMeshNodeArray& rhs );
SPMeshNodeArray& operator=(const SPMeshNodeArray& rhs);
~SPMeshNodeArray() { clear(); };
bool built;
- void read( SPMesh *mg );
- void write( SPMesh *mg );
- void create( SPMesh *mg, SPItem *item, Geom::OptRect bbox );
+ bool read( SPMeshGradient *mg );
+ void write( SPMeshGradient *mg );
+ void create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox );
void clear();
void print();
diff --git a/src/sp-mesh.cpp b/src/sp-mesh-gradient.cpp
index 5a6f2bd8e..572131c60 100644
--- a/src/sp-mesh.cpp
+++ b/src/sp-mesh-gradient.cpp
@@ -3,33 +3,59 @@
#include "attributes.h"
#include "display/cairo-utils.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
/*
* Mesh Gradient
*/
//#define MESH_DEBUG
-SPMesh::SPMesh() : SPGradient(), type( SP_MESH_TYPE_COONS ), type_set(false) {
+//#define OBJECT_TRACE
+
+SPMeshGradient::SPMeshGradient() : SPGradient(), type( SP_MESH_TYPE_COONS ), type_set(false) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::SPMeshGradient" );
+#endif
+
// Start coordinate of mesh
this->x.unset(SVGLength::NONE, 0.0, 0.0);
this->y.unset(SVGLength::NONE, 0.0, 0.0);
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::SPMeshGradient", false );
+#endif
}
-SPMesh::~SPMesh() {
+SPMeshGradient::~SPMeshGradient() {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::~SPMeshGradient (empty function)" );
+ objectTrace( "SPMeshGradient::~SPMeshGradient", false );
+#endif
}
-void SPMesh::build(SPDocument *document, Inkscape::XML::Node *repr) {
+void SPMeshGradient::build(SPDocument *document, Inkscape::XML::Node *repr) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::build" );
+#endif
+
SPGradient::build(document, repr);
- // Start coordinate of mesh
+ // Start coordinate of meshgradient
this->readAttr( "x" );
this->readAttr( "y" );
this->readAttr( "type" );
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::build", false );
+#endif
}
-void SPMesh::set(unsigned key, gchar const *value) {
+void SPMeshGradient::set(unsigned key, gchar const *value) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::set" );
+#endif
+
switch (key) {
case SP_ATTR_X:
if (!this->x.read(value)) {
@@ -54,11 +80,11 @@ void SPMesh::set(unsigned key, gchar const *value) {
} else if (!strcmp(value, "bicubic")) {
this->type = SP_MESH_TYPE_BICUBIC;
} else {
- std::cerr << "SPMesh::set(): invalid value " << value << std::endl;
+ std::cerr << "SPMeshGradient::set(): invalid value " << value << std::endl;
}
this->type_set = TRUE;
} else {
- // std::cout << "SPMesh::set() No value " << std::endl;
+ // std::cout << "SPMeshGradient::set() No value " << std::endl;
this->type = SP_MESH_TYPE_COONS;
this->type_set = FALSE;
}
@@ -70,18 +96,22 @@ void SPMesh::set(unsigned key, gchar const *value) {
SPGradient::set(key, value);
break;
}
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::set", false );
+#endif
}
/**
* 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;
+Inkscape::XML::Node* SPMeshGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::write", false );
#endif
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:mesh");
+ repr = xml_doc->createElement("svg:meshgradient");
}
if ((flags & SP_OBJECT_WRITE_ALL) || this->x._set) {
@@ -108,17 +138,13 @@ Inkscape::XML::Node* SPMesh::write(Inkscape::XML::Document *xml_doc, Inkscape::X
SPGradient::write(xml_doc, repr, flags);
+#ifdef OBJECT_TRACE
+ objectTrace( "SPMeshGradient::write", false );
+#endif
return repr;
}
-void
-sp_mesh_repr_write(SPMesh *mg)
-{
- mg->array.write( mg );
-}
-
-
-cairo_pattern_t* SPMesh::pattern_new(cairo_t * /*ct*/,
+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
@@ -132,7 +158,7 @@ cairo_pattern_t* SPMesh::pattern_new(cairo_t * /*ct*/,
using Geom::Y;
#ifdef MESH_DEBUG
- std::cout << "sp_mesh_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl;
+ std::cout << "sp_meshgradient_create_pattern: " << (*bbox) << " " << opacity << std::endl;
#endif
this->ensureArray();
@@ -145,7 +171,7 @@ cairo_pattern_t* SPMesh::pattern_new(cairo_t * /*ct*/,
if( type_set ) {
switch (type) {
case SP_MESH_TYPE_COONS:
- // std::cout << "SPMesh::pattern_new: Coons" << std::endl;
+ // std::cout << "SPMeshGradient::pattern_new: Coons" << std::endl;
break;
case SP_MESH_TYPE_BICUBIC:
array.bicubic( &array_smoothed, type );
diff --git a/src/sp-mesh-gradient.h b/src/sp-mesh-gradient.h
new file mode 100644
index 000000000..a221554a3
--- /dev/null
+++ b/src/sp-mesh-gradient.h
@@ -0,0 +1,43 @@
+#ifndef SP_MESH_GRADIENT_H
+#define SP_MESH_GRADIENT_H
+
+/** \file
+ * SPMeshGradient: SVG <meshgradient> implementation.
+ */
+
+#include "svg/svg-length.h"
+#include "sp-gradient.h"
+
+#define SP_MESHGRADIENT(obj) (dynamic_cast<SPMeshGradient*>((SPObject*)obj))
+#define SP_IS_MESHGRADIENT(obj) (dynamic_cast<const SPMeshGradient*>((SPObject*)obj) != NULL)
+
+/** Mesh gradient. */
+class SPMeshGradient : public SPGradient {
+public:
+ SPMeshGradient();
+ virtual ~SPMeshGradient();
+
+ SVGLength x; // Upper left corner of meshgradient
+ 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_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 9727ffef6..9a173a8db 100644
--- a/src/sp-mesh-patch.cpp
+++ b/src/sp-mesh-patch.cpp
@@ -57,7 +57,6 @@ SPMeshpatch* SPMeshpatch::getPrevMeshpatch()
/*
* Mesh Patch
*/
-
SPMeshpatch::SPMeshpatch() : SPObject() {
this->tensor_string = NULL;
}
@@ -74,7 +73,6 @@ 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) {
switch (key) {
case SP_ATTR_TENSOR: {
@@ -91,9 +89,36 @@ void SPMeshpatch::set(unsigned int key, const gchar* value) {
}
/**
- * Virtual set: set attribute to value.
+ * modified
*/
+void SPMeshpatch::modified(unsigned int flags) {
+ flags &= SP_OBJECT_MODIFIED_CASCADE;
+ GSList *l = NULL;
+
+ for (auto& child: children) {
+ sp_object_ref(&child);
+ l = g_slist_prepend(l, &child);
+ }
+
+ l = g_slist_reverse(l);
+
+ while (l) {
+ SPObject *child = SP_OBJECT(l->data);
+ l = g_slist_remove(l, child);
+
+ if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+ child->emitModified(flags);
+ }
+
+ sp_object_unref(child);
+ }
+}
+
+
+/**
+ * Virtual set: set attribute to value.
+ */
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");
diff --git a/src/sp-mesh-patch.h b/src/sp-mesh-patch.h
index 88d6325c3..e018b81ea 100644
--- a/src/sp-mesh-patch.h
+++ b/src/sp-mesh-patch.h
@@ -21,8 +21,8 @@
/** Gradient Meshpatch. */
class SPMeshpatch : public SPObject {
public:
- SPMeshpatch();
- virtual ~SPMeshpatch();
+ SPMeshpatch();
+ virtual ~SPMeshpatch();
SPMeshpatch* getNextMeshpatch();
SPMeshpatch* getPrevMeshpatch();
@@ -31,9 +31,10 @@ public:
//SVGLength ty[4]; // Tensor points
protected:
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, const char* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void set(unsigned int key, const char* value);
+ virtual void modified(unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SEEN_SP_MESHPATCH_H */
diff --git a/src/sp-mesh-row.cpp b/src/sp-mesh-row.cpp
index 90173da8c..5ac349c27 100644
--- a/src/sp-mesh-row.cpp
+++ b/src/sp-mesh-row.cpp
@@ -65,17 +65,44 @@ void SPMeshrow::build(SPDocument* doc, Inkscape::XML::Node* repr) {
SPObject::build(doc, repr);
}
+
/**
* Virtual build: set meshrow attributes from its associated XML node.
*/
-
void SPMeshrow::set(unsigned int /*key*/, const gchar* /*value*/) {
}
/**
- * Virtual set: set attribute to value.
+ * modified
*/
+void SPMeshrow::modified(unsigned int flags) {
+ flags &= SP_OBJECT_MODIFIED_CASCADE;
+ GSList *l = NULL;
+
+ for (auto& child: children) {
+ sp_object_ref(&child);
+ l = g_slist_prepend(l, &child);
+ }
+
+ l = g_slist_reverse(l);
+
+ while (l) {
+ SPObject *child = SP_OBJECT(l->data);
+ l = g_slist_remove(l, child);
+
+ if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+ child->emitModified(flags);
+ }
+
+ sp_object_unref(child);
+ }
+}
+
+
+/**
+ * Virtual set: set attribute to value.
+ */
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");
diff --git a/src/sp-mesh-row.h b/src/sp-mesh-row.h
index ffb3efa6b..40335e2b9 100644
--- a/src/sp-mesh-row.h
+++ b/src/sp-mesh-row.h
@@ -19,16 +19,17 @@
/** Gradient Meshrow. */
class SPMeshrow : public SPObject {
public:
- SPMeshrow();
- virtual ~SPMeshrow();
+ SPMeshrow();
+ virtual ~SPMeshrow();
SPMeshrow* getNextMeshrow();
SPMeshrow* getPrevMeshrow();
protected:
- virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
- virtual void set(unsigned int key, const char* value);
- virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
+ virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
+ virtual void set(unsigned int key, const char* value);
+ virtual void modified(unsigned int flags);
+ virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags);
};
#endif /* !SEEN_SP_MESHROW_H */
diff --git a/src/sp-mesh.h b/src/sp-mesh.h
deleted file mode 100644
index 6f992d034..000000000
--- a/src/sp-mesh.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef SP_MESH_H
-#define SP_MESH_H
-
-/** \file
- * SPMesh: SVG <mesh> implementation.
- */
-
-#include "svg/svg-length.h"
-#include "sp-gradient.h"
-
-#define SP_MESH(obj) (dynamic_cast<SPMesh*>((SPObject*)obj))
-#define SP_IS_MESH(obj) (dynamic_cast<const SPMesh*>((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/sp-object.cpp b/src/sp-object.cpp
index 0cd7b371e..da4367d5b 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -61,6 +61,10 @@ using std::strstr;
# define debug(f, a...) /* */
#endif
+// Define to enable indented tracing of SPObject.
+//#define OBJECT_TRACE
+unsigned SPObject::indent_level = 0;
+
guint update_in_progress = 0; // guard against update-during-update
Inkscape::XML::NodeEventVector object_event_vector = {
@@ -182,6 +186,10 @@ void SPObject::update(SPCtx* /*ctx*/, unsigned int /*flags*/) {
}
void SPObject::modified(unsigned int /*flags*/) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::modified (default) (empty function)" );
+ objectTrace( "SPObject::modified (default)", false );
+#endif
//throw;
}
@@ -640,6 +648,10 @@ void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * /
}
void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) {
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::build" );
+#endif
SPObject* object = this;
/* Nothing specific here */
@@ -665,10 +677,17 @@ void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) {
sp_object_unref(child, NULL);
child->invoke_build(document, rchild, object->cloned);
}
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::build", false );
+#endif
}
void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, unsigned int cloned)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::invoke_build" );
+#endif
debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance*)this));
//g_assert(object != NULL);
@@ -728,6 +747,10 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns
/* Signalling (should be connected AFTER processing derived methods */
sp_repr_add_listener(repr, &object_event_vector, this);
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::invoke_build", false );
+#endif
}
int SPObject::getIntAttribute(char const *key, int def)
@@ -835,6 +858,13 @@ void SPObject::repr_order_changed(Inkscape::XML::Node * /*repr*/, Inkscape::XML:
}
void SPObject::set(unsigned int key, gchar const* value) {
+
+#ifdef OBJECT_TRACE
+ std::stringstream temp;
+ temp << "SPObject::set: " << key << " " << (value?value:"null");
+ objectTrace( temp.str() );
+#endif
+
g_assert(key != SP_ATTR_INVALID);
SPObject* object = this;
@@ -918,6 +948,9 @@ void SPObject::set(unsigned int key, gchar const* value) {
default:
break;
}
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::set", false );
+#endif
}
void SPObject::setKeyValue(unsigned int key, gchar const *value)
@@ -982,6 +1015,10 @@ static gchar const *sp_xml_get_space_string(unsigned int space)
}
Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::write" );
+#endif
+
if (!repr && (flags & SP_OBJECT_WRITE_BUILD)) {
repr = this->getRepr()->duplicate(doc);
if (!( flags & SP_OBJECT_WRITE_EXT )) {
@@ -1050,38 +1087,68 @@ Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML
sp_style_unset_property_attrs (this);
}
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::write", false );
+#endif
return repr;
}
Inkscape::XML::Node * SPObject::updateRepr(unsigned int flags)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 1" );
+#endif
+
if ( !cloned ) {
Inkscape::XML::Node *repr = getRepr();
if (repr) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 1", false );
+#endif
return updateRepr(repr->document(), repr, flags);
} else {
g_critical("Attempt to update non-existent repr");
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 1", false );
+#endif
return NULL;
}
} else {
/* cloned objects have no repr */
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 1", false );
+#endif
return NULL;
}
}
Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags)
{
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 2" );
+#endif
+
g_assert(doc != NULL);
if (cloned) {
/* cloned objects have no repr */
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateRepr 2", false );
+#endif
return NULL;
}
if (!(flags & SP_OBJECT_WRITE_BUILD) && !repr) {
repr = getRepr();
}
+
+#ifdef OBJECT_TRACE
+ Inkscape::XML::Node *node = write(doc, repr, flags);
+ objectTrace( "SPObject::updateRepr 2", false );
+ return node;
+#else
return this->write(doc, repr, flags);
+#endif
}
@@ -1101,6 +1168,10 @@ void SPObject::requestDisplayUpdate(unsigned int flags)
g_return_if_fail((flags & SP_OBJECT_MODIFIED_FLAG) || (flags & SP_OBJECT_CHILD_MODIFIED_FLAG));
g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG)));
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::requestDisplayUpdate" );
+#endif
+
bool already_propagated = (!(this->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)));
this->uflags |= flags;
@@ -1115,12 +1186,21 @@ void SPObject::requestDisplayUpdate(unsigned int flags)
document->requestModified();
}
}
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::requestDisplayUpdate", false );
+#endif
+
}
void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags)
{
g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE));
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateDisplay" );
+#endif
+
update_in_progress ++;
#ifdef SP_OBJECT_DEBUG_CASCADE
@@ -1161,6 +1241,10 @@ void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags)
}
update_in_progress --;
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::updateDisplay", false );
+#endif
}
void SPObject::requestModified(unsigned int flags)
@@ -1173,6 +1257,10 @@ void SPObject::requestModified(unsigned int flags)
g_return_if_fail((flags & SP_OBJECT_MODIFIED_FLAG) || (flags & SP_OBJECT_CHILD_MODIFIED_FLAG));
g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG)));
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::requestModified" );
+#endif
+
bool already_propagated = (!(this->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)));
this->mflags |= flags;
@@ -1187,6 +1275,9 @@ void SPObject::requestModified(unsigned int flags)
document->requestModified();
}
}
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::requestModified", false );
+#endif
}
void SPObject::emitModified(unsigned int flags)
@@ -1194,6 +1285,10 @@ void SPObject::emitModified(unsigned int flags)
/* only the MODIFIED_CASCADE flag is legal here */
g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE));
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::emitModified", true, flags );
+#endif
+
#ifdef SP_OBJECT_DEBUG_CASCADE
g_print("Modified %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *) this), getId(), flags, this->uflags, this->mflags);
#endif
@@ -1210,6 +1305,10 @@ void SPObject::emitModified(unsigned int flags)
_modified_signal.emit(this, flags);
sp_object_unref(this);
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPObject::emitModified", false );
+#endif
}
gchar const *SPObject::getTagName(SPException *ex) const
@@ -1248,10 +1347,12 @@ void SPObject::setAttribute(gchar const *key, gchar const *value, SPException *e
//XML Tree being used here.
getRepr()->setAttribute(key, value, false);
}
+
void SPObject::setAttribute(char const *key, Glib::ustring const &value, SPException *ex)
{
setAttribute(key, value.empty() ? NULL : value.c_str(), ex);
}
+
void SPObject::setAttribute(Glib::ustring const &key, Glib::ustring const &value, SPException *ex)
{
setAttribute( key.empty() ? NULL : key.c_str(),
@@ -1536,6 +1637,34 @@ void SPObject::recursivePrintTree( unsigned level )
}
}
+// Function to allow tracing of program flow through SPObject and derived classes.
+// To trace function, add at entrance ('in' = true) and exit of function ('in' = false).
+void SPObject::objectTrace( std::string text, bool in, unsigned flags ) {
+ if( in ) {
+ for (unsigned i = 0; i < indent_level; ++i) {
+ std::cout << " ";
+ }
+ std::cout << text << ":"
+ << " entrance: "
+ << (id?id:"null")
+ << " uflags: " << uflags
+ << " mflags: " << mflags
+ << " flags: " << flags << std::endl;
+ ++indent_level;
+ } else {
+ --indent_level;
+ for (unsigned i = 0; i < indent_level; ++i) {
+ std::cout << " ";
+ }
+ std::cout << text << ":"
+ << " exit: "
+ << (id?id:"null")
+ << " uflags: " << uflags
+ << " mflags: " << mflags
+ << " flags: " << flags << std::endl;
+ }
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-object.h b/src/sp-object.h
index 1c6212664..ac3d0c851 100644
--- a/src/sp-object.h
+++ b/src/sp-object.h
@@ -861,6 +861,8 @@ public:
virtual void read_content();
void recursivePrintTree(unsigned level = 0); // For debugging
+ static unsigned indent_level;
+ void objectTrace( std::string, bool in=true, unsigned flags=0 );
};
diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp
index 40107096f..88dad5354 100644
--- a/src/sp-rect.cpp
+++ b/src/sp-rect.cpp
@@ -28,6 +28,7 @@
#define noRECT_VERBOSE
+//#define OBJECT_TRACE
SPRect::SPRect() : SPShape() {
}
@@ -36,6 +37,10 @@ SPRect::~SPRect() {
}
void SPRect::build(SPDocument* doc, Inkscape::XML::Node* repr) {
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::build" );
+#endif
+
SPShape::build(doc, repr);
this->readAttr("x");
@@ -44,9 +49,20 @@ void SPRect::build(SPDocument* doc, Inkscape::XML::Node* repr) {
this->readAttr("height");
this->readAttr("rx");
this->readAttr("ry");
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::build", false );
+#endif
}
void SPRect::set(unsigned key, gchar const *value) {
+
+#ifdef OBJECT_TRACE
+ std::stringstream temp;
+ temp << "SPRect::set: " << key << " " << (value?value:"null");
+ objectTrace( temp.str() );
+#endif
+
/* fixme: We need real error processing some time */
// We must update the SVGLengths immediately or nodes may be misplaced after they are moved.
@@ -104,9 +120,17 @@ void SPRect::set(unsigned key, gchar const *value) {
SPShape::set(key, value);
break;
}
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::set", false );
+#endif
}
void SPRect::update(SPCtx* ctx, unsigned int flags) {
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::update", true, flags );
+#endif
+
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
SPItemCtx const *ictx = reinterpret_cast<SPItemCtx const *>(ctx);
@@ -127,9 +151,17 @@ void SPRect::update(SPCtx* ctx, unsigned int flags) {
}
SPShape::update(ctx, flags);
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::update", false, flags );
+#endif
}
Inkscape::XML::Node * SPRect::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
+
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::write", true, flags );
+#endif
+
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
repr = xml_doc->createElement("svg:rect");
}
@@ -151,6 +183,10 @@ Inkscape::XML::Node * SPRect::write(Inkscape::XML::Document *xml_doc, Inkscape::
this->set_shape(); // evaluate SPCurve
SPShape::write(xml_doc, repr, flags);
+#ifdef OBJECT_TRACE
+ objectTrace( "SPRect::write", false, flags );
+#endif
+
return repr;
}
diff --git a/src/sp-stop.cpp b/src/sp-stop.cpp
index d31946b94..58746c951 100644
--- a/src/sp-stop.cpp
+++ b/src/sp-stop.cpp
@@ -114,6 +114,7 @@ void SPStop::set(unsigned int key, const gchar* value) {
// std::cout << "Got Curve" << std::endl;
//curve->unref();
//}
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
}
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index ed9ec3b0a..7ba6df978 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -134,10 +134,10 @@ void ActionAlign::do_action(SPDesktop *desktop, int index)
switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6)))
{
case LAST:
- focus = SP_ITEM(*selected.begin());
+ focus = SP_ITEM(*--(selected.end()));
break;
case FIRST:
- focus = SP_ITEM(*--(selected.end()));
+ focus = SP_ITEM(*selected.begin());
break;
case BIGGEST:
focus = selection->largestItem(horiz);
diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp
index 670e4c8b5..64a5d9866 100644
--- a/src/ui/dialog/export.cpp
+++ b/src/ui/dialog/export.cpp
@@ -145,6 +145,13 @@ Export::Export (void) :
browse_image(Gtk::StockID(Gtk::Stock::INDEX), Gtk::ICON_SIZE_BUTTON),
batch_box(false, 5),
batch_export(_("B_atch export all selected objects"), _("Export each selected object into its own PNG file, using export hints if any (caution, overwrites without asking!)")),
+ interlacing(_("Use interlacing"),_("Enables ADAM7 interlacing for PNG output. This results in slightly heavier images, but big images will look better sooner when loading the file")),
+ bitdepth_label(_("Bit depth")),
+ bitdepth_cb(),
+ zlib_label(_("Compression")),
+ zlib_compression(),
+ pHYs_label(_("pHYs dpi")),
+ pHYs_sb(pHYs_adj, 1.0, 2),
hide_box(false, 5),
hide_export(_("Hide a_ll except selected"), _("In the exported image, hide all objects except those that are selected")),
closeWhenDone(_("Close when complete"), _("Once the export completes, close this dialog")),
@@ -321,6 +328,34 @@ Export::Export (void) :
button_box.pack_start(closeWhenDone, true, true, 0 );
button_box.pack_end(export_button, false, false, 0);
+ /*Advanced*/
+ Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"),1));
+ expander.set_label_widget(*label_advanced);
+ const char* const modes_list[]={"Gray_1", "Gray_2","Gray_4","Gray_8","Gray_16","RGB_8","RGB_16","GrayAlpha_8","GrayAlpha_16","RGBA_8","RGBA_16"};
+ for(int i=0; i<11; ++i)
+ bitdepth_cb.append(modes_list[i]);
+ bitdepth_cb.set_active_text("RGBA_8");
+ bitdepth_cb.set_hexpand();
+ const char* const zlist[]={"Z_NO_COMPRESSION","Z_BEST_SPEED","2","3","4","5","Z_DEFAULT_COMPRESSION","7","8","Z_BEST_COMPRESSION"};
+ for(int i=0; i<10; ++i)
+ zlib_compression.append(zlist[i]);
+ zlib_compression.set_active_text("Z_DEFAULT_COMPRESSION");
+ pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0);
+ pHYs_sb.set_adjustment(pHYs_adj);
+ pHYs_sb.set_width_chars(7);
+ pHYs_sb.set_tooltip_text( _("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to work on your png with Photoshop") );
+ zlib_compression.set_hexpand();
+ auto table = new Gtk::Grid();
+ gtk_container_add(GTK_CONTAINER(expander.gobj()), (GtkWidget*)(table->gobj()));
+ table->attach(interlacing,0,0,1,1);
+ table->attach(bitdepth_label,0,1,1,1);
+ table->attach(bitdepth_cb,1,1,1,1);
+ table->attach(zlib_label,0,2,1,1);
+ table->attach(zlib_compression,1,2,1,1);
+ table->attach(pHYs_label,0,3,1,1);
+ table->attach(pHYs_sb,1,3,1,1);
+ table->show();
+
/* Main dialog */
Gtk::Box *contents = _getContents();
contents->set_spacing(0);
@@ -329,6 +364,7 @@ Export::Export (void) :
contents->pack_start(hide_box);
contents->pack_end(button_box, false, 0);
contents->pack_end(_prog, Gtk::PACK_EXPAND_WIDGET);
+ contents->pack_end(expander, FALSE, FALSE,0);
/* Signal handlers */
filename_entry.signal_changed().connect( sigc::mem_fun(*this, &Export::onFilenameModified) );
@@ -943,6 +979,18 @@ void Export::onExport ()
bool exportSuccessful = false;
bool hide = hide_export.get_active ();
+
+ // Advanced parameters
+ bool do_interlace = (interlacing.get_active());
+ float pHYs = 0;
+ int zlib = zlib_compression.get_active_row_number() ;
+ const char* const modes_list[]={"Gray_1", "Gray_2","Gray_4","Gray_8","Gray_16","RGB_8","RGB_16","GrayAlpha_8","GrayAlpha_16","RGBA_8","RGBA_16"};
+ int colortypes[] = {0,0,0,0,0,2,2,4,4,6,6}; //keep in sync with modes_list in Export constructor. values are from libpng doc.
+ int bitdepths[] = {1,2,4,8,16,8,16,8,16,8,16};
+ int color_type = colortypes[bitdepth_cb.get_active_row_number()] ;
+ int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()] ;
+
+
if (batch_export.get_active ()) {
// Batch export of selected objects
@@ -987,6 +1035,7 @@ void Export::onExport ()
if (dpi == 0.0) {
dpi = getValue(xdpi_adj);
}
+ pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : dpi;
Geom::OptRect area = item->desktopVisualBounds();
if (area) {
@@ -1003,11 +1052,12 @@ void Export::onExport ()
std::vector<SPItem*> x;
std::vector<SPItem*> selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end());
if (!sp_export_png_file (doc, path.c_str(),
- *area, width, height, dpi, dpi,
+ *area, width, height, pHYs, pHYs,
nv->pagecolor,
onProgressCallback, (void*)prog_dlg,
TRUE, // overwrite without asking
- hide ? selected : x
+ hide ? selected : x,
+ do_interlace, color_type, bit_depth, zlib
)) {
gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile);
@@ -1049,6 +1099,7 @@ void Export::onExport ()
float const y1 = getValuePx(y1_adj);
float const xdpi = getValue(xdpi_adj);
float const ydpi = getValue(ydpi_adj);
+ pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : xdpi;
unsigned long int const width = int(getValue(bmwidth_adj) + 0.5);
unsigned long int const height = int(getValue(bmheight_adj) + 0.5);
@@ -1094,12 +1145,13 @@ void Export::onExport ()
std::vector<SPItem*> x;
std::vector<SPItem*> selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end());
ExportResult status = sp_export_png_file(desktop->getDocument(), path.c_str(),
- Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)), width, height, xdpi, ydpi,
+ Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)), width, height, pHYs, pHYs, //previously xdpi, ydpi.
nv->pagecolor,
onProgressCallback, (void*)prog_dlg,
FALSE,
- hide ? selected : x
- );
+ hide ? selected : x,
+ do_interlace, color_type, bit_depth, zlib
+ );
if (status == EXPORT_ERROR) {
gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str());
gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile);
diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h
index a1c44714b..112f42312 100644
--- a/src/ui/dialog/export.h
+++ b/src/ui/dialog/export.h
@@ -13,6 +13,9 @@
#define SP_EXPORT_H
#include <gtkmm/progressbar.h>
+#include <gtkmm/expander.h>
+#include <gtkmm/grid.h>
+#include <gtkmm/comboboxtext.h>
#include "ui/dialog/desktop-tracker.h"
#include "ui/widget/panel.h"
@@ -314,6 +317,17 @@ private:
Inkscape::UI::Widget::CheckButton closeWhenDone;
+ /* Advanced */
+ Gtk::Expander expander;
+ Inkscape::UI::Widget::CheckButton interlacing;
+ Gtk::Label bitdepth_label;
+ Gtk::ComboBoxText bitdepth_cb;
+ Gtk::Label zlib_label;
+ Gtk::ComboBoxText zlib_compression;
+ Gtk::Label pHYs_label;
+ Glib::RefPtr<Gtk::Adjustment> pHYs_adj;
+ Gtk::SpinButton pHYs_sb;
+
/* Export Button widgets */
Gtk::HBox button_box;
Gtk::Button export_button;
diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp
index eae33ff83..d05c52531 100644
--- a/src/ui/dialog/xml-tree.cpp
+++ b/src/ui/dialog/xml-tree.cpp
@@ -790,7 +790,8 @@ void XmlTree::on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * n
void XmlTree::on_attr_unselect_row_clear_text()
{
attr_name.set_text("");
- attr_value.get_buffer()->set_text("", 0);
+ // Set text with empty Glib::ustring
+ attr_value.get_buffer()->set_text( Glib::ustring() );
}
void XmlTree::onNameChanged()
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index a084a8fd9..16df225e0 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -871,6 +871,7 @@ bool GradientTool::root_handler(GdkEvent* event) {
return ret;
}
+// Creates a new linear or radial gradient.
static void sp_gradient_drag(GradientTool &rc, Geom::Point const pt, guint /*state*/, guint32 etime)
{
SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop;
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index f2cf8c4a2..aac8239f3 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -47,7 +47,7 @@
// Mesh specific
#include "ui/tools/mesh-tool.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "display/sp-ctrlcurve.h"
using Inkscape::DocumentUndo;
@@ -161,9 +161,9 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) {
// if (style && (style->fill.isPaintserver())) {
// SPPaintServer *server = item->style->getFillPaintServer();
- // if ( SP_IS_MESH(server) ) {
+ // if ( SP_IS_MESHGRADIENT(server) ) {
- // SPMesh *mg = SP_MESH(server);
+ // SPMeshGradient *mg = SP_MESHGRADIENT(server);
// guint rows = 0;//mg->array.patches.size();
// for ( guint i = 0; i < rows; ++i ) {
@@ -265,14 +265,18 @@ sp_mesh_context_select_prev (ToolBase *event_context)
Returns true if mouse cursor over mesh edge.
*/
static bool
-sp_mesh_context_is_over_line (MeshTool *rc, SPItem *item, Geom::Point event_p)
+sp_mesh_context_is_over_line (MeshTool *rc, SPCtrlLine *line, Geom::Point event_p)
{
+ if (!SP_IS_CTRLCURVE(line) ) {
+ return false;
+ }
+
SPDesktop *desktop = SP_EVENT_CONTEXT (rc)->desktop;
//Translate mouse point into proper coord system
rc->mousepoint_doc = desktop->w2d(event_p);
- SPCtrlCurve *curve = SP_CTRLCURVE(item);
+ SPCtrlCurve *curve = SP_CTRLCURVE(line);
Geom::BezierCurveN<3> b( curve->p0, curve->p1, curve->p2, curve->p3 );
Geom::Coord coord = b.nearestTime( rc->mousepoint_doc ); // Coord == double
Geom::Point nearest = b( coord );
@@ -326,8 +330,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
SPDocument *doc = NULL;
GrDrag *drag = rc->_grdrag;
- std::map<SPMesh*, std::vector<guint> > points;
- std::map<SPMesh*, SPItem*> items;
+ std::map<SPMeshGradient*, std::vector<guint> > points;
+ std::map<SPMeshGradient*, SPItem*> items;
// Get list of selected draggers for each mesh.
// For all selected draggers
@@ -341,7 +345,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
if( d->point_type != POINT_MG_CORNER ) continue;
// Find the gradient
- SPMesh *gradient = SP_MESH( getGradient (d->item, d->fill_or_stroke) );
+ SPMeshGradient *gradient = SP_MESHGRADIENT( getGradient (d->item, d->fill_or_stroke) );
// Collect points together for same gradient
points[gradient].push_back( d->point_i );
@@ -350,8 +354,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
}
// Loop over meshes.
- for( std::map<SPMesh*, std::vector<guint> >::const_iterator iter = points.begin(); iter != points.end(); ++iter) {
- SPMesh *mg = SP_MESH( iter->first );
+ for( std::map<SPMeshGradient*, std::vector<guint> >::const_iterator iter = points.begin(); iter != points.end(); ++iter) {
+ SPMeshGradient *mg = SP_MESHGRADIENT( iter->first );
if( iter->second.size() > 0 ) {
guint noperation = 0;
switch (operation) {
@@ -425,6 +429,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
/**
Handles all keyboard and mouse input for meshs.
+Note: node/handle events are take care of elsewhere.
*/
bool MeshTool::root_handler(GdkEvent* event) {
static bool dragging;
@@ -454,12 +459,10 @@ bool MeshTool::root_handler(GdkEvent* event) {
if ( event->button.button == 1 ) {
// Are we over a mesh line?
bool over_line = false;
- SPCtrlCurve *line = NULL;
if (! drag->lines.empty()) {
for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
- line = (SPCtrlCurve*) (*l);
- over_line |= sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
+ over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -594,7 +597,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
if (!drag->lines.empty()) {
for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() ; ++l) {
- over_line |= sp_mesh_context_is_over_line (this, (SPItem*)(*l), Geom::Point(event->motion.x, event->motion.y));
+ over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -625,8 +628,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
if (!drag->lines.empty()) {
for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
- line = (SPCtrlLine*)(*l);
- over_line = sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
+ over_line = sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y));
if (over_line) {
break;
@@ -925,6 +927,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
return ret;
}
+// Creates a new mesh gradient.
static void sp_mesh_end_drag(MeshTool &rc) {
SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop;
Inkscape::Selection *selection = desktop->getSelection();
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index fd83a62c9..301a3b2e0 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -25,7 +25,7 @@
#include "sp-namedview.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-pattern.h"
#include "ui/dialog/dialog-manager.h"
#include "ui/dialog/fill-and-stroke.h"
@@ -1010,7 +1010,7 @@ SelectedStyle::update()
place->set_tooltip_text(__rgradient[i]);
_mode[i] = SS_RGRADIENT;
#ifdef WITH_MESH
- } else if (SP_IS_MESH(server)) {
+ } else if (SP_IS_MESHGRADIENT(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 fb540b5f5..0e689fee0 100644
--- a/src/widgets/mesh-toolbar.cpp
+++ b/src/widgets/mesh-toolbar.cpp
@@ -41,7 +41,7 @@
#include "ui/tools/gradient-tool.h"
#include "ui/tools/mesh-tool.h"
#include "gradient-drag.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "gradient-chemistry.h"
#include "ui/icon-names.h"
@@ -70,7 +70,7 @@ static bool blocked = false;
* Get the current selection and dragger status from the desktop
*/
void ms_read_selection( Inkscape::Selection *selection,
- SPMesh *&ms_selected,
+ SPMeshGradient *&ms_selected,
bool &ms_selected_multi,
SPMeshType &ms_type,
bool &ms_type_multi )
@@ -87,9 +87,9 @@ void ms_read_selection( Inkscape::Selection *selection,
if (style && (style->fill.isPaintserver())) {
SPPaintServer *server = item->style->getFillPaintServer();
- if ( SP_IS_MESH(server) ) {
+ if ( SP_IS_MESHGRADIENT(server) ) {
- SPMesh *gradient = SP_MESH(server); // ->getVector();
+ SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector();
SPMeshType type = gradient->type;
if (gradient != ms_selected) {
@@ -112,9 +112,9 @@ void ms_read_selection( Inkscape::Selection *selection,
if (style && (style->stroke.isPaintserver())) {
SPPaintServer *server = item->style->getStrokePaintServer();
- if ( SP_IS_MESH(server) ) {
+ if ( SP_IS_MESHGRADIENT(server) ) {
- SPMesh *gradient = SP_MESH(server); // ->getVector();
+ SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector();
SPMeshType type = gradient->type;
if (gradient != ms_selected) {
@@ -164,7 +164,7 @@ static void ms_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe
// // Hide/show handles?
// }
- SPMesh *ms_selected = 0;
+ SPMeshGradient *ms_selected = 0;
SPMeshType ms_type = SP_MESH_TYPE_COONS;
bool ms_selected_multi = false;
bool ms_type_multi = false;
@@ -203,9 +203,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, SPMesh *&ms_selected)
+void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient *&ms_selected)
{
- SPMesh *gradient = 0;
+ SPMeshGradient *gradient = 0;
auto itemlist= selection->items();
for(auto i=itemlist.begin();i!=itemlist.end();++i){
@@ -220,8 +220,8 @@ void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMesh *&ms_sel
server = item->style->getStrokePaintServer();
}
- if ( SP_IS_MESH(server) ) {
- gradient = SP_MESH(server);
+ if ( SP_IS_MESHGRADIENT(server) ) {
+ gradient = SP_MESHGRADIENT(server);
}
}
@@ -295,7 +295,7 @@ static void ms_type_changed(EgeSelectOneAction *act, GtkWidget *widget)
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(widget), "desktop"));
Inkscape::Selection *selection = desktop->getSelection();
- SPMesh *gradient = 0;
+ SPMeshGradient *gradient = 0;
ms_get_dt_selected_gradient(selection, gradient);
if (gradient) {
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index 01118f337..ddac90730 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -33,7 +33,7 @@
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh.h"
+#include "sp-mesh-gradient.h"
#include "sp-stop.h"
/* fixme: Move it from dialogs to here */
#include "gradient-selector.h"
@@ -1221,7 +1221,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_MESH(server)) {
+ } else if (SP_IS_MESHGRADIENT(server)) {
mode = MODE_GRADIENT_MESH;
#endif
} else if (SP_IS_PATTERN(server)) {