/** * 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; } }
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]); }
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]); }
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)); } } }
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(); } }
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; }
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(); }
// 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; }