예제 #1
0
static void
sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
{
    g_return_if_fail(lpeitem != NULL);

    SPMask * mask = lpeitem->mask_ref->getObject();
    if(mask)
    {
        sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
    }
    SPClipPath * clipPath = lpeitem->clip_ref->getObject();
    if(clipPath)
    {
        sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
    }
    if (SP_IS_GROUP(lpeitem)) {
        GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
        for ( GSList const *iter = item_list; iter; iter = iter->next ) {
            SPObject *subitem = static_cast<SPObject *>(iter->data);
            if (SP_IS_LPE_ITEM(subitem)) {
                sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem));
            }
        }
    }
    else if (SP_IS_PATH(lpeitem)) {
        Inkscape::XML::Node *pathrepr = lpeitem->getRepr();
        if ( !pathrepr->attribute("inkscape:original-d") ) {
            pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));
        }
    }
}
예제 #2
0
/**
 * Adds menu items for pattern list - derived from marker code, left hb etc in to make addition of previews easier at some point.
 */
static void
sp_pattern_menu_build (GtkWidget *combo, GSList *pattern_list, SPDocument */*source*/)
{
    GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
    GtkTreeIter iter;

    for (; pattern_list != NULL; pattern_list = pattern_list->next) {

        Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(pattern_list->data)->getRepr();

        // label for combobox
        gchar const *label;
        if (repr->attribute("inkscape:stockid")) {
            label = _(repr->attribute("inkscape:stockid"));
        } else {
            label = _(repr->attribute("id"));
        }

        gchar const *patid = repr->attribute("id");

        gboolean stockid = false;
        if (repr->attribute("inkscape:stockid")) {
            stockid = true;
        }

        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter,
                COMBO_COL_LABEL, label, COMBO_COL_STOCK, stockid, COMBO_COL_PATTERN, patid, COMBO_COL_SEP, FALSE, -1);

    }
}
예제 #3
0
bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc)
{
    bool changed = false;
    if ( doc ) {
        // TODO debug g_message("FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP");
        // TODO debug g_message("      base is [%s]", doc->getBase());

        std::vector<Glib::ustring> brokenHrefs = findBrokenLinks(doc);
        if ( !brokenHrefs.empty() ) {
            // TODO debug g_message("    FOUND SOME LINKS %d", static_cast<int>(brokenHrefs.size()));
            for ( std::vector<Glib::ustring>::iterator it = brokenHrefs.begin(); it != brokenHrefs.end(); ++it ) {
                // TODO debug g_message("        [%s]", it->c_str());
            }
        }

        std::map<Glib::ustring, Glib::ustring> mapping = locateLinks(doc->getBase(), brokenHrefs);
        for ( std::map<Glib::ustring, Glib::ustring>::iterator it = mapping.begin(); it != mapping.end(); ++it )
        {
            // TODO debug g_message("     [%s] ==> {%s}", it->first.c_str(), it->second.c_str());
        }

        bool savedUndoState = DocumentUndo::getUndoSensitive(doc);
        DocumentUndo::setUndoSensitive(doc, true);

        GSList const *images = doc->getResourceList("image");
        for (GSList const *it = images; it; it = it->next) {
            Inkscape::XML::Node *ir = static_cast<SPObject *>(it->data)->getRepr();

            gchar const *href = ir->attribute("xlink:href");
            if ( href ) {
                // TODO debug g_message("                  consider [%s]", href);
                
                if ( mapping.find(href) != mapping.end() ) {
                    // TODO debug g_message("                     Found a replacement");

                    ir->setAttribute( "xlink:href", mapping[href].c_str() );
                    if ( ir->attribute( "sodipodi:absref" ) ) {
                        ir->setAttribute( "sodipodi:absref", 0 ); // Remove this attribute
                    }

                    SPObject *updated = doc->getObjectByRepr(ir);
                    if (updated) {
                        // force immediate update of dependant attributes
                        updated->updateRepr();
                    }

                    changed = true;
                }
            }
        }
        if ( changed ) {
            DocumentUndo::done( doc, SP_VERB_DIALOG_XML_EDITOR, _("Fixup broken links") );
        }
        DocumentUndo::setUndoSensitive(doc, savedUndoState);
    }

    return changed;
}
예제 #4
0
std::string NodeTraits::get_type_string(Inkscape::XML::Node const &node)
{
    std::string name;

    switch (node.type()) {
    case Inkscape::XML::TEXT_NODE:
        name = "string";
        break;

    case Inkscape::XML::ELEMENT_NODE: {
        char const *const sptype = node.attribute("sodipodi:type");

        if (sptype) {
            name = sptype;
        } else {
            name = node.name();
        }
        break;
    }
    default:
        name = "";
        break;
    }

    return name;
}
예제 #5
0
Inkscape::XML::Node *Parameter::document_param_node(SPDocument * doc)
{
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
    Inkscape::XML::Node * defs = doc->getDefs()->getRepr();
    Inkscape::XML::Node * params = NULL;

    GQuark const name_quark = g_quark_from_string("inkscape:extension-params");

    for (Inkscape::XML::Node * child = defs->firstChild();
            child != NULL;
            child = child->next()) {
        if ((GQuark)child->code() == name_quark &&
                !strcmp(child->attribute("extension"), extension->get_id())) {
            params = child;
            break;
        }
    }

    if (params == NULL) {
        params = xml_doc->createElement("inkscape:extension-param");
        params->setAttribute("extension", extension->get_id());
        defs->appendChild(params);
        Inkscape::GC::release(params);
    }

    return params;
}
예제 #6
0
// Create a mask element (using passed elements), add it to <defs>
const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform)
{
    Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr();

    Inkscape::XML::Document *xml_doc = document->getReprDoc();
    Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath");
    repr->setAttribute("clipPathUnits", "userSpaceOnUse");

    defsrepr->appendChild(repr);
    const gchar *id = repr->attribute("id");
    SPObject *clip_path_object = document->getObjectById(id);

    for (GSList *it = reprs; it != NULL; it = it->next) {
        Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data);
        SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node));

        if (NULL != applyTransform) {
            Geom::Affine transform (item->transform);
            transform *= (*applyTransform);
            item->doWriteTransform(item->getRepr(), transform);
        }
    }

    Inkscape::GC::release(repr);
    return id;
}
예제 #7
0
// Create a mask element (using passed elements), add it to <defs>
const gchar *
sp_clippath_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform)
{
    Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));

    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
    Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath");
    repr->setAttribute("clipPathUnits", "userSpaceOnUse");

    defsrepr->appendChild(repr);
    const gchar *id = repr->attribute("id");
    SPObject *clip_path_object = document->getObjectById(id);

    for (GSList *it = reprs; it != NULL; it = it->next) {
        Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data);
        SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node));

        if (NULL != applyTransform) {
            Geom::Matrix transform (item->transform);
            transform *= (*applyTransform);
            sp_item_write_transform(item, SP_OBJECT_REPR(item), transform);
        }
    }

    Inkscape::GC::release(repr);
    return id;
}
예제 #8
0
std::vector<Glib::ustring> ResourceManagerImpl::findBrokenLinks( SPDocument *doc )
{
    std::vector<Glib::ustring> result;
    std::set<Glib::ustring> uniques;

    if ( doc ) {
        GSList const *images = doc->getResourceList("image");
        for (GSList const *it = images; it; it = it->next) {
            Inkscape::XML::Node *ir = static_cast<SPObject *>(it->data)->getRepr();

            gchar const *href = ir->attribute("xlink:href");
            if ( href &&  ( uniques.find(href) == uniques.end() ) ) {
                std::string uri;
                if ( extractFilepath( href, uri ) ) {
                    if ( Glib::path_is_absolute(uri) ) {
                        if ( !Glib::file_test(uri, Glib::FILE_TEST_EXISTS) ) {
                            result.push_back(href);
                            uniques.insert(href);
                        }
                    } else {
                        std::string combined = Glib::build_filename(doc->getBase(), uri);
                        if ( !Glib::file_test(uri, Glib::FILE_TEST_EXISTS) ) {
                            result.push_back(href);
                            uniques.insert(href);
                        }
                    }
                }
            }
        }        
    }

    return result;
}
예제 #9
0
Glib::ustring sp_filter_get_new_result_name(SPFilter *filter) {
    g_assert(filter != NULL);
    int largest = 0;

    SPObject *primitive_obj = filter->children;
    while (primitive_obj) {
        if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) {
            Inkscape::XML::Node *repr = primitive_obj->getRepr();
            char const *result = repr->attribute("result");
            int index;
            if (result)
            {
                if (sscanf(result, "result%5d", &index) == 1)
                {
                    if (index > largest)
                    {
                        largest = index;
                    }
                }
            }
        }
        primitive_obj = primitive_obj->next;
    }

    return "result" + Glib::Ascii::dtostr(largest + 1);
}
예제 #10
0
void spdc_create_single_dot(ToolBase *ec, Geom::Point const &pt, char const *tool, guint event_state) {
    g_return_if_fail(!strcmp(tool, "/tools/freehand/pen") || !strcmp(tool, "/tools/freehand/pencil"));
    Glib::ustring tool_path = tool;

    SPDesktop *desktop = ec->desktop;
    Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
    Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
    repr->setAttribute("sodipodi:type", "arc");
    SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr));
    Inkscape::GC::release(repr);

    // apply the tool's current style
    sp_desktop_apply_style_tool(desktop, repr, tool, false);

    // find out stroke width (TODO: is there an easier way??)
    double stroke_width = 3.0;
    gchar const *style_str = repr->attribute("style");
    if (style_str) {
        SPStyle style(SP_ACTIVE_DOCUMENT);
        style.mergeString(style_str);
        stroke_width = style.stroke_width.computed;
    }

    // unset stroke and set fill color to former stroke color
    gchar * str;
    str = g_strdup_printf("fill:#%06x;stroke:none;", sp_desktop_get_color_tool(desktop, tool, false) >> 8);
    repr->setAttribute("style", str);
    g_free(str);

    // put the circle where the mouse click occurred and set the diameter to the
    // current stroke width, multiplied by the amount specified in the preferences
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    Geom::Affine const i2d (item->i2dt_affine ());
    Geom::Point pp = pt * i2d.inverse();
    double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0);
    if (event_state & GDK_MOD1_MASK) {
        // TODO: We vary the dot size between 0.5*rad and 1.5*rad, where rad is the dot size
        // as specified in prefs. Very simple, but it might be sufficient in practice. If not,
        // we need to devise something more sophisticated.
        double s = g_random_double_range(-0.5, 0.5);
        rad *= (1 + s);
    }
    if (event_state & GDK_SHIFT_MASK) {
        // double the point size
        rad *= 2;
    }

    sp_repr_set_svg_double (repr, "sodipodi:cx", pp[Geom::X]);
    sp_repr_set_svg_double (repr, "sodipodi:cy", pp[Geom::Y]);
    sp_repr_set_svg_double (repr, "sodipodi:rx", rad * stroke_width);
    sp_repr_set_svg_double (repr, "sodipodi:ry", rad * stroke_width);
    item->updateRepr();

    desktop->getSelection()->set(item);

    desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating single dot"));
    DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE, _("Create single dot"));
}
예제 #11
0
void
SPLPEItem::apply_to_clippath(SPItem *item)
{
    SPClipPath *clipPath = item->clip_ref->getObject();
    if(clipPath) {
        SPObject * clip_data = clipPath->firstChild();
        SPCurve * clip_curve = NULL;

        if (SP_IS_PATH(clip_data)) {
            clip_curve = SP_PATH(clip_data)->get_original_curve();
        } else if(SP_IS_SHAPE(clip_data)) {
            clip_curve = SP_SHAPE(clip_data)->getCurve();
        } else if(SP_IS_GROUP(clip_data)) {
            apply_to_clip_or_mask_group(SP_ITEM(clip_data), item);
            return;
        }
        if(clip_curve) {
            bool success = false;
            if(SP_IS_GROUP(this)){
                clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
                success = this->performPathEffect(clip_curve);
                clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
            } else {
                success = this->performPathEffect(clip_curve);
            }
            Inkscape::XML::Node *reprClip = clip_data->getRepr();
            if (success) {
                gchar *str = sp_svg_write_path(clip_curve->get_pathvector());
                reprClip->setAttribute("d", str);
                g_free(str);
            } else {
                // LPE was unsuccesfull. Read the old 'd'-attribute.
                if (gchar const * value = reprClip->attribute("d")) {
                    Geom::PathVector pv = sp_svg_read_pathv(value);
                    SPCurve *oldcurve = new SPCurve(pv);
                    if (oldcurve) {
                        SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE);
                        oldcurve->unref();
                    }
                }
            }
            clip_curve->unref();
        }
    }
    if(SP_IS_GROUP(item)){
        GSList const *item_list = sp_item_group_item_list(SP_GROUP(item));
        for ( GSList const *iter = item_list; iter; iter = iter->next ) {
            SPObject *subitem = static_cast<SPObject *>(iter->data);
            apply_to_clippath(SP_ITEM(subitem));
        }
    }
}
예제 #12
0
/* function which evaluates if item should be displayed */
bool sp_item_evaluate(SPItem const *item) {
    Inkscape::XML::Node *grepr = SP_OBJECT_REPR (item);
    
    for ( unsigned int i = 0 ; i < sizeof(_condition_handlers)/sizeof(_condition_handlers[0]) ; i++ ) {
        gchar const *value = grepr->attribute(_condition_handlers[i].attribute);
        if ( NULL == value )
            continue;

        if (!_condition_handlers[i].evaluator(item, value))
            return false;
    }

    return true;
}
예제 #13
0
void
Effect::createAndApply(const char* name, SPDocument *doc, SPItem *item)
{
    // Path effect definition
    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
    Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");
    repr->setAttribute("effect", name);

    SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute
    const gchar * repr_id = repr->attribute("id");
    Inkscape::GC::release(repr);

    gchar *href = g_strdup_printf("#%s", repr_id);
    sp_lpe_item_add_path_effect(SP_LPE_ITEM(item), href, true);
    g_free(href);
}
예제 #14
0
static void
sp_path_update_patheffect(SPLPEItem *lpeitem, bool write)
{
    SPShape * const shape = (SPShape *) lpeitem;
    Inkscape::XML::Node *repr = shape->getRepr();

#ifdef PATH_VERBOSE
g_message("sp_path_update_patheffect");
#endif

    if (shape->_curve_before_lpe && sp_lpe_item_has_path_effect_recursive(lpeitem)) {
        SPCurve *curve = shape->_curve_before_lpe->copy();
        /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe.
         * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
        shape->setCurveInsync(curve, TRUE);

        bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve);
        if (success && write) {
            // could also do shape->getRepr()->updateRepr();  but only the d attribute needs updating.
#ifdef PATH_VERBOSE
g_message("sp_path_update_patheffect writes 'd' attribute");
#endif
            if ( shape->_curve != NULL ) {
                gchar *str = sp_svg_write_path(shape->_curve->get_pathvector());
                repr->setAttribute("d", str);
                g_free(str);
            } else {
                repr->setAttribute("d", NULL);
            }
        } else if (!success) {
            // LPE was unsuccesfull. Read the old 'd'-attribute.
            if (gchar const * value = repr->attribute("d")) {
                Geom::PathVector pv = sp_svg_read_pathv(value);
                SPCurve *oldcurve = new SPCurve(pv);
                if (oldcurve) {
                    shape->setCurve(oldcurve, TRUE);
                    oldcurve->unref();
                }
            }
        }
        shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
        curve->unref();
    }
}
예제 #15
0
void Preferences::_getRawValue(Glib::ustring const &path, gchar const *&result)
{
    // create node and attribute keys
    Glib::ustring node_key, attr_key;
    _keySplit(path, node_key, attr_key);
    
    // retrieve the attribute
    Inkscape::XML::Node *node = _getNode(node_key, false);
    if ( node == NULL ) {
        result = NULL;
    } else {
        gchar const *attr = node->attribute(attr_key.data());
        if ( attr == NULL ) {
            result = NULL;
        } else {
            result = attr;
        }
    }
}
예제 #16
0
void
PathEffect::processPathEffects (SPDocument * doc, Inkscape::XML::Node * path)
{
    gchar const * patheffectlist = path->attribute("inkscape:path-effects");
    if (patheffectlist == NULL)
        return;

    gchar ** patheffects = g_strsplit(patheffectlist, ";", 128);
    Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));

    for (int i = 0; patheffects[i] != NULL && i < 128; i++) {
        gchar * patheffect = patheffects[i];

        // This is weird, they should all be references... but anyway
        if (patheffect[0] != '#') continue;

        Inkscape::XML::Node * prefs = sp_repr_lookup_child(defs, "id", &(patheffect[1]));
        if (prefs == NULL) {

            continue;
        }

        gchar const * ext_id = prefs->attribute("extension");
        if (ext_id == NULL) {

            continue;
        }

        Inkscape::Extension::PathEffect * peffect;
        peffect = dynamic_cast<Inkscape::Extension::PathEffect *>(Inkscape::Extension::db.get(ext_id));
        if (peffect != NULL) {

            continue;
        }

        peffect->processPath(doc, path, prefs);
    }

    g_strfreev(patheffects);
    return;
}
예제 #17
0
static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points, FreehandBase *dc, SPItem *item)
{
    using namespace Inkscape::LivePathEffect;

    Effect::createAndApply(POWERSTROKE, dc->desktop->doc(), item);
    Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
    static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);

    // find out stroke width (TODO: is there an easier way??)
    SPDesktop *desktop = dc->desktop;
    Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
    Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
    Inkscape::GC::release(repr);

    char const* tool = SP_IS_PEN_CONTEXT(dc) ? "/tools/freehand/pen" : "/tools/freehand/pencil";

    // apply the tool's current style
    sp_desktop_apply_style_tool(desktop, repr, tool, false);

    double stroke_width = 1.0;
    char const *style_str = NULL;
    style_str = repr->attribute("style");
    if (style_str) {
        SPStyle style(SP_ACTIVE_DOCUMENT);
        style.mergeString(style_str);
        stroke_width = style.stroke_width.computed;
    }

    std::ostringstream s;
    s.imbue(std::locale::classic());
    s << points[0][Geom::X] << "," << stroke_width / 2.;

    // write powerstroke parameters:
    lpe->getRepr()->setAttribute("start_linecap_type", "zerowidth");
    lpe->getRepr()->setAttribute("end_linecap_type", "zerowidth");
    lpe->getRepr()->setAttribute("cusp_linecap_type", "round");
    lpe->getRepr()->setAttribute("sort_points", "true");
    lpe->getRepr()->setAttribute("interpolator_type", "CubicBezierJohan");
    lpe->getRepr()->setAttribute("interpolator_beta", "0.2");
    lpe->getRepr()->setAttribute("offset_points", s.str().c_str());
}
예제 #18
0
static void
sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
{
    SPItem *item = SP_ITEM(object);
    GtkWidget *w;

    /* Link dialog */
    w = gtk_menu_item_new_with_mnemonic(_("Image _Properties"));
    gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
    gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_properties), item);
    gtk_widget_show(w);
    gtk_menu_append(GTK_MENU(m), w);

    w = gtk_menu_item_new_with_mnemonic(_("Edit Externally..."));
    gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
    gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_edit), item);
    gtk_widget_show(w);
    gtk_menu_append(GTK_MENU(m), w);
    Inkscape::XML::Node *ir = SP_OBJECT_REPR(object);
    const gchar *href = ir->attribute("xlink:href");
    if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) {
        gtk_widget_set_sensitive( w, FALSE );
    }
}
예제 #19
0
static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop)
{

    if (!SP_IS_GRADIENT(gradient)) {
        return;
    }

    blocked = TRUE;

    /* Clear old list, if there is any */
    GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
    if (!combo_box) {
        return;
    }
    GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)));
    if (!store) {
        return;
    }
    gtk_list_store_clear(store);
    GtkTreeIter iter;

    /* Populate the combobox store */
    GSList *sl = NULL;
    if ( gradient->hasStops() ) {
        for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
            if (SP_IS_STOP(ochild)) {
                sl = g_slist_append(sl, ochild);
            }
        }
    }
    if (!sl) {
        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter, 0, NULL, 1, _("No stops in gradient"), 2, NULL, -1);
        gtk_widget_set_sensitive (combo_box, FALSE);

    } else {

        for (; sl != NULL; sl = sl->next){
            if (SP_IS_STOP(sl->data)){
                SPStop *stop = SP_STOP(sl->data);
                Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr();
                Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32()));
                GdkPixbuf *pb = cpv->toPixbuf(64, 16);

                gtk_list_store_append (store, &iter);
                gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1);
                gtk_widget_set_sensitive (combo_box, FALSE);
            }
        }

        gtk_widget_set_sensitive(combo_box, TRUE);
    }

    /* Set history */
    if (new_stop == NULL) {
        gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0);
    } else {
        select_stop_in_list(vb, gradient, new_stop);
    }

    blocked = FALSE;
}
예제 #20
0
static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, SPCurve *curve)
{
    using namespace Inkscape::LivePathEffect;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    if (item && SP_IS_LPE_ITEM(item)) {
        bool simplify = prefs->getInt(tool_name(dc) + "/simplify", 0);
        if(simplify){
            double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0);
            tol = tol/(100.0*(102.0-tol));
            std::ostringstream ss;
            ss << tol;
            spdc_apply_simplify(ss.str(), dc, item);
            sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
        }
        if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) {
            Effect::createAndApply(SPIRO, dc->desktop->doc(), item);
        }

        if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) {
            Effect::createAndApply(BSPLINE, dc->desktop->doc(), item);
        }
        SPShape *sp_shape = dynamic_cast<SPShape *>(item);
        if (sp_shape) {
            curve = sp_shape->getCurve();
        }

        //Store the clipboard path to apply in the future without the use of clipboard
        static Geom::PathVector previous_shape_pathv;

        shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0);
        bool shape_applied = false;
        SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
        const char *cstroke = sp_repr_css_property(css_item, "stroke", "none");
        static SPItem *bend_item;

#define SHAPE_LENGTH 10
#define SHAPE_HEIGHT 10


        if(shape == LAST_APPLIED){

            shape = previous_shape_type;
            if(shape == CLIPBOARD || shape == BEND_CLIPBOARD){
                shape = LAST_APPLIED;
            }
        }

        switch (shape) {
            case NONE:
                // don't apply any shape
                break;
            case TRIANGLE_IN:
            {
                // "triangle in"
                std::vector<Geom::Point> points(1);
                points[0] = Geom::Point(0., SHAPE_HEIGHT/2);
                spdc_apply_powerstroke_shape(points, dc, item);

                shape_applied = true;
                break;
            }
            case TRIANGLE_OUT:
            {
                // "triangle out"
                guint curve_length = curve->get_segment_count();
                std::vector<Geom::Point> points(1);
                points[0] = Geom::Point((double)curve_length, SHAPE_HEIGHT/2);
                spdc_apply_powerstroke_shape(points, dc, item);

                shape_applied = true;
                break;
            }
            case ELLIPSE:
            {
                // "ellipse"
                SPCurve *c = new SPCurve();
                const double C1 = 0.552;
                c->moveto(0, SHAPE_HEIGHT/2);
                c->curveto(0, (1 - C1) * SHAPE_HEIGHT/2, (1 - C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH/2, 0);
                c->curveto((1 + C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH, (1 - C1) * SHAPE_HEIGHT/2, SHAPE_LENGTH, SHAPE_HEIGHT/2);
                c->curveto(SHAPE_LENGTH, (1 + C1) * SHAPE_HEIGHT/2, (1 + C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, SHAPE_LENGTH/2, SHAPE_HEIGHT);
                c->curveto((1 - C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, 0, (1 + C1) * SHAPE_HEIGHT/2, 0, SHAPE_HEIGHT/2);
                c->closepath();
                spdc_paste_curve_as_freehand_shape(c->get_pathvector(), dc, item);
                c->unref();

                shape_applied = true;
                break;
            }
            case CLIPBOARD:
            {
                // take shape from clipboard;
                Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
                if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){
                    SPItem * pasted_clipboard = dc->selection->singleItem();
                    if(pasted_clipboard){
                        Inkscape::XML::Node *pasted_clipboard_root = pasted_clipboard->getRepr();
                        Inkscape::XML::Node *path = sp_repr_lookup_name(pasted_clipboard_root, "svg:path", -1); // unlimited search depth
                        if ( path != NULL ) {
                            gchar const *svgd = path->attribute("d");
                            dc->selection->remove(SP_OBJECT(pasted_clipboard));
                            previous_shape_pathv =  sp_svg_read_pathv(svgd);
                            previous_shape_pathv *= pasted_clipboard->transform;
                            spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item);

                            shape = CLIPBOARD;
                            shape_applied = true;
                            pasted_clipboard->deleteObject();
                        } else {
                            shape = NONE;
                        }
                    } else {
                        shape = NONE;
                    }
                } else {
                    shape = NONE;
                }
                break;
            }
            case BEND_CLIPBOARD:
            {
                Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
                if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){
                    gchar const *svgd = item->getRepr()->attribute("d");
                    bend_item = dc->selection->singleItem();
                    if(bend_item){
                        bend_item->moveTo(item,false);
                        bend_item->transform.setTranslation(Geom::Point());
                        spdc_apply_bend_shape(svgd, dc, bend_item);
                        dc->selection->add(SP_OBJECT(bend_item));

                        shape = BEND_CLIPBOARD;
                    } else {
                        shape = NONE;
                    }
                } else {
                    shape = NONE;
                }
                break;
            }
            case LAST_APPLIED:
            {
                if(previous_shape_type == CLIPBOARD){
                    if(previous_shape_pathv.size() != 0){
                        spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item);

                        shape_applied = true;
                        shape = CLIPBOARD;
                    } else{
                        shape = NONE;
                    }
                } else {
                    if(bend_item != NULL && bend_item->getRepr() != NULL){
                        gchar const *svgd = item->getRepr()->attribute("d");
                        dc->selection->add(SP_OBJECT(bend_item));
                        sp_selection_duplicate(dc->desktop);
                        dc->selection->remove(SP_OBJECT(bend_item));
                        bend_item = dc->selection->singleItem();
                        if(bend_item){
                            bend_item->moveTo(item,false);
                            Geom::Coord expansion_X = bend_item->transform.expansionX();
                            Geom::Coord expansion_Y = bend_item->transform.expansionY();
                            bend_item->transform = Geom::Affine(1,0,0,1,0,0);
                            bend_item->transform.setExpansionX(expansion_X);
                            bend_item->transform.setExpansionY(expansion_Y);
                            spdc_apply_bend_shape(svgd, dc, bend_item);
                            dc->selection->add(SP_OBJECT(bend_item));

                            shape = BEND_CLIPBOARD;
                        } else {
                            shape = NONE;
                        }
                    } else {
                        shape = NONE;
                    }
                }
                break;
            }
            default:
                break;
        }
        previous_shape_type = shape;

        if (shape_applied) {
            // apply original stroke color as fill and unset stroke; then return
            SPCSSAttr *css = sp_repr_css_attr_new();

            if (!strcmp(cstroke, "none")){
                sp_repr_css_set_property (css, "fill", "black");
            } else {
                sp_repr_css_set_property (css, "fill", cstroke);
            }
            sp_repr_css_set_property (css, "stroke", "none");
            sp_desktop_apply_css_recursive(item, css, true);
            sp_repr_css_attr_unref(css);
            return;
        }

        if (dc->waiting_LPE_type != INVALID_LPE) {
            Effect::createAndApply(dc->waiting_LPE_type, dc->desktop->doc(), item);
            dc->waiting_LPE_type = INVALID_LPE;

            if (SP_IS_LPETOOL_CONTEXT(dc)) {
                // since a geometric LPE was applied, we switch back to "inactive" mode
                lpetool_context_switch_mode(SP_LPETOOL_CONTEXT(dc), INVALID_LPE);
            }
        }
        if (SP_IS_PEN_CONTEXT(dc)) {
            SP_PEN_CONTEXT(dc)->setPolylineMode();
        }
    }
}
예제 #21
0
SPItem *SPUse::unlink() {
    Inkscape::XML::Node *repr = this->getRepr();

    if (!repr) {
        return NULL;
    }

    Inkscape::XML::Node *parent = repr->parent();
    SPDocument *document = this->document;
    Inkscape::XML::Document *xml_doc = document->getReprDoc();

    // Track the ultimate source of a chain of uses.
    SPItem *orig = this->root();

    if (!orig) {
        return NULL;
    }

    // Calculate the accumulated transform, starting from the original.
    Geom::Affine t = this->get_root_transform();

    Inkscape::XML::Node *copy = NULL;

    if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children
        copy = xml_doc->createElement("svg:g");

        for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) {
                Inkscape::XML::Node *newchild = child->duplicate(xml_doc);
                copy->appendChild(newchild);
        }
    } else { // just copy
        copy = orig->getRepr()->duplicate(xml_doc);
    }

    // Add the duplicate repr just after the existing one.
    parent->addChild(copy, repr);

    // Retrieve the SPItem of the resulting repr.
    SPObject *unlinked = document->getObjectByRepr(copy);

    // Merge style from the use.
    unlinked->style->merge( this->style );
    unlinked->style->cascade( unlinked->parent->style );
    unlinked->updateRepr();

    // Hold onto our SPObject and repr for now.
    sp_object_ref(this, NULL);
    Inkscape::GC::anchor(repr);

    // Remove ourselves, not propagating delete events to avoid a
    // chain-reaction with other elements that might reference us.
    this->deleteObject(false);

    // Give the copy our old id and let go of our old repr.
    copy->setAttribute("id", repr->attribute("id"));
    Inkscape::GC::release(repr);

    // Remove tiled clone attrs.
    copy->setAttribute("inkscape:tiled-clone-of", NULL);
    copy->setAttribute("inkscape:tile-w", NULL);
    copy->setAttribute("inkscape:tile-h", NULL);
    copy->setAttribute("inkscape:tile-cx", NULL);
    copy->setAttribute("inkscape:tile-cy", NULL);

    // Establish the succession and let go of our object.
    this->setSuccessor(unlinked);
    sp_object_unref(this, NULL);

    SPItem *item = dynamic_cast<SPItem *>(unlinked);
    g_assert(item != NULL);

    // Set the accummulated transform.
    {
        Geom::Affine nomove(Geom::identity());
        // Advertise ourselves as not moving.
        item->doWriteTransform(item->getRepr(), t, &nomove);
    }

    return item;
}
/**
 * \return   None
 * \brief    This is a generic function to use the save function of
 *           a module (including Autodetect)
 * \param    key       Identifier of which module to use
 * \param    doc       The document to be saved
 * \param    filename  The file that the document should be saved to
 * \param    official  (optional) whether to set :output_module and :modified in the
 *                     document; is true for normal save, false for temporary saves
 *
 * First things first, are we looking at an autodetection?  Well if that's the case then the module
 * needs to be found, and that is done with a database lookup through the module DB.  The foreach
 * function is called, with the parameter being a gpointer array.  It contains both the filename
 * (to find its extension) and where to write the module when it is found.
 *
 * If there is no autodetection the module database is queried with the key given.
 *
 * If everything is cool at this point, the module is loaded, and there is possibility for
 * preferences.  If there is a function, then it is executed to get the dialog to be displayed.
 * After it is finished the function continues.
 *
 * Lastly, the save function is called in the module itself.
 */
void
save(Extension *key, SPDocument *doc, gchar const *filename, bool setextension, bool check_overwrite, bool official)
{
    Output *omod;
    if (key == NULL) {
        gpointer parray[2];
        parray[0] = (gpointer)filename;
        parray[1] = (gpointer)&omod;
        omod = NULL;
        db.foreach(save_internal, (gpointer)&parray);

        /* This is a nasty hack, but it is required to ensure that
           autodetect will always save with the Inkscape extensions
           if they are available. */
        if (omod != NULL && !strcmp(omod->get_id(), SP_MODULE_KEY_OUTPUT_SVG)) {
            omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE));
        }
        /* If autodetect fails, save as Inkscape SVG */
        if (omod == NULL) {
            omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE));
        }
    } else {
        omod = dynamic_cast<Output *>(key);
    }

    if (!dynamic_cast<Output *>(omod)) {
        g_warning("Unable to find output module to handle file: %s\n", filename);
        throw Output::no_extension_found();
        return;
    }

    omod->set_state(Extension::STATE_LOADED);
    if (!omod->loaded()) {
        throw Output::save_failed();
    }

    if (!omod->prefs()) {
        throw Output::save_cancelled();
    }

    gchar *fileName = NULL;
    if (setextension) {
        gchar *lowerfile = g_utf8_strdown(filename, -1);
        gchar *lowerext = g_utf8_strdown(omod->get_extension(), -1);

        if (!g_str_has_suffix(lowerfile, lowerext)) {
            fileName = g_strdup_printf("%s%s", filename, omod->get_extension());
        }

        g_free(lowerfile);
        g_free(lowerext);
    }

    if (fileName == NULL) {
        fileName = g_strdup(filename);
    }

    if (check_overwrite && !sp_ui_overwrite_file(fileName)) {
        g_free(fileName);
        throw Output::no_overwrite();
    }

    Inkscape::XML::Node *repr = sp_document_repr_root(doc);

    // remember attributes in case this is an unofficial save
    bool saved_modified = false;
    gchar *saved_output_extension = NULL;
    gchar *saved_dataloss = NULL;
    gchar *saved_uri = NULL;
    if (!official) {
        saved_modified = doc->isModifiedSinceSave();
        if (repr->attribute("inkscape:output_extension")) {
            saved_output_extension = g_strdup(repr->attribute("inkscape:output_extension"));
        }
        if (repr->attribute("inkscape:dataloss")) {
            saved_dataloss = g_strdup(repr->attribute("inkscape:dataloss"));
        }
        if (doc->uri) {
            saved_uri = g_strdup(doc->uri);    
        }
    }    

    // update attributes:
    bool saved = sp_document_get_undo_sensitive(doc);
    sp_document_set_undo_sensitive (doc, false); 
        // save the filename for next use
        sp_document_set_uri(doc, fileName);
        // also save the extension for next use
        repr->setAttribute("inkscape:output_extension", omod->get_id());
        // set the "dataloss" attribute if the chosen extension is lossy
        repr->setAttribute("inkscape:dataloss", NULL);
        if ( omod->causes_dataloss() ) {
            repr->setAttribute("inkscape:dataloss", "true");
        }
    sp_document_set_undo_sensitive (doc, saved);
    doc->setModifiedSinceSave(false);

    omod->save(doc, fileName);
    
    // if it is an unofficial save, set the modified attributes back to what they were    
    if ( !official) {
        saved = sp_document_get_undo_sensitive(doc);
        sp_document_set_undo_sensitive (doc, false);
            repr->setAttribute("inkscape:output_extension", saved_output_extension);
            repr->setAttribute("inkscape:dataloss", saved_dataloss);
            sp_document_set_uri(doc, saved_uri);
        sp_document_set_undo_sensitive (doc, saved);
        doc->setModifiedSinceSave(saved_modified);
    }
    
    if (saved_output_extension)  g_free(saved_output_extension);
    if (saved_dataloss)          g_free(saved_dataloss);
    if (saved_uri)               g_free(saved_uri);    
    
    g_free(fileName);
    return;
}
SPDocument *
sp_document_create(Inkscape::XML::Document *rdoc,
                   gchar const *uri,
                   gchar const *base,
                   gchar const *name,
                   unsigned int keepalive)
{
    SPDocument *document;
    Inkscape::XML::Node *rroot;
    Inkscape::Version sodipodi_version;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    rroot = rdoc->root();

    document = new SPDocument();

    document->keepalive = keepalive;

    document->rdoc = rdoc;
    document->rroot = rroot;

#ifndef WIN32
    prepend_current_dir_if_relative(&(document->uri), uri);
#else
    // FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test!
    document->uri = uri? g_strdup(uri) : NULL;
#endif

    // base is simply the part of the path before filename; e.g. when running "inkscape ../file.svg" the base is "../"
    // which is why we use g_get_current_dir() in calculating the abs path above
    //This is NULL for a new document
    if (base)
        document->base = g_strdup(base);
    else
        document->base = NULL;
    document->name = g_strdup(name);

    document->root = sp_object_repr_build_tree(document, rroot);

    sodipodi_version = SP_ROOT(document->root)->version.sodipodi;

    /* fixme: Not sure about this, but lets assume ::build updates */
    rroot->setAttribute("sodipodi:version", SODIPODI_VERSION);
    rroot->setAttribute("inkscape:version", Inkscape::version_string);
    /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */

    /* Quick hack 2 - get default image size into document */
    if (!rroot->attribute("width")) rroot->setAttribute("width", "100%");
    if (!rroot->attribute("height")) rroot->setAttribute("height", "100%");
    /* End of quick hack 2 */

    /* Quick hack 3 - Set uri attributes */
    if (uri) {
        rroot->setAttribute("sodipodi:docname", uri);
    }
    /* End of quick hack 3 */

    /* Eliminate obsolete sodipodi:docbase, for privacy reasons */
    rroot->setAttribute("sodipodi:docbase", NULL);
    
    /* Eliminate any claim to adhere to a profile, as we don't try to */
    rroot->setAttribute("baseProfile", NULL);

    // creating namedview
    if (!sp_item_group_get_child_by_name((SPGroup *) document->root, NULL, "sodipodi:namedview")) {
        // if there's none in the document already,
        Inkscape::XML::Node *rnew = NULL;
        
        rnew = rdoc->createElement("sodipodi:namedview");
        //rnew->setAttribute("id", "base");

        // Add namedview data from the preferences
        // we can't use getAllEntries because this could produce non-SVG doubles
        Glib::ustring pagecolor = prefs->getString("/template/base/pagecolor");
        if (!pagecolor.empty()) {
            rnew->setAttribute("pagecolor", pagecolor.data());
        }
        Glib::ustring bordercolor = prefs->getString("/template/base/bordercolor");
        if (!bordercolor.empty()) {
            rnew->setAttribute("bordercolor", bordercolor.data());
        }
        sp_repr_set_svg_double(rnew, "borderopacity",
            prefs->getDouble("/template/base/borderopacity", 1.0));
        sp_repr_set_svg_double(rnew, "objecttolerance",
            prefs->getDouble("/template/base/objecttolerance", 10.0));
        sp_repr_set_svg_double(rnew, "gridtolerance",
            prefs->getDouble("/template/base/gridtolerance", 10.0));
        sp_repr_set_svg_double(rnew, "guidetolerance",
            prefs->getDouble("/template/base/guidetolerance", 10.0));
        sp_repr_set_svg_double(rnew, "inkscape:pageopacity",
            prefs->getDouble("/template/base/inkscape:pageopacity", 0.0));
        sp_repr_set_int(rnew, "inkscape:pageshadow",
            prefs->getInt("/template/base/inkscape:pageshadow", 2));
        sp_repr_set_int(rnew, "inkscape:window-width",
            prefs->getInt("/template/base/inkscape:window-width", 640));
        sp_repr_set_int(rnew, "inkscape:window-height",
            prefs->getInt("/template/base/inkscape:window-height", 480));
        
        // insert into the document
        rroot->addChild(rnew, NULL);
        // clean up
        Inkscape::GC::release(rnew);
    }

    /* Defs */
    if (!SP_ROOT(document->root)->defs) {
        Inkscape::XML::Node *r;
        r = rdoc->createElement("svg:defs");
        rroot->addChild(r, NULL);
        Inkscape::GC::release(r);
        g_assert(SP_ROOT(document->root)->defs);
    }

    /* Default RDF */
    rdf_set_defaults( document );

    if (keepalive) {
        inkscape_ref();
    }

    // Remark: Here, we used to create a "currentpersp3d" element in the document defs.
    // But this is probably a bad idea since we need to adapt it for every change of selection, which will
    // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup?

    document->current_persp3d = persp3d_document_first_persp(document);
    if (!document->current_persp3d) {
        document->current_persp3d = persp3d_create_xml_element (document);
    }

    sp_document_set_undo_sensitive(document, true);

    // reset undo key when selection changes, so that same-key actions on different objects are not coalesced
    if (!Inkscape::NSApplication::Application::getNewGui()) {
        g_signal_connect(G_OBJECT(INKSCAPE), "change_selection",
                         G_CALLBACK(sp_document_reset_key), document);
        g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
                         G_CALLBACK(sp_document_reset_key), document);
    } else {
        document->_selection_changed_connection = Inkscape::NSApplication::Editor::connectSelectionChanged (sigc::mem_fun (*document, &SPDocument::reset_key));
        document->_desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*document, &SPDocument::reset_key));
    }

    return document;
}
예제 #24
0
Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
    : Extension(in_repr, in_imp),
      _id_noprefs(Glib::ustring(get_id()) + ".noprefs"),
      _name_noprefs(Glib::ustring(_(get_name())) + _(" (No preferences)")),
      _verb(get_id(), get_name(), NULL, NULL, this, true),
      _verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false),
      _menu_node(NULL), _workingDialog(true),
      _prefDialog(NULL)
{
    Inkscape::XML::Node * local_effects_menu = NULL;

    // This is a weird hack
    if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
        return;

    bool hidden = false;

    no_doc = false;
    no_live_preview = false;

    if (repr != NULL) {

        for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) {
            if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) {
                if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) {
                  no_doc = true;
                }
                if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) {
                  no_live_preview = true;
                }
                for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) {
                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) {
                        // printf("Found local effects menu in %s\n", this->get_name());
                        local_effects_menu = sp_repr_children(effect_child);
                        if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) {
                            hidden = true;
                        }
                    }
                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") ||
                            !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) {
                        // printf("Found local effects menu in %s\n", this->get_name());
                        _verb.set_name(sp_repr_children(effect_child)->content());
                    }
                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") ||
                            !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) {
                        // printf("Found local effects menu in %s\n", this->get_name());
                        _verb.set_tip(sp_repr_children(effect_child)->content());
                    }
                } // children of "effect"
                break; // there can only be one effect
            } // find "effect"
        } // children of "inkscape-extension"
    } // if we have an XML file

    if (INKSCAPE != NULL) {
        if (_effects_list == NULL)
            _effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST);
        if (_filters_list == NULL)
            _filters_list = find_menu(inkscape_get_menus(INKSCAPE), FILTERS_LIST);
    }

    if ((_effects_list != NULL || _filters_list != NULL)) {
        Inkscape::XML::Document *xml_doc;
        xml_doc = _effects_list->document();
        _menu_node = xml_doc->createElement("verb");
        _menu_node->setAttribute("verb-id", this->get_id(), false);

        if (!hidden) {
            if (_filters_list &&
                local_effects_menu && 
                local_effects_menu->attribute("name") && 
                !strcmp(local_effects_menu->attribute("name"), ("Filters"))) {
                merge_menu(_filters_list->parent(), _filters_list, sp_repr_children(local_effects_menu), _menu_node);
            } else if (_effects_list) {
                merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
            }
        }
    }

    return;
}
예제 #25
0
/**
 * \return   None
 * \brief    This is a generic function to use the save function of
 *           a module (including Autodetect)
 * \param    key       Identifier of which module to use
 * \param    doc       The document to be saved
 * \param    filename  The file that the document should be saved to
 * \param    official  (optional) whether to set :output_module and :modified in the
 *                     document; is true for normal save, false for temporary saves
 *
 * First things first, are we looking at an autodetection?  Well if that's the case then the module
 * needs to be found, and that is done with a database lookup through the module DB.  The foreach
 * function is called, with the parameter being a gpointer array.  It contains both the filename
 * (to find its extension) and where to write the module when it is found.
 *
 * If there is no autodetection the module database is queried with the key given.
 *
 * If everything is cool at this point, the module is loaded, and there is possibility for
 * preferences.  If there is a function, then it is executed to get the dialog to be displayed.
 * After it is finished the function continues.
 *
 * Lastly, the save function is called in the module itself.
 */
void
save(Extension *key, SPDocument *doc, gchar const *filename, bool setextension, bool check_overwrite, bool official,
    Inkscape::Extension::FileSaveMethod save_method)
{
    Output *omod;
    if (key == NULL) {
        gpointer parray[2];
        parray[0] = (gpointer)filename;
        parray[1] = (gpointer)&omod;
        omod = NULL;
        db.foreach(save_internal, (gpointer)&parray);

        /* This is a nasty hack, but it is required to ensure that
           autodetect will always save with the Inkscape extensions
           if they are available. */
        if (omod != NULL && !strcmp(omod->get_id(), SP_MODULE_KEY_OUTPUT_SVG)) {
            omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE));
        }
        /* If autodetect fails, save as Inkscape SVG */
        if (omod == NULL) {
            // omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)); use exception and let user choose
        }
    } else {
        omod = dynamic_cast<Output *>(key);
    }

    if (!dynamic_cast<Output *>(omod)) {
        g_warning("Unable to find output module to handle file: %s\n", filename);
        throw Output::no_extension_found();
    }

    omod->set_state(Extension::STATE_LOADED);
    if (!omod->loaded()) {
        throw Output::save_failed();
    }

    if (!omod->prefs()) {
        throw Output::save_cancelled();
    }

    gchar *fileName = NULL;
    if (setextension) {
        gchar *lowerfile = g_utf8_strdown(filename, -1);
        gchar *lowerext = g_utf8_strdown(omod->get_extension(), -1);

        if (!g_str_has_suffix(lowerfile, lowerext)) {
            fileName = g_strdup_printf("%s%s", filename, omod->get_extension());
        }

        g_free(lowerfile);
        g_free(lowerext);
    }

    if (fileName == NULL) {
        fileName = g_strdup(filename);
    }

    if (check_overwrite && !sp_ui_overwrite_file(fileName)) {
        g_free(fileName);
        throw Output::no_overwrite();
    }

    // test if the file exists and is writable
    // the test only checks the file attributes and might pass where ACL does not allow to write
    if (Inkscape::IO::file_test(filename, G_FILE_TEST_EXISTS) && !Inkscape::IO::file_is_writable(filename)) {
        g_free(fileName);
        throw Output::file_read_only();
    }

    Inkscape::XML::Node *repr = doc->getReprRoot();


    // remember attributes in case this is an unofficial save and/or overwrite fails
    gchar *saved_uri = g_strdup(doc->getURI());
    gchar *saved_output_extension = NULL;
    gchar *saved_dataloss = NULL;
    bool saved_modified = doc->isModifiedSinceSave();
    saved_output_extension = g_strdup(get_file_save_extension(save_method).c_str());
    saved_dataloss = g_strdup(repr->attribute("inkscape:dataloss"));
    if (official) {
        // The document is changing name/uri.
        doc->changeUriAndHrefs(fileName);
    }

    // Update attributes:
    {
        bool const saved = DocumentUndo::getUndoSensitive(doc);
        DocumentUndo::setUndoSensitive(doc, false);
        {
            // also save the extension for next use
            store_file_extension_in_prefs (omod->get_id(), save_method);
            // set the "dataloss" attribute if the chosen extension is lossy
            repr->setAttribute("inkscape:dataloss", NULL);
            if (omod->causes_dataloss()) {
                repr->setAttribute("inkscape:dataloss", "true");
            }
        }
        DocumentUndo::setUndoSensitive(doc, saved);
        doc->setModifiedSinceSave(false);
    }

    try {
        omod->save(doc, fileName);
    }
    catch(...) {
        // revert attributes in case of official and overwrite
        if(check_overwrite && official) {
            bool const saved = DocumentUndo::getUndoSensitive(doc);
            DocumentUndo::setUndoSensitive(doc, false);
            {
                store_file_extension_in_prefs (saved_output_extension, save_method);
                repr->setAttribute("inkscape:dataloss", saved_dataloss);
            }
            DocumentUndo::setUndoSensitive(doc, saved);
            doc->changeUriAndHrefs(saved_uri);
        }
        doc->setModifiedSinceSave(saved_modified);
        // free used ressources
        g_free(saved_output_extension);
        g_free(saved_dataloss);
        g_free(saved_uri);

        g_free(fileName);

        throw Inkscape::Extension::Output::save_failed();
    }

    // If it is an unofficial save, set the modified attributes back to what they were.
    if ( !official) {
        bool const saved = DocumentUndo::getUndoSensitive(doc);
        DocumentUndo::setUndoSensitive(doc, false);
        {
            store_file_extension_in_prefs (saved_output_extension, save_method);
            repr->setAttribute("inkscape:dataloss", saved_dataloss);
        }
        DocumentUndo::setUndoSensitive(doc, saved);
        doc->setModifiedSinceSave(saved_modified);

        g_free(saved_output_extension);
        g_free(saved_dataloss);
    }

    g_free(fileName);
    return;
}
예제 #26
0
static gboolean update_stop_list( GtkWidget *stop_combo, SPGradient *gradient, SPStop *new_stop, GtkWidget *widget, bool gr_multi)
{
    gboolean sensitive = FALSE;

    if (!stop_combo) {
        return sensitive;
    }

    GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model(GTK_COMBO_BOX(stop_combo));
    if (!store) {
        return sensitive;
    }

    blocked = TRUE;

    /* Clear old list, if there is any */
    gtk_list_store_clear(store);
    GtkTreeIter iter;

    if (!SP_IS_GRADIENT(gradient)) {
        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1);
        gtk_combo_box_set_active(GTK_COMBO_BOX(stop_combo) , 0);
        sensitive = FALSE;
        blocked = FALSE;
        return sensitive;
    }

    /* Populate the combobox store */
    GSList *sl = NULL;
    if ( gradient->hasStops() ) {
        for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
            if (SP_IS_STOP(ochild)) {
                sl = g_slist_append(sl, ochild);
            }
        }
    }
    if (!sl) {
        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter, 0, _("No stops in gradient"), 1, NULL, 2, NULL, -1);
        sensitive = FALSE;

    } else {

        for (; sl != NULL; sl = sl->next){
            if (SP_IS_STOP(sl->data)){
                SPStop *stop = SP_STOP(sl->data);
                Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr();
                Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32()));
                GdkPixbuf *pb = cpv->toPixbuf(32, 16);
                Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25);

                gtk_list_store_append(store, &iter);
                gtk_list_store_set(store, &iter, 0, label.c_str(), 1, pb, 2, stop, -1);
                sensitive = FALSE;
            }
        }

        sensitive = TRUE;
    }

    if (gr_multi) {
        sensitive = FALSE;
    }

    if (new_stop == NULL) {
        gtk_combo_box_set_active(GTK_COMBO_BOX(stop_combo) , 0);
    } else {
        select_stop_in_list(stop_combo, gradient, new_stop, widget, TRUE);
    }

    blocked = FALSE;

    return sensitive;
}
예제 #27
0
ParamComboBox::ParamComboBox(const gchar *name, const gchar *guitext, const gchar *desc,
                             const Parameter::_scope_t scope, bool gui_hidden, const gchar *gui_tip,
                             Inkscape::Extension::Extension *ext, Inkscape::XML::Node *xml)
    : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext)
    , _value(NULL)
    , _indent(0)
    , choices(NULL)
{
    const char *xmlval = NULL; // the value stored in XML

    if (xml != NULL) {
        // Read XML tree to add enumeration items:
        for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) {
            char const * chname = node->name();
            if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
                Glib::ustring newguitext, newvalue;
                const char * contents = NULL;
                if (node->firstChild()) {
                    contents = node->firstChild()->content();
                }
                if (contents != NULL) {
                    // don't translate when 'item' but do translate when '_item'
                    // NOTE: internal extensions use build_from_mem and don't need _item but
                    //       still need to include if are to be localized
                    if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
                        if (node->attribute("msgctxt") != NULL) {
                            newguitext =  g_dpgettext2(NULL, node->attribute("msgctxt"), contents);
                        } else {
                            newguitext =  _(contents);
                        }
                    } else {
                        newguitext =  contents;
                    }
                } else
                    continue;

                const char * val = node->attribute("value");
                if (val != NULL) {
                    newvalue = val;
                } else {
                    newvalue = contents;
                }

                if ( (!newguitext.empty()) && (!newvalue.empty()) ) {   // logical error if this is not true here
                    choices = g_slist_append( choices, new enumentry(newvalue, newguitext) );
                }
            }
        }
    
        // Initialize _value with the default value from xml
        // for simplicity : default to the contents of the first xml-child
        if (xml->firstChild() && xml->firstChild()->firstChild()) {
            xmlval = xml->firstChild()->attribute("value");
        }

        const char *indent = xml->attribute("indent");
        if (indent != NULL) {
            _indent = atoi(indent) * 12;
        }
    }

    gchar * pref_name = this->pref_name();
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    Glib::ustring paramval = prefs ? prefs->getString(extension_pref_root + pref_name) : "";
    g_free(pref_name);

    if (!paramval.empty()) {
        _value = g_strdup(paramval.data());
    } else if (xmlval) {
        _value = g_strdup(xmlval);
    }
}
예제 #28
0
static void
draw_page (GtkPrintOperation */*operation*/,
           GtkPrintContext   *context,
           gint               /*page_nr*/,
           gpointer           user_data)
{
    struct workaround_gtkmm *junk = (struct workaround_gtkmm*)user_data;
    //printf("%s %d\n",__FUNCTION__, page_nr);

    if (junk->_tab->as_bitmap()) {
        // Render as exported PNG
        gdouble width = sp_document_width(junk->_doc);
        gdouble height = sp_document_height(junk->_doc);
        gdouble dpi = junk->_tab->bitmap_dpi();
        std::string tmp_png;
        std::string tmp_base = "inkscape-print-png-XXXXXX";

        int tmp_fd;
        if ( (tmp_fd = Inkscape::IO::file_open_tmp (tmp_png, tmp_base)) >= 0) {
            close(tmp_fd);

            guint32 bgcolor = 0x00000000;
            Inkscape::XML::Node *nv = sp_repr_lookup_name (junk->_doc->rroot, "sodipodi:namedview");
            if (nv && nv->attribute("pagecolor"))
                bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
            if (nv && nv->attribute("inkscape:pageopacity"))
                bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));

            sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0,
                width, height,
                (unsigned long)(width * dpi / PX_PER_IN),
                (unsigned long)(height * dpi / PX_PER_IN),
                dpi, dpi, bgcolor, NULL, NULL, true, NULL);

            // This doesn't seem to work:
            //context->set_cairo_context ( Cairo::Context::create (Cairo::ImageSurface::create_from_png (tmp_png) ), dpi, dpi );
            //
            // so we'll use a surface pattern blat instead...
            //
            // but the C++ interface isn't implemented in cairomm:
            //context->get_cairo_context ()->set_source_surface(Cairo::ImageSurface::create_from_png (tmp_png) );
            //
            // so do it in C:
            {
                Cairo::RefPtr<Cairo::ImageSurface> png = Cairo::ImageSurface::create_from_png (tmp_png);
                cairo_t *cr = gtk_print_context_get_cairo_context (context);
		cairo_matrix_t m;
		cairo_get_matrix(cr, &m);
		cairo_scale(cr, PT_PER_IN / dpi, PT_PER_IN / dpi);
                // FIXME: why is the origin offset??
                cairo_set_source_surface(cr, png->cobj(), -16.0, -16.0);
		cairo_paint(cr);
		cairo_set_matrix(cr, &m);
            }

            // Clean up
            unlink (tmp_png.c_str());
        }
        else {
            g_warning(_("Could not open temporary PNG for bitmap printing"));
        }
    }
    else {
        // Render as vectors
        Inkscape::Extension::Internal::CairoRenderer renderer;
        Inkscape::Extension::Internal::CairoRenderContext *ctx = renderer.createContext();

        // ctx->setPSLevel(CAIRO_PS_LEVEL_3);
        ctx->setTextToPath(false);
        ctx->setFilterToBitmap(true);
        ctx->setBitmapResolution(72);

        cairo_t *cr = gtk_print_context_get_cairo_context (context);
        cairo_surface_t *surface = cairo_get_target(cr);


/**
	Call cairo_win32_printing_surface directly as a workaround until GTK uses this call.
	When GTK uses cairo_win32_printing_surface this automatically reverts.
*/
#ifdef WIN32
        if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_WIN32) {
        HDC dc = cairo_win32_surface_get_dc (surface);
        surface = _cairo_win32_printing_surface_create (dc);
        }
#endif

        bool ret = ctx->setSurfaceTarget (surface, true);        if (ret) {
            ret = renderer.setupDocument (ctx, junk->_doc, TRUE, NULL);
            if (ret) {
                renderer.renderItem(ctx, junk->_base);
                ret = ctx->finish();
            }
            else {
                g_warning(_("Could not set up Document"));
            }
        }
        else {
            g_warning(_("Failed to set CairoRenderContext"));
        }

        // Clean up
        renderer.destroyContext(ctx);
    }

}
예제 #29
0
void
Effect::merge_menu (Inkscape::XML::Node * base,
                    Inkscape::XML::Node * start,
                    Inkscape::XML::Node * patern,
                    Inkscape::XML::Node * mergee) {
    Glib::ustring mergename;
    Inkscape::XML::Node * tomerge = NULL;
    Inkscape::XML::Node * submenu = NULL;

    /* printf("Merge menu with '%s' '%s' '%s'\n",
            base != NULL ? base->name() : "NULL",
            patern != NULL ? patern->name() : "NULL",
            mergee != NULL ? mergee->name() : "NULL"); */

    if (patern == NULL) {
        // Merge the verb name
        tomerge = mergee;
        mergename = _(this->get_name());
    } else {
        gchar const * menuname = patern->attribute("name");
        if (menuname == NULL) menuname = patern->attribute("_name");
        if (menuname == NULL) return;
        
        Inkscape::XML::Document *xml_doc;
        xml_doc = base->document();
        tomerge = xml_doc->createElement("submenu");
        tomerge->setAttribute("name", menuname, false);

        mergename = _(menuname);
    }

    int position = -1;

    if (start != NULL) {
        Inkscape::XML::Node * menupass;
        for (menupass = start; menupass != NULL && strcmp(menupass->name(), "separator"); menupass = menupass->next()) {
            gchar const * compare_char = NULL;
            if (!strcmp(menupass->name(), "verb")) {
                gchar const * verbid = menupass->attribute("verb-id");
                Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
                if (verb == NULL) {
					g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid);
                    continue;
                }
                compare_char = verb->get_name();
            } else if (!strcmp(menupass->name(), "submenu")) {
                compare_char = menupass->attribute("name");
                if (compare_char == NULL)
                    compare_char = menupass->attribute("_name");
            }

            position = menupass->position() + 1;

            /* This will cause us to skip tags we don't understand */
            if (compare_char == NULL) {
                continue;
            }

            Glib::ustring compare(_(compare_char));

            if (mergename == compare) {
                Inkscape::GC::release(tomerge);
                tomerge = NULL;
                submenu = menupass;
                break;
            }

            if (mergename < compare) {
                position = menupass->position();
                break;
            }
        } // for menu items
    } // start != NULL

    if (tomerge != NULL) {
        base->appendChild(tomerge);
        Inkscape::GC::release(tomerge);
        if (position != -1)
            tomerge->setPosition(position);
    }

    if (patern != NULL) {
        if (submenu == NULL)
            submenu = tomerge;
        merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
    }

    return;
}
예제 #30
0
static void sp_image_image_edit(GtkMenuItem *menuitem, SPAnchor *anchor)
{
    SPObject* obj = anchor;
    Inkscape::XML::Node *ir = obj->getRepr();
    const gchar *href = ir->attribute("xlink:href");

    GError* errThing = 0;
    Glib::ustring cmdline = getImageEditorName();
    Glib::ustring name;
    Glib::ustring fullname;
    
#ifdef WIN32
    // g_spawn_command_line_sync parsing is done according to Unix shell rules,
    // not Windows command interpreter rules. Thus we need to enclose the
    // executable path with sigle quotes.
    int index = cmdline.find(".exe");
    if ( index < 0 ) index = cmdline.find(".bat");
    if ( index < 0 ) index = cmdline.find(".com");
    if ( index >= 0 ) {
        Glib::ustring editorBin = cmdline.substr(0, index + 4).c_str();
        Glib::ustring args = cmdline.substr(index + 4, cmdline.length()).c_str();
        editorBin.insert(0, "'");
        editorBin.append("'");
        cmdline = editorBin;
        cmdline.append(args);
    } else {
        // Enclose the whole command line if no executable path can be extracted.
        cmdline.insert(0, "'");
        cmdline.append("'");
    }
#endif

    if (strncmp (href,"file:",5) == 0) {
    // URI to filename conversion
      name = g_filename_from_uri(href, NULL, NULL);
    } else {
      name.append(href);
    }


    if (Glib::path_is_absolute(name)) {
        fullname = name;
    } else if (SP_ACTIVE_DOCUMENT->getBase()) {
        fullname = Glib::build_filename(SP_ACTIVE_DOCUMENT->getBase(), name);
    } else {
        fullname = Glib::build_filename(Glib::get_current_dir(), name);
    }


    cmdline.append(" '");
    cmdline.append(fullname.c_str());
    cmdline.append("'");

    //g_warning("##Command line: %s\n", cmdline.c_str());

    g_spawn_command_line_async(cmdline.c_str(),
                  &errThing); 

    if ( errThing ) {
        g_warning("Problem launching editor (%d). %s", errThing->code, errThing->message);
        SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, errThing->message);
        g_error_free(errThing);
        errThing = 0;
    }
}