summaryrefslogtreecommitdiffstats
path: root/src/gradient-chemistry.cpp
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2012-05-23 12:00:49 +0000
committertavmjong-free <tavmjong@free.fr>2012-05-23 12:00:49 +0000
commit0ea9b448ee16fe941d46395c2877f4d2e815b9ed (patch)
treea49cb57d691df46475d1e9fe197aeade8b0fa10c /src/gradient-chemistry.cpp
parentCorrect improper flipping of sRGB transform from RGB to BGR with cairo change... (diff)
downloadinkscape-0ea9b448ee16fe941d46395c2877f4d2e815b9ed.tar.gz
inkscape-0ea9b448ee16fe941d46395c2877f4d2e815b9ed.zip
Add Mesh tool (experimental, requires Cario >= 1.11.4, disabled by default).
(bzr r11406)
Diffstat (limited to 'src/gradient-chemistry.cpp')
-rw-r--r--src/gradient-chemistry.cpp326
1 files changed, 252 insertions, 74 deletions
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 119adfc79..ab525e482 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -7,7 +7,9 @@
* Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
+ * Tavmjong Bah <tavmjong@free.fr>
*
+ * Copyright (C) 2012 Tavmjong Bah
* Copyright (C) 2010 Authors
* Copyright (C) 2007 Johan Engelen
* Copyright (C) 2001-2005 authors
@@ -27,8 +29,10 @@
#include "sp-gradient-vector.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
+#include "sp-mesh-gradient.h"
#include "sp-stop.h"
#include "widgets/gradient-vector.h"
+#include "gradient-drag.h"
#include "sp-text.h"
#include "sp-tspan.h"
@@ -130,14 +134,18 @@ static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGr
Inkscape::XML::Node *repr;
if (type == SP_GRADIENT_TYPE_LINEAR) {
repr = xml_doc->createElement("svg:linearGradient");
- } else {
+ } else if(type == SP_GRADIENT_TYPE_RADIAL) {
repr = xml_doc->createElement("svg:radialGradient");
+ } else {
+ // Rows/patches added in sp_gradient_reset_to_userspace for new meshes.
+ repr = xml_doc->createElement("svg:meshGradient");
}
// privates are garbage-collectable
repr->setAttribute("inkscape:collect", "always");
// link to vector
+ // MESH FIXME: Meshes don't used vector... but meshes simulating gradient across/along path might.
sp_gradient_repr_set_link(repr, vector);
/* Append the new private gradient to defs */
@@ -248,11 +256,13 @@ SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *ve
repr_new->setAttribute("fx", repr->attribute("fx"));
repr_new->setAttribute("fy", repr->attribute("fy"));
repr_new->setAttribute("r", repr->attribute("r"));
- } else {
+ } else if (SP_IS_LINEARGRADIENT(gr)) {
repr_new->setAttribute("x1", repr->attribute("x1"));
repr_new->setAttribute("y1", repr->attribute("y1"));
repr_new->setAttribute("x2", repr->attribute("x2"));
repr_new->setAttribute("y2", repr->attribute("y2"));
+ } else {
+ std::cout << "sp_gradient_fork_private_if_necessary: mesh not implemented" << std::endl;
}
return gr_new;
@@ -344,11 +354,19 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item)
gr->getRepr()->setAttribute("gradientTransform", c);
g_free(c);
}
- } else {
+ } else if (SP_IS_LINEARGRADIENT(gr)) {
sp_repr_set_svg_double(repr, "x1", (center - Geom::Point(width/2, 0))[Geom::X]);
sp_repr_set_svg_double(repr, "y1", (center - Geom::Point(width/2, 0))[Geom::Y]);
sp_repr_set_svg_double(repr, "x2", (center + Geom::Point(width/2, 0))[Geom::X]);
sp_repr_set_svg_double(repr, "y2", (center + Geom::Point(width/2, 0))[Geom::Y]);
+ } else {
+ // Mesh
+ // THIS IS BEING CALLED TWICE WHENEVER A NEW GRADIENT IS CREATED, WRITING HERE CAUSES PROBLEMS
+ // IN SPMeshNodeArray::create()
+ //sp_repr_set_svg_double(repr, "x", bbox->min()[Geom::X]);
+ //sp_repr_set_svg_double(repr, "y", bbox->min()[Geom::Y]);
+ SPMeshGradient* mg = SP_MESHGRADIENT( gr );
+ mg->array.create( mg, item, bbox );
}
// set the gradientUnits
@@ -633,6 +651,7 @@ void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, guint poin
}
break;
default:
+ g_warning( "Unhandled gradient handle" );
break;
}
}
@@ -644,49 +663,78 @@ guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type,
if (!gradient || !SP_IS_GRADIENT(gradient))
return 0;
- SPGradient *vector = gradient->getVector();
+ if (SP_IS_LINEARGRADIENT(gradient) || SP_IS_RADIALGRADIENT(gradient) ) {
- if (!vector) // orphan!
- return 0; // what else to do?
+ SPGradient *vector = gradient->getVector();
- switch (point_type) {
- case POINT_LG_BEGIN:
- case POINT_RG_CENTER:
- case POINT_RG_FOCUS:
- {
- SPStop *first = vector->getFirstStop();
- if (first) {
- return sp_stop_get_rgba32(first);
+ if (!vector) // orphan!
+ return 0; // what else to do?
+
+ switch (point_type) {
+ case POINT_LG_BEGIN:
+ case POINT_RG_CENTER:
+ case POINT_RG_FOCUS:
+ {
+ SPStop *first = vector->getFirstStop();
+ if (first) {
+ return sp_stop_get_rgba32(first);
+ }
}
- }
- break;
+ break;
- case POINT_LG_END:
- case POINT_RG_R1:
- case POINT_RG_R2:
- {
- SPStop *last = sp_last_stop (vector);
- if (last) {
- return sp_stop_get_rgba32(last);
+ case POINT_LG_END:
+ case POINT_RG_R1:
+ case POINT_RG_R2:
+ {
+ SPStop *last = sp_last_stop (vector);
+ if (last) {
+ return sp_stop_get_rgba32(last);
+ }
}
- }
- break;
+ break;
- case POINT_LG_MID:
- case POINT_RG_MID1:
- case POINT_RG_MID2:
- {
- SPStop *stopi = sp_get_stop_i (vector, point_i);
- if (stopi) {
- return sp_stop_get_rgba32(stopi);
+ case POINT_LG_MID:
+ case POINT_RG_MID1:
+ case POINT_RG_MID2:
+ {
+ SPStop *stopi = sp_get_stop_i (vector, point_i);
+ if (stopi) {
+ return sp_stop_get_rgba32(stopi);
+ }
}
+ break;
+
+ default:
+ g_warning( "Bad linear/radial gradient handle type" );
+ break;
}
- break;
+ return 0;
+ } else {
- default:
- break;
+ // Mesh gradient
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+
+ switch (point_type) {
+ case POINT_MG_CORNER: {
+
+ SPColor color = mg->array.corners[ point_i ]->color;
+ double opacity = mg->array.corners[ point_i ]->opacity;
+ return color.toRGBA32( opacity );
+ break;
+ }
+
+ case POINT_MG_HANDLE:
+ case POINT_MG_TENSOR:
+ {
+ // Do nothing. Handles and tensors don't have color
+ break;
+ }
+
+ default:
+ g_warning( "Bad mesh handle type" );
+ }
+ return 0;
}
- return 0;
}
void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke, SPCSSAttr *stop)
@@ -699,52 +747,102 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint
if (!gradient || !SP_IS_GRADIENT(gradient))
return;
- SPGradient *vector = gradient->getVector();
+ if (SP_IS_LINEARGRADIENT(gradient) || SP_IS_RADIALGRADIENT(gradient) ) {
- if (!vector) // orphan!
- return;
+ SPGradient *vector = gradient->getVector();
- vector = sp_gradient_fork_vector_if_necessary (vector);
- if ( gradient != vector && gradient->ref->getObject() != vector ) {
- sp_gradient_repr_set_link(gradient->getRepr(), vector);
- }
+ if (!vector) // orphan!
+ return;
- switch (point_type) {
- case POINT_LG_BEGIN:
- case POINT_RG_CENTER:
- case POINT_RG_FOCUS:
- {
- SPStop *first = vector->getFirstStop();
- if (first) {
- sp_repr_css_change(first->getRepr(), stop, "style");
- }
+ vector = sp_gradient_fork_vector_if_necessary (vector);
+ if ( gradient != vector && gradient->ref->getObject() != vector ) {
+ sp_gradient_repr_set_link(gradient->getRepr(), vector);
}
- break;
- case POINT_LG_END:
- case POINT_RG_R1:
- case POINT_RG_R2:
- {
- SPStop *last = sp_last_stop (vector);
- if (last) {
- sp_repr_css_change(last->getRepr(), stop, "style");
+ switch (point_type) {
+ case POINT_LG_BEGIN:
+ case POINT_RG_CENTER:
+ case POINT_RG_FOCUS:
+ {
+ SPStop *first = vector->getFirstStop();
+ if (first) {
+ sp_repr_css_change(first->getRepr(), stop, "style");
+ }
}
- }
- break;
+ break;
- case POINT_LG_MID:
- case POINT_RG_MID1:
- case POINT_RG_MID2:
- {
- SPStop *stopi = sp_get_stop_i (vector, point_i);
- if (stopi) {
- sp_repr_css_change(stopi->getRepr(), stop, "style");
+ case POINT_LG_END:
+ case POINT_RG_R1:
+ case POINT_RG_R2:
+ {
+ SPStop *last = sp_last_stop (vector);
+ if (last) {
+ sp_repr_css_change(last->getRepr(), stop, "style");
+ }
}
- }
- break;
+ break;
- default:
+ case POINT_LG_MID:
+ case POINT_RG_MID1:
+ case POINT_RG_MID2:
+ {
+ SPStop *stopi = sp_get_stop_i (vector, point_i);
+ if (stopi) {
+ sp_repr_css_change(stopi->getRepr(), stop, "style");
+ }
+ }
break;
+
+ default:
+ g_warning( "Bad linear/radial gradient handle type" );
+ break;
+ }
+ } else {
+
+ // Mesh gradient
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+
+ bool changed = false;
+ switch (point_type) {
+ case POINT_MG_CORNER: {
+
+ gchar const* color_str = sp_repr_css_property( stop, "stop-color", NULL );
+ if( color_str ) {
+ SPColor color( 0 );
+ SPStyle* style = sp_style_new(0);
+ SPIPaint paint;
+ paint.read( color_str, *style );
+ if( paint.isColor() ) {
+ color = paint.value.color;
+ }
+ mg->array.corners[ point_i ]->color = color;
+ changed = true;
+ }
+ gchar const* opacity_str = sp_repr_css_property( stop, "stop-opacity", NULL );
+ if( opacity_str ) {
+ std::stringstream os( opacity_str );
+ double opacity = 1.0;
+ os >> opacity;
+ mg->array.corners[ point_i ]->opacity = opacity;
+ changed = true;
+ }
+ if( changed ) {
+ gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ mg->array.write( mg );
+ }
+ break;
+ }
+
+ case POINT_MG_HANDLE:
+ case POINT_MG_TENSOR:
+ {
+ // Do nothing. Handles and tensors don't have colors.
+ break;
+ }
+
+ default:
+ g_warning( "Bad mesh handle type" );
+ }
}
}
@@ -820,6 +918,7 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
if (!gradient || !SP_IS_GRADIENT(gradient))
return;
+ // Needed only if units are set to SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX
gradient = sp_gradient_convert_to_userspace(gradient, item, (fill_or_stroke == Inkscape::FOR_FILL) ? "fill" : "stroke");
Geom::Affine i2d (item->i2dt_affine ());
@@ -887,6 +986,7 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
}
break;
default:
+ g_warning( "Bad linear gradient handle type" );
break;
}
} else if (SP_IS_RADIALGRADIENT(gradient)) {
@@ -963,7 +1063,7 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
break;
}
- case POINT_RG_MID1:
+ case POINT_RG_MID1:
{
Geom::Point start = Geom::Point (rg->cx.computed, rg->cy.computed);
Geom::Point end = Geom::Point (rg->cx.computed + rg->r.computed, rg->cy.computed);
@@ -980,7 +1080,8 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
}
break;
}
- case POINT_RG_MID2:
+ case POINT_RG_MID2:
+ {
Geom::Point start = Geom::Point (rg->cx.computed, rg->cy.computed);
Geom::Point end = Geom::Point (rg->cx.computed, rg->cy.computed - rg->r.computed);
double offset = Geom::LineSegment(start, end).nearestPoint(p);
@@ -995,6 +1096,10 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
stopi->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
break;
+ }
+ default:
+ g_warning( "Bad radial gradient handle type" );
+ break;
}
if (transform_set) {
@@ -1008,7 +1113,41 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
}
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ //Geom::Affine new_transform;
+ //bool transform_set = false;
+
+ switch (point_type) {
+ case POINT_MG_CORNER:
+ {
+ mg->array.corners[ point_i ]->p = p;
+ // Handles are moved in gradient-drag.cpp
+ gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ }
+
+ case POINT_MG_HANDLE: {
+ mg->array.handles[ point_i ]->p = p;
+ gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ }
+
+ case POINT_MG_TENSOR: {
+ mg->array.tensors[ point_i ]->p = p;
+ gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ }
+
+ default:
+ g_warning( "Bad mesh handle type" );
+ }
+ if( write_repr ) {
+ //std::cout << "Write mesh repr" << std::endl;
+ sp_meshgradient_repr_write( mg );
+ }
}
+
}
SPGradient *sp_item_gradient_get_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke)
@@ -1033,6 +1172,10 @@ SPGradientSpread sp_item_gradient_get_spread(SPItem *item, Inkscape::PaintTarget
}
+/**
+Returns the position of point point_type of the gradient applied to item (either fill_or_stroke),
+in desktop coordinates.
+*/
Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke)
{
#ifdef SP_GR_VERBOSE
@@ -1060,6 +1203,9 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
p = (1-offset) * Geom::Point(lg->x1.computed, lg->y1.computed) + offset * Geom::Point(lg->x2.computed, lg->y2.computed);
}
break;
+ default:
+ g_warning( "Bad linear gradient handle type" );
+ break;
}
} else if (SP_IS_RADIALGRADIENT(gradient)) {
SPRadialGradient *rg = SP_RADIALGRADIENT(gradient);
@@ -1088,9 +1234,34 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
p = (1-offset) * Geom::Point (rg->cx.computed, rg->cy.computed) + offset * Geom::Point(rg->cx.computed, rg->cy.computed - rg->r.computed);
}
break;
+ default:
+ g_warning( "Bad radial gradient handle type" );
+ break;
+ }
+ } else if (SP_IS_MESHGRADIENT(gradient)) {
+ SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ switch (point_type) {
+
+ case POINT_MG_CORNER:
+ p = mg->array.corners[ point_i ]->p;
+ break;
+
+ case POINT_MG_HANDLE: {
+ p = mg->array.handles[ point_i ]->p;
+ break;
+ }
+
+ case POINT_MG_TENSOR: {
+ p = mg->array.tensors[ point_i ]->p;
+ break;
+ }
+
+ default:
+ g_warning( "Bad mesh handle type" );
}
}
+
if (SP_GRADIENT(gradient)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
item->document->ensureUpToDate();
Geom::OptRect bbox = item->visualBounds(); // we need "true" bbox without item_i2d_affine
@@ -1104,6 +1275,11 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
return p;
}
+/**
+ * Sets item fill or stroke to the gradient of the specified type with given vector, creating
+ * new private gradient, if needed.
+ * gr has to be a normalized vector.
+ */
SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType type, Inkscape::PaintTarget fill_or_stroke)
{
@@ -1168,6 +1344,8 @@ SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType ty
} else {
/* Current fill style is not a gradient or wrong type, so construct everything */
+ /* This is where mesh gradients are constructed. */
+ g_assert(SP_IS_GRADIENT(gr)); // TEMP
SPGradient *constructed = sp_gradient_get_private_normalized(item->document, gr, type);
constructed = sp_gradient_reset_to_userspace(constructed, item);
sp_style_set_property_url(item, ( (fill_or_stroke == Inkscape::FOR_FILL) ? "fill" : "stroke" ), constructed, true);