Esempio n. 1
0
void
gr_apply_gradient_to_item (SPItem *item, SPGradient *gr, SPGradientType new_type, guint new_fill, bool do_fill, bool do_stroke)
{
    SPStyle *style = SP_OBJECT_STYLE (item);

    if (do_fill) {
        if (style && (style->fill.isPaintserver()) &&
            SP_IS_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (item))) {
            SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item);
            if (SP_IS_LINEARGRADIENT (server)) {
                sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, true);
            } else if (SP_IS_RADIALGRADIENT (server)) {
                sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, true);
            }
        } else if (new_fill) {
            sp_item_set_gradient(item, gr, new_type, true);
        }
    }

    if (do_stroke) {
        if (style && (style->stroke.isPaintserver()) &&
            SP_IS_GRADIENT (SP_OBJECT_STYLE_STROKE_SERVER (item))) {
            SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item);
            if (SP_IS_LINEARGRADIENT (server)) {
                sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, false);
            } else if (SP_IS_RADIALGRADIENT (server)) {
                sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, false);
            }
        } else if (!new_fill) {
            sp_item_set_gradient(item, gr, new_type, false);
        }
    }
}
Esempio n. 2
0
/**
 * Writes the gradient's internal vector (whether from its own stops, or
 * inherited from refs) into the gradient repr as svg:stop elements.
 */
void
sp_gradient_repr_write_vector(SPGradient *gr)
{
    g_return_if_fail(gr != NULL);
    g_return_if_fail(SP_IS_GRADIENT(gr));

    Inkscape::XML::Document *xml_doc = gr->document->getReprDoc();
    Inkscape::XML::Node *repr = gr->getRepr();

    /* We have to be careful, as vector may be our own, so construct repr list at first */
    GSList *cl = NULL;

    for (guint i = 0; i < gr->vector.stops.size(); i++) {
        Inkscape::CSSOStringStream os;
        Inkscape::XML::Node *child = xml_doc->createElement("svg:stop");
        sp_repr_set_css_double(child, "offset", gr->vector.stops[i].offset);
        /* strictly speaking, offset an SVG <number> rather than a CSS one, but exponents make no
         * sense for offset proportions. */
        os << "stop-color:" << gr->vector.stops[i].color.toString() << ";stop-opacity:" << gr->vector.stops[i].opacity;
        child->setAttribute("style", os.str().c_str());
        /* Order will be reversed here */
        cl = g_slist_prepend(cl, child);
    }

    sp_gradient_repr_clear_vector(gr);

    /* And insert new children from list */
    while (cl) {
        Inkscape::XML::Node *child = static_cast<Inkscape::XML::Node *>(cl->data);
        repr->addChild(child, NULL);
        Inkscape::GC::release(child);
        cl = g_slist_remove(cl, child);
    }
}
Esempio n. 3
0
/**
 * Returns the first of {src, src-\>ref-\>getObject(),
 * src-\>ref-\>getObject()-\>ref-\>getObject(),...}
 * for which \a match is true, or NULL if none found.
 *
 * The raison d'être of this routine is that it correctly handles cycles in the href chain (e.g., if
 * a gradient gives itself as its href, or if each of two gradients gives the other as its href).
 *
 * \pre SP_IS_GRADIENT(src).
 */
static SPGradient *
chase_hrefs(SPGradient *const src, bool (*match)(SPGradient const *))
{
    g_return_val_if_fail(SP_IS_GRADIENT(src), NULL);

    /* Use a pair of pointers for detecting loops: p1 advances half as fast as p2.  If there is a
       loop, then once p1 has entered the loop, we'll detect it the next time the distance between
       p1 and p2 is a multiple of the loop size. */
    SPGradient *p1 = src, *p2 = src;
    bool do1 = false;
    for (;;) {
        if (match(p2)) {
            return p2;
        }

        p2 = p2->ref->getObject();
        if (!p2) {
            return p2;
        }
        if (do1) {
            p1 = p1->ref->getObject();
        }
        do1 = !do1;

        if ( p2 == p1 ) {
            /* We've been here before, so return NULL to indicate that no matching gradient found
             * in the chain. */
            return NULL;
        }
    }
}
Esempio n. 4
0
/**
 * Gets called when the gradient is (re)attached to another gradient.
 */
void SPGradient::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr)
{
    if (old_ref) {
        gr->modified_connection.disconnect();
    }
    if ( SP_IS_GRADIENT(ref)
         && ref != 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.
    // So, as we're now (re)linked, we assign linkee's values to this gradient if they are not yet set -
    // but without setting the _set flags.
    // FIXME: do the same for gradientTransform too
    if (!gr->units_set) {
        gr->units = gr->fetchUnits();
    }
    if (!gr->spread_set) {
        gr->spread = gr->fetchSpread();
    }

    /// \todo Fixme: what should the flags (second) argument be? */
    gradientRefModified(ref, 0, gr);
}
Esempio n. 5
0
// TODO: So a solid brush is a gradient with a swatch and zero stops?
// Should we derive a new class for that? Or at least make this method
// virtual and move it out of the way?
bool SPPaintServer::isSolid() const
{
    bool solid = false;
    if (swatch && SP_IS_GRADIENT(this)) {
        SPGradient *grad = SP_GRADIENT(this);
        if ( grad->hasStops() && (grad->getStopCount() == 0) ) {
            solid = true;
        }
    }
    return solid;
}
static void
sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc)
{
    SPDocument *doc = NULL;
    GrDrag *drag = rc->_grdrag;

    GSList *these_stops = NULL;
    GSList *next_stops = NULL;

    std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops);

    if (g_slist_length(these_stops) == 0 && drag->numSelected() == 1) {
        // if a single stop is selected, add between that stop and the next one
        GrDragger *dragger = (GrDragger *) drag->selected->data;
        for (GSList const* j = dragger->draggables; j != NULL; j = j->next) { 
            GrDraggable *d = (GrDraggable *) j->data;
            SPGradient *gradient = sp_item_gradient (d->item, d->fill_or_stroke);
            SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false);
            SPStop *this_stop = sp_get_stop_i (vector, d->point_i);
            SPStop *next_stop = sp_next_stop (this_stop);
            if (this_stop && next_stop) {
                these_stops = g_slist_prepend (these_stops, this_stop);
                next_stops = g_slist_prepend (next_stops, next_stop);
            }
        }
    }

    // now actually create the new stops
    GSList *i = these_stops;
    GSList *j = next_stops;
    for (; i != NULL && j != NULL; i = i->next, j = j->next) {
        SPStop *this_stop = (SPStop *) i->data;
        SPStop *next_stop = (SPStop *) j->data;
        gfloat offset = 0.5*(this_stop->offset + next_stop->offset);
        SPObject *parent = SP_OBJECT_PARENT(this_stop);
        if (SP_IS_GRADIENT (parent)) {
            doc = SP_OBJECT_DOCUMENT (parent);
            sp_vector_add_stop (SP_GRADIENT (parent), this_stop, next_stop, offset);
            sp_gradient_ensure_vector (SP_GRADIENT (parent));
        }
    }

    if (g_slist_length(these_stops) > 0 && doc) {
        sp_document_done (doc, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop"));
        drag->updateDraggers();
        // so that it does not automatically update draggers in idle loop, as this would deselect
        drag->local_change = true;
        // select all the old selected and new created draggers
        drag->selectByCoords(coords);
    }

    g_slist_free (these_stops);
    g_slist_free (next_stops);
}
Esempio n. 7
0
static SPObject *
sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc)
{
    static SPDocument *doc = NULL;
    static unsigned int edoc = FALSE;
    if (!current_doc) {
        return NULL;
    }
    /* Try to load from document */
    if (!edoc && !doc) {
        gchar *gradients = g_build_filename(INKSCAPE_GRADIENTSDIR, "/gradients.svg", NULL);
        if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) {
            doc = SPDocument::createNewDoc(gradients, FALSE);
        }
        if (!doc) {
        gchar *gradients = g_build_filename(CREATE_GRADIENTSDIR, "/gradients.svg", NULL);
        if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) {
            doc = SPDocument::createNewDoc(gradients, FALSE);
        }
        g_free(gradients);
        if (doc) {
            doc->ensureUpToDate();
        } else {
            edoc = TRUE;
        }
        }
    }
    if (!edoc && doc) {
        /* Get the gradient we want */
        SPObject *object = doc->getObjectById(name);
        if (object && SP_IS_GRADIENT(object)) {
            SPDefs *defs = current_doc->getDefs();
            Inkscape::XML::Document *xml_doc = current_doc->getReprDoc();
            Inkscape::XML::Node *pat_repr = object->getRepr()->duplicate(xml_doc);
            defs->getRepr()->addChild(pat_repr, NULL);
            Inkscape::GC::release(pat_repr);
            return object;
        }
    }
    return NULL;
}
Esempio n. 8
0
SPObject *get_stock_item(gchar const *urn, gboolean stock)
{
    g_assert(urn != NULL);
    
    /* check its an inkscape URN */
    if (!strncmp (urn, "urn:inkscape:", 13)) {

        gchar const *e = urn + 13;
        int a = 0;
        gchar * name = g_strdup(e);
        gchar *name_p = name;
        while (*name_p != ':' && *name_p != '\0'){
            name_p++;
            a++;
        }
        
        if (*name_p ==':') {
            name_p++;
        }
        
        gchar * base = g_strndup(e, a);

        SPDesktop *desktop = SP_ACTIVE_DESKTOP;
        SPDocument *doc = desktop->getDocument();
        SPDefs *defs = doc->getDefs();
        if (!defs) {
            g_free(base);
            return NULL;
        }
        SPObject *object = NULL;
        if (!strcmp(base, "marker") && !stock) {
            for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
            {
                if (child->getRepr()->attribute("inkscape:stockid") &&
                    !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
                    SP_IS_MARKER(child))
                {
                    object = child;
                }
            }
            
        }
        else if (!strcmp(base,"pattern") && !stock)  {
            for ( SPObject *child = defs->firstChild() ; child; child = child->getNext() )
            {
                if (child->getRepr()->attribute("inkscape:stockid") &&
                    !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
                    SP_IS_PATTERN(child))
                {
                    object = child;
                }
            }
            
        }
        else if (!strcmp(base,"gradient") && !stock)  {
            for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
            {
                if (child->getRepr()->attribute("inkscape:stockid") &&
                    !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
                    SP_IS_GRADIENT(child))
                {
                    object = child;
                }
            }
            
        }
        
        if (object == NULL) {
            
            if (!strcmp(base, "marker"))  {
                object = sp_marker_load_from_svg(name_p, doc);
            }
            else if (!strcmp(base, "pattern"))  {
                object = sp_pattern_load_from_svg(name_p, doc);
            }
            else if (!strcmp(base, "gradient"))  {
                object = sp_gradient_load_from_svg(name_p, doc);
            }
        }
        
        g_free(base);
        g_free(name);
        
        if (object) {
            object->getRepr()->setAttribute("inkscape:isstock", "true");
        }

        return object;
    }
    
    else {
        
        SPDesktop *desktop = SP_ACTIVE_DESKTOP;
        SPDocument *doc = desktop->getDocument();
        SPObject *object = doc->getObjectById(urn);

        return object;
    }
}
Esempio n. 9
0
void
gr_read_selection (Inkscape::Selection *selection, GrDrag *drag, SPGradient **gr_selected, bool *gr_multi, SPGradientSpread *spr_selected, bool *spr_multi)
{
    if (drag && drag->selected) {
        // GRADIENTFIXME: make this work for more than one selected dragger?
        GrDragger *dragger = (GrDragger*) drag->selected->data;
        for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger
            GrDraggable *draggable = (GrDraggable *) i->data;
            SPGradient *gradient = sp_item_gradient_get_vector (draggable->item, draggable->fill_or_stroke);
            SPGradientSpread spread = sp_item_gradient_get_spread (draggable->item, draggable->fill_or_stroke);

            if (gradient != *gr_selected) {
                if (*gr_selected != NULL) {
                    *gr_multi = true;
                } else {
                    *gr_selected = gradient;
                }
            }
            if (spread != *spr_selected) {
                if (*spr_selected != INT_MAX) {
                    *spr_multi = true;
                } else {
                    *spr_selected = spread;
                }
            }
         }
        return;
    }

   // If no selected dragger, read desktop selection
   for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
        SPItem *item = SP_ITEM(i->data);
        SPStyle *style = SP_OBJECT_STYLE (item);

        if (style && (style->fill.isPaintserver())) {
            SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item);
            if (SP_IS_GRADIENT (server)) {
                SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false);
                SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server));
                if (gradient != *gr_selected) {
                    if (*gr_selected != NULL) {
                        *gr_multi = true;
                    } else {
                        *gr_selected = gradient;
                    }
                }
                if (spread != *spr_selected) {
                    if (*spr_selected != INT_MAX) {
                        *spr_multi = true;
                    } else {
                        *spr_selected = spread;
                    }
                }
            }
        }
        if (style && (style->stroke.isPaintserver())) {
            SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item);
            if (SP_IS_GRADIENT (server)) {
                SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false);
                SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server));
                if (gradient != *gr_selected) {
                    if (*gr_selected != NULL) {
                        *gr_multi = true;
                    } else {
                        *gr_selected = gradient;
                    }
                }
                if (spread != *spr_selected) {
                    if (*spr_selected != INT_MAX) {
                        *spr_multi = true;
                    } else {
                        *spr_selected = spread;
                    }
                }
            }
        }
    }
 }