Example #1
0
Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
        repr = xml_doc->createElement("svg:use");
    }

    SPItem::write(xml_doc, repr, flags);

    sp_repr_set_svg_double(repr, "x", this->x.computed);
    sp_repr_set_svg_double(repr, "y", this->y.computed);
    repr->setAttribute("width", sp_svg_length_write_with_units(this->width).c_str());
    repr->setAttribute("height", sp_svg_length_write_with_units(this->height).c_str());

    if (this->ref->getURI()) {
        gchar *uri_string = this->ref->getURI()->toString();
        repr->setAttribute("xlink:href", uri_string);
        g_free(uri_string);
    }

    if (SP_IS_SHAPE(this->child)) {
        SP_SHAPE(this->child)->set_shape(); // evaluate SPCurve of child
    } else if (SP_IS_TEXT(this->child)) {
        SP_TEXT(this->child)->rebuildLayout(); // refresh Layout, LP Bug 1339305
    } else if (SP_IS_FLOWTEXT(this->child)) {
        if (SP_IS_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild()))
            SP_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild())->UpdateComputed();
        SP_FLOWTEXT(this->child)->rebuildLayout();
    }

    return repr;
}
Example #2
0
/**
 * Sensing a movement of the original, this function attempts to compensate for it in such a way
 * that the clone stays unmoved or moves in parallel (depending on user setting) regardless of the
 * clone's transform.
 */
void SPUse::move_compensate(Geom::Affine const *mp) {
    // the clone is orphaned; or this is not a real use, but a clone of another use;
    // we skip it, otherwise duplicate compensation will occur
    if (this->cloned) {
        return;
    }

    // never compensate uses which are used in flowtext
    if (this->parent && SP_IS_FLOWREGION(this->parent)) {
        return;
    }

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
    // user wants no compensation
    if (mode == SP_CLONE_COMPENSATION_NONE)
        return;

    Geom::Affine m(*mp);

    // this is not a simple move, do not try to compensate
    if (!(m.isTranslation()))
        return;

    // restore item->transform field from the repr, in case it was changed by seltrans
    this->readAttr ("transform");

    Geom::Affine t = this->get_parent_transform();
    Geom::Affine clone_move = t.inverse() * m * t;

    // calculate the compensation matrix and the advertized movement matrix
    Geom::Affine advertized_move;
    if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
        clone_move = clone_move.inverse() * m;
        advertized_move = m;
    } else if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
        clone_move = clone_move.inverse();
        advertized_move.setIdentity();
    } else {
        g_assert_not_reached();
    }

    // commit the compensation
    this->transform *= clone_move;
    this->doWriteTransform(this->getRepr(), this->transform, &advertized_move);
    this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
Example #3
0
void SPUse::delete_self() {
    // always delete uses which are used in flowtext
    if (this->parent && SP_IS_FLOWREGION(this->parent)) {
        this->deleteObject();
        return;
    }

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    guint const mode = prefs->getInt("/options/cloneorphans/value",
                                               SP_CLONE_ORPHANS_UNLINK);

    if (mode == SP_CLONE_ORPHANS_UNLINK) {
        this->unlink();
    } else if (mode == SP_CLONE_ORPHANS_DELETE) {
        this->deleteObject();
    }
}
Example #4
0
void
text_flow_into_shape()
{
    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
    if (!desktop)
        return;

    SPDocument *doc = sp_desktop_document (desktop);
    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);

    Inkscape::Selection *selection = sp_desktop_selection(desktop);

    SPItem *text = text_or_flowtext_in_selection(selection);
    SPItem *shape = shape_in_selection(selection);

    if (!text || !shape || g_slist_length((GSList *) selection->itemList()) < 2) {
        sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>a text</b> and one or more <b>paths or shapes</b> to flow text into frame."));
        return;
    }

    if (SP_IS_TEXT(text)) {
      // remove transform from text, but recursively scale text's fontsize by the expansion
      SP_TEXT(text)->_adjustFontsizeRecursive(text, NR::expansion(SP_ITEM(text)->transform));
      SP_OBJECT_REPR(text)->setAttribute("transform", NULL);
    }

    Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot");
    root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create
    root_repr->setAttribute("style", SP_OBJECT_REPR(text)->attribute("style")); // fixme: transfer style attrs too
    SP_OBJECT_REPR(SP_OBJECT_PARENT(shape))->appendChild(root_repr);
    SPObject *root_object = doc->getObjectByRepr(root_repr);
    g_return_if_fail(SP_IS_FLOWTEXT(root_object));

    Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion");
    root_repr->appendChild(region_repr);
    SPObject *object = doc->getObjectByRepr(region_repr);
    g_return_if_fail(SP_IS_FLOWREGION(object));

    /* Add clones */
    for (GSList *items = (GSList *) selection->itemList();
         items != NULL;
         items = items->next) {
        SPItem *item = SP_ITEM(items->data);
        if (SP_IS_SHAPE(item)){
            Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
            clone->setAttribute("x", "0");
            clone->setAttribute("y", "0");
            clone->setAttribute("xlink:href", g_strdup_printf("#%s", SP_OBJECT_REPR(item)->attribute("id")));

            // add the new clone to the region
            region_repr->appendChild(clone);
        }
    }

    if (SP_IS_TEXT(text)) { // flow from text, as string
        Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara");
        root_repr->appendChild(para_repr);
        object = doc->getObjectByRepr(para_repr);
        g_return_if_fail(SP_IS_FLOWPARA(object));

        Inkscape::Text::Layout const *layout = te_get_layout(text);
        Glib::ustring text_ustring = sp_te_get_string_multiline(text, layout->begin(), layout->end());

        Inkscape::XML::Node *text_repr = xml_doc->createTextNode(text_ustring.c_str()); // FIXME: transfer all formatting! and convert newlines into flowParas!
        para_repr->appendChild(text_repr);

        Inkscape::GC::release(para_repr);
        Inkscape::GC::release(text_repr);

    } else { // reflow an already flowed text, preserving paras
        for (SPObject *o = SP_OBJECT(text)->children; o != NULL; o = o->next) {
            if (SP_IS_FLOWPARA(o)) {
                Inkscape::XML::Node *para_repr = SP_OBJECT_REPR(o)->duplicate(xml_doc);
                root_repr->appendChild(para_repr);
                object = doc->getObjectByRepr(para_repr);
                g_return_if_fail(SP_IS_FLOWPARA(object));
                Inkscape::GC::release(para_repr);
            }
        }
    }

    SP_OBJECT(text)->deleteObject (true);

    sp_document_done(doc, SP_VERB_CONTEXT_TEXT,
                     _("Flow text into shape"));

    sp_desktop_selection(desktop)->set(SP_ITEM(root_object));

    Inkscape::GC::release(root_repr);
    Inkscape::GC::release(region_repr);
}