예제 #1
0
/**
 *  Sets a value in the path object given by 'key', to 'value'.  This is used
 *  for setting attributes and markers on a path object.
 */
static void
sp_path_set(SPObject *object, unsigned int key, gchar const *value)
{
    SPPath *path = (SPPath *) object;

    switch (key) {
        case SP_ATTR_INKSCAPE_ORIGINAL_D:
                if (value) {
                    Geom::PathVector pv = sp_svg_read_pathv(value);
                    SPCurve *curve = new SPCurve(pv);
                    if (curve) {
                        path->set_original_curve(curve, TRUE, true);
                        curve->unref();
                    }
                } else {
                    path->set_original_curve(NULL, TRUE, true);
                }
                object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
            break;
       case SP_ATTR_D:
                if (value) {
                    Geom::PathVector pv = sp_svg_read_pathv(value);
                    SPCurve *curve = new SPCurve(pv);
                    if (curve) {
                        ((SPShape *) path)->setCurve(curve, TRUE);
                        curve->unref();
                    }
                } else {
                    ((SPShape *) path)->setCurve(NULL, TRUE);
                }
                object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
            break;
        case SP_PROP_MARKER:
        case SP_PROP_MARKER_START:
        case SP_PROP_MARKER_MID:
        case SP_PROP_MARKER_END:
            sp_shape_set_marker(object, key, value);
            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
            break;
        case SP_ATTR_CONNECTOR_TYPE:
        case SP_ATTR_CONNECTOR_CURVATURE:
        case SP_ATTR_CONNECTION_START:
        case SP_ATTR_CONNECTION_END:
        case SP_ATTR_CONNECTION_START_POINT:
        case SP_ATTR_CONNECTION_END_POINT:
            path->connEndPair.setAttr(key, value);
            break;
        default:
            if (((SPObjectClass *) parent_class)->set) {
                ((SPObjectClass *) parent_class)->set(object, key, value);
            }
            break;
    }
}
예제 #2
0
void
LPESimplify::drawHandle(Geom::Point p)
{
    double r = radius_helper_nodes;
    char const * svgd;
    svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z";
    Geom::PathVector pathv = sp_svg_read_pathv(svgd);
    pathv *= Geom::Scale(r) * Geom::Translate(p - Geom::Point(0.35*r,0.35*r));
    hp.push_back(pathv[0]);
}
예제 #3
0
void
LPESimplify::drawNode(Geom::Point p)
{
    double r = radius_helper_nodes;
    char const * svgd;
    svgd = "M 0.55,0.5 A 0.05,0.05 0 0 1 0.5,0.55 0.05,0.05 0 0 1 0.45,0.5 0.05,0.05 0 0 1 0.5,0.45 0.05,0.05 0 0 1 0.55,0.5 Z M 0,0 1,0 1,1 0,1 Z";
    Geom::PathVector pathv = sp_svg_read_pathv(svgd);
    pathv *= Geom::Scale(r) * Geom::Translate(p - Geom::Point(0.5*r,0.5*r));
    hp.push_back(pathv[0]);
    hp.push_back(pathv[1]);
}
예제 #4
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));
        }
    }
}
예제 #5
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();
    }
}
예제 #6
0
cairo_status_t
SvgFont::scaled_font_render_glyph (cairo_scaled_font_t  */*scaled_font*/,
                                   unsigned long         glyph,
                                   cairo_t              *cr,
                                   cairo_text_extents_t */*metrics*/)
{
    // This method does the actual rendering of glyphs.

    // We have glyphs.size() glyphs and possibly one missing-glyph declared on this SVG document
    // The id of the missing-glyph is always equal to glyphs.size()
    // All the other glyphs have ids ranging from 0 to glyphs.size()-1

    if (glyph > this->glyphs.size())     return CAIRO_STATUS_SUCCESS;//TODO: this is an error!

    SPObject* node;
    if (glyph == this->glyphs.size()){
        if (!this->missingglyph) return CAIRO_STATUS_SUCCESS;
        node = (SPObject*) this->missingglyph;
    } else {
        node = (SPObject*) this->glyphs[glyph];
    }

    if (!SP_IS_GLYPH(node) && !SP_IS_MISSING_GLYPH(node)) {
        return CAIRO_STATUS_SUCCESS;  // FIXME: is this the right code to return?
    }

    SPFont* spfont = (SPFont*) node->parent;
    if (!spfont) {
        return CAIRO_STATUS_SUCCESS;  // FIXME: is this the right code to return?
    }

    //glyphs can be described by arbitrary SVG declared in the childnodes of a glyph node
    // or using the d attribute of a glyph node.
    // pathv stores the path description from the d attribute:
    Geom::PathVector pathv;
    if (SP_IS_GLYPH(node) && ((SPGlyph*)node)->d) {
        pathv = sp_svg_read_pathv(((SPGlyph*)node)->d);
        pathv = flip_coordinate_system(spfont, pathv);
        this->render_glyph_path(cr, &pathv);
    } else if (SP_IS_MISSING_GLYPH(node) && ((SPMissingGlyph*)node)->d) {
        pathv = sp_svg_read_pathv(((SPMissingGlyph*)node)->d);
        pathv = flip_coordinate_system(spfont, pathv);
        this->render_glyph_path(cr, &pathv);
    }

    if (node->hasChildren()){
        //render the SVG described on this glyph's child nodes.
        for(node = node->children; node; node=node->next){
            if (SP_IS_PATH(node)){
                pathv = ((SPShape*)node)->_curve->get_pathvector();
                pathv = flip_coordinate_system(spfont, pathv);
                this->render_glyph_path(cr, &pathv);
            }
            if (SP_IS_OBJECTGROUP(node)){
                g_warning("TODO: svgfonts: render OBJECTGROUP");
            }
            if (SP_IS_USE(node)){
                SPItem* item = SP_USE(node)->ref->getObject();
                if (SP_IS_PATH(item)){
                    pathv = ((SPShape*)item)->_curve->get_pathvector();
                    pathv = flip_coordinate_system(spfont, pathv);
                    this->render_glyph_path(cr, &pathv);
                }

                glyph_modified_connection = ((SPObject*) item)->connectModified(sigc::mem_fun(*this, &SvgFont::glyph_modified));
            }
        }
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #7
0
파일: sp-star.cpp 프로젝트: zanqi/inkscape
void SPStar::set_shape() {
    // perhaps we should convert all our shapes into LPEs without source path
    // and with knotholders for parameters, then this situation will be handled automatically
    // by disabling the entire stack (including the shape LPE)
    if (hasBrokenPathEffect()) {
        g_warning ("The star shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as star will remove the bad LPE");

        if (this->getRepr()->attribute("d")) {
            // unconditionally read the curve from d, if any, to preserve appearance
            Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d"));
            SPCurve *cold = new SPCurve(pv);
            this->setCurveInsync( cold, TRUE);
            this->setCurveBeforeLPE(cold);
            cold->unref();
        }

        return;
    }

    SPCurve *c = new SPCurve ();

    bool not_rounded = (fabs (this->rounded) < 1e-4);

    // note that we pass randomized=true to sp_star_get_xy, because the curve must be randomized;
    // other places that call that function (e.g. the knotholder) need the exact point

    // draw 1st segment
    c->moveto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true));

    if (this->flatsided == false) {
        if (not_rounded) {
            c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true));
        } else {
            c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, NEXT),
                sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, 0, PREV),
                sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true));
        }
    }

    // draw all middle segments
    for (gint i = 1; i < sides; i++) {
        if (not_rounded) {
            c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true));
        } else {
            if (this->flatsided == false) {
                c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i - 1, NEXT),
                        sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV),
                        sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true));
            } else {
                c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i - 1, NEXT),
                        sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV),
                        sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true));
            }
        }

        if (this->flatsided == false) {
            if (not_rounded) {
                       c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true));
            } else {
                c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, NEXT),
                    sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i, PREV),
                    sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true));
            }
        }
    }

    // draw last segment
	if (!not_rounded) {
		if (this->flatsided == false) {
			c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, sides - 1, NEXT),
				sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV),
				sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true));
		} else {
			c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, sides - 1, NEXT),
				sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV),
				sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true));
		}
	}

    c->closepath();

    /* Reset the shape'scurve to the "original_curve"
     * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
    this->setCurveInsync( c, TRUE);
    this->setCurveBeforeLPE( c );

    if (hasPathEffect() && pathEffectsEnabled()) {
        SPCurve *c_lpe = c->copy();
        bool success = this->performPathEffect(c_lpe);

        if (success) {
            this->setCurveInsync( c_lpe, TRUE);
        } 

        c_lpe->unref();
    }

    c->unref();
}
예제 #8
0
// Create path for rendering shape on screen
void SPGenericEllipse::set_shape()
{
    // std::cout << "SPGenericEllipse::set_shape: Entrance" << std::endl;
    if (hasBrokenPathEffect()) {
        g_warning("The ellipse shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as ellipse will remove the bad LPE");

        if (this->getRepr()->attribute("d")) {
            // unconditionally read the curve from d, if any, to preserve appearance
            Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d"));
            SPCurve *cold = new SPCurve(pv);
            this->setCurveInsync(cold, TRUE);
            cold->unref();
        }

        return;
    }
    if (Geom::are_near(this->rx.computed, 0) || Geom::are_near(this->ry.computed, 0)) {
        return;
    }

    this->normalize();

    SPCurve *curve = NULL;

    // For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations.
    Geom::Circle circle(0, 0, 1);

    if (!this->_isSlice()) {
        start = 0.0;
        end = 2.0*M_PI;
    }
    double incr = end - start; // arc angle
    if (incr < 0.0) incr += 2.0*M_PI;    

    int numsegs = 1 + int(incr*2.0/M_PI); // number of arc segments
    if (numsegs > 4) numsegs = 4;

    incr = incr/numsegs; // limit arc angle to less than 90 degrees
    Geom::Path path(Geom::Point::polar(start));
    Geom::EllipticalArc* arc;
    for (int seg = 0; seg < numsegs; seg++) {
        arc = circle.arc(Geom::Point::polar(start + seg*incr), Geom::Point::polar(start + (seg + 0.5)*incr), Geom::Point::polar(start + (seg + 1.0)*incr));
        path.append(*arc);
        delete arc;
    }
    Geom::PathBuilder pb;
    pb.append(path);
    if (this->_isSlice() && this->_closed) {
        pb.lineTo(Geom::Point(0, 0));
    }
    if (this->_closed) {
        pb.closePath();
    } else {
        pb.flush();
    }
    curve = new SPCurve(pb.peek());

    // gchar *str = sp_svg_write_path(curve->get_pathvector());
    // std::cout << "  path: " << str << std::endl;
    // g_free(str);

    // Stretching / moving the calculated shape to fit the actual dimensions.
    Geom::Affine aff = Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed);
    curve->transform(aff);

    /* Reset the shape's curve to the "original_curve"
     * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
    this->setCurveInsync(curve, TRUE);
    this->setCurveBeforeLPE(curve);

    if (hasPathEffect() && pathEffectsEnabled()) {
        SPCurve *c_lpe = curve->copy();
        bool success = this->performPathEffect(c_lpe);

        if (success) {
            this->setCurveInsync(c_lpe, TRUE);
        }

        c_lpe->unref();
    }

    curve->unref();
    // std::cout << "SPGenericEllipse::set_shape: Exit" << std::endl;
}