diff options
Diffstat (limited to 'src/sp-gradient.cpp')
| -rw-r--r-- | src/sp-gradient.cpp | 1333 |
1 files changed, 132 insertions, 1201 deletions
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 70e90f33c..530e5be40 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -60,231 +60,6 @@ /// Has to be power of 2 Seems to be unused. //#define NCOLORS NR_GRADIENT_VECTOR_LENGTH -#include "sp-factory.h" - -namespace { - SPObject* createStop() { - return new SPStop(); - } - - SPObject* createMeshRow() { - return new SPMeshRow(); - } - - SPObject* createMeshPatch() { - return new SPMeshPatch(); - } - - SPObject* createLinearGradient() { - return new SPLinearGradient(); - } - - SPObject* createRadialGradient() { - return new SPRadialGradient(); - } - - SPObject* createMeshGradient() { - return new SPMeshGradient(); - } - - bool stopRegistered = SPFactory::instance().registerObject("svg:stop", createStop); - bool meshRowRegistered = SPFactory::instance().registerObject("svg:meshRow", createMeshRow); - bool meshPatchRegistered = SPFactory::instance().registerObject("svg:meshPatch", createMeshPatch); - bool linearGradientRegistered = SPFactory::instance().registerObject("svg:linearGradient", createLinearGradient); - bool radialGradientRegistered = SPFactory::instance().registerObject("svg:radialGradient", createRadialGradient); - bool meshGradientRegistered = SPFactory::instance().registerObject("svg:meshGradient", createMeshGradient); -} - - -// SPStop -G_DEFINE_TYPE(SPStop, sp_stop, G_TYPE_OBJECT); - -// SPMeshRow -G_DEFINE_TYPE(SPMeshRow, sp_meshrow, G_TYPE_OBJECT); - -// SPMeshPatch -G_DEFINE_TYPE(SPMeshPatch, sp_meshpatch, G_TYPE_OBJECT); - - -/** - * Callback to initialize SPStop vtable. - */ -static void sp_stop_class_init(SPStopClass *klass) -{ -} - -CStop::CStop(SPStop* stop) : CObject(stop) { - this->spstop = stop; -} - -CStop::~CStop() { -} - -SPStop::SPStop() : SPObject() { - SPStop* stop = this; - - stop->cstop = new CStop(stop); - stop->typeHierarchy.insert(typeid(SPStop)); - - delete stop->cobject; - stop->cobject = stop->cstop; - - stop->path_string = NULL; - - stop->offset = 0.0; - stop->currentColor = false; - stop->specified_color.set( 0x000000ff ); - stop->opacity = 1.0; -} - -/** - * Callback to initialize SPStop object. - */ -static void -sp_stop_init(SPStop *stop) -{ - new (stop) SPStop(); -} - -void CStop::build(SPDocument* doc, Inkscape::XML::Node* repr) { - SPStop* object = this->spstop; - - CObject::build(doc, repr); - - object->readAttr( "offset" ); - object->readAttr( "stop-color" ); - object->readAttr( "stop-opacity" ); - object->readAttr( "style" ); - object->readAttr( "path" ); // For mesh -} - -/** - * Virtual build: set stop attributes from its associated XML node. - */ - -void CStop::set(unsigned int key, const gchar* value) { - SPStop* object = this->spstop; - - SPStop *stop = SP_STOP(object); - - switch (key) { - case SP_ATTR_STYLE: { - /** \todo - * fixme: We are reading simple values 3 times during build (Lauris). - * \par - * We need presentation attributes etc. - * \par - * remove the hackish "style reading" from here: see comments in - * sp_object_get_style_property about the bugs in our current - * approach. However, note that SPStyle doesn't currently have - * stop-color and stop-opacity properties. - */ - { - gchar const *p = object->getStyleProperty( "stop-color", "black"); - if (streq(p, "currentColor")) { - stop->currentColor = true; - } else { - stop->specified_color = SPStop::readStopColor( p ); - } - } - { - gchar const *p = object->getStyleProperty( "stop-opacity", "1"); - gdouble opacity = sp_svg_read_percentage(p, stop->opacity); - stop->opacity = opacity; - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - break; - } - case SP_PROP_STOP_COLOR: { - { - gchar const *p = object->getStyleProperty( "stop-color", "black"); - if (streq(p, "currentColor")) { - stop->currentColor = true; - } else { - stop->currentColor = false; - stop->specified_color = SPStop::readStopColor( p ); - } - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - break; - } - case SP_PROP_STOP_OPACITY: { - { - gchar const *p = object->getStyleProperty( "stop-opacity", "1"); - gdouble opacity = sp_svg_read_percentage(p, stop->opacity); - stop->opacity = opacity; - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - break; - } - case SP_ATTR_OFFSET: { - stop->offset = sp_svg_read_percentage(value, 0.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - break; - } - case SP_PROP_STOP_PATH: { - if (value) { - stop->path_string = new Glib::ustring( value ); - //Geom::PathVector pv = sp_svg_read_pathv(value); - //SPCurve *curve = new SPCurve(pv); - //if( curve ) { - // std::cout << "Got Curve" << std::endl; - //curve->unref(); - //} - } - break; - } - default: { - CObject::set(key, value); - break; - } - } -} - -/** - * Virtual set: set attribute to value. - */ - -Inkscape::XML::Node* CStop::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { - SPStop* object = this->spstop; - - SPStop *stop = SP_STOP(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:stop"); - } - - Glib::ustring colorStr = stop->specified_color.toString(); - gfloat opacity = stop->opacity; - - CObject::write(xml_doc, repr, flags); - - // Since we do a hackish style setting here (because SPStyle does not support stop-color and - // stop-opacity), we must do it AFTER calling the parent write method; otherwise - // sp_object_write would clear our style= attribute (bug 1695287) - - Inkscape::CSSOStringStream os; - os << "stop-color:"; - if (stop->currentColor) { - os << "currentColor"; - } else { - os << colorStr; - } - os << ";stop-opacity:" << opacity; - repr->setAttribute("style", os.str().c_str()); - repr->setAttribute("stop-color", NULL); - repr->setAttribute("stop-opacity", NULL); - sp_repr_set_css_double(repr, "offset", stop->offset); - /* strictly speaking, offset an SVG <number> rather than a CSS one, but exponents make no sense - * for offset proportions. */ - - return repr; -} - -/** - * Virtual write: write object attributes to repr. - */ - bool SPGradient::hasStops() const { return has_stops; @@ -361,425 +136,199 @@ gboolean SPGradient::isEquivalent(SPGradient *that) } -/** - * Return stop's color as 32bit value. - */ -guint32 -sp_stop_get_rgba32(SPStop const *const stop) -{ - guint32 rgb0 = 0; - /* Default value: arbitrarily black. (SVG1.1 and CSS2 both say that the initial - * value depends on user agent, and don't give any further restrictions that I can - * see.) */ - if (stop->currentColor) { - char const *str = stop->getStyleProperty( "color", NULL); - if (str) { - rgb0 = sp_svg_read_color(str, rgb0); - } - unsigned const alpha = static_cast<unsigned>(stop->opacity * 0xff + 0.5); - g_return_val_if_fail((alpha & ~0xff) == 0, - rgb0 | 0xff); - return rgb0 | alpha; - } else { - return stop->specified_color.toRGBA32( stop->opacity ); - } -} - -/* - * Mesh Row - */ - -/** - * Callback to initialize SPMeshRow vtable. - */ -static void sp_meshrow_class_init(SPMeshRowClass *klass) -{ -} - -CMeshRow::CMeshRow(SPMeshRow* meshrow) : CObject(meshrow) { - this->spmeshrow = meshrow; -} - -CMeshRow::~CMeshRow() { -} - -SPMeshRow::SPMeshRow() : SPObject() { - SPMeshRow* meshrow = this; - - meshrow->cmeshrow = new CMeshRow(meshrow); - meshrow->typeHierarchy.insert(typeid(SPMeshRow)); - - delete meshrow->cobject; - meshrow->cobject = meshrow->cmeshrow; -} - -/** - * Callback to initialize SPMeshRow object. - */ -static void sp_meshrow_init(SPMeshRow * meshrow) -{ - new (meshrow) SPMeshRow(); -} - -void CMeshRow::build(SPDocument* doc, Inkscape::XML::Node* repr) { - CObject::build(doc, repr); -} - -/** - * Virtual build: set meshrow attributes from its associated XML node. - */ - -void CMeshRow::set(unsigned int key, const gchar* value) { -} - -/** - * Virtual set: set attribute to value. - */ - -Inkscape::XML::Node* CMeshRow::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"); - } - - CObject::write(xml_doc, repr, flags); - - return repr; -} - -/** - * Virtual write: write object attributes to repr. - */ - -/* - * Mesh Patch - */ - -/** - * Callback to initialize SPMeshPatch vtable. - */ -static void sp_meshpatch_class_init(SPMeshPatchClass *klass) -{ -} - -CMeshPatch::CMeshPatch(SPMeshPatch* meshpatch) : CObject(meshpatch) { - this->spmeshpatch = meshpatch; -} - -CMeshPatch::~CMeshPatch() { -} - -SPMeshPatch::SPMeshPatch() : SPObject() { - SPMeshPatch* meshpatch = this; - - meshpatch->cmeshpatch = new CMeshPatch(meshpatch); - meshpatch->typeHierarchy.insert(typeid(SPMeshPatch)); - - delete meshpatch->cobject; - meshpatch->cobject = meshpatch->cmeshpatch; - - meshpatch->tensor_string = NULL; -} - -/** - * Callback to initialize SPMeshPatch object. - */ -static void sp_meshpatch_init(SPMeshPatch * meshpatch) -{ - new (meshpatch) SPMeshPatch(); -} - -void CMeshPatch::build(SPDocument* doc, Inkscape::XML::Node* repr) { - SPMeshPatch* object = this->spmeshpatch; - - CObject::build(doc, repr); - - object->readAttr( "tensor" ); -} - -/** - * Virtual build: set meshpatch attributes from its associated XML node. - */ - -void CMeshPatch::set(unsigned int key, const gchar* value) { - SPMeshPatch* object = this->spmeshpatch; - - SPMeshPatch *patch = SP_MESHPATCH(object); - - switch (key) { - case SP_ATTR_TENSOR: { - if (value) { - patch->tensor_string = new Glib::ustring( value ); - // std::cout << "sp_meshpatch_set: Tensor string: " << patch->tensor_string->c_str() << std::endl; - } - break; - } - default: { - // Do nothing - } - } -} - -/** - * Virtual set: set attribute to value. - */ - -Inkscape::XML::Node* CMeshPatch::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"); - } - - CObject::write(xml_doc, repr, flags); - - return repr; -} - -/** - * Virtual write: write object attributes to repr. - */ - - /* * Gradient */ -static SPPaintServerClass *gradient_parent_class; - -/** - * Registers SPGradient class and returns its type. - */ -GType SPGradient::getType() -{ - static GType gradient_type = 0; - if (!gradient_type) { - - GTypeInfo gradient_info = { - sizeof(SPGradientClass), - NULL, NULL, - 0, //(GClassInitFunc) CGradient::classInit, - NULL, NULL, - sizeof(SPGradient), - 16, - (GInstanceInitFunc) CGradient::init, - NULL, /* value_table */ - }; - gradient_type = g_type_register_static(G_TYPE_OBJECT, "SPGradient", - &gradient_info, (GTypeFlags)0); - } - return gradient_type; -} - -/** - * SPGradient vtable initialization. - */ -void CGradient::classInit(SPGradientClass *klass) -{ - gradient_parent_class = (SPPaintServerClass *)g_type_class_ref(SP_TYPE_PAINT_SERVER); -} - -CGradient::CGradient(SPGradient* gradient) : CPaintServer(gradient) { - this->spgradient = gradient; -} - -CGradient::~CGradient() { -} - -SPGradient::SPGradient() : SPPaintServer(), units(), +SPGradient::SPGradient() : SPPaintServer(), units(), spread(), ref(NULL), state(2), vector() { - SPGradient* gr = this; - - gr->cgradient = new CGradient(gr); - gr->typeHierarchy.insert(typeid(SPGradient)); + this->cobject = this; - delete gr->cpaintserver; - gr->cpaintserver = gr->cgradient; - gr->cobject = gr->cgradient; + this->has_patches = 0; - gr->has_patches = 0; - - gr->ref = new SPGradientReference(gr); - gr->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(CGradient::gradientRefChanged), gr)); + this->ref = new SPGradientReference(this); + this->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(SPGradient::gradientRefChanged), this)); /** \todo * Fixme: reprs being rearranged (e.g. via the XML editor) * may require us to clear the state. */ - gr->state = SP_GRADIENT_STATE_UNKNOWN; + this->state = SP_GRADIENT_STATE_UNKNOWN; - gr->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; - gr->units_set = FALSE; + this->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; + this->units_set = FALSE; - gr->gradientTransform = Geom::identity(); - gr->gradientTransform_set = FALSE; + this->gradientTransform = Geom::identity(); + this->gradientTransform_set = FALSE; - gr->spread = SP_GRADIENT_SPREAD_PAD; - gr->spread_set = FALSE; + this->spread = SP_GRADIENT_SPREAD_PAD; + this->spread_set = FALSE; - gr->has_stops = FALSE; + this->has_stops = FALSE; - gr->vector.built = false; - gr->vector.stops.clear(); + this->vector.built = false; + this->vector.stops.clear(); - new (&gr->modified_connection) sigc::connection(); + new (&this->modified_connection) sigc::connection(); } -/** - * Callback for SPGradient object initialization. - */ -void CGradient::init(SPGradient *gr) -{ - new (gr) SPGradient(); +SPGradient::~SPGradient() { } /** * Virtual build: set gradient attributes from its associated repr. */ -void CGradient::build(SPDocument *document, Inkscape::XML::Node *repr) +void SPGradient::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPGradient* object = this->spgradient; - SPGradient *gradient = SP_GRADIENT(object); - // Work-around in case a swatch had been marked for immediate collection: if ( repr->attribute("osb:paint") && repr->attribute("inkscape:collect") ) { repr->setAttribute("inkscape:collect", 0); } - CPaintServer::build(document, repr); + SPPaintServer::build(document, repr); - for ( SPObject *ochild = object->firstChild() ; ochild ; ochild = ochild->getNext() ) { + for ( SPObject *ochild = this->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { - gradient->has_stops = TRUE; + this->has_stops = TRUE; break; } } - object->readAttr( "gradientUnits" ); - object->readAttr( "gradientTransform" ); - object->readAttr( "spreadMethod" ); - object->readAttr( "xlink:href" ); - object->readAttr( "osb:paint" ); + this->readAttr( "gradientUnits" ); + this->readAttr( "gradientTransform" ); + this->readAttr( "spreadMethod" ); + this->readAttr( "xlink:href" ); + this->readAttr( "osb:paint" ); // Register ourselves - document->addResource("gradient", object); + document->addResource("gradient", this); } /** * Virtual release of SPGradient members before destruction. */ -void CGradient::release() +void SPGradient::release() { - SPGradient* object = this->spgradient; - SPGradient *gradient = (SPGradient *) object; #ifdef SP_GRADIENT_VERBOSE - g_print("Releasing gradient %s\n", object->getId()); + g_print("Releasing this %s\n", this->getId()); #endif - if (object->document) { + if (this->document) { // Unregister ourselves - object->document->removeResource("gradient", object); + this->document->removeResource("gradient", this); } - if (gradient->ref) { - gradient->modified_connection.disconnect(); - gradient->ref->detach(); - delete gradient->ref; - gradient->ref = NULL; + if (this->ref) { + this->modified_connection.disconnect(); + this->ref->detach(); + delete this->ref; + this->ref = NULL; } - gradient->modified_connection.~connection(); + this->modified_connection.~connection(); - CPaintServer::release(); + SPPaintServer::release(); } /** * Set gradient attribute to value. */ -void CGradient::set(unsigned key, gchar const *value) +void SPGradient::set(unsigned key, gchar const *value) { - SPGradient* object = this->spgradient; - SPGradient *gr = SP_GRADIENT(object); - switch (key) { case SP_ATTR_GRADIENTUNITS: if (value) { if (!strcmp(value, "userSpaceOnUse")) { - gr->units = SP_GRADIENT_UNITS_USERSPACEONUSE; + this->units = SP_GRADIENT_UNITS_USERSPACEONUSE; } else { - gr->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; + this->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; } - gr->units_set = TRUE; + + this->units_set = TRUE; } else { - gr->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; - gr->units_set = FALSE; + this->units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; + this->units_set = FALSE; } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + case SP_ATTR_GRADIENTTRANSFORM: { Geom::Affine t; if (value && sp_svg_transform_read(value, &t)) { - gr->gradientTransform = t; - gr->gradientTransform_set = TRUE; + this->gradientTransform = t; + this->gradientTransform_set = TRUE; } else { - gr->gradientTransform = Geom::identity(); - gr->gradientTransform_set = FALSE; + this->gradientTransform = Geom::identity(); + this->gradientTransform_set = FALSE; } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; } case SP_ATTR_SPREADMETHOD: if (value) { if (!strcmp(value, "reflect")) { - gr->spread = SP_GRADIENT_SPREAD_REFLECT; + this->spread = SP_GRADIENT_SPREAD_REFLECT; } else if (!strcmp(value, "repeat")) { - gr->spread = SP_GRADIENT_SPREAD_REPEAT; + this->spread = SP_GRADIENT_SPREAD_REPEAT; } else { - gr->spread = SP_GRADIENT_SPREAD_PAD; + this->spread = SP_GRADIENT_SPREAD_PAD; } - gr->spread_set = TRUE; + + this->spread_set = TRUE; } else { - gr->spread_set = FALSE; + this->spread_set = FALSE; } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; + case SP_ATTR_XLINK_HREF: if (value) { try { - gr->ref->attach(Inkscape::URI(value)); + this->ref->attach(Inkscape::URI(value)); } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); - gr->ref->detach(); + this->ref->detach(); } } else { - gr->ref->detach(); + this->ref->detach(); } break; + case SP_ATTR_OSB_SWATCH: { bool newVal = (value != 0); bool modified = false; - if (newVal != gr->swatch) { - gr->swatch = newVal; + + if (newVal != this->swatch) { + this->swatch = newVal; modified = true; } + if (newVal) { // Might need to flip solid/gradient - Glib::ustring paintVal = ( gr->hasStops() && (gr->getStopCount() == 0) ) ? "solid" : "gradient"; + Glib::ustring paintVal = ( this->hasStops() && (this->getStopCount() == 0) ) ? "solid" : "gradient"; + if ( paintVal != value ) { - gr->setAttribute( "osb:paint", paintVal.c_str(), 0 ); + this->setAttribute( "osb:paint", paintVal.c_str(), 0 ); modified = true; } } + if (modified) { - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); } } break; default: - CPaintServer::set(key, value); + SPPaintServer::set(key, value); break; } } @@ -787,7 +336,7 @@ void CGradient::set(unsigned key, gchar const *value) /** * Gets called when the gradient is (re)attached to another gradient. */ -void CGradient::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr) +void SPGradient::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr) { if (old_ref) { gr->modified_connection.disconnect(); @@ -795,7 +344,7 @@ void CGradient::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient if ( SP_IS_GRADIENT(ref) && ref != gr ) { - gr->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&CGradient::gradientRefModified), gr)); + gr->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&SPGradient::gradientRefModified), gr)); } // Per SVG, all unset attributes must be inherited from linked gradient. @@ -816,82 +365,74 @@ void CGradient::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient /** * Callback for child_added event. */ -void CGradient::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) +void SPGradient::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) { - SPGradient* object = this->spgradient; - SPGradient *gr = SP_GRADIENT(object); - - gr->invalidateVector(); + this->invalidateVector(); - CPaintServer::child_added(child, ref); + SPPaintServer::child_added(child, ref); - SPObject *ochild = object->get_child_by_repr(child); + SPObject *ochild = this->get_child_by_repr(child); if ( ochild && SP_IS_STOP(ochild) ) { - gr->has_stops = TRUE; - if ( gr->getStopCount() > 0 ) { - gchar const * attr = gr->getAttribute("osb:paint"); + this->has_stops = TRUE; + if ( this->getStopCount() > 0 ) { + gchar const * attr = this->getAttribute("osb:paint"); if ( attr && strcmp(attr, "gradient") ) { - gr->setAttribute( "osb:paint", "gradient", 0 ); + this->setAttribute( "osb:paint", "gradient", 0 ); } } } /// \todo Fixme: should we schedule "modified" here? - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); } /** * Callback for remove_child event. */ -void CGradient::remove_child(Inkscape::XML::Node *child) +void SPGradient::remove_child(Inkscape::XML::Node *child) { - SPGradient* object = this->spgradient; - SPGradient *gr = SP_GRADIENT(object); + this->invalidateVector(); - gr->invalidateVector(); + SPPaintServer::remove_child(child); - CPaintServer::remove_child(child); - - gr->has_stops = FALSE; - for ( SPObject *ochild = object->firstChild() ; ochild ; ochild = ochild->getNext() ) { + this->has_stops = FALSE; + for ( SPObject *ochild = this->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { - gr->has_stops = TRUE; + this->has_stops = TRUE; break; } } - if ( gr->getStopCount() == 0 ) { - gchar const * attr = gr->getAttribute("osb:paint"); + if ( this->getStopCount() == 0 ) { + gchar const * attr = this->getAttribute("osb:paint"); + if ( attr && strcmp(attr, "solid") ) { - gr->setAttribute( "osb:paint", "solid", 0 ); + this->setAttribute( "osb:paint", "solid", 0 ); } } /* Fixme: should we schedule "modified" here? */ - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); } /** * Callback for modified event. */ -void CGradient::modified(guint flags) +void SPGradient::modified(guint flags) { - SPGradient* object = this->spgradient; - SPGradient *gr = SP_GRADIENT(object); - if (flags & SP_OBJECT_CHILD_MODIFIED_FLAG) { - if( gr->get_type() != SP_GRADIENT_TYPE_MESH ) { - gr->invalidateVector(); + if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { + this->invalidateVector(); } else { - gr->invalidateArray(); + this->invalidateArray(); } } if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - if( gr->get_type() != SP_GRADIENT_TYPE_MESH ) { - gr->ensureVector(); + if( this->get_type() != SP_GRADIENT_TYPE_MESH ) { + this->ensureVector(); } else { - gr->ensureArray(); + this->ensureArray(); } } @@ -900,17 +441,22 @@ void CGradient::modified(guint flags) // FIXME: climb up the ladder of hrefs GSList *l = NULL; - for (SPObject *child = object->firstChild() ; child; child = child->getNext() ) { + + for (SPObject *child = this->firstChild() ; child; child = child->getNext() ) { 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); } } @@ -940,21 +486,21 @@ int SPGradient::getStopCount() const /** * Write gradient attributes to repr. */ -Inkscape::XML::Node *CGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +Inkscape::XML::Node *SPGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPGradient* object = this->spgradient; - SPGradient *gr = SP_GRADIENT(object); - - CPaintServer::write(xml_doc, repr, flags); + SPPaintServer::write(xml_doc, repr, flags); if (flags & SP_OBJECT_WRITE_BUILD) { GSList *l = NULL; - for (SPObject *child = object->firstChild(); child; child = child->getNext()) { + + for (SPObject *child = this->firstChild(); child; child = child->getNext()) { Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); + if (crepr) { l = g_slist_prepend(l, crepr); } } + while (l) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); Inkscape::GC::release((Inkscape::XML::Node *) l->data); @@ -962,14 +508,14 @@ Inkscape::XML::Node *CGradient::write(Inkscape::XML::Document *xml_doc, Inkscape } } - if (gr->ref->getURI()) { - gchar *uri_string = gr->ref->getURI()->toString(); + if (this->ref->getURI()) { + gchar *uri_string = this->ref->getURI()->toString(); repr->setAttribute("xlink:href", uri_string); g_free(uri_string); } - if ((flags & SP_OBJECT_WRITE_ALL) || gr->units_set) { - switch (gr->units) { + if ((flags & SP_OBJECT_WRITE_ALL) || this->units_set) { + switch (this->units) { case SP_GRADIENT_UNITS_USERSPACEONUSE: repr->setAttribute("gradientUnits", "userSpaceOnUse"); break; @@ -979,17 +525,17 @@ Inkscape::XML::Node *CGradient::write(Inkscape::XML::Document *xml_doc, Inkscape } } - if ((flags & SP_OBJECT_WRITE_ALL) || gr->gradientTransform_set) { - gchar *c=sp_svg_transform_write(gr->gradientTransform); + if ((flags & SP_OBJECT_WRITE_ALL) || this->gradientTransform_set) { + gchar *c=sp_svg_transform_write(this->gradientTransform); repr->setAttribute("gradientTransform", c); g_free(c); } - if ((flags & SP_OBJECT_WRITE_ALL) || gr->spread_set) { - /* FIXME: Ensure that gr->spread is the inherited value - * if !gr->spread_set. Not currently happening: see SPGradient::modified. + if ((flags & SP_OBJECT_WRITE_ALL) || this->spread_set) { + /* FIXME: Ensure that this->spread is the inherited value + * if !this->spread_set. Not currently happening: see SPGradient::modified. */ - switch (gr->spread) { + switch (this->spread) { case SP_GRADIENT_SPREAD_REFLECT: repr->setAttribute("spreadMethod", "reflect"); break; @@ -1002,8 +548,8 @@ Inkscape::XML::Node *CGradient::write(Inkscape::XML::Document *xml_doc, Inkscape } } - if ( (flags & SP_OBJECT_WRITE_EXT) && gr->isSwatch() ) { - if ( gr->isSolid() ) { + if ( (flags & SP_OBJECT_WRITE_EXT) && this->isSwatch() ) { + if ( this->isSolid() ) { repr->setAttribute( "osb:paint", "solid" ); } else { repr->setAttribute( "osb:paint", "gradient" ); @@ -1235,7 +781,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) } -void CGradient::gradientRefModified(SPObject */*href*/, guint /*flags*/, SPGradient *gradient) +void SPGradient::gradientRefModified(SPObject */*href*/, guint /*flags*/, SPGradient *gradient) { if ( gradient->invalidateVector() ) { gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -1449,422 +995,12 @@ sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, gr->requestModified(SP_OBJECT_MODIFIED_FLAG); } -/* - * Linear Gradient - */ -G_DEFINE_TYPE(SPLinearGradient, sp_lineargradient, G_TYPE_OBJECT); -/** - * SPLinearGradient vtable initialization. - */ -static void sp_lineargradient_class_init(SPLinearGradientClass *klass) -{ -} - -CLinearGradient::CLinearGradient(SPLinearGradient* lineargradient) : CGradient(lineargradient) { - this->splineargradient = lineargradient; -} - -CLinearGradient::~CLinearGradient() { -} -SPLinearGradient::SPLinearGradient() : SPGradient() { - SPLinearGradient* lg = this; - - lg->clineargradient = new CLinearGradient(lg); - lg->typeHierarchy.insert(typeid(SPLinearGradient)); - - delete lg->cgradient; - lg->cgradient = lg->clineargradient; - lg->cpaintserver = lg->clineargradient; - lg->cobject = lg->clineargradient; - - lg->x1.unset(SVGLength::PERCENT, 0.0, 0.0); - lg->y1.unset(SVGLength::PERCENT, 0.0, 0.0); - lg->x2.unset(SVGLength::PERCENT, 1.0, 1.0); - lg->y2.unset(SVGLength::PERCENT, 0.0, 0.0); -} - -/** - * Callback for SPLinearGradient object initialization. - */ -static void sp_lineargradient_init(SPLinearGradient *lg) -{ - new (lg) SPLinearGradient(); -} - -void CLinearGradient::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPLinearGradient* object = this->splineargradient; - - CGradient::build(document, repr); - - object->readAttr( "x1" ); - object->readAttr( "y1" ); - object->readAttr( "x2" ); - object->readAttr( "y2" ); -} - -/** - * Callback: set attribute. - */ -void CLinearGradient::set(unsigned int key, const gchar* value) { - SPLinearGradient* object = this->splineargradient; - - SPLinearGradient *lg = SP_LINEARGRADIENT(object); - - switch (key) { - case SP_ATTR_X1: - lg->x1.readOrUnset(value, SVGLength::PERCENT, 0.0, 0.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_Y1: - lg->y1.readOrUnset(value, SVGLength::PERCENT, 0.0, 0.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_X2: - lg->x2.readOrUnset(value, SVGLength::PERCENT, 1.0, 1.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_Y2: - lg->y2.readOrUnset(value, SVGLength::PERCENT, 0.0, 0.0); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - default: - CGradient::set(key, value); - break; - } -} - -/** - * Callback: write attributes to associated repr. - */ -Inkscape::XML::Node* CLinearGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPLinearGradient* object = this->splineargradient; - - SPLinearGradient *lg = SP_LINEARGRADIENT(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:linearGradient"); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || lg->x1._set) - sp_repr_set_svg_double(repr, "x1", lg->x1.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || lg->y1._set) - sp_repr_set_svg_double(repr, "y1", lg->y1.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || lg->x2._set) - sp_repr_set_svg_double(repr, "x2", lg->x2.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || lg->y2._set) - sp_repr_set_svg_double(repr, "y2", lg->y2.computed); - - CGradient::write(xml_doc, repr, flags); - - return repr; -} - - -/** - * Directly set properties of linear gradient and request modified. - */ -void -sp_lineargradient_set_position(SPLinearGradient *lg, - gdouble x1, gdouble y1, - gdouble x2, gdouble y2) -{ - g_return_if_fail(lg != NULL); - g_return_if_fail(SP_IS_LINEARGRADIENT(lg)); - - /* fixme: units? (Lauris) */ - lg->x1.set(SVGLength::NONE, x1, x1); - lg->y1.set(SVGLength::NONE, y1, y1); - lg->x2.set(SVGLength::NONE, x2, x2); - lg->y2.set(SVGLength::NONE, y2, y2); - - lg->requestModified(SP_OBJECT_MODIFIED_FLAG); -} - -/* - * Radial Gradient - */ -G_DEFINE_TYPE(SPRadialGradient, sp_radialgradient, G_TYPE_OBJECT); - -/** - * SPRadialGradient vtable initialization. - */ -static void sp_radialgradient_class_init(SPRadialGradientClass *klass) -{ -} - -CRadialGradient::CRadialGradient(SPRadialGradient* radialgradient) : CGradient(radialgradient) { - this->spradialgradient = radialgradient; -} - -CRadialGradient::~CRadialGradient() { -} - -SPRadialGradient::SPRadialGradient() : SPGradient() { - SPRadialGradient* rg = this; - - rg->cradialgradient = new CRadialGradient(rg); - rg->typeHierarchy.insert(typeid(SPRadialGradient)); - - delete rg->cgradient; - rg->cgradient = rg->cradialgradient; - rg->cpaintserver = rg->cradialgradient; - rg->cobject = rg->cradialgradient; - - rg->cx.unset(SVGLength::PERCENT, 0.5, 0.5); - rg->cy.unset(SVGLength::PERCENT, 0.5, 0.5); - rg->r.unset(SVGLength::PERCENT, 0.5, 0.5); - rg->fx.unset(SVGLength::PERCENT, 0.5, 0.5); - rg->fy.unset(SVGLength::PERCENT, 0.5, 0.5); -} - -/** - * Callback for SPRadialGradient object initialization. - */ -static void -sp_radialgradient_init(SPRadialGradient *rg) -{ - new (rg) SPRadialGradient(); -} - -/** - * Set radial gradient attributes from associated repr. - */ -void CRadialGradient::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPRadialGradient* object = this->spradialgradient; - - CGradient::build(document, repr); - - object->readAttr( "cx" ); - object->readAttr( "cy" ); - object->readAttr( "r" ); - object->readAttr( "fx" ); - object->readAttr( "fy" ); -} - -/** - * Set radial gradient attribute. - */ -void CRadialGradient::set(unsigned key, gchar const *value) { - SPRadialGradient* object = this->spradialgradient; - - SPRadialGradient *rg = SP_RADIALGRADIENT(object); - - switch (key) { - case SP_ATTR_CX: - if (!rg->cx.read(value)) { - rg->cx.unset(SVGLength::PERCENT, 0.5, 0.5); - } - if (!rg->fx._set) { - rg->fx.value = rg->cx.value; - rg->fx.computed = rg->cx.computed; - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_CY: - if (!rg->cy.read(value)) { - rg->cy.unset(SVGLength::PERCENT, 0.5, 0.5); - } - if (!rg->fy._set) { - rg->fy.value = rg->cy.value; - rg->fy.computed = rg->cy.computed; - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_R: - if (!rg->r.read(value)) { - rg->r.unset(SVGLength::PERCENT, 0.5, 0.5); - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_FX: - if (!rg->fx.read(value)) { - rg->fx.unset(rg->cx.unit, rg->cx.value, rg->cx.computed); - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_FY: - if (!rg->fy.read(value)) { - rg->fy.unset(rg->cy.unit, rg->cy.value, rg->cy.computed); - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - default: - CGradient::set(key, value); - break; - } -} - -/** - * Write radial gradient attributes to associated repr. - */ -Inkscape::XML::Node* CRadialGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPRadialGradient* object = this->spradialgradient; - - SPRadialGradient *rg = SP_RADIALGRADIENT(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:radialGradient"); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || rg->cx._set) sp_repr_set_svg_double(repr, "cx", rg->cx.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || rg->cy._set) sp_repr_set_svg_double(repr, "cy", rg->cy.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || rg->r._set) sp_repr_set_svg_double(repr, "r", rg->r.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || rg->fx._set) sp_repr_set_svg_double(repr, "fx", rg->fx.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || rg->fy._set) sp_repr_set_svg_double(repr, "fy", rg->fy.computed); - - CGradient::write(xml_doc, repr, flags); - - return repr; -} - -/** - * Directly set properties of radial gradient and request modified. - */ -void -sp_radialgradient_set_position(SPRadialGradient *rg, - gdouble cx, gdouble cy, gdouble fx, gdouble fy, gdouble r) -{ - g_return_if_fail(rg != NULL); - g_return_if_fail(SP_IS_RADIALGRADIENT(rg)); - - /* fixme: units? (Lauris) */ - rg->cx.set(SVGLength::NONE, cx, cx); - rg->cy.set(SVGLength::NONE, cy, cy); - rg->fx.set(SVGLength::NONE, fx, fx); - rg->fy.set(SVGLength::NONE, fy, fy); - rg->r.set(SVGLength::NONE, r, r); - - rg->requestModified(SP_OBJECT_MODIFIED_FLAG); -} - -/* - * Mesh Gradient - */ - -//#define MESH_DEBUG - -G_DEFINE_TYPE(SPMeshGradient, sp_meshgradient, G_TYPE_OBJECT); - -/** - * SPMeshGradient vtable initialization. - */ -static void sp_meshgradient_class_init(SPMeshGradientClass *klass) -{ -#ifdef MESH_DEBUG - std::cout << "sp_meshgradient_class_init()" << std::endl; -#endif -} - -CMeshGradient::CMeshGradient(SPMeshGradient* meshgradient) : CGradient(meshgradient) { - this->spmeshgradient = meshgradient; -} - -CMeshGradient::~CMeshGradient() { -} - -SPMeshGradient::SPMeshGradient() : SPGradient() { - SPMeshGradient* mg = this; - - mg->cmeshgradient = new CMeshGradient(mg); - mg->typeHierarchy.insert(typeid(SPMeshGradient)); - - delete mg->cgradient; - mg->cgradient = mg->cmeshgradient; - mg->cpaintserver = mg->cmeshgradient; - mg->cobject = mg->cmeshgradient; - - // Start coordinate of mesh - mg->x.unset(SVGLength::NONE, 0.0, 0.0); - mg->y.unset(SVGLength::NONE, 0.0, 0.0); -} - -/** - * Callback for SPMeshGradient object initialization. - */ -static void -sp_meshgradient_init(SPMeshGradient *mg) -{ - new (mg) SPMeshGradient(); -} - -void CMeshGradient::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPMeshGradient* object = this->spmeshgradient; - - CGradient::build(document, repr); - - // Start coordinate of mesh - object->readAttr( "x" ); - object->readAttr( "y" ); -} - - -void CMeshGradient::set(unsigned key, gchar const *value) { - SPMeshGradient* object = this->spmeshgradient; - - SPMeshGradient *mg = SP_MESHGRADIENT(object); - - switch (key) { - case SP_ATTR_X: - if (!mg->x.read(value)) { - mg->x.unset(SVGLength::NONE, 0.0, 0.0); - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_Y: - if (!mg->y.read(value)) { - mg->y.unset(SVGLength::NONE, 0.0, 0.0); - } - object->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - default: - CGradient::set(key, value); - break; - } -} - -/** - * Write mesh gradient attributes to associated repr. - */ -Inkscape::XML::Node* CMeshGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPMeshGradient* object = this->spmeshgradient; - -#ifdef MESH_DEBUG - std::cout << "sp_meshgradient_write() ***************************" << std::endl; -#endif - SPMeshGradient *mg = SP_MESHGRADIENT(object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:meshGradient"); - } - - if ((flags & SP_OBJECT_WRITE_ALL) || mg->x._set) sp_repr_set_svg_double(repr, "x", mg->x.computed); - if ((flags & SP_OBJECT_WRITE_ALL) || mg->y._set) sp_repr_set_svg_double(repr, "y", mg->y.computed); - - CGradient::write(xml_doc, repr, flags); - - return repr; -} - -/** - * Directly set properties of mesh gradient and request modified. - */ -void -sp_meshgradient_set_position(SPMeshGradient *mg, gdouble x, gdouble y) -{ - g_return_if_fail(mg != NULL); - g_return_if_fail(SP_IS_MESHGRADIENT(mg)); - - mg->x.set(SVGLength::NONE, x, x); - mg->y.set(SVGLength::NONE, y, y); - - mg->requestModified(SP_OBJECT_MODIFIED_FLAG); -} /* CAIRO RENDERING STUFF */ -static void +void sp_gradient_pattern_common_setup(cairo_pattern_t *cp, SPGradient *gr, Geom::OptRect const &bbox, @@ -1902,205 +1038,6 @@ sp_gradient_pattern_common_setup(cairo_pattern_t *cp, ink_cairo_pattern_set_matrix(cp, gs2user.inverse()); } - -cairo_pattern_t* CRadialGradient::pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) { - SPRadialGradient* ps = this->spradialgradient; - - SPRadialGradient *rg = SP_RADIALGRADIENT(ps); - SPGradient *gr = SP_GRADIENT(ps); - - gr->ensureVector(); - - Geom::Point focus(rg->fx.computed, rg->fy.computed); - Geom::Point center(rg->cx.computed, rg->cy.computed); - double radius = rg->r.computed; - double scale = 1.0; - double tolerance = cairo_get_tolerance(ct); - - // NOTE: SVG2 will allow the use of a focus circle which can - // have its center outside the first circle. - - // code below suggested by Cairo devs to overcome tolerance problems - // more: https://bugs.freedesktop.org/show_bug.cgi?id=40918 - - // Corrected for - // https://bugs.launchpad.net/inkscape/+bug/970355 - - Geom::Affine gs2user = gr->gradientTransform; - Geom::Scale gs2user_scale; - - if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX && bbox) { - Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top()); - gs2user *= bbox2user; - gs2user_scale = Geom::Scale( gs2user[0], gs2user[3] ); - } - - Geom::Point d = focus - center; - Geom::Point d_user = d * gs2user_scale; - Geom::Point r_user( radius, 0 ); - r_user *= gs2user_scale; - - if (d_user.length() + tolerance > r_user.length()) { - scale = r_user.length() / d_user.length(); - double dx = d_user.x(), dy = d_user.y(); - cairo_user_to_device_distance(ct, &dx, &dy); - if (!Geom::are_near(dx, 0, tolerance) || - !Geom::are_near(dy, 0, tolerance)) - { - scale *= 1.0 - 2.0 * tolerance / hypot(dx, dy); - } - } - - cairo_pattern_t *cp = cairo_pattern_create_radial( - scale * d.x() + center.x(), scale * d.y() + center.y(), 0, - center.x(), center.y(), radius); - - sp_gradient_pattern_common_setup(cp, gr, bbox, opacity); - - return cp; -} - -cairo_pattern_t* CMeshGradient::pattern_new(cairo_t *ct, -#if defined(MESH_DEBUG) || (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4)) - Geom::OptRect const &bbox, - double opacity -#else - Geom::OptRect const & /*bbox*/, - double /*opacity*/ -#endif - ) -{ - using Geom::X; - using Geom::Y; - - SPMeshGradient* ps = this->spmeshgradient; - -#ifdef MESH_DEBUG - std::cout << "sp_meshgradient_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl; -#endif - //SPMeshGradient *mg = SP_MESHGRADIENT(ps); - SPGradient *gr = SP_GRADIENT(ps); - - gr->ensureArray(); - - cairo_pattern_t *cp = NULL; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4) - SPMeshNodeArray* array = &(gr->array); - - cp = cairo_pattern_create_mesh(); - - for( unsigned int i = 0; i < array->patch_rows(); ++i ) { - for( unsigned int j = 0; j < array->patch_columns(); ++j ) { - - SPMeshPatchI patch( &(array->nodes), i, j ); - - cairo_mesh_pattern_begin_patch( cp ); - cairo_mesh_pattern_move_to( cp, patch.getPoint( 0, 0 )[X], patch.getPoint( 0, 0 )[Y] ); - - for( unsigned int k = 0; k < 4; ++k ) { -#ifdef DEBUG_MESH - std::cout << i << " " << j << " " - << patch.getPathType( k ) << " ("; - for( int p = 0; p < 4; ++p ) { - std::cout << patch.getPoint( k, p ); - } - std::cout << ") " - << patch.getColor( k ).toString() << std::endl; -#endif - - switch ( patch.getPathType( k ) ) { - case 'l': - case 'L': - case 'z': - case 'Z': - cairo_mesh_pattern_line_to( cp, - patch.getPoint( k, 3 )[X], - patch.getPoint( k, 3 )[Y] ); - break; - case 'c': - case 'C': - { - std::vector< Geom::Point > pts = patch.getPointsForSide( k ); - cairo_mesh_pattern_curve_to( cp, - pts[1][X], pts[1][Y], - pts[2][X], pts[2][Y], - pts[3][X], pts[3][Y] ); - break; - } - default: - // Shouldn't happen - std::cout << "sp_meshgradient_create_pattern: path error" << std::endl; - } - - if( patch.tensorIsSet(k) ) { - // Tensor point defined relative to corner. - Geom::Point t = patch.getTensorPoint(k); - cairo_mesh_pattern_set_control_point( cp, k, t[X], t[Y] ); - //std::cout << " sp_meshgradient_create_pattern: tensor " << k - // << " set to " << t << "." << std::endl; - } else { - // Geom::Point t = patch.coonsTensorPoint(k); - //std::cout << " sp_meshgradient_create_pattern: tensor " << k - // << " calculated as " << t << "." <<std::endl; - } - - cairo_mesh_pattern_set_corner_color_rgba( - cp, k, - patch.getColor( k ).v.c[0], - patch.getColor( k ).v.c[1], - patch.getColor( k ).v.c[2], - patch.getOpacity( k ) * opacity ); - } - - cairo_mesh_pattern_end_patch( cp ); - } - } - - // set pattern matrix - Geom::Affine gs2user = gr->gradientTransform; - if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top()); - gs2user *= bbox2user; - } - ink_cairo_pattern_set_matrix(cp, gs2user.inverse()); - -#else - static bool shown = false; - if( !shown ) { - std::cout << "sp_meshgradient_create_pattern: needs cairo >= 1.11.4, using " - << cairo_version_string() << std::endl; - shown = true; - } -#endif - -/* - cairo_pattern_t *cp = cairo_pattern_create_radial( - rg->fx.computed, rg->fy.computed, 0, - rg->cx.computed, rg->cy.computed, rg->r.computed); - sp_gradient_pattern_common_setup(cp, gr, bbox, opacity); -*/ - - return cp; -} - -cairo_pattern_t* CLinearGradient::pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) { - SPLinearGradient* ps = this->splineargradient; - - SPLinearGradient *lg = SP_LINEARGRADIENT(ps); - SPGradient *gr = SP_GRADIENT(ps); - - gr->ensureVector(); - - cairo_pattern_t *cp = cairo_pattern_create_linear( - lg->x1.computed, lg->y1.computed, - lg->x2.computed, lg->y2.computed); - - sp_gradient_pattern_common_setup(cp, gr, bbox, opacity); - - return cp; -} - cairo_pattern_t * sp_gradient_create_preview_pattern(SPGradient *gr, double width) { @@ -2123,12 +1060,6 @@ sp_gradient_create_preview_pattern(SPGradient *gr, double width) return pat; } -void -sp_meshgradient_repr_write(SPMeshGradient *mg) -{ - mg->array.write( mg ); -} - /* Local Variables: mode:c++ |
