Logo Search packages:      
Sourcecode: inkscape version File versions

void Inkscape::XML::rebase_hrefs ( SPDocument *const   doc,
gchar const *const   new_base,
bool const   spns 
)

Change relative hrefs in doc to be relative to new_base instead of doc.base.

(NULL doc base or new_base is interpreted as current working directory.)

Parameters:
spns True iff doc should contain sodipodi:absref attributes.

Definition at line 202 of file rebase-hrefs.cpp.

References Inkscape::XML::Node::attribute(), SPDocument::base, Inkscape::XML::Node::setAttribute(), and sp_relative_path_from_path().

Referenced by file_import().

{
    gchar *const old_abs_base = calc_abs_doc_base(doc->base);
    gchar *const new_abs_base = calc_abs_doc_base(new_base);

    /* TODO: Should handle not just image but also:
     *
     *    a, altGlyph, animElementAttrs, animate, animateColor, animateMotion, animateTransform,
     *    animation, audio, color-profile, cursor, definition-src, discard, feImage, filter,
     *    font-face-uri, foreignObject, glyphRef, handler, linearGradient, mpath, pattern,
     *    prefetch, radialGradient, script, set, textPath, tref, use, video
     *
     * (taken from the union of the xlink:href elements listed at
     * http://www.w3.org/TR/SVG11/attindex.html and
     * http://www.w3.org/TR/SVGMobile12/attributeTable.html).
     *
     * Also possibly some other attributes of type <URI> or <IRI> or list-thereof, or types like
     * <paint> that can include an IRI/URI, and stylesheets and style attributes.  (xlink:base is a
     * special case.  xlink:role and xlink:arcrole can be assumed to be already absolute, based on
     * http://www.w3.org/TR/SVG11/struct.html#xlinkRefAttrs .)
     *
     * Note that it may not useful to set sodipodi:absref for anything other than image.
     *
     * Note also that Inkscape only supports fragment hrefs (href="#pattern257") for many of these
     * cases. */
    GSList const *images = sp_document_get_resource_list(doc, "image");
    for (GSList const *l = images; l != NULL; l = l->next) {
        Inkscape::XML::Node *ir = SP_OBJECT_REPR(l->data);

        gchar const *const href = ir->attribute("xlink:href");
        /* TODO: Most of this function currently treats href as if it were a simple filename
         * (e.g. passing it to g_path_is_absolute, g_build_filename or IO::file_test, or avoiding
         * changing non-file hrefs), which breaks if href starts with a scheme or if href contains
         * any escaping. */

        if (!href || !href_needs_rebasing(href)) {
            continue;
        }

        gchar *const abs_href(calc_abs_href(old_abs_base, href, ir->attribute("sodipodi:absref")));

        /* todo: One difficult case once we support writing to non-file locations is where
         * existing hrefs in the document point to local files.  In this case, we should
         * probably copy those referenced files to the new location at the same time.  It's
         * less clear what to do when copying from one non-file location to another.  We may
         * need to ask the user in some way (even if it's as a checkbox), but we'd like to
         * bother the user as little as possible yet also want to warn the user about the case
         * of file hrefs. */

        gchar const *const new_href = sp_relative_path_from_path(abs_href, new_abs_base);
        ir->setAttribute("xlink:href", new_href);
        ir->setAttribute("sodipodi:absref", ( spns
                                              ? abs_href
                                              : NULL ));
        /* impl: I assume that if !spns then any existing sodipodi:absref is about to get
         * cleared (or is already cleared) anyway, in which case it doesn't matter whether we
         * clear or leave any existing sodipodi:absref value.  If that assumption turns out to
         * be wrong, then leaving it means risking leaving the wrong value (if xlink:href
         * referred to a different file than sodipodi:absref) while clearing it means risking
         * losing information. */

        g_free(abs_href);
        /* (No need to free new_href, it's guaranteed to point into used_abs_href.) */
    }

    g_free(new_abs_base);
    g_free(old_abs_base);
}


Generated by  Doxygen 1.6.0   Back to index