X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-ellipse.cpp;h=769fa54fd62ed41b84ac16d06b6b9251eebe0041;hb=71e828c2a578057f747982e0a477dcb98085b01f;hp=bee7e1b5d6279290b53cb60a58c5237a095a52aa;hpb=3329f64342c406b1a508e985f0d6ce302888f9e3;p=inkscape.git diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index bee7e1b5d..769fa54fd 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -28,6 +28,7 @@ #include "display/curve.h" #include #include <2geom/transforms.h> +#include <2geom/pathvector.h> #include "document.h" #include "sp-ellipse.h" @@ -72,7 +73,7 @@ static void sp_genericellipse_init(SPGenericEllipse *ellipse); static void sp_genericellipse_update(SPObject *object, SPCtx *ctx, guint flags); -static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_genericellipse_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_genericellipse_set_shape(SPShape *shape); static void sp_genericellipse_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -143,13 +144,16 @@ sp_genericellipse_update(SPObject *object, SPCtx *ctx, guint flags) if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { SPGenericEllipse *ellipse = (SPGenericEllipse *) object; SPStyle const *style = object->style; - double const d = 1.0 / NR::expansion(((SPItemCtx const *) ctx)->i2vp); + Geom::OptRect viewbox = ((SPItemCtx const *) ctx)->vp; + double const dx = viewbox->width(); + double const dy = viewbox->height(); + double const dr = sqrt(dx*dx + dy*dy)/sqrt(2); double const em = style->font_size.computed; double const ex = em * 0.5; // fixme: get from pango or libnrtype - ellipse->cx.update(em, ex, d); - ellipse->cy.update(em, ex, d); - ellipse->rx.update(em, ex, d); - ellipse->ry.update(em, ex, d); + ellipse->cx.update(em, ex, dx); + ellipse->cy.update(em, ex, dy); + ellipse->rx.update(em, ex, dr); + ellipse->ry.update(em, ex, dr); sp_shape_set_shape((SPShape *) object); } @@ -177,13 +181,22 @@ sp_genericellipse_update_patheffect(SPLPEItem *lpeitem, bool write) ((SPObject *)shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } - -#define C1 0.552 - /* fixme: Think (Lauris) */ /* Can't we use arcto in this method? */ static void sp_genericellipse_set_shape(SPShape *shape) { + if (sp_lpe_item_has_broken_path_effect(SP_LPE_ITEM(shape))) { + 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 (SP_OBJECT_REPR(shape)->attribute("d")) { + // unconditionally read the curve from d, if any, to preserve appearance + Geom::PathVector pv = sp_svg_read_pathv(SP_OBJECT_REPR(shape)->attribute("d")); + SPCurve *cold = new SPCurve(pv); + sp_shape_set_curve_insync (shape, cold, TRUE); + cold->unref(); + } + return; + } + double rx, ry, s, e; double x0, y0, x1, y1, x2, y2, x3, y3; double len; @@ -217,7 +230,7 @@ static void sp_genericellipse_set_shape(SPShape *shape) e = s + M_PI_2; if (e > ellipse->end) e = ellipse->end; - len = C1 * (e - s) / M_PI_2; + len = 4*tan((e - s)/4)/3; x0 = cos(s); y0 = sin(s); x1 = x0 + len * cos(s + M_PI_2); @@ -257,16 +270,21 @@ static void sp_genericellipse_set_shape(SPShape *shape) curve->unref(); } -static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_genericellipse_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { g_assert(item != NULL); g_assert(SP_IS_GENERICELLIPSE(item)); + // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes + if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { + return; + } + SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item); sp_genericellipse_normalize(ellipse); - NR::Matrix const i2d = sp_item_i2d_affine(item); + Geom::Matrix const i2d = sp_item_i2d_affine(item); - // figure out if we have a slice, whilst guarding against rounding errors + // figure out if we have a slice, while guarding against rounding errors bool slice = false; double len = fmod(ellipse->end - ellipse->start, SP_2PI); if (len < 0.0) len += SP_2PI; @@ -282,28 +300,37 @@ static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, I double cx = ellipse->cx.computed; double cy = ellipse->cy.computed; + Geom::Point pt; + // Snap to the 4 quadrant points of the ellipse, but only if the arc // spans far enough to include them - double angle = 0; - for (angle = 0; angle < SP_2PI; angle += M_PI_2) { - if (angle >= ellipse->start && angle <= ellipse->end) { - *p = NR::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d; - } + if (snapprefs->getSnapToItemNode()) { //TODO: Make a separate snap option toggle for this? + double angle = 0; + for (angle = 0; angle < SP_2PI; angle += M_PI_2) { + if (angle >= ellipse->start && angle <= ellipse->end) { + pt = Geom::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_ELLIPSE_QUADRANT_POINT) : int(Inkscape::SNAPSOURCE_ELLIPSE_QUADRANT_POINT))); + } + } } - // And if we have a slice, also snap to the endpoints and the centre point - if (slice) { - // Add the centre, if we have a closed slice - if (ellipse->closed) { - *p = NR::Point(cx, cy) * i2d; - } + // Add the centre, if we have a closed slice or when explicitly asked for + if ((snapprefs->getSnapToItemNode() && slice && ellipse->closed) || snapprefs->getSnapObjectMidpoints()) { + pt = Geom::Point(cx, cy) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_CENTER) : int(Inkscape::SNAPSOURCE_CENTER))); + } + + // And if we have a slice, also snap to the endpoints + if (snapprefs->getSnapToItemNode() && slice) { // Add the start point, if it's not coincident with a quadrant point if (fmod(ellipse->start, M_PI_2) != 0.0 ) { - *p = NR::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d; + pt = Geom::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP))); } // Add the end point, if it's not coincident with a quadrant point if (fmod(ellipse->end, M_PI_2) != 0.0 ) { - *p = NR::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d; + pt = Geom::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP))); } } } @@ -680,8 +707,6 @@ sp_arc_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) if (((SPObjectClass *) arc_parent_class)->build) (* ((SPObjectClass *) arc_parent_class)->build) (object, document, repr); - Inkscape::Version version = sp_object_get_sodipodi_version(object); - sp_object_read_attr(object, "sodipodi:cx"); sp_object_read_attr(object, "sodipodi:cy"); sp_object_read_attr(object, "sodipodi:rx"); @@ -707,8 +732,8 @@ sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr) Inkscape::SVG::PathString str; - NR::Point p1 = sp_arc_get_xy(arc, ge->start); - NR::Point p2 = sp_arc_get_xy(arc, ge->end); + Geom::Point p1 = sp_arc_get_xy(arc, ge->start); + Geom::Point p2 = sp_arc_get_xy(arc, ge->end); double rx = ge->rx.computed; double ry = ge->ry.computed; @@ -716,7 +741,7 @@ sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr) double dt = fmod(ge->end - ge->start, SP_2PI); if (fabs(dt) < 1e-6) { - NR::Point ph = sp_arc_get_xy(arc, (ge->start + ge->end) / 2.0); + Geom::Point ph = sp_arc_get_xy(arc, (ge->start + ge->end) / 2.0); str.arcTo(rx, ry, 0, true, true, ph) .arcTo(rx, ry, 0, true, true, p2) .closePath(); @@ -725,7 +750,7 @@ sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr) bool fs = (dt > 0); str.arcTo(rx, ry, 0, fa, fs, p2); if (ge->closed) { - NR::Point center = NR::Point(ge->cx.computed, ge->cy.computed); + Geom::Point center = Geom::Point(ge->cx.computed, ge->cy.computed); str.lineTo(center).closePath(); } } @@ -830,7 +855,7 @@ sp_arc_set(SPObject *object, unsigned int key, gchar const *value) static void sp_arc_modified(SPObject *object, guint flags) { - if (flags & SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG) { + if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { sp_shape_set_shape((SPShape *) object); } @@ -880,11 +905,11 @@ sp_arc_position_set(SPArc *arc, gdouble x, gdouble y, gdouble rx, gdouble ry) ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -NR::Point sp_arc_get_xy(SPArc *arc, gdouble arg) +Geom::Point sp_arc_get_xy(SPArc *arc, gdouble arg) { SPGenericEllipse *ge = SP_GENERICELLIPSE(arc); - return NR::Point(ge->rx.computed * cos(arg) + ge->cx.computed, + return Geom::Point(ge->rx.computed * cos(arg) + ge->cx.computed, ge->ry.computed * sin(arg) + ge->cy.computed); }