diff options
| author | Liam P. White <inkscapebrony@gmail.com> | 2014-11-24 03:07:36 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebrony@gmail.com> | 2014-11-24 03:07:36 +0000 |
| commit | f12a73dd77175bd6126319f3a698eb16193e7b68 (patch) | |
| tree | b5a59803e5bd212f0e355faa029295aa79d47a0e /src | |
| parent | Update to trunk r13690 (diff) | |
| parent | Extensions: try to calculate the SVG unit (diff) | |
| download | inkscape-f12a73dd77175bd6126319f3a698eb16193e7b68.tar.gz inkscape-f12a73dd77175bd6126319f3a698eb16193e7b68.zip | |
Update to trunk r13750
(bzr r13341.5.23)
Diffstat (limited to 'src')
65 files changed, 1503 insertions, 941 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0bacff16..9ab3c28a9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -364,6 +364,7 @@ set(inkscape_SRC number-opt-number.h object-hierarchy.h object-snapper.h + object-test.h path-chemistry.h path-prefix.h persp3d-reference.h diff --git a/src/Makefile_insert b/src/Makefile_insert index acf317c47..488ab52c5 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -247,6 +247,7 @@ CXXTEST_TESTSUITES += \ $(srcdir)/extract-uri-test.h \ $(srcdir)/marker-test.h \ $(srcdir)/mod360-test.h \ + $(srcdir)/object-test.h \ $(srcdir)/preferences-test.h \ $(srcdir)/round-test.h \ $(srcdir)/sp-gradient-test.h \ diff --git a/src/attribute-rel-css.cpp b/src/attribute-rel-css.cpp index 89678edb5..b904cd5f4 100644 --- a/src/attribute-rel-css.cpp +++ b/src/attribute-rel-css.cpp @@ -60,6 +60,7 @@ bool SPAttributeRelCSS::findIfValid(Glib::ustring property, Glib::ustring elemen || property.substr(0,4) == "rdf:" || property.substr(0,3) == "cc:" || property.substr(0,4) == "ns1:" // JessyInk + || property.substr(0,4) == "osb:" // Open Swatch Book || (SPAttributeRelCSS::instance->propertiesOfElements[temp].find(property) != SPAttributeRelCSS::instance->propertiesOfElements[temp].end()) ) { return true; diff --git a/src/attribute-rel-svg.cpp b/src/attribute-rel-svg.cpp index 49c97ae64..0064f4c62 100644 --- a/src/attribute-rel-svg.cpp +++ b/src/attribute-rel-svg.cpp @@ -56,6 +56,7 @@ bool SPAttributeRelSVG::findIfValid(Glib::ustring attribute, Glib::ustring eleme || attribute.substr(0,4) == "rdf:" || attribute.substr(0,3) == "cc:" || attribute.substr(0,4) == "ns1:" // JessyInk + || attribute.substr(0,4) == "osb:" // Open Swatch Book || (SPAttributeRelSVG::instance->attributesOfElements[temp].find(attribute) != SPAttributeRelSVG::instance->attributesOfElements[temp].end()) ) { return true; diff --git a/src/attributes.cpp b/src/attributes.cpp index d142d1a06..2b04843a7 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -115,7 +115,7 @@ static SPStyleProp const props[] = { {SP_ATTR_INKSCAPE_SNAP_BBOX_CORNER, "inkscape:bbox-nodes"}, {SP_ATTR_INKSCAPE_SNAP_PAGE_BORDER, "inkscape:snap-page"}, {SP_ATTR_INKSCAPE_CURRENT_LAYER, "inkscape:current-layer"}, - {SP_ATTR_INKSCAPE_DOCUMENT_UNITS, "inkscape:document-units"}, + {SP_ATTR_INKSCAPE_DOCUMENT_UNITS, "inkscape:document-units"}, // This setting sets the Display units, *not* the units used in SVG {SP_ATTR_UNITS, "units"}, {SP_ATTR_INKSCAPE_CONNECTOR_SPACING, "inkscape:connector-spacing"}, /* SPColorProfile */ diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index 15dc339cf..30869d87d 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -49,6 +49,24 @@ #include "box3d-side.h" #include <2geom/math-utils.h> +namespace { + +bool isTextualItem(SPObject const *obj) +{ + bool isTextual = dynamic_cast<SPText const *>(obj) // + || dynamic_cast<SPFlowtext const *>(obj) // + || dynamic_cast<SPTSpan const *>(obj) // + || dynamic_cast<SPTRef const *>(obj) // + || dynamic_cast<SPTextPath const *>(obj) // + || dynamic_cast<SPFlowdiv const *>(obj) // + || dynamic_cast<SPFlowpara const *>(obj) // + || dynamic_cast<SPFlowtspan const *>(obj); + + return isTextual; +} + +} // namespace + /** * Set color on selection on desktop. */ @@ -89,8 +107,10 @@ void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) { // non-items should not have style - if (!SP_IS_ITEM(o)) + SPItem *item = dynamic_cast<SPItem *>(o); + if (!item) { return; + } // 1. tspans with role=line are not regular objects in that they are not supposed to have style of their own, // but must always inherit from the parent text. Same for textPath. @@ -100,22 +120,24 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) // it, be it clone or not; it's just styleless shape (because that's how Inkscape does // flowtext). + SPTSpan *tspan = dynamic_cast<SPTSpan *>(o); + if (!(skip_lines - && ((SP_IS_TSPAN(o) && SP_TSPAN(o)->role == SP_TSPAN_ROLE_LINE) - || SP_IS_FLOWDIV(o) - || SP_IS_FLOWPARA(o) - || SP_IS_TEXTPATH(o)) + && ((tspan && tspan->role == SP_TSPAN_ROLE_LINE) + || dynamic_cast<SPFlowdiv *>(o) + || dynamic_cast<SPFlowpara *>(o) + || dynamic_cast<SPTextPath *>(o)) && !o->getAttribute("style")) && - !(SP_IS_FLOWREGION(o) || - SP_IS_FLOWREGIONEXCLUDE(o) || - (SP_IS_USE(o) && + !(dynamic_cast<SPFlowregionbreak *>(o) || + dynamic_cast<SPFlowregionExclude *>(o) || + (dynamic_cast<SPUse *>(o) && o->parent && - (SP_IS_FLOWREGION(o->parent) || - SP_IS_FLOWREGIONEXCLUDE(o->parent) - ) - ) - ) + (dynamic_cast<SPFlowregion *>(o->parent) || + dynamic_cast<SPFlowregionExclude *>(o->parent) + ) + ) + ) ) { SPCSSAttr *css_set = sp_repr_css_attr_new(); @@ -123,7 +145,7 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) // Scale the style by the inverse of the accumulated parent transform in the paste context. { - Geom::Affine const local(SP_ITEM(o)->i2doc_affine()); + Geom::Affine const local(item->i2doc_affine()); double const ex(local.descrim()); if ( ( ex != 0. ) && ( ex != 1. ) ) { @@ -137,8 +159,9 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) } // setting style on child of clone spills into the clone original (via shared repr), don't do it! - if (SP_IS_USE(o)) + if (dynamic_cast<SPUse *>(o)) { return; + } for ( SPObject *child = o->firstChild() ; child ; child = child->getNext() ) { if (sp_repr_css_property(css, "opacity", NULL) != NULL) { @@ -212,11 +235,10 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write css_no_text = sp_css_attr_unset_text(css_no_text); for (GSList const *i = desktop->selection->itemList(); i != NULL; i = i->next) { + SPItem *item = reinterpret_cast<SPItem *>(i->data); // If not text, don't apply text attributes (can a group have text attributes? Yes! FIXME) - if ( SP_IS_TEXT(i->data) || SP_IS_FLOWTEXT(i->data) - || SP_IS_TSPAN(i->data) || SP_IS_TREF(i->data) || SP_IS_TEXTPATH(i->data) - || SP_IS_FLOWDIV(i->data) || SP_IS_FLOWPARA(i->data) || SP_IS_FLOWTSPAN(i->data)) { + if (isTextualItem(item)) { // If any font property has changed, then we have written out the font // properties in longhand and we need to remove the 'font' shorthand. @@ -224,11 +246,11 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write sp_repr_css_unset_property(css, "font"); } - sp_desktop_apply_css_recursive(SP_OBJECT(i->data), css, true); + sp_desktop_apply_css_recursive(item, css, true); } else { - sp_desktop_apply_css_recursive(SP_OBJECT(i->data), css_no_text, true); + sp_desktop_apply_css_recursive(item, css_no_text, true); } } @@ -427,16 +449,17 @@ stroke_average_width (GSList const *objects) int n_notstroked = 0; for (GSList const *l = objects; l != NULL; l = l->next) { - if (!SP_IS_ITEM (l->data)) + SPObject *obj = reinterpret_cast<SPObject *>(l->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + if (!item) { continue; + } - Geom::Affine i2dt = SP_ITEM(l->data)->i2dt_affine(); - - SPObject *object = SP_OBJECT(l->data); + Geom::Affine i2dt = item->i2dt_affine(); - double width = object->style->stroke_width.computed * i2dt.descrim(); + double width = item->style->stroke_width.computed * i2dt.descrim(); - if ( object->style->stroke.isNone() || IS_NAN(width)) { + if ( item->style->stroke.isNone() || IS_NAN(width)) { ++n_notstroked; // do not count nonstroked objects continue; } else { @@ -493,7 +516,10 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill bool same_color = true; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!obj) { + continue; + } SPStyle *style = obj->style; if (!style) { continue; @@ -504,9 +530,9 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill // We consider paint "effectively set" for anything within text hierarchy SPObject *parent = obj->parent; bool paint_effectively_set = - paint->set || (SP_IS_TEXT(parent) || SP_IS_TEXTPATH(parent) || SP_IS_TSPAN(parent) - || SP_IS_FLOWTEXT(parent) || SP_IS_FLOWDIV(parent) || SP_IS_FLOWPARA(parent) - || SP_IS_FLOWTSPAN(parent) || SP_IS_FLOWLINE(parent)); + paint->set || (dynamic_cast<SPText *>(parent) || dynamic_cast<SPTextPath *>(parent) || dynamic_cast<SPTSpan *>(parent) + || dynamic_cast<SPFlowtext *>(parent) || dynamic_cast<SPFlowdiv *>(parent) || dynamic_cast<SPFlowpara *>(parent) + || dynamic_cast<SPFlowtspan *>(parent) || dynamic_cast<SPFlowline*>(parent)); // 1. Bail out with QUERY_STYLE_MULTIPLE_DIFFERENT if necessary @@ -518,38 +544,45 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill if (paint_res->set && paint->set && paint_res->isPaintserver()) { // both previous paint and this paint were a server, see if the servers are compatible - SPPaintServer *server_res = isfill? SP_STYLE_FILL_SERVER (style_res) : SP_STYLE_STROKE_SERVER (style_res); - SPPaintServer *server = isfill? SP_STYLE_FILL_SERVER (style) : SP_STYLE_STROKE_SERVER (style); + SPPaintServer *server_res = isfill ? style_res->getFillPaintServer() : style_res->getStrokePaintServer(); + SPPaintServer *server = isfill ? style->getFillPaintServer() : style->getStrokePaintServer(); - if (SP_IS_LINEARGRADIENT (server_res)) { - - if (!SP_IS_LINEARGRADIENT(server)) + SPLinearGradient *linear_res = dynamic_cast<SPLinearGradient *>(server_res); + SPRadialGradient *radial_res = linear_res ? NULL : dynamic_cast<SPRadialGradient *>(server_res); + SPPattern *pattern_res = (linear_res || radial_res) ? NULL : dynamic_cast<SPPattern *>(server_res); + if (linear_res) { + SPLinearGradient *linear = dynamic_cast<SPLinearGradient *>(server); + if (!linear) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server + } - SPGradient *vector = SP_GRADIENT(server)->getVector(); - SPGradient *vector_res = SP_GRADIENT(server_res)->getVector(); - if (vector_res != vector) + SPGradient *vector = linear->getVector(); + SPGradient *vector_res = linear_res->getVector(); + if (vector_res != vector) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different gradient vectors - - } else if (SP_IS_RADIALGRADIENT (server_res)) { - - if (!SP_IS_RADIALGRADIENT(server)) + } + } else if (radial_res) { + SPRadialGradient *radial = dynamic_cast<SPRadialGradient *>(server); + if (!radial) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server + } - SPGradient *vector = SP_GRADIENT(server)->getVector(); - SPGradient *vector_res = SP_GRADIENT(server_res)->getVector(); - if (vector_res != vector) + SPGradient *vector = radial->getVector(); + SPGradient *vector_res = radial_res->getVector(); + if (vector_res != vector) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different gradient vectors - - } else if (SP_IS_PATTERN (server_res)) { - - if (!SP_IS_PATTERN(server)) + } + } else if (pattern_res) { + SPPattern *pattern = dynamic_cast<SPPattern *>(server); + if (!pattern) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server + } - SPPattern *pat = pattern_getroot (SP_PATTERN (server)); - SPPattern *pat_res = pattern_getroot (SP_PATTERN (server_res)); - if (pat_res != pat) + SPPattern *pat = pattern_getroot (pattern); + SPPattern *pat_res = pattern_getroot (pattern_res); + if (pat_res != pat) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different pattern roots + } } } @@ -667,7 +700,10 @@ objects_query_opacity (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!obj) { + continue; + } SPStyle *style = obj->style; if (!style) { continue; @@ -720,8 +756,12 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res) int n_stroked = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!obj) { + continue; + } + SPItem *item = dynamic_cast<SPItem *>(obj); + if (!item) { continue; } SPStyle *style = obj->style; @@ -740,7 +780,7 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res) noneSet &= style->stroke.isNone(); - Geom::Affine i2d = SP_ITEM(obj)->i2dt_affine(); + Geom::Affine i2d = item->i2dt_affine(); double sw = style->stroke_width.computed * i2d.descrim(); if (!IS_NAN(sw)) { @@ -790,8 +830,8 @@ objects_query_miterlimit (GSList *objects, SPStyle *style_res) bool same_ml = true; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!dynamic_cast<SPItem *>(obj)) { continue; } SPStyle *style = obj->style; @@ -849,8 +889,8 @@ objects_query_strokecap (GSList *objects, SPStyle *style_res) int n_stroked = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!dynamic_cast<SPItem *>(obj)) { continue; } SPStyle *style = obj->style; @@ -903,8 +943,8 @@ objects_query_strokejoin (GSList *objects, SPStyle *style_res) int n_stroked = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!dynamic_cast<SPItem *>(obj)) { continue; } SPStyle *style = obj->style; @@ -966,11 +1006,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) int no_size = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); - if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) - && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { + if (!isTextualItem(obj)) { continue; } @@ -980,7 +1018,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) } texts ++; - double dummy = style->font_size.computed * Geom::Affine(SP_ITEM(obj)->i2dt_affine()).descrim(); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + double dummy = style->font_size.computed * Geom::Affine(item->i2dt_affine()).descrim(); if (!IS_NAN(dummy)) { size += dummy; /// \todo FIXME: we assume non-% units here } else { @@ -1085,12 +1125,11 @@ objects_query_fontstyle (GSList *objects, SPStyle *style_res) int texts = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); - if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) - && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) + if (!isTextualItem(obj)) { continue; + } SPStyle *style = obj->style; if (!style) { @@ -1155,11 +1194,9 @@ objects_query_baselines (GSList *objects, SPStyle *style_res) int texts = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); - if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) - && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { + if (!isTextualItem(obj)) { continue; } @@ -1245,12 +1282,10 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res) style_res->font_family.set = FALSE; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); // std::cout << " " << reinterpret_cast<SPObject*>(i->data)->getId() << std::endl; - if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) - && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { + if (!isTextualItem(obj)) { continue; } @@ -1303,12 +1338,10 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res) style_res->font_specification.set = FALSE; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); // std::cout << " " << reinterpret_cast<SPObject*>(i->data)->getId() << std::endl; - if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) - && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { + if (!isTextualItem(obj)) { continue; } @@ -1363,9 +1396,12 @@ objects_query_blend (GSList *objects, SPStyle *style_res) guint items = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!obj) { + continue; + } SPStyle *style = obj->style; - if (!style || !SP_IS_ITEM(obj)) { + if (!style || !dynamic_cast<SPItem *>(obj)) { continue; } @@ -1378,14 +1414,14 @@ objects_query_blend (GSList *objects, SPStyle *style_res) // determine whether filter is simple (blend and/or blur) or complex for(SPObject *primitive_obj = style->getFilter()->children; - primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); + primitive_obj && dynamic_cast<SPFilterPrimitive *>(primitive_obj); primitive_obj = primitive_obj->next) { - SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj); - if(SP_IS_FEBLEND(primitive)) + SPFilterPrimitive *primitive = dynamic_cast<SPFilterPrimitive *>(primitive_obj); + if (dynamic_cast<SPFeBlend *>(primitive)) { ++blendcount; - else if(SP_IS_GAUSSIANBLUR(primitive)) + } else if (dynamic_cast<SPGaussianBlur *>(primitive)) { ++blurcount; - else { + } else { blurcount = complex_filter; break; } @@ -1394,10 +1430,10 @@ objects_query_blend (GSList *objects, SPStyle *style_res) // simple filter if(blurcount == 1 || blendcount == 1) { for(SPObject *primitive_obj = style->getFilter()->children; - primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); + primitive_obj && dynamic_cast<SPFilterPrimitive *>(primitive_obj); primitive_obj = primitive_obj->next) { - if(SP_IS_FEBLEND(primitive_obj)) { - SPFeBlend *spblend = SP_FEBLEND(primitive_obj); + SPFeBlend *spblend = dynamic_cast<SPFeBlend *>(primitive_obj); + if (spblend) { blend = spblend->blend_mode; } } @@ -1450,16 +1486,20 @@ objects_query_blur (GSList *objects, SPStyle *style_res) guint items = 0; for (GSList const *i = objects; i != NULL; i = i->next) { - SPObject *obj = SP_OBJECT (i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + if (!obj) { + continue; + } SPStyle *style = obj->style; if (!style) { continue; } - if (!SP_IS_ITEM(obj)) { + SPItem *item = dynamic_cast<SPItem *>(obj); + if (!item) { continue; } - Geom::Affine i2d = SP_ITEM(obj)->i2dt_affine(); + Geom::Affine i2d = item->i2dt_affine(); items ++; @@ -1468,12 +1508,12 @@ objects_query_blur (GSList *objects, SPStyle *style_res) //cycle through filter primitives SPObject *primitive_obj = style->getFilter()->children; while (primitive_obj) { - if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) { - SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj); + SPFilterPrimitive *primitive = dynamic_cast<SPFilterPrimitive *>(primitive_obj); + if (primitive) { //if primitive is gaussianblur - if(SP_IS_GAUSSIANBLUR(primitive)) { - SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive); + SPGaussianBlur * spblur = dynamic_cast<SPGaussianBlur *>(primitive); + if (spblur) { float num = spblur->stdDeviation.getNumber(); float dummy = num * i2d.descrim(); if (!IS_NAN(dummy)) { diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 84b4bd080..011f51977 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -4,6 +4,7 @@ * * Authors: * Felipe C. da S. Sanches <juca@members.fsf.org> + * Jon A. Cruz <jon@joncruz.org> * * Copyright (C) 2008 Felipe C. da S. Sanches * @@ -32,9 +33,9 @@ #include "sp-font.h" #include "sp-glyph-kerning.h" -//*************************// +// ************************// // UserFont Implementation // -//*************************// +// ************************// // I wrote this binding code because Cairomm does not yet support userfonts. I have moved this code to cairomm and sent them a patch. // Once Cairomm incorporate the UserFonts binding, this code should be removed from inkscape and Cairomm API should be used. @@ -111,16 +112,38 @@ unsigned int size_of_substring(const char* substring, gchar* str){ return 0; } -//TODO: in these macros, verify what happens when using unicode strings. -#define Match_VKerning_Rule ((SP_VKERN(node))->u1->contains(previous_unicode[0])\ - || (SP_VKERN(node))->g1->contains(previous_glyph_name)) &&\ - ((SP_VKERN(node))->u2->contains(this->glyphs[i]->unicode[0])\ - || (SP_VKERN(node))->g2->contains(this->glyphs[i]->glyph_name.c_str())) -#define Match_HKerning_Rule ((SP_HKERN(node))->u1->contains(previous_unicode[0])\ - || (SP_HKERN(node))->g1->contains(previous_glyph_name)) &&\ - ((SP_HKERN(node))->u2->contains(this->glyphs[i]->unicode[0])\ - || (SP_HKERN(node))->g2->contains(this->glyphs[i]->glyph_name.c_str())) +namespace { + +//TODO: in these functions, verify what happens when using unicode strings. + +bool MatchVKerningRule(SPVkern const *vkern, + SPGlyph *glyph, + char const *previous_unicode, + gchar const *previous_glyph_name) +{ + bool value = (vkern->u1->contains(previous_unicode[0]) + || vkern->g1->contains(previous_glyph_name)) + && (vkern->u2->contains(glyph->unicode[0]) + || vkern->g2->contains(glyph->glyph_name.c_str())); + + return value; +} + +bool MatchHKerningRule(SPHkern const *hkern, + SPGlyph *glyph, + char const *previous_unicode, + gchar const *previous_glyph_name) +{ + bool value = (hkern->u1->contains(previous_unicode[0]) + || hkern->g1->contains(previous_glyph_name)) + && (hkern->u2->contains(glyph->unicode[0]) + || hkern->g2->contains(glyph->glyph_name.c_str())); + + return value; +} + +} // namespace cairo_status_t SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, @@ -182,11 +205,13 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){ //apply glyph kerning if appropriate - if (SP_IS_HKERN(node) && is_horizontal_text && Match_HKerning_Rule ){ - x -= ((SP_HKERN(node))->k / 1000.0);//TODO: use here the height of the font + SPHkern *hkern = dynamic_cast<SPHkern *>(node); + if (hkern && is_horizontal_text && MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + x -= (hkern->k / 1000.0);//TODO: use here the height of the font } - if (SP_IS_VKERN(node) && !is_horizontal_text && Match_VKerning_Rule ){ - y -= ((SP_VKERN(node))->k / 1000.0);//TODO: use here the "height" of the font + SPVkern *vkern = dynamic_cast<SPVkern *>(node); + if (vkern && !is_horizontal_text && MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font } } previous_unicode = const_cast<char*>(this->glyphs[i]->unicode.c_str());//used for kerning checking @@ -246,9 +271,8 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){ Geom::PathVector SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){ double units_per_em = 1000; - SPObject* obj; - for (obj = (SP_OBJECT(spfont))->children; obj; obj=obj->next){ - if (SP_IS_FONTFACE(obj)){ + for (SPObject *obj = spfont->children; obj; obj = obj->next){ + if (dynamic_cast<SPFontFace *>(obj)) { //XML Tree being directly used here while it shouldn't be. sp_repr_get_double(obj->getRepr(), "units_per_em", &units_per_em); } @@ -275,19 +299,21 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, 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 = SP_OBJECT(this->missingglyph); + SPObject *node = NULL; + if (glyph == glyphs.size()){ + if (!missingglyph) { + return CAIRO_STATUS_SUCCESS; + } + node = missingglyph; } else { - node = SP_OBJECT(this->glyphs[glyph]); + node = glyphs[glyph]; } - if (!SP_IS_GLYPH(node) && !SP_IS_MISSING_GLYPH(node)) { + if (!dynamic_cast<SPGlyph *>(node) && !dynamic_cast<SPMissingGlyph *>(node)) { return CAIRO_STATUS_SUCCESS; // FIXME: is this the right code to return? } - SPFont* spfont = SP_FONT(node->parent); + SPFont* spfont = dynamic_cast<SPFont *>(node->parent); if (!spfont) { return CAIRO_STATUS_SUCCESS; // FIXME: is this the right code to return? } @@ -296,36 +322,48 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, // 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) && (SP_GLYPH(node))->d) { - pathv = sp_svg_read_pathv((SP_GLYPH(node))->d); - pathv = flip_coordinate_system(spfont, pathv); - this->render_glyph_path(cr, &pathv); - } else if (SP_IS_MISSING_GLYPH(node) && (SP_MISSING_GLYPH(node))->d) { - pathv = sp_svg_read_pathv((SP_MISSING_GLYPH(node))->d); + + SPGlyph *glyphNode = dynamic_cast<SPGlyph *>(node); + if (glyphNode && glyphNode->d) { + pathv = sp_svg_read_pathv(glyphNode->d); pathv = flip_coordinate_system(spfont, pathv); - this->render_glyph_path(cr, &pathv); + render_glyph_path(cr, &pathv); + } else { + SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(node); + if (missing && missing->d) { + pathv = sp_svg_read_pathv(missing->d); + pathv = flip_coordinate_system(spfont, pathv); + 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 = (SP_SHAPE(node))->_curve->get_pathvector(); - pathv = flip_coordinate_system(spfont, pathv); - this->render_glyph_path(cr, &pathv); + { + SPPath *path = dynamic_cast<SPPath *>(node); + if (path) { + pathv = path->_curve->get_pathvector(); + pathv = flip_coordinate_system(spfont, pathv); + render_glyph_path(cr, &pathv); + } } - if (SP_IS_OBJECTGROUP(node)){ + if (dynamic_cast<SPObjectGroup *>(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 = (SP_SHAPE(item))->_curve->get_pathvector(); + SPUse *use = dynamic_cast<SPUse *>(node); + if (use) { + SPItem* item = use->ref->getObject(); + SPPath *path = dynamic_cast<SPPath *>(item); + if (path) { + SPShape *shape = dynamic_cast<SPShape *>(item); + g_assert(shape != NULL); + pathv = shape->_curve->get_pathvector(); pathv = flip_coordinate_system(spfont, pathv); this->render_glyph_path(cr, &pathv); } - glyph_modified_connection = (SP_OBJECT(item))->connectModified(sigc::mem_fun(*this, &SvgFont::glyph_modified)); + glyph_modified_connection = item->connectModified(sigc::mem_fun(*this, &SvgFont::glyph_modified)); } } } @@ -337,11 +375,13 @@ cairo_font_face_t* SvgFont::get_font_face(){ if (!this->userfont) { for(SPObject* node = this->font->children;node;node=node->next){ - if (SP_IS_GLYPH(node)){ - this->glyphs.push_back(SP_GLYPH(node)); + SPGlyph *glyph = dynamic_cast<SPGlyph *>(node); + if (glyph) { + glyphs.push_back(glyph); } - if (SP_IS_MISSING_GLYPH(node)){ - this->missingglyph=SP_MISSING_GLYPH(node); + SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(node); + if (missing) { + missingglyph = missing; } } this->userfont = new UserFont(this); diff --git a/src/document.cpp b/src/document.cpp index b3d606417..2832536af 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -716,11 +716,9 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double const old_height = getHeight().value("px"); Inkscape::Util::Unit const *nv_units = unit_table.getUnit("px"); + if (root->height.unit) + nv_units = unit_table.getUnit(root->height.unit); SPNamedView *nv = sp_document_namedview(this, NULL); - if (nv != NULL) { - if (nv->getAttribute("units")) - nv_units = unit_table.getUnit(nv->getAttribute("units")); - } /* in px */ double margin_top = 0.0; diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 1d9bb09d0..5a9a28ef9 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -147,13 +147,13 @@ Here comes the rendering part which could be put into the 'render' methods of SP /* The below functions are copy&pasted plus slightly modified from *_invoke_print functions. */ static void sp_item_invoke_render(SPItem *item, CairoRenderContext *ctx); -static void sp_group_render(SPItem *item, CairoRenderContext *ctx); -static void sp_use_render(SPItem *item, CairoRenderContext *ctx); -static void sp_shape_render(SPItem *item, CairoRenderContext *ctx); -static void sp_text_render(SPItem *item, CairoRenderContext *ctx); -static void sp_flowtext_render(SPItem *item, CairoRenderContext *ctx); -static void sp_image_render(SPItem *item, CairoRenderContext *ctx); -static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx); +static void sp_group_render(SPGroup *group, CairoRenderContext *ctx); +static void sp_use_render(SPUse *use, CairoRenderContext *ctx); +static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx); +static void sp_text_render(SPText *text, CairoRenderContext *ctx); +static void sp_flowtext_render(SPFlowtext *flowtext, CairoRenderContext *ctx); +static void sp_image_render(SPImage *image, CairoRenderContext *ctx); +static void sp_symbol_render(SPSymbol *symbol, CairoRenderContext *ctx); static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx); static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affine tr, SPStyle* style, CairoRenderContext *ctx) @@ -179,17 +179,15 @@ static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affi } } -static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) +static void sp_shape_render(SPShape *shape, CairoRenderContext *ctx) { - SPShape *shape = SP_SHAPE(item); - if (!shape->_curve) { return; } - Geom::OptRect pbox = item->geometricBounds(); + Geom::OptRect pbox = shape->geometricBounds(); - SPStyle* style = item->style; + SPStyle* style = shape->style; Geom::PathVector const & pathv = shape->_curve->get_pathvector(); if (pathv.empty()) { @@ -201,7 +199,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( shape->_marker[i] ) { - SPMarker* marker = SP_MARKER (shape->_marker[i]); + SPMarker* marker = shape->_marker[i]; Geom::Affine tr; if (marker->orient_mode == MARKER_ORIENT_AUTO) { tr = sp_shape_marker_get_transform_at_start(pathv.begin()->front()); @@ -216,7 +214,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) // MID marker for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID if ( !shape->_marker[i] ) continue; - SPMarker* marker = SP_MARKER (shape->_marker[i]); + SPMarker* marker = shape->_marker[i]; for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { // START position if ( path_it != pathv.begin() @@ -268,7 +266,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) // END marker for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END if ( shape->_marker[i] ) { - SPMarker* marker = SP_MARKER (shape->_marker[i]); + SPMarker* marker = shape->_marker[i]; /* Get reference to last curve in the path. * For moveto-only path, this returns the "closing line segment". */ @@ -291,26 +289,25 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) } } -static void sp_group_render(SPItem *item, CairoRenderContext *ctx) +static void sp_group_render(SPGroup *group, CairoRenderContext *ctx) { - SPGroup *group = SP_GROUP(item); CairoRenderer *renderer = ctx->getRenderer(); TRACE(("sp_group_render opacity: %f\n", SP_SCALE24_TO_FLOAT(item->style->opacity.value))); GSList *l = g_slist_reverse(group->childList(false)); while (l) { - SPObject *o = SP_OBJECT (l->data); - if (SP_IS_ITEM(o)) { - renderer->renderItem (ctx, SP_ITEM (o)); + SPObject *o = reinterpret_cast<SPObject *>(l->data); + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { + renderer->renderItem(ctx, item); } l = g_slist_remove (l, o); } } -static void sp_use_render(SPItem *item, CairoRenderContext *ctx) +static void sp_use_render(SPUse *use, CairoRenderContext *ctx) { bool translated = false; - SPUse *use = SP_USE(item); CairoRenderer *renderer = ctx->getRenderer(); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { @@ -320,8 +317,8 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx) translated = true; } - if (use->child && SP_IS_ITEM(use->child)) { - renderer->renderItem(ctx, SP_ITEM(use->child)); + if (use->child) { + renderer->renderItem(ctx, use->child); } if (translated) { @@ -329,30 +326,27 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx) } } -static void sp_text_render(SPItem *item, CairoRenderContext *ctx) +static void sp_text_render(SPText *text, CairoRenderContext *ctx) { - SPText *group = SP_TEXT (item); - group->layout.showGlyphs(ctx); + text->layout.showGlyphs(ctx); } -static void sp_flowtext_render(SPItem *item, CairoRenderContext *ctx) +static void sp_flowtext_render(SPFlowtext *flowtext, CairoRenderContext *ctx) { - SPFlowtext *group = SP_FLOWTEXT(item); - group->layout.showGlyphs(ctx); + flowtext->layout.showGlyphs(ctx); } -static void sp_image_render(SPItem *item, CairoRenderContext *ctx) +static void sp_image_render(SPImage *image, CairoRenderContext *ctx) { - SPImage *image; - int w, h; - - image = SP_IMAGE (item); - - if (!image->pixbuf) return; - if ((image->width.computed <= 0.0) || (image->height.computed <= 0.0)) return; + if (!image->pixbuf) { + return; + } + if ((image->width.computed <= 0.0) || (image->height.computed <= 0.0)) { + return; + } - w = image->pixbuf->width(); - h = image->pixbuf->height(); + int w = image->pixbuf->width(); + int h = image->pixbuf->height(); double x = image->x.computed; double y = image->y.computed; @@ -372,12 +366,11 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx) Geom::Scale s(width / (double)w, height / (double)h); Geom::Affine t(s * tp); - ctx->renderImage (image->pixbuf, t, item->style); + ctx->renderImage(image->pixbuf, t, image->style); } -static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) +static void sp_symbol_render(SPSymbol *symbol, CairoRenderContext *ctx) { - SPSymbol *symbol = SP_SYMBOL(item); if (!symbol->cloned) { return; } @@ -412,7 +405,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) ctx->transform(vb2user); } - sp_group_render(item, ctx); + sp_group_render(symbol, ctx); ctx->popState(); } @@ -524,34 +517,56 @@ static void sp_item_invoke_render(SPItem *item, CairoRenderContext *ctx) SPStyle* style = item->style; if((ctx->getFilterToBitmap() == TRUE) && (style->filter.set != 0)) { - return sp_asbitmap_render(item, ctx); + sp_asbitmap_render(item, ctx); } - if (SP_IS_ROOT(item)) { + SPRoot *root = dynamic_cast<SPRoot *>(item); + if (root) { TRACE(("root\n")); - return sp_root_render(SP_ROOT(item), ctx); - } else if (SP_IS_SYMBOL(item)) { - TRACE(("symbol\n")); - return sp_symbol_render(item, ctx); - } else if (SP_IS_GROUP(item)) { - TRACE(("group\n")); - return sp_group_render(item, ctx); - } else if (SP_IS_SHAPE(item)) { - TRACE(("shape\n")); - return sp_shape_render(item, ctx); - } else if (SP_IS_USE(item)) { - TRACE(("use begin---\n")); - sp_use_render(item, ctx); - TRACE(("---use end\n")); - } else if (SP_IS_TEXT(item)) { - TRACE(("text\n")); - return sp_text_render(item, ctx); - } else if (SP_IS_FLOWTEXT(item)) { - TRACE(("flowtext\n")); - return sp_flowtext_render(item, ctx); - } else if (SP_IS_IMAGE(item)) { - TRACE(("image\n")); - return sp_image_render(item, ctx); + sp_root_render(root, ctx); + } else { + SPSymbol *symbol = dynamic_cast<SPSymbol *>(item); + if (symbol) { + TRACE(("symbol\n")); + sp_symbol_render(symbol, ctx); + } else { + SPGroup *group = dynamic_cast<SPGroup *>(item); + if (group) { + TRACE(("group\n")); + sp_group_render(group, ctx); + } else { + SPShape *shape = dynamic_cast<SPShape *>(item); + if (shape) { + TRACE(("shape\n")); + sp_shape_render(shape, ctx); + } else { + SPUse *use = dynamic_cast<SPUse *>(item); + if (use) { + TRACE(("use begin---\n")); + sp_use_render(use, ctx); + TRACE(("---use end\n")); + } else { + SPText *text = dynamic_cast<SPText *>(item); + if (text) { + TRACE(("text\n")); + sp_text_render(text, ctx); + } else { + SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item); + if (flowtext) { + TRACE(("flowtext\n")); + sp_flowtext_render(flowtext, ctx); + } else { + SPImage *image = dynamic_cast<SPImage *>(item); + if (image) { + TRACE(("image\n")); + sp_image_render(image, ctx); + } + } + } + } + } + } + } } } @@ -571,8 +586,9 @@ CairoRenderer::setStateForItem(CairoRenderContext *ctx, SPItem const *item) // This is so because we use the image's/(flow)text's transform for positioning // instead of explicitly specifying it and letting the renderer do the // transformation before rendering the item. - if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_IMAGE(item)) + if (dynamic_cast<SPText const *>(item) || dynamic_cast<SPFlowtext const *>(item) || dynamic_cast<SPImage const *>(item)) { state->parent_has_userspace = TRUE; + } TRACE(("setStateForItem opacity: %f\n", state->opacity)); } @@ -700,8 +716,8 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) TRACE(("BEGIN clip\n")); SPObject const *co = cp; for ( SPObject const *child = co->firstChild() ; child; child = child->getNext() ) { - if (SP_IS_ITEM(child)) { - SPItem const *item = SP_ITEM(child); + SPItem const *item = dynamic_cast<SPItem const *>(child); + if (item) { // combine transform of the item in clippath and the item using clippath: Geom::Affine tempmat = item->transform * ctx->getCurrentState()->item_transform; @@ -759,8 +775,8 @@ CairoRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask) TRACE(("BEGIN mask\n")); SPObject const *co = mask; for ( SPObject const *child = co->firstChild() ; child; child = child->getNext() ) { - if (SP_IS_ITEM(child)) { - SPItem const *item = SP_ITEM(child); + SPItem const *item = dynamic_cast<SPItem const *>(child); + if (item) { // TODO fix const correctness: renderItem(ctx, const_cast<SPItem*>(item)); } diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 398c9f061..ab0733848 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -66,7 +66,8 @@ latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, bool pageBoundingBox = true; if (exportId && strcmp(exportId, "")) { // we want to export the given item only - base = SP_ITEM(doc->getObjectById(exportId)); + base = dynamic_cast<SPItem *>(doc->getObjectById(exportId)); + g_assert(base != NULL); pageBoundingBox = exportCanvas; } else { @@ -225,26 +226,22 @@ LaTeXTextRenderer::writePostamble() fprintf(_stream, "%s", postamble); } -void -LaTeXTextRenderer::sp_group_render(SPItem *item) +void LaTeXTextRenderer::sp_group_render(SPGroup *group) { - SPGroup *group = SP_GROUP(item); - GSList *l = g_slist_reverse(group->childList(false)); while (l) { - SPObject *o = SP_OBJECT (l->data); - if (SP_IS_ITEM(o)) { - renderItem (SP_ITEM (o)); + SPObject *o = reinterpret_cast<SPObject *>(l->data); + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { + renderItem(item); } l = g_slist_remove (l, o); } } -void -LaTeXTextRenderer::sp_use_render(SPItem *item) +void LaTeXTextRenderer::sp_use_render(SPUse *use) { bool translated = false; - SPUse *use = SP_USE(item); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed)); @@ -252,8 +249,9 @@ LaTeXTextRenderer::sp_use_render(SPItem *item) translated = true; } - if (use->child && SP_IS_ITEM(use->child)) { - renderItem(SP_ITEM(use->child)); + SPItem *childItem = dynamic_cast<SPItem *>(use->child); + if (childItem) { + renderItem(childItem); } if (translated) { @@ -261,16 +259,14 @@ LaTeXTextRenderer::sp_use_render(SPItem *item) } } -void -LaTeXTextRenderer::sp_text_render(SPItem *item) +void LaTeXTextRenderer::sp_text_render(SPText *textobj) { // Only PDFLaTeX supports importing a single page of a graphics file, // so only PDF backend gets interleaved text/graphics if (_pdflatex && _omittext_state == GRAPHIC_ON_TOP) _omittext_state = NEW_PAGE_ON_GRAPHIC; - SPText *textobj = SP_TEXT (item); - SPStyle *style = item->style; + SPStyle *style = textobj->style; // get position and alignment // Align vertically on the baseline of the font (retreived from the anchor point) @@ -312,7 +308,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) } // get rotation - Geom::Affine i2doc = item->i2doc_affine(); + Geom::Affine i2doc = textobj->i2doc_affine(); Geom::Affine wotransl = i2doc.withoutTranslation(); double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); bool has_rotation = !Geom::are_near(degrees,0.); @@ -336,11 +332,11 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) // Walk through all spans in the text object. // Write span strings to LaTeX, associated with font weight and style. - Inkscape::Text::Layout const &layout = *(te_get_layout (item)); + Inkscape::Text::Layout const &layout = *(te_get_layout (textobj)); for (Inkscape::Text::Layout::iterator li = layout.begin(), le = layout.end(); li != le; li.nextStartOfSpan()) { - SPStyle const &spanstyle = *(sp_te_style_at_position (item, li)); + SPStyle const &spanstyle = *(sp_te_style_at_position (textobj, li)); bool is_bold = false, is_italic = false, is_oblique = false; if (spanstyle.font_weight.computed == SP_CSS_FONT_WEIGHT_500 || @@ -367,7 +363,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) Inkscape::Text::Layout::iterator ln = li; ln.nextStartOfSpan(); - Glib::ustring uspanstr = sp_te_get_string_multiline (item, li, ln); + Glib::ustring uspanstr = sp_te_get_string_multiline (textobj, li, ln); const gchar *spanstr = uspanstr.c_str(); if (!spanstr) { continue; @@ -394,8 +390,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) fprintf(_stream, "%s", os.str().c_str()); } -void -LaTeXTextRenderer::sp_flowtext_render(SPItem * item) +void LaTeXTextRenderer::sp_flowtext_render(SPFlowtext *flowtext) { /* Flowtext is possible by using a minipage! :) @@ -407,16 +402,15 @@ Flowing in rectangle is possible, not in arb shape. if (_pdflatex && _omittext_state == GRAPHIC_ON_TOP) _omittext_state = NEW_PAGE_ON_GRAPHIC; - SPFlowtext *flowtext = SP_FLOWTEXT(item); - SPStyle *style = item->style; + SPStyle *style = flowtext->style; SPItem *frame_item = flowtext->get_frame(NULL); - if (!frame_item || !SP_IS_RECT(frame_item)) { + SPRect *frame = dynamic_cast<SPRect *>(frame_item); + if (!frame_item || !frame) { g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text."); return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think } - SPRect *frame = SP_RECT(frame_item); Geom::Rect framebox = frame->getRect() * transform(); // get position and alignment @@ -460,7 +454,7 @@ Flowing in rectangle is possible, not in arb shape. } // get rotation - Geom::Affine i2doc = item->i2doc_affine(); + Geom::Affine i2doc = flowtext->i2doc_affine(); Geom::Affine wotransl = i2doc.withoutTranslation(); double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); bool has_rotation = !Geom::are_near(degrees,0.); @@ -485,11 +479,11 @@ Flowing in rectangle is possible, not in arb shape. // Walk through all spans in the text object. // Write span strings to LaTeX, associated with font weight and style. - Inkscape::Text::Layout const &layout = *(te_get_layout (item)); + Inkscape::Text::Layout const &layout = *(te_get_layout(flowtext)); for (Inkscape::Text::Layout::iterator li = layout.begin(), le = layout.end(); li != le; li.nextStartOfSpan()) { - SPStyle const &spanstyle = *(sp_te_style_at_position (item, li)); + SPStyle const &spanstyle = *(sp_te_style_at_position(flowtext, li)); bool is_bold = false, is_italic = false, is_oblique = false; if (spanstyle.font_weight.computed == SP_CSS_FONT_WEIGHT_500 || @@ -516,7 +510,7 @@ Flowing in rectangle is possible, not in arb shape. Inkscape::Text::Layout::iterator ln = li; ln.nextStartOfSpan(); - Glib::ustring uspanstr = sp_te_get_string_multiline (item, li, ln); + Glib::ustring uspanstr = sp_te_get_string_multiline(flowtext, li, ln); const gchar *spanstr = uspanstr.c_str(); if (!spanstr) { continue; @@ -558,22 +552,36 @@ LaTeXTextRenderer::sp_item_invoke_render(SPItem *item) return; } - if (SP_IS_ROOT(item)) { - return sp_root_render(SP_ROOT(item)); - } else if (SP_IS_GROUP(item)) { - return sp_group_render(item); - } else if (SP_IS_USE(item)) { - sp_use_render(item); - } else if (SP_IS_TEXT(item)) { - return sp_text_render(item); - } else if (SP_IS_FLOWTEXT(item)) { - return sp_flowtext_render(item); + SPRoot *root = dynamic_cast<SPRoot *>(item); + if (root) { + sp_root_render(root); } else { - // Only PDFLaTeX supports importing a single page of a graphics file, - // so only PDF backend gets interleaved text/graphics - if (_pdflatex && (_omittext_state == EMPTY || _omittext_state == NEW_PAGE_ON_GRAPHIC)) - writeGraphicPage(); - _omittext_state = GRAPHIC_ON_TOP; + SPGroup *group = dynamic_cast<SPGroup *>(item); + if (group) { + sp_group_render(group); + } else { + SPUse *use = dynamic_cast<SPUse *>(item); + if (use) { + sp_use_render(use); + } else { + SPText *text = dynamic_cast<SPText *>(item); + if (text) { + sp_text_render(text); + } else { + SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item); + if (flowtext) { + sp_flowtext_render(flowtext); + } else { + // Only PDFLaTeX supports importing a single page of a graphics file, + // so only PDF backend gets interleaved text/graphics + if (_pdflatex && (_omittext_state == EMPTY || _omittext_state == NEW_PAGE_ON_GRAPHIC)) { + writeGraphicPage(); + } + _omittext_state = GRAPHIC_ON_TOP; + } + } + } + } } } diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h index 77d12bc61..b9563b53b 100644 --- a/src/extension/internal/latex-text-renderer.h +++ b/src/extension/internal/latex-text-renderer.h @@ -23,6 +23,10 @@ class SPItem; class SPRoot; +class SPGroup; +class SPUse; +class SPText; +class SPFlowtext; namespace Inkscape { namespace Extension { @@ -73,10 +77,10 @@ protected: void sp_item_invoke_render(SPItem *item); void sp_root_render(SPRoot *item); - void sp_group_render(SPItem *item); - void sp_use_render(SPItem *item); - void sp_text_render(SPItem *item); - void sp_flowtext_render(SPItem *item); + void sp_group_render(SPGroup *group); + void sp_use_render(SPUse *use); + void sp_text_render(SPText *text); + void sp_flowtext_render(SPFlowtext *flowtext); }; } /* namespace Internal */ diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index a14220cfa..d945231fc 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -782,6 +782,8 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui // unlink and delete this dragger dragger->parent->draggers = g_list_remove (dragger->parent->draggers, dragger); + d_new->parent->draggers = g_list_remove (d_new->parent->draggers, dragger); + d_new->parent->selected = g_list_remove (d_new->parent->selected, dragger); delete dragger; // throw out delayed snap context diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index acb2be4da..9639096fb 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -34,20 +34,21 @@ #include "helper/pixbuf-ops.h" -// TODO look for copy-n-past duplication of this function: +// TODO look for copy-n-paste duplication of this function: /** * Hide all items that are not listed in list, recursively, skipping groups and defs. */ static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey) { - if ( SP_IS_ITEM(o) - && !SP_IS_DEFS(o) - && !SP_IS_ROOT(o) - && !SP_IS_GROUP(o) - && !SP_IS_USE(o) + SPItem *item = dynamic_cast<SPItem *>(o); + if ( item + && !dynamic_cast<SPDefs *>(item) + && !dynamic_cast<SPRoot *>(item) + && !dynamic_cast<SPGroup *>(item) + && !dynamic_cast<SPUse *>(item) && !g_slist_find(list, o) ) { - SP_ITEM(o)->invoke_hide(dkey); + item->invoke_hide(dkey); } // recurse diff --git a/src/inkscape-manifest-x64.xml b/src/inkscape-manifest-x64.xml index 38526cfe6..b5a6f11f2 100644 --- a/src/inkscape-manifest-x64.xml +++ b/src/inkscape-manifest-x64.xml @@ -1,5 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings> + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> + </windowsSettings> + </application> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 7eb53446f..bd1acbe46 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -704,6 +704,7 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){ // create the Layout::Character(s) double advance_width = new_glyph.width; if (newcluster){ + newcluster = 0; // find where the text ends for this log_cluster end_byte = it_span->start.iter_span->text_bytes; // Upper limit for(int next_glyph_index = glyph_index+1; next_glyph_index < unbroken_span.glyph_string->num_glyphs; next_glyph_index++){ @@ -751,18 +752,15 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){ log_cluster_size_chars--; } - if (newcluster){ - advance_width *= direction_sign; - if (new_span.direction != para.direction) { - counter_directional_width_remaining -= advance_width; - x -= advance_width; - x_in_span_last -= advance_width; - } else { - x += advance_width; - x_in_span_last += advance_width; - } + advance_width *= direction_sign; + if (new_span.direction != para.direction) { + counter_directional_width_remaining -= advance_width; + x -= advance_width; + x_in_span_last -= advance_width; + } else { + x += advance_width; + x_in_span_last += advance_width; } - newcluster = 0; } } else if (_flow._input_stream[unbroken_span.input_index]->Type() == CONTROL_CODE) { x += static_cast<InputStreamControlCode const *>(_flow._input_stream[unbroken_span.input_index])->width; @@ -1080,7 +1078,9 @@ void Layout::Calculator::_computeFontLineHeight(font_instance *font, double font bool compareGlyphWidth(const PangoGlyphInfo &a, const PangoGlyphInfo &b) { - return (a.geometry.width > b.geometry.width); + bool retval = false; + if ( b.geometry.width == 0 && (a.geometry.width > 0))retval = true; + return (retval); } @@ -1227,13 +1227,27 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const /* CAREFUL, within a log_cluster the order of glyphs may not map 1:1, or even in the same order, to the original unicode characters!!! Among - other things, diacritical mark glyphs can end up in front of the base - character. That makes determining kerning, even approximately, difficult - later on. To resolve this somewhat sort the glyphs with the same - log_cluster into descending order by width. In theory there should be 1 - that is nonzero, and N that are zero. The order of the zero width ones - does not matter. Sort the glyphs before copying. If ligatures other than with - Mark, nonspacing are ever implemented in Pango this will screw up, for instance + other things, diacritical mark glyphs can end up sequentially in front of the base + character glyph. That makes determining kerning, even approximately, difficult + later on. + + To resolve this to the extent possible sort the glyphs within the same + log_cluster into descending order by width in a special manner before copying. Diacritical marks + and similar have zero width and the glyph they modify has nonzero width. The order + of the zero width ones does not matter. A logical cluster is sorted into sequential order + [base] [zw_modifier1] [zw_modifier2] + where all the modifiers have zero width and the base does not. This works for languages like Hebrew. + + Pango also creates log clusters for languages like Telugu having many glyphs with nonzero widths. + Since these are nonzero, their order is not modified. + + If some language mixes these modes, having a log cluster having something like + [base1] [zw_modifier1] [base2] [zw_modifier2] + the result will be incorrect: + base1] [base2] [zw_modifier1] [zw_modifier2] + + + If ligatures other than with Mark, nonspacing are ever implemented in Pango this will screw up, for instance changing "fi" to "if". */ if(j - i){ @@ -1258,6 +1272,7 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const while( (j < nglyphs-1) && (new_span.glyph_string->log_clusters[j+1] == new_span.glyph_string->log_clusters[i]) )j++; + /* see note in preceding section */ if(j - i){ std::sort(&(new_span.glyph_string->glyphs[i]), &(new_span.glyph_string->glyphs[j+1]), compareGlyphWidth); } diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index efb5ebc24..fd5bbfaef 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -481,6 +481,7 @@ public: from a call to appendText() then the optional \a text_iterator parameter is set to point to the actual character, otherwise \a text_iterator is unaltered. */ + // TODO FIXME a void* cookie is a very unsafe design, and C++ makes it unnecessary. void getSourceOfCharacter(iterator const &it, void **source_cookie, Glib::ustring::iterator *text_iterator = NULL) const; /** For latin text, the left side of the character, on the baseline */ diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 349caafd9..39420134b 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -413,13 +413,15 @@ bool Effect::isNodePointSelected(Geom::Point const &nodePoint) const { if (selectedNodesPoints.size() > 0) { + using Geom::X; + using Geom::Y; for (std::vector<Geom::Point>::const_iterator i = selectedNodesPoints.begin(); i != selectedNodesPoints.end(); ++i) { Geom::Point p = *i; - std::cout << p << "p\n"; - p[Geom::X] = Inkscape::Util::Quantity::convert(p[Geom::X], "px", *defaultUnit); - p[Geom::Y] = Inkscape::Util::Quantity::convert(p[Geom::Y], "px", *defaultUnit); - if (Geom::are_near(p, nodePoint, 0.01)) { + Geom::Affine transformCoordinate = sp_lpe_item->i2dt_affine(); + Geom::Point p2(nodePoint[X],nodePoint[Y]); + p2 *= transformCoordinate; + if (Geom::are_near(p, p2, 0.01)) { return true; } } diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index fdaeaf897..2bed90139 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -88,25 +88,12 @@ void LPEBSpline::doBeforeEffect (SPLPEItem const* /*lpeitem*/) } -void LPEBSpline::createAndApply(const char *name, SPDocument *doc, - SPItem *item) +void LPEBSpline::doOnApply(SPLPEItem const* lpeitem) { - if (!SP_IS_SHAPE(item)) { + if (!SP_IS_SHAPE(lpeitem)) { g_warning("LPE BSpline can only be applied to shapes (not groups)."); - } else { - // Path effect definition - Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect"); - repr->setAttribute("effect", name); - - doc->getDefs()->getRepr() - ->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute - const gchar *repr_id = repr->attribute("id"); - Inkscape::GC::release(repr); - - gchar *href = g_strdup_printf("#%s", repr_id); - SP_LPE_ITEM(item)->addPathEffect(href, true); - g_free(href); + SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + item->removeCurrentPathEffect(false); } } diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h index 8751a5720..a17c0c4ac 100644 --- a/src/live_effects/lpe-bspline.h +++ b/src/live_effects/lpe-bspline.h @@ -19,10 +19,10 @@ public: LPEBSpline(LivePathEffectObject *lpeobject); virtual ~LPEBSpline(); - virtual void createAndApply(const char *name, SPDocument *doc, SPItem *item); virtual LPEPathFlashType pathFlashType() const { return SUPPRESS_FLASH; } + virtual void doOnApply(SPLPEItem const* lpeitem); virtual void doEffect(SPCurve *curve); virtual void doBeforeEffect (SPLPEItem const* lpeitem); void drawHandle(Geom::Point p, double radiusHelperNodes); diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index e466093d3..51787e292 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -38,12 +38,6 @@ public: virtual Geom::Point knot_get() const; }; -class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity { -public: - KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; } // namespace CR @@ -52,6 +46,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0), rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 30.0), num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 5), + copiesTo360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copiesTo360", &wr, this, true), origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this, "Adjust the origin of the rotation"), dist_angle_handle(100) { @@ -59,6 +54,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : _provides_knotholder_entities = true; // register all your parameters here, so Inkscape knows which parameters this effect has: + registerParameter( dynamic_cast<Parameter *>(&copiesTo360) ); registerParameter( dynamic_cast<Parameter *>(&starting_angle) ); registerParameter( dynamic_cast<Parameter *>(&rotation_angle) ); registerParameter( dynamic_cast<Parameter *>(&num_copies) ); @@ -76,11 +72,13 @@ LPECopyRotate::~LPECopyRotate() void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { - SPCurve const *curve = SP_SHAPE(lpeitem)->_curve; + using namespace Geom; - A = *(curve->first_point()); - B = *(curve->last_point()); + original_bbox(lpeitem); + Point A(boundingbox_X.min(), boundingbox_Y.middle()); + Point B(boundingbox_X.max(), boundingbox_Y.middle()); + Point C(boundingbox_X.middle(), boundingbox_Y.middle()); origin.param_setValue(A); dir = unit_vector(B - A); @@ -95,7 +93,11 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle; - rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle)) * dist_angle_handle; + double rotation_angle_end = rotation_angle; + if(copiesTo360){ + rotation_angle_end = 360.0/(double)num_copies; + } + rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle_end)) * dist_angle_handle; A = pwd2_in.firstValue(); B = pwd2_in.lastValue(); @@ -107,7 +109,7 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p for (int i = 0; i < num_copies; ++i) { // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) - Rotate rot(-deg_to_rad(rotation_angle * i)); + Rotate rot(-deg_to_rad(rotation_angle_end * i)); Affine t = pre * rot * Translate(origin); output.concat(pwd2_in * t); } @@ -123,12 +125,12 @@ LPECopyRotate::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geo Path path(start_pos); path.appendNew<LineSegment>((Geom::Point) origin); path.appendNew<LineSegment>(rot_pos); - PathVector pathv; pathv.push_back(path); hp_vec.push_back(pathv); } + void LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) { { KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this); @@ -136,12 +138,6 @@ void LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *des _("Adjust the starting angle") ); knotholder->add(e); } - { - KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the rotation angle") ); - knotholder->add(e); - } }; namespace CR { @@ -168,26 +164,6 @@ KnotHolderEntityStartingAngle::knot_set(Geom::Point const &p, Geom::Point const sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); } -void -KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) -{ - LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - lpe->rotation_angle.param_set_value(rad_to_deg(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle); - if (state & GDK_SHIFT_MASK) { - lpe->dist_angle_handle = L2(lpe->B - lpe->A); - } else { - lpe->dist_angle_handle = L2(p - lpe->origin); - } - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - Geom::Point KnotHolderEntityStartingAngle::knot_get() const { @@ -195,13 +171,6 @@ KnotHolderEntityStartingAngle::knot_get() const return lpe->start_pos; } -Geom::Point -KnotHolderEntityRotationAngle::knot_get() const -{ - LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect); - return lpe->rot_pos; -} - } // namespace CR diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h index ca7aa269c..123c92cdd 100644 --- a/src/live_effects/lpe-copy_rotate.h +++ b/src/live_effects/lpe-copy_rotate.h @@ -16,6 +16,7 @@ #include "live_effects/effect.h" #include "live_effects/parameter/point.h" +#include "live_effects/lpegroupbbox.h" namespace Inkscape { namespace LivePathEffect { @@ -26,7 +27,7 @@ namespace CR { class KnotHolderEntityRotationAngle; } -class LPECopyRotate : public Effect { +class LPECopyRotate : public Effect, GroupBBoxEffect { public: LPECopyRotate(LivePathEffectObject *lpeobject); virtual ~LPECopyRotate(); @@ -37,7 +38,6 @@ public: /* the knotholder entity classes must be declared friends */ friend class CR::KnotHolderEntityStartingAngle; - friend class CR::KnotHolderEntityRotationAngle; void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); protected: @@ -47,6 +47,7 @@ private: ScalarParam starting_angle; ScalarParam rotation_angle; ScalarParam num_copies; + BoolParam copiesTo360; PointParam origin; diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index c491ea858..119759b87 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -79,7 +79,7 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : radius.param_set_range(0., infinity()); radius.param_set_increments(1, 1); radius.param_set_digits(4); - chamfer_steps.param_set_range(0, infinity()); + chamfer_steps.param_set_range(1, 999); chamfer_steps.param_set_increments(1, 1); chamfer_steps.param_set_digits(0); helper_size.param_set_range(0, infinity()); @@ -116,7 +116,7 @@ Gtk::Widget *LPEFilletChamfer::newWidget() } } else if (param->param_key == "chamfer_steps") { Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); - widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer)); + widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamferSubdivisions)); widg = widgRegistered; if (widg) { Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg); @@ -153,21 +153,26 @@ Gtk::Widget *LPEFilletChamfer::newWidget() ++it; } - - Gtk::VBox *buttonsContainer = Gtk::manage(new Gtk::VBox(true, 0)); + Gtk::HBox *filletContainer = Gtk::manage(new Gtk::HBox(true, 0)); Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet")))); fillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::fillet)); - buttonsContainer->pack_start(*fillet, true, true, 2); - Gtk::Button *inverse = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet")))); - inverse->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverse)); - buttonsContainer->pack_start(*inverse, true, true, 2); - + filletContainer->pack_start(*fillet, true, true, 2); + Gtk::Button *inverseFillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet")))); + inverseFillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseFillet)); + filletContainer->pack_start(*inverseFillet, true, true, 2); + + Gtk::HBox *chamferContainer = Gtk::manage(new Gtk::HBox(true, 0)); Gtk::Button *chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Chamfer")))); chamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer)); - buttonsContainer->pack_start(*chamfer, true, true, 2); - vbox->pack_start(*buttonsContainer, true, true, 2); + chamferContainer->pack_start(*chamfer, true, true, 2); + Gtk::Button *inverseChamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse chamfer")))); + inverseChamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseChamfer)); + chamferContainer->pack_start(*inverseChamfer, true, true, 2); + + vbox->pack_start(*filletContainer, true, true, 2); + vbox->pack_start(*chamferContainer, true, true, 2); return vbox; } @@ -232,17 +237,31 @@ void LPEFilletChamfer::fillet() doChangeType(path_from_piecewise(pwd2, tolerance), 1); } -void LPEFilletChamfer::inverse() +void LPEFilletChamfer::inverseFillet() { Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); doChangeType(path_from_piecewise(pwd2, tolerance), 2); } +void LPEFilletChamfer::chamferSubdivisions() +{ + fillet_chamfer_values.set_chamfer_steps(chamfer_steps); + Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); + doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 5000); +} + void LPEFilletChamfer::chamfer() { - fillet_chamfer_values.set_chamfer_steps(chamfer_steps + 3); + fillet_chamfer_values.set_chamfer_steps(chamfer_steps); Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); - doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3); + doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3000); +} + +void LPEFilletChamfer::inverseChamfer() +{ + fillet_chamfer_values.set_chamfer_steps(chamfer_steps); + Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); + doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 4000); } void LPEFilletChamfer::refreshKnots() @@ -333,6 +352,13 @@ void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_path toggle = false; } if (toggle) { + if(type >= 5000){ + if(filletChamferData[counter][Y] >= 3000 && filletChamferData[counter][Y] < 4000){ + type = type - 2000; + } else if (filletChamferData[counter][Y] >= 4000 && filletChamferData[counter][Y] < 5000){ + type = type - 1000; + } + } result.push_back(Point(filletChamferData[counter][X], type)); } else { result.push_back(filletChamferData[counter]); @@ -405,6 +431,8 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) fillet_chamfer_values.param_set_and_write_new_value(point); } else { g_warning("LPE Fillet can only be applied to shapes (not groups)."); + SPLPEItem * item = const_cast<SPLPEItem*>(lpeItem); + item->removeCurrentPathEffect(false); } } @@ -416,6 +444,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) } else { fillet_chamfer_values.set_helper_size(helper_size); } + fillet_chamfer_values.set_document_unit(defaultUnit); fillet_chamfer_values.set_use_distance(use_knot_distance); fillet_chamfer_values.set_unit(unit.get_abbreviation()); SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem) @@ -551,8 +580,10 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) } else { type = std::abs(filletChamferData[counter + 1][Y]); } - if (type >= 3) { - unsigned int chamferSubs = type-2; + if(are_near(middle_point(startArcPoint,endArcPoint),curve_it1->finalPoint(), 0.0001)){ + path_out.appendNew<Geom::LineSegment>(endArcPoint); + } else if (type >= 3000 && type < 4000) { + unsigned int chamferSubs = type-3000; Geom::Path path_chamfer; path_chamfer.start(path_out.finalPoint()); if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ @@ -566,6 +597,22 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) path_out.appendNew<Geom::LineSegment>(chamferStep); } path_out.appendNew<Geom::LineSegment>(endArcPoint); + } else if (type >= 4000 && type < 5000) { + unsigned int chamferSubs = type-4000; + Geom::Path path_chamfer; + path_chamfer.start(path_out.finalPoint()); + if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ + ccwToggle = ccwToggle?0:1; + path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); + }else{ + path_chamfer.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); + } + double chamfer_stepsTime = 1.0/chamferSubs; + for(unsigned int i = 1; i < chamferSubs; i++){ + Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); + path_out.appendNew<Geom::LineSegment>(chamferStep); + } + path_out.appendNew<Geom::LineSegment>(endArcPoint); } else if (type == 2) { if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ ccwToggle = ccwToggle?0:1; @@ -573,7 +620,7 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) }else{ path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); } - } else { + } else if (type == 1){ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); } else { diff --git a/src/live_effects/lpe-fillet-chamfer.h b/src/live_effects/lpe-fillet-chamfer.h index e3589197c..0d6a1ff17 100644 --- a/src/live_effects/lpe-fillet-chamfer.h +++ b/src/live_effects/lpe-fillet-chamfer.h @@ -56,8 +56,10 @@ public: void toggleHide(); void toggleFlexFixed(); void chamfer(); + void chamferSubdivisions(); + void inverseChamfer(); void fillet(); - void inverse(); + void inverseFillet(); void updateFillet(); void doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power); void doChangeType(std::vector<Geom::Path> const& original_pathv, int type); diff --git a/src/live_effects/lpe-perspective_path.cpp b/src/live_effects/lpe-perspective_path.cpp index 8097de783..901519b4f 100644 --- a/src/live_effects/lpe-perspective_path.cpp +++ b/src/live_effects/lpe-perspective_path.cpp @@ -23,7 +23,7 @@ #include "knot-holder-entity.h" #include "knotholder.h" #include "desktop.h" - +#include <util/units.h> #include "inkscape.h" #include <2geom/path.h> @@ -44,6 +44,8 @@ public: } // namespace PP static Glib::ustring perspectiveID = _("First perspective"); + + LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) : Effect(lpeobject), // initialise your parameters here: @@ -62,36 +64,42 @@ LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) : concatenate_before_pwd2 = true; // don't split the path into its subpaths _provides_knotholder_entities = true; +} - unapply = false; - Persp3D *persp = persp3d_document_first_persp(lpeobject->document); +LPEPerspectivePath::~LPEPerspectivePath() +{ + +} +void +LPEPerspectivePath::doOnApply(SPLPEItem const* lpeitem) +{ + Persp3D *persp = persp3d_document_first_persp(lpeitem->document); if(persp == 0 ){ char *msg = _("You need a BOX 3D object"); Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true); dialog.run(); - unapply = true; - return; + SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + item->removeCurrentPathEffect(false); } - Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat; - pmat = pmat * SP_ACTIVE_DESKTOP->doc2dt(); - pmat.copy_tmat(tmat); } - -LPEPerspectivePath::~LPEPerspectivePath() -{ - -} - void LPEPerspectivePath::doBeforeEffect (SPLPEItem const* lpeitem) { original_bbox(lpeitem, true); - if(unapply){ - SP_LPE_ITEM(lpeitem)->removeCurrentPathEffect(false); + SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + Persp3D *persp = persp3d_document_first_persp(lpeitem->document); + if(persp == 0 ){ + char *msg = _("You need a BOX 3D object"); + Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_INFO, + Gtk::BUTTONS_OK, true); + dialog.run(); return; } - SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); + Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat; + Geom::Affine doc2d = Geom::Scale(1, -1) * Geom::Translate(0, item->document->getHeight().value("px")); + pmat = pmat * doc2d; + pmat.copy_tmat(tmat); item->apply_to_clippath(item); item->apply_to_mask(item); } diff --git a/src/live_effects/lpe-perspective_path.h b/src/live_effects/lpe-perspective_path.h index 6ccac4a51..c4ddf1853 100644 --- a/src/live_effects/lpe-perspective_path.h +++ b/src/live_effects/lpe-perspective_path.h @@ -33,9 +33,8 @@ class LPEPerspectivePath : public Effect, GroupBBoxEffect { public: LPEPerspectivePath(LivePathEffectObject *lpeobject); virtual ~LPEPerspectivePath(); - virtual void doBeforeEffect (SPLPEItem const* lpeitem); - + virtual void doOnApply(SPLPEItem const* lpeitem); virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in); virtual void refresh(Gtk::Entry* perspective); @@ -53,8 +52,6 @@ private: ScalarParam offsety; BoolParam uses_plane_xy; // there are all kinds of parameters. Check the /live_effects/parameter directory which types exist! - - bool unapply; Geom::Point orig; LPEPerspectivePath(const LPEPerspectivePath&); diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp index 31d996ad0..7d8c8e9b0 100644 --- a/src/live_effects/parameter/filletchamferpointarray.cpp +++ b/src/live_effects/parameter/filletchamferpointarray.cpp @@ -354,6 +354,11 @@ void FilletChamferPointArrayParam::set_pwd2( last_pwd2_normal = pwd2_normal_in; } +void FilletChamferPointArrayParam::set_document_unit(Glib::ustring const * value_document_unit) +{ + documentUnit = value_document_unit; +} + void FilletChamferPointArrayParam::set_helper_size(int hs) { helper_size = hs; @@ -688,28 +693,6 @@ void FilletChamferPointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, knot_mode = mode; knot_color = color; } -/* -class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity { -public: - FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam -*p, unsigned int index); - virtual ~FilletChamferPointArrayParamKnotHolderEntity() {} - - virtual void knot_set(Point const &p, Point const &origin, guint state); - virtual Point knot_get() const; - virtual void knot_click(guint state); - virtual void knot_doubleclicked(guint state); - - /Checks whether the index falls within the size of the parameter's vector/ - bool valid_index(unsigned int index) const { - return (_pparam->_vector.size() > index); - }; - -private: - FilletChamferPointArrayParam *_pparam; - unsigned int _index; -}; -/*/ FilletChamferPointArrayParamKnotHolderEntity:: FilletChamferPointArrayParamKnotHolderEntity( @@ -718,18 +701,17 @@ FilletChamferPointArrayParamKnotHolderEntity( void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p, Point const &/*origin*/, - guint /*state*/) + guint state) { using namespace Geom; if (!valid_index(_index)) { return; } - /// @todo how about item transforms??? Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2(); - //todo: add snapping - //Geom::Point const s = snap_knot_position(p, state); double t = nearest_point(p, pwd2[_index]); + Geom::Point const s = snap_knot_position(pwd2[_index].valueAt(t), state); + t = nearest_point(s, pwd2[_index]); if (t == 1) { t = 0.9999; } @@ -772,13 +754,21 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) }else{ using namespace Geom; int type = (int)_pparam->_vector.at(_index)[Y]; - + if (type >=3000 && type < 4000){ + type = 3; + } + if (type >=4000 && type < 5000){ + type = 4; + } switch(type){ case 1: type = 2; break; case 2: - type = _pparam->chamfer_steps; + type = _pparam->chamfer_steps + 3000; + break; + case 3: + type = _pparam->chamfer_steps + 4000; break; default: type = 1; @@ -788,8 +778,12 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) _pparam->param_set_and_write_new_value(_pparam->_vector); sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); const gchar *tip; - if (type >= 3) { - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + if (type >=3000 && type < 4000){ + tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + "<b>Shift+Click</b> open dialog, " + "<b>Ctrl+Alt+Click</b> reset"); + } else if (type >=4000 && type < 5000) { + tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); } else if (type == 2) { @@ -819,7 +813,7 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) bool aprox = (A[0].degreesOfFreedom() != 2 || B[0].degreesOfFreedom() != 2) && !_pparam->use_distance?true:false; Geom::Point offset = Geom::Point(xModified, _pparam->_vector.at(_index).y()); Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog( - this->desktop, offset, this, _pparam->unit, _pparam->use_distance, aprox); + this->desktop, offset, this, _pparam->unit, _pparam->use_distance, aprox, _pparam->documentUnit); } } @@ -845,8 +839,12 @@ void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, continue; } const gchar *tip; - if (_vector[i][Y] >= 3) { - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + if (_vector[i][Y] >=3000 && _vector[i][Y] < 4000){ + tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toogle type, " + "<b>Shift+Click</b> open dialog, " + "<b>Ctrl+Alt+Click</b> reset"); + } else if (_vector[i][Y] >=4000 && _vector[i][Y] < 5000) { + tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toogle type, " "<b>Shift+Click</b> open dialog, " "<b>Ctrl+Alt+Click</b> reset"); } else if (_vector[i][Y] == 2) { diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h index 1dd31d6d4..6e5cce353 100644 --- a/src/live_effects/parameter/filletchamferpointarray.h +++ b/src/live_effects/parameter/filletchamferpointarray.h @@ -53,6 +53,7 @@ public: virtual void set_helper_size(int hs); virtual void set_use_distance(bool use_knot_distance); virtual void set_chamfer_steps(int value_chamfer_steps); + virtual void set_document_unit(Glib::ustring const * value_document_unit); virtual void set_unit(const gchar *abbr); virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); @@ -89,6 +90,7 @@ private: int chamfer_steps; bool use_distance; const gchar *unit; + Glib::ustring const * documentUnit; Geom::PathVector hp; Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2; diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 2b29814b0..338f91463 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -91,7 +91,8 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, for ( SPObject *o = parent->firstChild(); o; o = o->getNext() ) { g_assert(dt != NULL); - if (SP_IS_ITEM(o) && !(dt->itemIsHidden(SP_ITEM(o)) && !clip_or_mask)) { + SPItem *item = dynamic_cast<SPItem *>(o); + if (item && !(dt->itemIsHidden(item) && !clip_or_mask)) { // Snapping to items in a locked layer is allowed // Don't snap to hidden objects, unless they're a clipped path or a mask /* See if this item is on the ignore list */ @@ -104,23 +105,22 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, } if (it == NULL || i == it->end()) { - SPItem *item = SP_ITEM(o); if (item) { if (!clip_or_mask) { // cannot clip or mask more than once // The current item is not a clipping path or a mask, but might // still be the subject of clipping or masking itself ; if so, then // we should also consider that path or mask for snapping to - SPObject *obj = SP_OBJECT(item->clip_ref ? item->clip_ref->getObject() : NULL); + SPObject *obj = item->clip_ref ? item->clip_ref->getObject() : NULL; if (obj && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_CLIP)) { _findCandidates(obj, it, false, bbox_to_snap, true, item->i2doc_affine()); } - obj = SP_OBJECT(item->mask_ref ? item->mask_ref->getObject() : NULL); + obj = item->mask_ref ? item->mask_ref->getObject() : NULL; if (obj && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_MASK)) { _findCandidates(obj, it, false, bbox_to_snap, true, item->i2doc_affine()); } } - if (SP_IS_GROUP(o)) { + if (dynamic_cast<SPGroup *>(item)) { _findCandidates(o, it, false, bbox_to_snap, clip_or_mask, additional_affine); } else { Geom::OptRect bbox_of_item; @@ -197,8 +197,10 @@ void Inkscape::ObjectSnapper::_collectNodes(SnapSourceType const &t, for (std::vector<SnapCandidateItem>::const_iterator i = _candidates->begin(); i != _candidates->end(); ++i) { //Geom::Affine i2doc(Geom::identity()); SPItem *root_item = (*i).item; - if (SP_IS_USE((*i).item)) { - root_item = SP_USE((*i).item)->root(); + + SPUse *use = dynamic_cast<SPUse *>((*i).item); + if (use) { + root_item = use->root(); } g_return_if_fail(root_item); @@ -382,9 +384,10 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, Geom::Affine i2doc(Geom::identity()); SPItem *root_item = NULL; /* We might have a clone at hand, so make sure we get the root item */ - if (SP_IS_USE((*i).item)) { - i2doc = SP_USE((*i).item)->get_root_transform(); - root_item = SP_USE((*i).item)->root(); + SPUse *use = dynamic_cast<SPUse *>((*i).item); + if (use) { + i2doc = use->get_root_transform(); + root_item = use->root(); g_return_if_fail(root_item); } else { i2doc = (*i).item->i2doc_affine(); @@ -396,7 +399,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, //Add the item's path to snap to if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION, SNAPTARGET_TEXT_BASELINE)) { if (p_is_other || p_is_a_node || (!_snapmanager->snapprefs.getStrictSnapping() && p_is_a_bbox)) { - if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) { + if (dynamic_cast<SPText *>(root_item) || dynamic_cast<SPFlowtext *>(root_item)) { if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_TEXT_BASELINE)) { // Snap to the text baseline Text::Layout const *layout = te_get_layout(static_cast<SPItem *>(root_item)); @@ -411,15 +414,17 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, // the CPU, so we'll only snap to paths having no more than 500 nodes // This also leads to a lag of approx. 500 msec (in my lousy test set-up). bool very_complex_path = false; - if (SP_IS_PATH(root_item)) { - very_complex_path = SP_PATH(root_item)->nodesInPath() > 500; + SPPath *path = dynamic_cast<SPPath *>(root_item); + if (path) { + very_complex_path = path->nodesInPath() > 500; } if (!very_complex_path && root_item && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION)) { SPCurve *curve = NULL; - if (SP_IS_SHAPE(root_item)) { - curve = SP_SHAPE(root_item)->getCurve(); - }/* else if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) { + SPShape *shape = dynamic_cast<SPShape *>(root_item); + if (shape) { + curve = shape->getCurve(); + }/* else if (dynamic_cast<SPText *>(root_item) || dynamic_cast<SPFlowtext *>(root_item)) { curve = te_get_layout(root_item)->convertToCurves(); }*/ if (curve) { @@ -711,10 +716,11 @@ void Inkscape::ObjectSnapper::freeSnap(IntermSnapResults &isr, * That path must not be ignored however when snapping to the paths, so we add it here * manually when applicable */ - SPPath *path = NULL; + SPPath const *path = NULL; if (it != NULL) { - if (it->size() == 1 && SP_IS_PATH(*it->begin())) { - path = SP_PATH(*it->begin()); + SPPath const *tmpPath = dynamic_cast<SPPath const *>(*it->begin()); + if ((it->size() == 1) && tmpPath) { + path = tmpPath; } // else: *it->begin() might be a SPGroup, e.g. when editing a LPE of text that has been converted to a group of paths // as reported in bug #356743. In that case we can just ignore it, i.e. not snap to this item } diff --git a/src/object-test.h b/src/object-test.h new file mode 100644 index 000000000..d6a9dbbd3 --- /dev/null +++ b/src/object-test.h @@ -0,0 +1,233 @@ +#ifndef SEEN_OBJECT_TEST_H +#define SEEN_OBJECT_TEST_H + +#include <cassert> +#include <ctime> +#include <cxxtest/TestSuite.h> +#include <string> +#include <vector> + +#include "document.h" +#include "sp-item-group.h" +#include "sp-object.h" +#include "sp-path.h" +#include "sp-root.h" +#include "xml/document.h" +#include "xml/node.h" + +class ObjectTest : public CxxTest::TestSuite +{ +public: + virtual ~ObjectTest() {} + + static ObjectTest *createSuite() { return new ObjectTest(); } + static void destroySuite(ObjectTest *suite) { delete suite; } + + void testObjects() + { + clock_t begin, end; + // Sample document + // svg:svg + // svg:defs + // svg:path + // svg:linearGradient + // svg:stop + // svg:filter + // svg:feGaussianBlur (feel free to implement for other filters) + // svg:clipPath + // svg:rect + // svg:g + // svg:use + // svg:circle + // svg:ellipse + // svg:text + // svg:polygon + // svg:polyline + // svg:image + // svg:line + + char const *docString = + "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n" + "<!-- just a comment -->\n" + "<title id=\"title\">SVG test</title>\n" + "<defs>\n" + " <path id=\"P\" d=\"M -21,-4 -5,0 -18,12 -3,4 -4,21 0,5 12,17 4,2 21,3 5,-1 17,-12 2,-4 3,-21 -1,-5 -12,-18 -4,-3z\"/>\n" + " <linearGradient id=\"LG\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n" + " <stop offset=\"0%\" style=\"stop-color:#ffff00;stop-opacity:1\"/>\n" + " <stop offset=\"100%\" style=\"stop-color:red;stop-opacity:1\"/>\n" + " </linearGradient>\n" + " <clipPath id=\"clip\" clipPathUnits=\"userSpaceOnUse\">\n" + " <rect x=\"10\" y=\"10\" width=\"100\" height=\"100\"/>\n" + " </clipPath>\n" + " <filter style=\"color-interpolation-filters:sRGB\" id=\"filter\" x=\"-0.15\" width=\"1.34\" y=\"0\" height=\"1\">\n" + " <feGaussianBlur stdDeviation=\"4.26\"/>\n" + " </filter>\n" + "</defs>\n" + + "<g id=\"G\" transform=\"skewX(10.5) translate(9,5)\">\n" + " <use id=\"U\" xlink:href=\"#P\" opacity=\"0.5\" fill=\"#1dace3\" transform=\"rotate(4)\"/>\n" + " <circle id=\"C\" cx=\"45.5\" cy=\"67\" r=\"23\" fill=\"#000\"/>\n" + " <ellipse id=\"E\" cx=\"200\" cy=\"70\" rx=\"85\" ry=\"55\" fill=\"url(#LG)\"/>\n" + " <text id=\"T\" fill=\"#fff\" style=\"font-size:45;font-family:Verdana\" x=\"150\" y=\"86\">TEST</text>\n" + " <polygon id=\"PG\" points=\"60,20 100,40 100,80 60,100 20,80 20,40\" clip-path=\"url(#clip)\" filter=\"url(#filter)\"/>\n" + " <polyline id=\"PL\" points=\"0,40 40,40 40,80 80,80 80,120 120,120 120,160\" style=\"fill:none;stroke:red;stroke-width:4\"/>\n" + " <image id=\"I\" xlink:href=\"data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE4MCIgd2lkdGg9IjUwMCI+PHBhdGggZD0iTTAsNDAgNDAsNDAgNDAs" // this is one line + "ODAgODAsODAgODAsMTIwIDEyMCwxMjAgMTIwLDE2MCIgc3R5bGU9ImZpbGw6d2hpdGU7c3Ryb2tlOnJlZDtzdHJva2Utd2lkdGg6NCIvPjwvc3ZnPgo=\"/>\n" + " <line id=\"L\" x1=\"20\" y1=\"100\" x2=\"100\" y2=\"20\" stroke=\"black\" stroke-width=\"2\"/>\n" + "</g>\n" + "</svg>\n"; + + begin = clock(); + SPDocument *doc = SPDocument::createNewDocFromMem(docString, strlen(docString), false); + end = clock(); + + assert(doc != NULL); // cannot continue if doc is null, abort! + assert(doc->getRoot() != NULL); + + SPRoot *root = doc->getRoot(); + assert(root->getRepr() != NULL); + assert(root->hasChildren()); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to construct the test document\n"; + + SPPath *path = dynamic_cast<SPPath *>(doc->getObjectById("P")); + testClones(path); + + SPGroup *group = dynamic_cast<SPGroup *>(doc->getObjectById("G")); + testGrouping(group); + + // Test parent behavior + SPObject *child = root->firstChild(); + assert(child != NULL); + TS_ASSERT(child->parent == root); + TS_ASSERT(child->document == doc); + TS_ASSERT(root->isAncestorOf(child)); + + // Test list behavior + SPObject *next = child->getNext(); + SPObject *prev = next; + TS_ASSERT(next->getPrev() == child); + prev = next; + next = next->getNext(); + while (next != NULL) { + // Walk the list + TS_ASSERT(next->getPrev() == prev); + prev = next; + next = next->getNext(); + } + TS_ASSERT(child->lastChild() == next); + + // Test hrefcount + TS_ASSERT(path->isReferenced()); + } + + void testClones(SPPath *path) + { + clock_t begin, end; + + assert(path != NULL); + + // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit. + Inkscape::XML::Node *node = path->getRepr(); + assert(node != NULL); + + Inkscape::XML::Document *xml_doc = node->document(); + + Inkscape::XML::Node *parent = node->parent(); + assert(parent != NULL); + + TS_TRACE("Benchmarking clones..."); + const size_t num_clones = 10000; + + std::string href(std::string("#") + std::string(path->getId())); + std::vector<Inkscape::XML::Node *> clones(num_clones, NULL); + + begin = clock(); + // Create num_clones clones of this path and stick them in the document + for (size_t i = 0; i < num_clones; ++i) { + Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); + Inkscape::GC::release(clone); + clone->setAttribute("xlink:href", href.c_str()); + parent->addChild(clone, node); + clones[i] = clone; + } + end = clock(); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_clones << " clones of a path\n"; + + begin = clock(); + // Remove those clones + for (size_t i = num_clones - 1; i >= 1; --i) { + parent->removeChild(clones[i]); + } + end = clock(); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_clones << " clones of a path\n"; + } + + void testGrouping(SPGroup *group) + { + clock_t begin, end; + + assert(group != NULL); + + // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit. + Inkscape::XML::Node *node = group->getRepr(); + assert(node != NULL); + + Inkscape::XML::Document *xml_doc = node->document(); + + TS_TRACE("Benchmarking groups..."); + const size_t num_elements = 10000; + + Inkscape::XML::Node *new_group = xml_doc->createElement("svg:g"); + Inkscape::GC::release(new_group); + node->addChild(new_group, NULL); + + std::vector<Inkscape::XML::Node *> elements(num_elements, NULL); + + begin = clock(); + for (size_t i = 0; i < num_elements; ++i) { + Inkscape::XML::Node *circle = xml_doc->createElement("svg:circle"); + Inkscape::GC::release(circle); + circle->setAttribute("cx", "2048"); + circle->setAttribute("cy", "1024"); + circle->setAttribute("r", "1.5"); + new_group->addChild(circle, NULL); + elements[i] = circle; + } + end = clock(); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_elements << " elements into a group\n"; + + SPGroup *n_group = dynamic_cast<SPGroup *>(group->get_child_by_repr(new_group)); + assert(n_group != NULL); + + begin = clock(); + sp_item_group_ungroup(n_group, NULL, false); + end = clock(); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to ungroup a <g> with " << num_elements << " elements\n"; + + begin = clock(); + // Remove those elements + for (size_t i = num_elements - 1; i >= 1; --i) { + elements[i]->parent()->removeChild(elements[i]); + } + end = clock(); + + std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_elements << " elements\n"; + } +}; +#endif // SEEN_OBJECT_TEST_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index b4f7ebdd7..406ea6da2 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -1643,7 +1643,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons item->doWriteTransform(item->getRepr(), move, &move, compensate); } else if (prefs_unmoved) { - //if (SP_IS_USE(sp_use_get_original(SP_USE(item)))) + //if (dynamic_cast<SPUse *>(sp_use_get_original(dynamic_cast<SPUse *>(item)))) // clone_move = Geom::identity(); Geom::Affine move = result * clone_move; item->doWriteTransform(item->getRepr(), move, &t, compensate); @@ -4186,7 +4186,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) { // Collect all clipped paths and masks within a single group Inkscape::XML::Node *copy = SP_OBJECT(child)->getRepr()->duplicate(xml_doc); - if(copy->attribute("inkscape:original-d")) + if(copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) { copy->setAttribute("d", copy->attribute("inkscape:original-d")); } diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 1cb96fed0..f7814fd57 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -5,6 +5,7 @@ * MenTaLguY <mental@rydia.net> * bulia byak <buliabyak@users.sf.net> * Abhishek Sharma + * Jon A. Cruz <jon@joncruz.org> * * Copyright (C) 2004-2006 Authors * @@ -46,11 +47,14 @@ char* collect_terms (GSList *items) bool first = true; for (GSList *i = (GSList *)items; i != NULL; i = i->next) { - const char *term = SP_ITEM(i->data)->displayName(); - if (term != NULL && g_slist_find (check, term) == NULL) { - check = g_slist_prepend (check, (void *) term); - ss << (first ? "" : ", ") << "<b>" << term << "</b>"; - first = false; + SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(i->data)); + if (item) { + const char *term = item->displayName(); + if (term != NULL && g_slist_find (check, term) == NULL) { + check = g_slist_prepend (check, (void *) term); + ss << (first ? "" : ", ") << "<b>" << term << "</b>"; + first = false; + } } } return g_strdup(ss.str().c_str()); @@ -62,10 +66,13 @@ static int count_terms (GSList *items) GSList *check = NULL; int count=0; for (GSList *i = (GSList *)items; i != NULL; i = i->next) { - const char *term = SP_ITEM(i->data)->displayName(); - if (term != NULL && g_slist_find (check, term) == NULL) { - check = g_slist_prepend (check, (void *) term); - count++; + SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(i->data)); + if (item) { + const char *term = item->displayName(); + if (term != NULL && g_slist_find (check, term) == NULL) { + check = g_slist_prepend (check, (void *) term); + count++; + } } } return count; @@ -76,8 +83,10 @@ static int count_filtered (GSList *items) { int count=0; for (GSList *i = items; i != NULL; i = i->next) { - SPItem *item = SP_ITEM(i->data); - count += item->isFiltered(); + SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>((i->data))); + if (item) { + count += item->isFiltered(); + } } return count; } @@ -118,7 +127,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select if (!items) { // no items _context.set(Inkscape::NORMAL_MESSAGE, _when_nothing); } else { - SPItem *item = SP_ITEM(items->data); + SPItem *item = dynamic_cast<SPItem *>(reinterpret_cast<SPObject *>(items->data)); + g_assert(item != NULL); SPObject *layer = selection->layers()->layerForObject(item); SPObject *root = selection->layers()->currentRoot(); @@ -181,30 +191,41 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select if (!items->next) { // one item char *item_desc = item->detailedDescription(); - if (SP_IS_USE(item) && SP_IS_SYMBOL(item->firstChild())) { + bool isUse = dynamic_cast<SPUse *>(item) != NULL; + if (isUse && dynamic_cast<SPSymbol *>(item->firstChild())) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Convert symbol to group to edit"), _when_selected); - } else if (SP_IS_SYMBOL(item)) { + } else if (dynamic_cast<SPSymbol *>(item)) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.", item_desc, in_phrase, _("Remove from symbols tray to edit symbol")); - } else if (SP_IS_USE(item) || (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref)) { - _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", - item_desc, in_phrase, - _("Use <b>Shift+D</b> to look up original"), _when_selected); - } else if (SP_IS_TEXT_TEXTPATH(item)) { - _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", - item_desc, in_phrase, - _("Use <b>Shift+D</b> to look up path"), _when_selected); - } else if (SP_IS_FLOWTEXT(item) && !SP_FLOWTEXT(item)->has_internal_frame()) { - _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", - item_desc, in_phrase, - _("Use <b>Shift+D</b> to look up frame"), _when_selected); } else { - _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.", - item_desc, in_phrase, _when_selected); + SPOffset *offset = (isUse) ? NULL : dynamic_cast<SPOffset *>(item); + if (isUse || (offset && offset->sourceHref)) { + _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", + item_desc, in_phrase, + _("Use <b>Shift+D</b> to look up original"), _when_selected); + } else { + SPText *text = dynamic_cast<SPText *>(item); + if (text && text->firstChild() && dynamic_cast<SPText *>(text->firstChild())) { + _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", + item_desc, in_phrase, + _("Use <b>Shift+D</b> to look up path"), _when_selected); + } else { + SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item); + if (flowtext && !flowtext->has_internal_frame()) { + _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", + item_desc, in_phrase, + _("Use <b>Shift+D</b> to look up frame"), _when_selected); + } else { + _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.", + item_desc, in_phrase, _when_selected); + } + } + } } + g_free(item_desc); } else { // multiple items int objcount = g_slist_length((GSList *)items); diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index b5c6e4af8..a74d4687d 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -604,7 +604,7 @@ void SPGenericEllipse::update_patheffect(bool write) if (write) { Inkscape::XML::Node *repr = this->getRepr(); - if (this->_curve != NULL) { + if (this->_curve != NULL && type == SP_GENERIC_ELLIPSE_ARC) { gchar *str = sp_svg_write_path(this->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); @@ -642,8 +642,8 @@ bool SPGenericEllipse::set_elliptical_path_attribute(Inkscape::XML::Node *repr) // Make sure our pathvector is up to date. this->set_shape(); - if (this->getCurve() != NULL) { - gchar* d = sp_svg_write_path(this->getCurve()->get_pathvector()); + if (_curve != NULL) { + gchar* d = sp_svg_write_path(_curve->get_pathvector()); repr->setAttribute("d", d); diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index 32d3b0f60..580945d74 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -85,12 +85,14 @@ void SPFlowregion::update(SPCtx *ctx, unsigned int flags) { l = g_slist_reverse(l); while (l) { - SPObject *child = SP_OBJECT(l->data); + SPObject *child = reinterpret_cast<SPObject *>(l->data); + g_assert(child != NULL); l = g_slist_remove(l, child); + SPItem *item = dynamic_cast<SPItem *>(child); if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - if (SP_IS_ITEM (child)) { - SPItem const &chi = *SP_ITEM(child); + if (item) { + SPItem const &chi = *item; cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; child->updateDisplay((SPCtx *)&cctx, childflags); @@ -138,7 +140,8 @@ void SPFlowregion::modified(guint flags) { l = g_slist_reverse(l); while (l) { - SPObject *child = SP_OBJECT(l->data); + SPObject *child = reinterpret_cast<SPObject *>(l->data); + g_assert(child != NULL); l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { @@ -157,7 +160,7 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc GSList *l = NULL; for ( SPObject *child = this->firstChild() ; child; child = child->getNext() ) { - if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) { + if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) { Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); if (crepr) { @@ -174,7 +177,7 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc } else { for ( SPObject *child = this->firstChild() ; child; child = child->getNext() ) { - if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) { + if ( !dynamic_cast<SPTitle *>(child) && !dynamic_cast<SPDesc *>(child) ) { child->updateRepr(flags); } } @@ -240,12 +243,14 @@ void SPFlowregionExclude::update(SPCtx *ctx, unsigned int flags) { l = g_slist_reverse (l); while (l) { - SPObject *child = SP_OBJECT(l->data); + SPObject *child = reinterpret_cast<SPObject *>(l->data); + g_assert(child != NULL); l = g_slist_remove(l, child); if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - if (SP_IS_ITEM (child)) { - SPItem const &chi = *SP_ITEM(child); + SPItem *item = dynamic_cast<SPItem *>(child); + if (item) { + SPItem const &chi = *item; cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; child->updateDisplay((SPCtx *)&cctx, flags); @@ -290,7 +295,8 @@ void SPFlowregionExclude::modified(guint flags) { l = g_slist_reverse (l); while (l) { - SPObject *child = SP_OBJECT(l->data); + SPObject *child = reinterpret_cast<SPObject *>(l->data); + g_assert(child != NULL); l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { @@ -363,20 +369,28 @@ static void GetDest(SPObject* child,Shape **computed) SPCurve *curve=NULL; Geom::Affine tr_mat; - SPObject* u_child=child; - if ( SP_IS_USE(u_child) ) { - u_child=SP_USE(u_child)->child; - tr_mat = SP_ITEM(u_child)->getRelativeTransform(child->parent); - } else { - tr_mat = SP_ITEM(u_child)->transform; - } - if ( SP_IS_SHAPE (u_child) ) { - if (!(SP_SHAPE(u_child)->_curve)) - SP_SHAPE (u_child)->set_shape (); - curve = SP_SHAPE (u_child)->getCurve (); - } else if ( SP_IS_TEXT (u_child) ) { - curve = SP_TEXT (u_child)->getNormalizedBpath (); - } + SPObject* u_child = child; + SPItem *item = dynamic_cast<SPItem *>(u_child); + g_assert(item != NULL); + SPUse *use = dynamic_cast<SPUse *>(item); + if ( use ) { + u_child = use->child; + tr_mat = use->getRelativeTransform(child->parent); + } else { + tr_mat = item->transform; + } + SPShape *shape = dynamic_cast<SPShape *>(u_child); + if ( shape ) { + if (!(shape->_curve)) { + shape->set_shape(); + } + curve = shape->getCurve(); + } else { + SPText *text = dynamic_cast<SPText *>(u_child); + if ( text ) { + curve = text->getNormalizedBpath(); + } + } if ( curve ) { Path* temp=new Path; diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 72fe86daf..766026980 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -86,12 +86,14 @@ void SPFlowtext::update(SPCtx* ctx, unsigned int flags) { l = g_slist_reverse(l); while (l) { - SPObject *child = SP_OBJECT(l->data); + SPObject *child = reinterpret_cast<SPObject *>(l->data); + g_assert(child != NULL); l = g_slist_remove(l, child); if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - if (SP_IS_ITEM(child)) { - SPItem const &chi = *SP_ITEM(child); + SPItem *item = dynamic_cast<SPItem *>(child); + if (item) { + SPItem const &chi = *item; cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; child->updateDisplay((SPCtx *)&cctx, childflags); @@ -129,19 +131,18 @@ void SPFlowtext::modified(unsigned int flags) { // FIXME: the below stanza is copied over from sp_text_modified, consider factoring it out if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) { - SPFlowtext *text = SP_FLOWTEXT(this); - Geom::OptRect pbox = text->geometricBounds(); + Geom::OptRect pbox = geometricBounds(); - for (SPItemView* v = text->display; v != NULL; v = v->next) { + for (SPItemView* v = display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - text->_clearFlow(g); - g->setStyle(this->style); - text->layout.show(g, pbox); + _clearFlow(g); + g->setStyle(style); + layout.show(g, pbox); } } for ( SPObject *o = this->firstChild() ; o ; o = o->getNext() ) { - if (SP_IS_FLOWREGION(o)) { + if (dynamic_cast<SPFlowregion *>(o)) { region = o; break; } @@ -231,7 +232,7 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { Inkscape::XML::Node *c_repr = NULL; - if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) { + if ( dynamic_cast<SPFlowdiv *>(child) || dynamic_cast<SPFlowpara *>(child) || dynamic_cast<SPFlowregion *>(child) || dynamic_cast<SPFlowregionExclude *>(child)) { c_repr = child->updateRepr(doc, NULL, flags); } @@ -247,7 +248,7 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X } } else { for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { - if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child) ) { + if ( dynamic_cast<SPFlowdiv *>(child) || dynamic_cast<SPFlowpara *>(child) || dynamic_cast<SPFlowregion *>(child) || dynamic_cast<SPFlowregionExclude *>(child)) { child->updateRepr(flags); } } @@ -285,7 +286,7 @@ void SPFlowtext::print(SPPrintContext *ctx) { } const char* SPFlowtext::displayName() const { - if (SP_FLOWTEXT(this)->has_internal_frame()) { + if (has_internal_frame()) { return _("Flowed Text"); } else { return _("Linked Flowed Text"); @@ -293,7 +294,6 @@ const char* SPFlowtext::displayName() const { } gchar* SPFlowtext::description() const { - Inkscape::Text::Layout const &layout = SP_FLOWTEXT(this)->layout; int const nChars = layout.iteratorToCharIndex(layout.end()); char const *trunc = (layout.inputTruncated()) ? _(" [truncated]") : ""; @@ -346,12 +346,17 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, Inkscape::Text::Layout::OptionalTextTagAttrs pi; bool with_indent = false; - if (SP_IS_FLOWPARA(root)) { + if (dynamic_cast<SPFlowpara *>(root)) { // emulate par-indent with the first char's kern SPObject *t = root; - for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = t->parent){}; - if (SP_IS_FLOWTEXT(t)) { - double indent = SP_FLOWTEXT(t)->par_indent; + SPFlowtext *ft = NULL; + while (t && !ft) { + ft = dynamic_cast<SPFlowtext *>(t); + t = t->parent; + } + + if (ft) { + double indent = ft->par_indent; if (indent != 0) { with_indent = true; SVGLength sl; @@ -363,7 +368,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, } if (*pending_line_break_object) { - if (SP_IS_FLOWREGIONBREAK(*pending_line_break_object)) { + if (dynamic_cast<SPFlowregionbreak *>(*pending_line_break_object)) { layout.appendControlCode(Inkscape::Text::Layout::SHAPE_BREAK, *pending_line_break_object); } else { layout.appendControlCode(Inkscape::Text::Layout::PARAGRAPH_BREAK, *pending_line_break_object); @@ -372,9 +377,10 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, } for (SPObject *child = root->firstChild() ; child ; child = child->getNext() ) { - if (SP_IS_STRING(child)) { + SPString *str = dynamic_cast<SPString *>(child); + if (str) { if (*pending_line_break_object) { - if (SP_IS_FLOWREGIONBREAK(*pending_line_break_object)) + if (dynamic_cast<SPFlowregionbreak *>(*pending_line_break_object)) layout.appendControlCode(Inkscape::Text::Layout::SHAPE_BREAK, *pending_line_break_object); else { layout.appendControlCode(Inkscape::Text::Layout::PARAGRAPH_BREAK, *pending_line_break_object); @@ -382,31 +388,35 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, *pending_line_break_object = NULL; } if (with_indent) { - layout.appendText(SP_STRING(child)->string, root->style, child, &pi); + layout.appendText(str->string, root->style, child, &pi); } else { - layout.appendText(SP_STRING(child)->string, root->style, child); + layout.appendText(str->string, root->style, child); } - } else if (SP_IS_FLOWREGION(child)) { - std::vector<Shape*> const &computed = SP_FLOWREGION(child)->computed; - for (std::vector<Shape*>::const_iterator it = computed.begin() ; it != computed.end() ; ++it) { - shapes->push_back(Shape()); - if (exclusion_shape->hasEdges()) { - shapes->back().Booleen(*it, const_cast<Shape*>(exclusion_shape), bool_op_diff); - } else { - shapes->back().Copy(*it); + } else { + SPFlowregion *region = dynamic_cast<SPFlowregion *>(child); + if (region) { + std::vector<Shape*> const &computed = region->computed; + for (std::vector<Shape*>::const_iterator it = computed.begin() ; it != computed.end() ; ++it) { + shapes->push_back(Shape()); + if (exclusion_shape->hasEdges()) { + shapes->back().Booleen(*it, const_cast<Shape*>(exclusion_shape), bool_op_diff); + } else { + shapes->back().Copy(*it); + } + layout.appendWrapShape(&shapes->back()); } - layout.appendWrapShape(&shapes->back()); } - } - //XML Tree is being directly used while it shouldn't be. - else if (!SP_IS_FLOWREGIONEXCLUDE(child) && !sp_repr_is_meta_element(child->getRepr())) { - _buildLayoutInput(child, exclusion_shape, shapes, pending_line_break_object); + //Xml Tree is being directly used while it shouldn't be. + else if (!dynamic_cast<SPFlowregionExclude *>(child) && !sp_repr_is_meta_element(child->getRepr())) { + _buildLayoutInput(child, exclusion_shape, shapes, pending_line_break_object); + } } } - if (SP_IS_FLOWDIV(root) || SP_IS_FLOWPARA(root) || SP_IS_FLOWREGIONBREAK(root) || SP_IS_FLOWLINE(root)) { - if (!root->hasChildren()) + if (dynamic_cast<SPFlowdiv *>(root) || dynamic_cast<SPFlowpara *>(root) || dynamic_cast<SPFlowregionbreak *>(root) || dynamic_cast<SPFlowline *>(root)) { + if (!root->hasChildren()) { layout.appendText("", root->style, root); + } *pending_line_break_object = root; } } @@ -418,16 +428,13 @@ Shape* SPFlowtext::_buildExclusionShape() const for (SPObject *child = children ; child ; child = child->getNext() ) { // RH: is it right that this shouldn't be recursive? - if ( SP_IS_FLOWREGIONEXCLUDE(child) ) { - SPFlowregionExclude *c_child = SP_FLOWREGIONEXCLUDE(child); - - if ( c_child->computed && c_child->computed->hasEdges() ) { - if (shape->hasEdges()) { - shape_temp->Booleen(shape, c_child->computed, bool_op_union); - std::swap(shape, shape_temp); - } else { - shape->Copy(c_child->computed); - } + SPFlowregionExclude *c_child = dynamic_cast<SPFlowregionExclude *>(child); + if ( c_child && c_child->computed && c_child->computed->hasEdges() ) { + if (shape->hasEdges()) { + shape_temp->Booleen(shape, c_child->computed, bool_op_union); + std::swap(shape, shape_temp); + } else { + shape->Copy(c_child->computed); } } } @@ -514,24 +521,23 @@ Inkscape::XML::Node *SPFlowtext::getAsText() sp_repr_set_svg_double(line_tspan, "y", anchor_point[Geom::Y]); } - SPObject *source_obj = 0; void *rawptr = 0; Glib::ustring::iterator span_text_start_iter; this->layout.getSourceOfCharacter(it, &rawptr, &span_text_start_iter); - source_obj = SP_OBJECT (rawptr); - gchar *style_text = sp_style_write_difference((SP_IS_STRING(source_obj) ? source_obj->parent : source_obj)->style, this->style); + SPObject *source_obj = reinterpret_cast<SPObject *>(rawptr); + gchar *style_text = sp_style_write_difference((dynamic_cast<SPString *>(source_obj) ? source_obj->parent : source_obj)->style, this->style); if (style_text && *style_text) { span_tspan->setAttribute("style", style_text); g_free(style_text); } - if (SP_IS_STRING(source_obj)) { - Glib::ustring *string = &SP_STRING(source_obj)->string; - SPObject *span_end_obj = 0; + SPString *str = dynamic_cast<SPString *>(source_obj); + if (str) { + Glib::ustring *string = &(str->string); // TODO fixme: dangerous, unsafe premature-optimization void *rawptr = 0; Glib::ustring::iterator span_text_end_iter; this->layout.getSourceOfCharacter(it_span_end, &rawptr, &span_text_end_iter); - span_end_obj = SP_OBJECT(rawptr); + SPObject *span_end_obj = reinterpret_cast<SPObject *>(rawptr); if (span_end_obj != source_obj) { if (it_span_end == this->layout.end()) { span_text_end_iter = span_text_start_iter; @@ -562,13 +568,19 @@ Inkscape::XML::Node *SPFlowtext::getAsText() return repr; } -SPItem *SPFlowtext::get_frame(SPItem *after) +SPItem const *SPFlowtext::get_frame(SPItem const *after) const +{ + SPItem *item = const_cast<SPFlowtext *>(this)->get_frame(after); + return item; +} + +SPItem *SPFlowtext::get_frame(SPItem const *after) { SPItem *frame = 0; SPObject *region = 0; for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { - if (SP_IS_FLOWREGION(o)) { + if (dynamic_cast<SPFlowregion *>(o)) { region = o; break; } @@ -578,29 +590,31 @@ SPItem *SPFlowtext::get_frame(SPItem *after) bool past = false; for (SPObject *o = region->firstChild() ; o ; o = o->getNext() ) { - if (SP_IS_ITEM(o)) { + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { if ( (after == NULL) || past ) { - frame = SP_ITEM(o); + frame = item; } else { - if (SP_ITEM(o) == after) { + if (item == after) { past = true; } } } } - if ( frame && SP_IS_USE(frame) ) { - frame = SP_USE(frame)->get_original(); + SPUse *use = dynamic_cast<SPUse *>(frame); + if ( use ) { + frame = use->get_original(); } } return frame; } -bool SPFlowtext::has_internal_frame() +bool SPFlowtext::has_internal_frame() const { - SPItem *frame = get_frame(NULL); + SPItem const *frame = get_frame(NULL); - return (frame && this->isAncestorOf(frame) && SP_IS_RECT(frame)); + return (frame && isAncestorOf(frame) && dynamic_cast<SPRect const *>(frame)); } @@ -611,19 +625,21 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Inkscape::XML::Document *xml_doc = doc->getReprDoc(); 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 - SPItem *ft_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(root_repr)); + SPItem *ft_item = dynamic_cast<SPItem *>(desktop->currentLayer()->appendChildRepr(root_repr)); + g_assert(ft_item != NULL); SPObject *root_object = doc->getObjectByRepr(root_repr); - g_assert(SP_IS_FLOWTEXT(root_object)); + g_assert(dynamic_cast<SPFlowtext *>(root_object) != NULL); Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion"); root_repr->appendChild(region_repr); SPObject *region_object = doc->getObjectByRepr(region_repr); - g_assert(SP_IS_FLOWREGION(region_object)); + g_assert(dynamic_cast<SPFlowregion *>(region_object) != NULL); Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path region_repr->appendChild(rect_repr); - SPRect *rect = SP_RECT(doc->getObjectByRepr(rect_repr)); + SPRect *rect = dynamic_cast<SPRect *>(doc->getObjectByRepr(rect_repr)); + g_assert(rect != NULL); p0 *= desktop->dt2doc(); p1 *= desktop->dt2doc(); @@ -642,7 +658,7 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); SPObject *para_object = doc->getObjectByRepr(para_repr); - g_assert(SP_IS_FLOWPARA(para_object)); + g_assert(dynamic_cast<SPFlowpara *>(para_object) != NULL); Inkscape::XML::Node *text = xml_doc->createTextNode(""); para_repr->appendChild(text); @@ -652,7 +668,10 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Inkscape::GC::release(para_repr); Inkscape::GC::release(rect_repr); - ft_item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + + SPItem *item = dynamic_cast<SPItem *>(desktop->currentLayer()); + g_assert(item != NULL); + ft_item->transform = item->i2doc_affine().inverse(); return ft_item; } @@ -675,14 +694,14 @@ Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform) SPObject *region = NULL; for ( SPObject *o = this->firstChild() ; o ; o = o->getNext() ) { - if (SP_IS_FLOWREGION(o)) { + if (dynamic_cast<SPFlowregion *>(o)) { region = o; break; } } if (region) { - if (SP_IS_RECT(region->firstChild())) { - SPRect *rect = SP_RECT(region->firstChild()); + SPRect *rect = dynamic_cast<SPRect *>(region->firstChild()); + if (rect) { rect->set_i2d_affine(xform * rect->i2dt_affine()); rect->doWriteTransform(rect->getRepr(), rect->transform, NULL, true); } diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h index 743d55030..9e6046469 100644 --- a/src/sp-flowtext.h +++ b/src/sp-flowtext.h @@ -31,9 +31,13 @@ public: but losing the automatic wrapping ability. */ Inkscape::XML::Node *getAsText(); - SPItem *get_frame(SPItem *after); + // TODO check if these should return SPRect instead of SPItem - bool has_internal_frame(); + SPItem *get_frame(SPItem const *after); + + SPItem const *get_frame(SPItem const *after) const; + + bool has_internal_frame() const; //semiprivate: (need to be accessed by the C-style functions still) Inkscape::Text::Layout layout; diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 613ace5c1..992bca631 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -662,8 +662,13 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bo { if ( hasChildren() ) { for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { - SPItem *item = dynamic_cast<SPItem *>(o); - if ( item ) { + if ( SPDefs *defs = dynamic_cast<SPDefs *>(o) ) { // select symbols from defs, ignore clips, masks, patterns + for (SPObject *defschild = defs->firstChild() ; defschild ; defschild = defschild->getNext() ) { + SPGroup *defsgroup = dynamic_cast<SPGroup *>(defschild); + if (defsgroup) + defsgroup->scaleChildItemsRec(sc, p, false); + } + } else if ( SPItem *item = dynamic_cast<SPItem *>(o) ) { SPGroup *group = dynamic_cast<SPGroup *>(item); if (group && !dynamic_cast<SPBox3D *>(item)) { /* Using recursion breaks clipping because transforms are applied diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 2fa36f834..f836b0316 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -130,7 +130,8 @@ bool SPItem::isVisibleAndUnlocked(unsigned display_key) const { bool SPItem::isLocked() const { for (SPObject const *o = this; o != NULL; o = o->parent) { - if (SP_IS_ITEM(o) && !(SP_ITEM(o)->sensitive)) { + SPItem const *item = dynamic_cast<SPItem const *>(o); + if (item && !(item->sensitive)) { return true; } } @@ -185,14 +186,17 @@ guint32 SPItem::highlight_color() const { { return atoi(_highlightColor) | 0x00000000; } - else if (parent && parent != this && SP_IS_ITEM(parent)) - { - return SP_ITEM(parent)->highlight_color(); - } - else - { - static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - return prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) | 0x00000000; + else { + SPItem const *item = dynamic_cast<SPItem const *>(parent); + if (parent && (parent != this) && item) + { + return item->highlight_color(); + } + else + { + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + return prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) | 0x00000000; + } } } @@ -209,8 +213,9 @@ void SPItem::resetEvaluated() { requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); } } if ( StatusSet == _evaluated_status ) { - if (SP_IS_SWITCH(parent)) { - SP_SWITCH(parent)->resetChildEvaluated(); + SPSwitch *switchItem = dynamic_cast<SPSwitch *>(parent); + if (switchItem) { + switchItem->resetChildEvaluated(); } } } @@ -306,7 +311,7 @@ SPItem::scaleCenter(Geom::Scale const &sc) { namespace { bool is_item(SPObject const &object) { - return SP_IS_ITEM(&object); + return dynamic_cast<SPItem const *>(&object) != NULL; } } @@ -566,20 +571,23 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item) SPItemView *v; /* Hide clippath */ for (v = item->display; v != NULL; v = v->next) { - SP_CLIPPATH(old_clip)->hide(v->arenaitem->key()); + SPClipPath *oldPath = dynamic_cast<SPClipPath *>(old_clip); + g_assert(oldPath != NULL); + oldPath->hide(v->arenaitem->key()); } } - if (SP_IS_CLIPPATH(clip)) { + SPClipPath *clipPath = dynamic_cast<SPClipPath *>(clip); + if (clipPath) { Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { if (!v->arenaitem->key()) { v->arenaitem->setKey(SPItem::display_key_new(3)); } - Inkscape::DrawingItem *ai = SP_CLIPPATH(clip)->show( + Inkscape::DrawingItem *ai = clipPath->show( v->arenaitem->drawing(), v->arenaitem->key()); v->arenaitem->setClip(ai); - SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), bbox); + clipPath->setBBox(v->arenaitem->key(), bbox); clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } @@ -590,34 +598,37 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item) if (old_mask) { /* Hide mask */ for (SPItemView *v = item->display; v != NULL; v = v->next) { - SP_MASK(old_mask)->sp_mask_hide(v->arenaitem->key()); + SPMask *maskItem = dynamic_cast<SPMask *>(old_mask); + g_assert(maskItem != NULL); + maskItem->sp_mask_hide(v->arenaitem->key()); } } - if (SP_IS_MASK(mask)) { + SPMask *maskItem = dynamic_cast<SPMask *>(mask); + if (maskItem) { Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { if (!v->arenaitem->key()) { v->arenaitem->setKey(SPItem::display_key_new(3)); } - Inkscape::DrawingItem *ai = SP_MASK(mask)->sp_mask_show( + Inkscape::DrawingItem *ai = maskItem->sp_mask_show( v->arenaitem->drawing(), v->arenaitem->key()); v->arenaitem->setMask(ai); - SP_MASK(mask)->sp_mask_set_bbox(v->arenaitem->key(), bbox); + maskItem->sp_mask_set_bbox(v->arenaitem->key(), bbox); mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } } void SPItem::fill_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) { - SPPaintServer *old_fill_ps = SP_PAINT_SERVER(old_ps); + SPPaintServer *old_fill_ps = dynamic_cast<SPPaintServer *>(old_ps); if (old_fill_ps) { for (SPItemView *v =item->display; v != NULL; v = v->next) { old_fill_ps->hide(v->arenaitem->key()); } } - SPPaintServer *new_fill_ps = SP_PAINT_SERVER(ps); + SPPaintServer *new_fill_ps = dynamic_cast<SPPaintServer *>(ps); if (new_fill_ps) { Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { @@ -635,14 +646,14 @@ void SPItem::fill_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) { } void SPItem::stroke_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) { - SPPaintServer *old_stroke_ps = SP_PAINT_SERVER(old_ps); + SPPaintServer *old_stroke_ps = dynamic_cast<SPPaintServer *>(old_ps); if (old_stroke_ps) { for (SPItemView *v =item->display; v != NULL; v = v->next) { old_stroke_ps->hide(v->arenaitem->key()); } } - SPPaintServer *new_stroke_ps = SP_PAINT_SERVER(ps); + SPPaintServer *new_stroke_ps = dynamic_cast<SPPaintServer *>(ps); if (new_stroke_ps) { Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { @@ -731,7 +742,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X if (flags & SP_OBJECT_WRITE_BUILD) { GSList *l = NULL; for (SPObject *child = object->firstChild(); child != NULL; child = child->next ) { - if (SP_IS_TITLE(child) || SP_IS_DESC(child)) { + if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) { Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); if (crepr) { l = g_slist_prepend (l, crepr); @@ -745,7 +756,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X } } else { for (SPObject *child = object->firstChild() ; child != NULL; child = child->next ) { - if (SP_IS_TITLE(child) || SP_IS_DESC(child)) { + if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) { child->updateRepr(flags); } } @@ -821,13 +832,14 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const Geom::OptRect bbox; - if ( style && style->filter.href && style->getFilter() && SP_IS_FILTER(style->getFilter())) { + + SPFilter *filter = (style && style->filter.href) ? dynamic_cast<SPFilter *>(style->getFilter()) : NULL; + if ( filter ) { // call the subclass method // CPPIFY //bbox = this->bbox(Geom::identity(), SPItem::VISUAL_BBOX); bbox = const_cast<SPItem*>(this)->bbox(Geom::identity(), SPItem::GEOMETRIC_BBOX); // see LP Bug 1229971 - SPFilter *filter = SP_FILTER(style->getFilter()); // default filer area per the SVG spec: SVGLength x, y, w, h; Geom::Point minp, maxp; @@ -874,8 +886,10 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const bbox = const_cast<SPItem*>(this)->bbox(transform, SPItem::VISUAL_BBOX); } if (clip_ref->getObject()) { - SP_ITEM(clip_ref->getOwner())->bbox_valid = FALSE; // LP Bug 1349018 - bbox.intersectWith(SP_CLIPPATH(clip_ref->getObject())->geometricBounds(transform)); + SPItem *ownerItem = dynamic_cast<SPItem *>(clip_ref->getOwner()); + g_assert(ownerItem != NULL); + ownerItem->bbox_valid = FALSE; // LP Bug 1349018 + bbox.intersectWith(clip_ref->getObject()->geometricBounds(transform)); } return bbox; @@ -955,7 +969,7 @@ unsigned int SPItem::pos_in_parent() const { return pos; } - if (SP_IS_ITEM(iter)) { + if (dynamic_cast<SPItem *>(iter)) { pos++; } } @@ -997,10 +1011,11 @@ void SPItem::getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscap if (*o) { // obj is a group object, the children are the actual clippers for (SPObject *child = (*o)->children ; child ; child = child->next) { - if (SP_IS_ITEM(child)) { + SPItem *item = dynamic_cast<SPItem *>(child); + if (item) { std::vector<Inkscape::SnapCandidatePoint> p_clip_or_mask; // Please note the recursive call here! - SP_ITEM(child)->getSnappoints(p_clip_or_mask, snapprefs); + item->getSnappoints(p_clip_or_mask, snapprefs); // Take into account the transformation of the item being clipped or masked for (std::vector<Inkscape::SnapCandidatePoint>::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); ++p_orig) { // All snappoints are in desktop coordinates, but the item's transformation is @@ -1122,7 +1137,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned ai->setClip(ac); // Update bbox, in case the clip uses bbox units - SP_CLIPPATH(cp)->setBBox(clip_key, item_bbox); + cp->setBBox(clip_key, item_bbox); cp->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } if (mask_ref->getObject()) { @@ -1138,7 +1153,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned ai->setMask(ac); // Update bbox, in case the mask uses bbox units - SP_MASK(mask)->sp_mask_set_bbox(mask_key, item_bbox); + mask->sp_mask_set_bbox(mask_key, item_bbox); mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } @@ -1226,8 +1241,9 @@ void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransf bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH); if (fill && style && (style->fill.isPaintserver())) { SPObject *server = style->getFillPaintServer(); - if ( SP_IS_PATTERN(server) ) { - SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "fill"); + SPPattern *serverPatt = dynamic_cast<SPPattern *>(server); + if ( serverPatt ) { + SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "fill"); sp_pattern_transform_multiply(pattern, postmul, set); } } @@ -1235,8 +1251,9 @@ void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransf bool stroke = (pt == TRANSFORM_STROKE || pt == TRANSFORM_BOTH); if (stroke && style && (style->stroke.isPaintserver())) { SPObject *server = style->getStrokePaintServer(); - if ( SP_IS_PATTERN(server) ) { - SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "stroke"); + SPPattern *serverPatt = dynamic_cast<SPPattern *>(server); + if ( serverPatt ) { + SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "stroke"); sp_pattern_transform_multiply(pattern, postmul, set); } } @@ -1246,7 +1263,8 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set ) { if ( style && style->fill.isPaintserver() ) { SPPaintServer *server = style->getFillPaintServer(); - if ( SP_IS_GRADIENT(server) ) { + SPGradient *serverGrad = dynamic_cast<SPGradient *>(server); + if ( serverGrad ) { /** * \note Bbox units for a gradient are generally a bad idea because @@ -1257,7 +1275,7 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set ) * \todo FIXME: convert back to bbox units after transforming with * the item, so as to preserve the original units. */ - SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "fill" ); + SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "fill" ); sp_gradient_transform_multiply( gradient, postmul, set ); } @@ -1265,8 +1283,9 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set ) if ( style && style->stroke.isPaintserver() ) { SPPaintServer *server = style->getStrokePaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "stroke"); + SPGradient *serverGrad = dynamic_cast<SPGradient *>(server); + if ( serverGrad ) { + SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "stroke"); sp_gradient_transform_multiply( gradient, postmul, set ); } } @@ -1318,10 +1337,11 @@ void SPItem::adjust_stroke_width_recursive(double expansion) adjust_stroke (expansion); // A clone's child is the ghost of its original - we must not touch it, skip recursion - if ( !SP_IS_USE(this) ) { + if ( !dynamic_cast<SPUse *>(this) ) { for ( SPObject *o = children; o; o = o->getNext() ) { - if (SP_IS_ITEM(o)) { - SP_ITEM(o)->adjust_stroke_width_recursive(expansion); + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { + item->adjust_stroke_width_recursive(expansion); } } } @@ -1332,10 +1352,11 @@ void SPItem::freeze_stroke_width_recursive(bool freeze) freeze_stroke_width = freeze; // A clone's child is the ghost of its original - we must not touch it, skip recursion - if ( !SP_IS_USE(this) ) { + if ( !dynamic_cast<SPUse *>(this) ) { for ( SPObject *o = children; o; o = o->getNext() ) { - if (SP_IS_ITEM(o)) { - SP_ITEM(o)->freeze_stroke_width_recursive(freeze); + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { + item->freeze_stroke_width_recursive(freeze); } } } @@ -1347,13 +1368,16 @@ void SPItem::freeze_stroke_width_recursive(bool freeze) static void sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform) { - if (SP_IS_RECT (item)) { - SP_RECT(item)->compensateRxRy(advertized_transform); + SPRect *rect = dynamic_cast<SPRect *>(item); + if (rect) { + rect->compensateRxRy(advertized_transform); } for (SPObject *o = item->children; o != NULL; o = o->next) { - if (SP_IS_ITEM(o)) - sp_item_adjust_rects_recursive(SP_ITEM(o), advertized_transform); + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { + sp_item_adjust_rects_recursive(item, advertized_transform); + } } } @@ -1368,12 +1392,13 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af // Within text, we do not fork gradients, and so must not recurse to avoid double compensation; // also we do not recurse into clones, because a clone's child is the ghost of its original - // we must not touch it - if (!(this && (SP_IS_TEXT(this) || SP_IS_USE(this)))) { + if (!(this && (dynamic_cast<SPText *>(this) || dynamic_cast<SPUse *>(this)))) { for (SPObject *o = children; o != NULL; o = o->next) { - if (SP_IS_ITEM(o)) { + SPItem *item = dynamic_cast<SPItem *>(o); + if (item) { // At the level of the transformed item, t_ancestors is identity; // below it, it is the accmmulated chain of transforms from this level to the top level - SP_ITEM(o)->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern); + item->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern); } } } @@ -1392,20 +1417,18 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set) { - if ( SP_IS_LPE_ITEM(this) ) { - SPLPEItem *lpeitem = SP_LPE_ITEM (this); - if ( lpeitem->hasPathEffect() ) { - lpeitem->forkPathEffectsIfNecessary(); - - // now that all LPEs are forked_if_necessary, we can apply the transform - PathEffectList effect_list = lpeitem->getEffectList(); - for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it) - { - LivePathEffectObject *lpeobj = (*it)->lpeobject; - if (lpeobj && lpeobj->get_lpe()) { - Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe(); - effect->transform_multiply(postmul, set); - } + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(this); + if ( lpeitem && lpeitem->hasPathEffect() ) { + lpeitem->forkPathEffectsIfNecessary(); + + // now that all LPEs are forked_if_necessary, we can apply the transform + PathEffectList effect_list = lpeitem->getEffectList(); + for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (lpeobj && lpeobj->get_lpe()) { + Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe(); + effect->transform_multiply(postmul, set); } } } @@ -1480,7 +1503,7 @@ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &tra // onSetTransform cannot be pure due to the fact that not all visible Items are transformable. if ( // run the object's set_transform (i.e. embed transform) only if: - SP_IS_TEXT_TEXTPATH(this) || + (dynamic_cast<SPText *>(this) && firstChild() && dynamic_cast<SPTextPath *>(firstChild())) || (!preserve && // user did not chose to preserve all transforms (!clip_ref || !clip_ref->getObject()) && // the object does not have a clippath (!mask_ref || !mask_ref->getObject()) && // the object does not have a mask @@ -1551,11 +1574,14 @@ Geom::Affine i2anc_affine(SPObject const *object, SPObject const *const ancestor g_return_val_if_fail(object != NULL, ret); /* stop at first non-renderable ancestor */ - while ( object != ancestor && SP_IS_ITEM(object) ) { - if (SP_IS_ROOT(object)) { - ret *= SP_ROOT(object)->c2p; + while ( object != ancestor && dynamic_cast<SPItem const *>(object) ) { + SPRoot const *root = dynamic_cast<SPRoot const *>(object); + if (root) { + ret *= root->c2p; } else { - ret *= SP_ITEM(object)->transform; + SPItem const *item = dynamic_cast<SPItem const *>(object); + g_assert(item != NULL); + ret *= item->transform; } object = object->parent; } @@ -1619,7 +1645,7 @@ Geom::Affine SPItem::dt2i_affine() const SPItemView *SPItem::sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *drawing_item) { g_assert(item != NULL); - g_assert(SP_IS_ITEM(item)); + g_assert(dynamic_cast<SPItem *>(item) != NULL); g_assert(drawing_item != NULL); SPItemView *new_view = g_new(SPItemView, 1); @@ -1677,8 +1703,9 @@ SPItem *sp_item_first_item_child(SPObject *obj) { SPItem *child = 0; for ( SPObject *iter = obj->firstChild() ; iter ; iter = iter->next ) { - if ( SP_IS_ITEM(iter) ) { - child = SP_ITEM(iter); + SPItem *tmp = dynamic_cast<SPItem *>(iter); + if ( tmp ) { + child = tmp; break; } } diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp index 8b28347f1..b68421dc6 100644 --- a/src/sp-namedview.cpp +++ b/src/sp-namedview.cpp @@ -72,7 +72,7 @@ SPNamedView::SPNamedView() : SPObjectGroup(), snap_manager(this) { this->guidehicolor = 0; this->views = NULL; this->borderlayer = 0; - this->units = NULL; + this->page_size_units = NULL; this->window_x = 0; this->cy = 0; this->window_y = 0; @@ -581,6 +581,7 @@ void SPNamedView::set(unsigned int key, const gchar* value) { break; } case SP_ATTR_UNITS: { + // Only used in "Custom size" section of Document Properties dialog Inkscape::Util::Unit const *new_unit = NULL; if (value) { @@ -599,7 +600,7 @@ void SPNamedView::set(unsigned int key, const gchar* value) { /* fixme: Don't use g_log (see above). */ } } - this->units = new_unit; + this->page_size_units = new_unit; this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; } diff --git a/src/sp-namedview.h b/src/sp-namedview.h index 37310dc76..4746b2962 100644 --- a/src/sp-namedview.h +++ b/src/sp-namedview.h @@ -62,7 +62,7 @@ public: bool grids_visible; Inkscape::Util::Unit const *doc_units; - Inkscape::Util::Unit const *units; + Inkscape::Util::Unit const *page_size_units; // Only used in "Custom size" part of Document Properties dialog GQuark default_layer_id; diff --git a/src/sp-object.cpp b/src/sp-object.cpp index fcff43aa5..024fce85a 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -406,9 +406,9 @@ void SPObject::requestOrphanCollection() { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // do not remove style or script elements (Bug #276244) - if (SP_IS_STYLE_ELEM(this)) { + if (dynamic_cast<SPStyleElem *>(this)) { // leave it - } else if (SP_IS_SCRIPT(this)) { + } else if (dynamic_cast<SPScript *>(this)) { // leave it } else if ((! prefs->getBool("/options/cleanupswatches/value", false)) && SP_IS_PAINT_SERVER(this) && static_cast<SPPaintServer*>(this)->isSwatch() ) { diff --git a/src/sp-script.h b/src/sp-script.h index b71f86720..cdacb8493 100644 --- a/src/sp-script.h +++ b/src/sp-script.h @@ -6,6 +6,7 @@ * * Author: * Felipe C. da S. Sanches <juca@members.fsf.org> + * Jon A. Cruz <jon@joncruz.org> * * Copyright (C) 2008 Author * @@ -15,9 +16,6 @@ #include "sp-object.h" #include "document.h" -#define SP_SCRIPT(obj) (dynamic_cast<SPScript*>((SPObject*)obj)) -#define SP_IS_SCRIPT(obj) (dynamic_cast<const SPScript*>((SPObject*)obj) != NULL) - /* SPScript */ class SPScript : public SPObject { public: diff --git a/src/sp-style-elem.cpp b/src/sp-style-elem.cpp index 84f110134..da17b08d9 100644 --- a/src/sp-style-elem.cpp +++ b/src/sp-style-elem.cpp @@ -26,23 +26,18 @@ SPStyleElem::~SPStyleElem() { } void SPStyleElem::set(unsigned int key, const gchar* value) { - SPStyleElem* object = this; - - g_return_if_fail(object); - SPStyleElem &style_elem = *SP_STYLE_ELEM(object); - switch (key) { case SP_ATTR_TYPE: { if (!value) { /* TODO: `type' attribute is required. Give error message as per http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */ - style_elem.is_css = false; + is_css = false; } else { /* fixme: determine what whitespace is allowed. Will probably need to ask on SVG - * list; though the relevant RFC may give info on its lexer. */ - style_elem.is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0 - && ( value[8] == '\0' || - value[8] == ';' ) ); + list; though the relevant RFC may give info on its lexer. */ + is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0 + && ( value[8] == '\0' || + value[8] == ';' ) ); } break; } @@ -67,14 +62,18 @@ static void child_add_rm_cb(Inkscape::XML::Node *, Inkscape::XML::Node *, Inkscape::XML::Node *, void *const data) { - static_cast<SPObject *>(data)->read_content(); + SPObject *obj = reinterpret_cast<SPObject *>(data); + g_assert(data != NULL); + obj->read_content(); } static void content_changed_cb(Inkscape::XML::Node *, gchar const *, gchar const *, void *const data) { - static_cast<SPObject *>(data)->read_content(); + SPObject *obj = reinterpret_cast<SPObject *>(data); + g_assert(data != NULL); + obj->read_content(); } static void @@ -82,24 +81,22 @@ child_order_changed_cb(Inkscape::XML::Node *, Inkscape::XML::Node *, Inkscape::XML::Node *, Inkscape::XML::Node *, void *const data) { - static_cast<SPObject *>(data)->read_content(); + SPObject *obj = reinterpret_cast<SPObject *>(data); + g_assert(data != NULL); + obj->read_content(); } Inkscape::XML::Node* SPStyleElem::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) { - SPStyleElem* object = this; - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:style"); } - g_return_val_if_fail(object, repr); - SPStyleElem &style_elem = *SP_STYLE_ELEM(object); if (flags & SP_OBJECT_WRITE_BUILD) { g_warning("nyi: Forming <style> content for SP_OBJECT_WRITE_BUILD."); /* fixme: Consider having the CRStyleSheet be a member of SPStyleElem, and then pretty-print to a string s, then repr->addChild(xml_doc->createTextNode(s), NULL). */ } - if (style_elem.is_css) { + if (is_css) { repr->setAttribute("type", "text/css"); } /* todo: media */ @@ -263,10 +260,6 @@ property_cb(CRDocHandler *const a_handler, } void SPStyleElem::read_content() { - SPStyleElem* object = this; - - SPStyleElem &style_elem = *SP_STYLE_ELEM(object); - /* fixme: If there's more than one <style> element in a document, then the document stylesheet * will be set to a random one of them, even switching between them. * @@ -283,7 +276,7 @@ void SPStyleElem::read_content() { */ //XML Tree being used directly here while it shouldn't be. - GString *const text = concat_children(*style_elem.getRepr()); + GString *const text = concat_children(*getRepr()); CRParser *parser = cr_parser_new_from_buf(reinterpret_cast<guchar *>(text->str), text->len, CR_UTF_8, FALSE); @@ -312,7 +305,7 @@ void SPStyleElem::read_content() { CRStatus const parse_status = cr_parser_parse(parser); g_assert(sac_handler->app_data == &parse_tmp); if (parse_status == CR_OK) { - cr_cascade_set_sheet(style_elem.document->style_cascade, stylesheet, ORIGIN_AUTHOR); + cr_cascade_set_sheet(document->style_cascade, stylesheet, ORIGIN_AUTHOR); } else { if (parse_status != CR_PARSING_ERROR) { g_printerr("parsing error code=%u\n", unsigned(parse_status)); @@ -323,7 +316,7 @@ void SPStyleElem::read_content() { } } cr_parser_destroy(parser); - //object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + //requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); // Style references via class= do not, and actually cannot, use autoupdating URIReferences. // Therefore, if an object refers to a stylesheet which has not yet loaded when the object is being loaded @@ -331,7 +324,6 @@ void SPStyleElem::read_content() { // Below is a partial hack that fixes this for a single case: when the <style> is a child of the object // that uses a style from it. It just forces the parent of <style> to reread its style as soon as the stylesheet // is fully loaded. Naturally, this won't work if the user of the stylesheet is its grandparent or precedent. - SPObject *parent = object->parent; if ( parent ) { sp_style_read_from_object(parent->style, parent); } @@ -351,12 +343,10 @@ rec_add_listener(Inkscape::XML::Node &repr, } void SPStyleElem::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPStyleElem* object = this; - - object->read_content(); + read_content(); - object->readAttr( "type" ); - object->readAttr( "media" ); + readAttr( "type" ); + readAttr( "media" ); static Inkscape::XML::NodeEventVector const nodeEventVector = { child_add_rm_cb, // child_added @@ -365,7 +355,7 @@ void SPStyleElem::build(SPDocument *document, Inkscape::XML::Node *repr) { content_changed_cb, // content_changed child_order_changed_cb, // order_changed }; - rec_add_listener(*repr, &nodeEventVector, object); + rec_add_listener(*repr, &nodeEventVector, this); SPObject::build(document, repr); } diff --git a/src/sp-style-elem.h b/src/sp-style-elem.h index 766770216..a3f4bdc70 100644 --- a/src/sp-style-elem.h +++ b/src/sp-style-elem.h @@ -4,9 +4,6 @@ #include "sp-object.h" #include "media.h" -#define SP_STYLE_ELEM(obj) (dynamic_cast<SPStyleElem*>((SPObject*)obj)) -#define SP_IS_STYLE_ELEM(obj) (dynamic_cast<const SPStyleElem*>((SPObject*)obj) != NULL) - class SPStyleElem : public SPObject { public: SPStyleElem(); diff --git a/src/sp-use.cpp b/src/sp-use.cpp index e3fcd252a..2bd6757ff 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -50,10 +50,17 @@ namespace { } SPUse::SPUse() - : SPItem() - , child(NULL) - , href(NULL) - , ref(new SPUseReference(this)) + : SPItem(), + child(NULL), + x(), + y(), + width(), + height(), + href(NULL), + ref(new SPUseReference(this)), + _delete_connection(), + _changed_connection(), + _transformed_connection() { this->x.unset(); this->y.unset(); @@ -179,14 +186,23 @@ Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XM 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(); + SPShape *shape = dynamic_cast<SPShape *>(child); + if (shape) { + shape->set_shape(); // evaluate SPCurve of child + } else { + SPText *text = dynamic_cast<SPText *>(child); + if (text) { + text->rebuildLayout(); // refresh Layout, LP Bug 1339305 + } else { + SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(child); + if (flowtext) { + SPFlowregion *flowregion = dynamic_cast<SPFlowregion *>(flowtext->firstChild()); + if (flowregion) { + flowregion->UpdateComputed(); + } + flowtext->rebuildLayout(); + } + } } return repr; @@ -223,18 +239,18 @@ void SPUse::print(SPPrintContext* ctx) { } const char* SPUse::displayName() const { - if (this->child && SP_IS_SYMBOL( this->child )) { + if (dynamic_cast<SPSymbol *>(child)) { return _("Symbol"); + } else { + return _("Clone"); } - - return _("Clone"); } gchar* SPUse::description() const { - if (this->child) { - if( SP_IS_SYMBOL( this->child ) ) { - if (this->child->title()) { - return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(NULL, "Symbol", this->child->title()))).c_str()); + if (child) { + if ( dynamic_cast<SPSymbol *>(child) ) { + if (child->title()) { + return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(NULL, "Symbol", child->title()))).c_str()); } else { return g_strdup_printf(_("called %s"), _("Unnamed Symbol")); } @@ -302,12 +318,10 @@ void SPUse::hide(unsigned int key) { SPItem *SPUse::root() { SPItem *orig = this->child; - while (orig && SP_IS_USE(orig)) { - orig = SP_USE(orig)->child; - } - - if (!orig) { - return NULL; + SPUse *use = dynamic_cast<SPUse *>(orig); + while (orig && use) { + orig = use->child; + use = dynamic_cast<SPUse *>(orig); } return orig; @@ -325,13 +339,16 @@ int SPUse::cloneDepth() const { unsigned depth = 1; SPItem *orig = this->child; - while (orig && SP_IS_USE(orig)) { + while (orig && dynamic_cast<SPUse *>(orig)) { ++depth; - orig = SP_USE(orig)->child; + orig = dynamic_cast<SPUse *>(orig)->child; } - if (!orig) return -1; - return depth; + if (!orig) { + return -1; + } else { + return depth; + } } /** @@ -345,9 +362,9 @@ Geom::Affine SPUse::get_root_transform() { GSList *chain = NULL; chain = g_slist_prepend(chain, this); - while (SP_IS_USE(orig)) { + while (dynamic_cast<SPUse *>(orig)) { chain = g_slist_prepend(chain, orig); - orig = SP_USE(orig)->child; + orig = dynamic_cast<SPUse *>(orig)->child; } chain = g_slist_prepend(chain, orig); @@ -357,14 +374,13 @@ Geom::Affine SPUse::get_root_transform() { Geom::Affine t(Geom::identity()); for (GSList *i = chain; i != NULL; i = i->next) { - SPItem *i_tem = SP_ITEM(i->data); + SPItem *i_tem = reinterpret_cast<SPItem *>(i->data); // "An additional transformation translate(x,y) is appended to the end (i.e., // right-side) of the transform attribute on the generated 'g', where x and y // represent the values of the x and y attributes on the 'use' element." - http://www.w3.org/TR/SVG11/struct.html#UseElement - if (SP_IS_USE(i_tem)) { - SPUse *i_use = SP_USE(i_tem); - + SPUse *i_use = dynamic_cast<SPUse *>(i_tem); + if (i_use) { if ((i_use->x._set && i_use->x.computed != 0) || (i_use->y._set && i_use->y.computed != 0)) { t = t * Geom::Translate(i_use->x._set ? i_use->x.computed : 0, i_use->y._set ? i_use->y.computed : 0); } @@ -405,7 +421,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { } // never compensate uses which are used in flowtext - if (this->parent && SP_IS_FLOWREGION(this->parent)) { + if (parent && dynamic_cast<SPFlowregion *>(parent)) { return; } @@ -462,8 +478,9 @@ void SPUse::href_changed() { SPObject* obj = SPFactory::instance().createObject(NodeTraits::get_type_string(*childrepr)); - if (SP_IS_ITEM(obj)) { - this->child = SP_ITEM(obj); + SPItem *item = dynamic_cast<SPItem *>(obj); + if (item) { + child = item; this->attach(this->child, this->lastChild()); sp_object_unref(this->child, this); @@ -495,8 +512,8 @@ void SPUse::href_changed() { void SPUse::delete_self() { // always delete uses which are used in flowtext - if (this->parent && SP_IS_FLOWREGION(this->parent)) { - this->deleteObject(); + if (parent && dynamic_cast<SPFlowregion *>(parent)) { + deleteObject(); return; } @@ -547,9 +564,10 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { sp_object_ref(this->child); if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - SPItem const &chi = *SP_ITEM(this->child); - cctx.i2doc = chi.transform * ictx->i2doc; - cctx.i2vp = chi.transform * ictx->i2vp; + SPItem const *chi = dynamic_cast<SPItem const *>(child); + g_assert(chi != NULL); + cctx.i2doc = chi->transform * ictx->i2doc; + cctx.i2vp = chi->transform * ictx->i2vp; this->child->updateDisplay((SPCtx *)&cctx, childflags); } @@ -621,7 +639,7 @@ SPItem *SPUse::unlink() { Inkscape::XML::Node *copy = NULL; - if (SP_IS_SYMBOL(orig)) { // make a group, copy children + if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) { @@ -669,7 +687,8 @@ SPItem *SPUse::unlink() { this->setSuccessor(unlinked); sp_object_unref(this, NULL); - SPItem *item = SP_ITEM(unlinked); + SPItem *item = dynamic_cast<SPItem *>(unlinked); + g_assert(item != NULL); // Set the accummulated transform. { diff --git a/src/sp-use.h b/src/sp-use.h index 97385b986..81e4391aa 100644 --- a/src/sp-use.h +++ b/src/sp-use.h @@ -6,7 +6,9 @@ * * Authors: * Lauris Kaplinski <lauris@kaplinski.com> + * Jon A. Cruz <jon@joncruz.org> * + * Copyright (C) 1999-2014 Authors * Copyright (C) 1999-2002 Lauris Kaplinski * Copyright (C) 2000-2001 Ximian, Inc. * @@ -20,9 +22,6 @@ #include "sp-item.h" #include "enums.h" -#define SP_USE(obj) (dynamic_cast<SPUse*>((SPObject*)obj)) -#define SP_IS_USE(obj) (dynamic_cast<const SPUse*>((SPObject*)obj) != NULL) - class SPUseReference; class SPUse : public SPItem { diff --git a/src/style-internal.h b/src/style-internal.h index 32792827a..faae76ac5 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -36,6 +36,12 @@ static const unsigned SP_STYLE_FLAG_ALWAYS (1 << 2); static const unsigned SP_STYLE_FLAG_IFSET (1 << 0); static const unsigned SP_STYLE_FLAG_IFDIFF (1 << 1); +enum SPStyleSrc { + SP_STYLE_SRC_UNSET, + SP_STYLE_SRC_STYLE_PROP, + SP_STYLE_SRC_STYLE_SHEET, + SP_STYLE_SRC_ATTRIBUTE +}; /* General comments: * @@ -113,7 +119,7 @@ public: inherits(inherits), set(false), inherit(false), - style_att(false), + style_src(SP_STYLE_SRC_UNSET), style(NULL) {} @@ -150,7 +156,7 @@ public: inherits = rhs.inherits; set = rhs.set; inherit = rhs.inherit; - style_att = rhs.style_att; + style_src = rhs.style_src; style = rhs.style; return *this; } @@ -170,7 +176,7 @@ public: unsigned inherits : 1; // Property inherits by default from parent. unsigned set : 1; // Property has been explicitly set (vs. inherited). unsigned inherit : 1; // Property value set to 'inherit'. - unsigned style_att : 2; // Source (attribute, style attribute, style-sheet). NOT USED YET FIX ME + SPStyleSrc style_src : 2; // Source (attribute, style attribute, style-sheet). NOT USED YET FIX ME // To do: make private after g_asserts removed public: diff --git a/src/svg/stringstream-test.h b/src/svg/stringstream-test.h index ce32683f8..305cf6b8d 100644 --- a/src/svg/stringstream-test.h +++ b/src/svg/stringstream-test.h @@ -37,9 +37,9 @@ public: svg_test_float(-0.0625, "-0.0625"); svg_test_float(30.0, "30"); svg_test_float(12345678.0, "12345678"); - svg_test_float(3e9, "3e+09"); - svg_test_float(-3.5e9, "-3.5e+09"); - svg_test_float(32768e9, "3.2768e+13"); + svg_test_float(3e9, "3e+009"); + svg_test_float(-3.5e9, "-3.5e+009"); + svg_test_float(32768e9, "3.2768e+013"); svg_test_float(-10.5, "-10.5"); } diff --git a/src/svg/svg-affine-test.h b/src/svg/svg-affine-test.h index 6d8387328..af670a3a8 100644 --- a/src/svg/svg-affine-test.h +++ b/src/svg/svg-affine-test.h @@ -35,7 +35,7 @@ private: static test_t const write_matrix_tests[2]; static test_t const write_translate_tests[3]; static test_t const write_scale_tests[3]; - static test_t const write_rotate_tests[2]; + static test_t const write_rotate_tests[3]; static test_t const write_skew_tests[3]; public: SvgAffineTest() { @@ -242,9 +242,10 @@ SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[3] = { {"scale(0)",Geom::Affine(0,0,0,0,0,0)}, {"scale(7)",Geom::Affine(7,0,0,7,0,0)}, {"scale(2,3)",Geom::Affine(2,0,0,3,0,0)}}; -SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[2] = { +SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[3] = { {"rotate(13)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)}, - {"rotate(-13,7,11)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)}}; + {"rotate(-13,7,11)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)}, + {"rotate(-34.5,6.7,89)",Geom::Affine(cos(-34.5*DEGREE),sin(-34.5*DEGREE),-sin(-34.5*DEGREE),cos(-34.5*DEGREE),(1-cos(-34.5*DEGREE))*6.7+sin(-34.5*DEGREE)*89,(1-cos(-34.5*DEGREE))*89-sin(-34.5*DEGREE)*6.7)}}; SvgAffineTest::test_t const SvgAffineTest::write_skew_tests[3] = { {"skewX(30)",Geom::Affine(1,0,tan(30.*DEGREE),1,0,0)}, {"skewX(-30)",Geom::Affine(1,0,tan(-30.*DEGREE),1,0,0)}, diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp index af58c4544..c853f9930 100644 --- a/src/svg/svg-affine.cpp +++ b/src/svg/svg-affine.cpp @@ -217,29 +217,29 @@ sp_svg_transform_write(Geom::Affine const &transform) c[p++] = ')'; c[p] = '\000'; - /* } else if (transform.withoutTranslation().isRotation()) { - // FIXME someone please figure out if this can actually be done - // The rotation angle is correct, the points are not + } else if (transform.withoutTranslation().isRotation()) { + // Solution found by Johan Engelen // Refer to the matrix in svg-affine-test.h // We are a rotation about a special axis strcpy(c + p, "rotate("); p += 7; - Geom::Affine const sans_translate = transform.withoutTranslation(); - double angle = std::atan2(sans_translate[1], sans_translate[0]) * (180 / M_PI); + double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI); p += sp_svg_number_write_de(c + p, sizeof(c) - p, angle, prec, min_exp); c[p++] = ','; - Geom::Point pt = transform.translation(); - p += sp_svg_number_write_de(c + p, sizeof(c) - p, pt[Geom::X], prec, min_exp); + Geom::Affine const& m = transform; + double tx = (m[2]*m[5]+m[4]-m[4]*m[3]) / (1-m[3]-m[0]+m[0]*m[3]-m[2]*m[1]); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, tx, prec, min_exp); c[p++] = ','; - p += sp_svg_number_write_de(c + p, sizeof(c) - p, pt[Geom::Y], prec, min_exp); + double ty = (m[1]*tx + m[5]) / (1 - m[3]); + p += sp_svg_number_write_de(c + p, sizeof(c) - p, ty, prec, min_exp); c[p++] = ')'; - c[p] = '\000';*/ + c[p] = '\000'; } else if (transform.isHShear()) { // We are more or less a pure skewX strcpy(c + p, "skewX("); diff --git a/src/svg/svg-length-test.h b/src/svg/svg-length-test.h index fbdb7588d..796943e45 100644 --- a/src/svg/svg-length-test.h +++ b/src/svg/svg-length-test.h @@ -168,9 +168,9 @@ SvgLengthTest::test_t const SvgLengthTest::absolute_tests[12] = { {"1e2pt", SVGLength::PT , 100 , 400.0/3.0}, {"3pc", SVGLength::PC , 3 , 48}, {"-3.5pc", SVGLength::PC , -3.5 , -3.5*16.0}, - {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678*96.0/25.4}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?) - {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678*96.0/2.54}, - {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987*96}}; + {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678f*96.0/25.4}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?) + {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678f*96.0/2.54}, // Note that svg_length_read is casting the result from g_ascii_strtod to float. + {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987f*96.0/1.00}}; SvgLengthTest::test_t const SvgLengthTest::relative_tests[3] = { {"123em", SVGLength::EM, 123, 123. * 7.}, {"123ex", SVGLength::EX, 123, 123. * 13.}, diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 931a295d8..7c82fb230 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -330,6 +330,13 @@ void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* use->setAttribute("xlink:href", id.c_str() ); // Set a default style in <use> rather than <symbol> so it can be changed. use->setAttribute("style", style ); + + Inkscape::XML::Node *nv_repr = sp_desktop_namedview(SP_ACTIVE_DESKTOP)->getRepr(); + gdouble scale_units = Inkscape::Util::Quantity::convert(1, nv_repr->attribute("inkscape:document-units"), "px"); + gchar *transform_str = sp_svg_transform_write(Geom::Scale(scale_units, scale_units)); + use->setAttribute("transform", transform_str); + g_free(transform_str); + _root->appendChild(use); // This min and max sets offsets, we don't have any so set to zero. diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index 5ac2ef29d..d538ea5c5 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -1,5 +1,6 @@ -/** @file +/** + * @file * Clone tiling dialog */ /* Authors: @@ -2002,7 +2003,7 @@ bool CloneTiler::clonetiler_is_a_clone_of(SPObject *tile, SPObject *obj) id_href = g_strdup_printf("#%s", obj_repr->attribute("id")); } - if (SP_IS_USE(tile) && + if (dynamic_cast<SPUse *>(tile) && tile->getRepr()->attribute("xlink:href") && (!id_href || !strcmp(id_href, tile->getRepr()->attribute("xlink:href"))) && tile->getRepr()->attribute("inkscape:tiled-clone-of") && @@ -2025,8 +2026,10 @@ void CloneTiler::clonetiler_trace_hide_tiled_clones_recursively(SPObject *from) return; for (SPObject *o = from->firstChild(); o != NULL; o = o->next) { - if (SP_IS_ITEM(o) && clonetiler_is_a_clone_of (o, NULL)) - SP_ITEM(o)->invoke_hide(trace_visionkey); // FIXME: hide each tiled clone's original too! + SPItem *item = dynamic_cast<SPItem *>(o); + if (item && clonetiler_is_a_clone_of(o, NULL)) { + item->invoke_hide(trace_visionkey); // FIXME: hide each tiled clone's original too! + } clonetiler_trace_hide_tiled_clones_recursively (o); } } @@ -2160,7 +2163,9 @@ void CloneTiler::clonetiler_remove(GtkWidget */*widget*/, GtkWidget *dlg, bool d } } for (GSList *i = to_delete; i; i = i->next) { - SP_OBJECT(i->data)->deleteObject(); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + g_assert(obj != NULL); + obj->deleteObject(); } g_slist_free (to_delete); @@ -2330,7 +2335,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg) bool invert_picked = prefs->getBool(prefs_path + "invert_picked"); double gamma_picked = prefs->getDoubleLimited(prefs_path + "gamma_picked", 0, -10, 10); - SPItem *item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0; + SPItem *item = dynamic_cast<SPItem *>(obj); if (dotrace) { clonetiler_trace_setup (sp_desktop_document(desktop), 1.0, item); } @@ -2621,9 +2626,10 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg) if (center_set) { SPObject *clone_object = sp_desktop_document(desktop)->getObjectByRepr(clone); - if (clone_object && SP_IS_ITEM(clone_object)) { + SPItem *item = dynamic_cast<SPItem *>(clone_object); + if (clone_object && item) { clone_object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - SP_ITEM(clone_object)->setCenter(desktop->doc2dt(new_center)); + item->setCenter(desktop->doc2dt(new_center)); clone_object->updateRepr(); } } diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 93e5eb51b..084a1e98d 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -114,7 +114,7 @@ DocumentProperties::DocumentProperties() _rcb_shad(_("_Show border shadow"), _("If set, page border shows a shadow on its right and lower side"), "inkscape:showpageshadow", _wr, false), _rcp_bg(_("Back_ground color:"), _("Background color"), _("Color of the page background. Note: transparency setting ignored while editing but used when exporting to bitmap."), "pagecolor", "inkscape:pageopacity", _wr), _rcp_bord(_("Border _color:"), _("Page border color"), _("Color of the page border"), "bordercolor", "borderopacity", _wr), - _rum_deflt(_("Default _units:"), "inkscape:document-units", _wr), + _rum_deflt(_("Display _units:"), "inkscape:document-units", _wr), _page_sizer(_wr), //--------------------------------------------------------------- //General snap options @@ -1205,10 +1205,10 @@ void DocumentProperties::removeExternalScript(){ const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); while ( current ) { - if (current->data && SP_IS_OBJECT(current->data)) { - SPObject* obj = SP_OBJECT(current->data); - SPScript* script = SP_SCRIPT(obj); - if (name == script->xlinkhref){ + SPObject* obj = reinterpret_cast<SPObject *>(current->data); + if (obj) { + SPScript* script = dynamic_cast<SPScript *>(obj); + if (script && (name == script->xlinkhref)) { //XML Tree being used directly here while it shouldn't be. Inkscape::XML::Node *repr = obj->getRepr(); @@ -1354,10 +1354,15 @@ void DocumentProperties::populate_script_lists(){ _ExternalScriptsListStore->clear(); _EmbeddedScriptsListStore->clear(); const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); - if (current) _scripts_observer.set(SP_OBJECT(current->data)->parent); + if (current) { + SPObject *obj = reinterpret_cast<SPObject *>(current->data); + g_assert(obj != NULL); + _scripts_observer.set(obj->parent); + } while ( current ) { - SPObject* obj = SP_OBJECT(current->data); - SPScript* script = SP_SCRIPT(obj); + SPObject* obj = reinterpret_cast<SPObject *>(current->data); + SPScript* script = dynamic_cast<SPScript *>(obj); + g_assert(script != NULL); if (script->xlinkhref) { Gtk::TreeModel::Row row = *(_ExternalScriptsListStore->append()); @@ -1703,7 +1708,10 @@ void DocumentProperties::onDocUnitChange() Inkscape::SVGOStringStream os; os << doc_unit->abbr; repr->setAttribute("inkscape:document-units", os.str().c_str()); - + + // Disable changing of SVG Units. The intent here is to change the units in the UI, not the units in SVG. + // This code should be moved (and fixed) once we have an "SVG Units" setting that sets what units are used in SVG data. +#if 0 // Set viewBox if (doc->getRoot()->viewBox_set) { gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); @@ -1755,10 +1763,11 @@ void DocumentProperties::onDocUnitChange() prefs->setBool("/options/transform/rectcorners", transform_rectcorners); prefs->setBool("/options/transform/pattern", transform_pattern); prefs->setBool("/options/transform/gradient", transform_gradient); +#endif doc->setModifiedSinceSave(); - DocumentUndo::done(doc, SP_VERB_NONE, _("Changed document unit")); + DocumentUndo::done(doc, SP_VERB_NONE, _("Changed default display unit")); } } // namespace Dialog diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 1a4823e4a..1a7832688 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -241,7 +241,7 @@ Find::Find() Inkscape::Selection *selection = sp_desktop_selection (SP_ACTIVE_DESKTOP); SPItem *item = selection->singleItem(); if (item) { - if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) { gchar *str; str = sp_te_get_string_multiline (item); entry_find.getEntry()->set_text(str); @@ -343,7 +343,7 @@ bool Find::item_text_match (SPItem *item, const gchar *find, bool exact, bool ca return false; } - if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + if (dynamic_cast<SPText *>(item) || dynamic_cast<SPFlowtext *>(item)) { const gchar *item_text = sp_te_get_string_multiline (item); if (item_text == NULL) { return false; @@ -388,7 +388,7 @@ bool Find::item_id_match (SPItem *item, const gchar *id, bool exact, bool casema return false; } - if (SP_IS_STRING(item)) { // SPStrings have "on demand" ids which are useless for searching + if (dynamic_cast<SPString *>(item)) { // SPStrings have "on demand" ids which are useless for searching return false; } @@ -561,11 +561,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (check_searchin_text.get_active()) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_text_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_text_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_text_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_text_match(item, text, exact, casematch, _action_replace); } } } @@ -581,11 +584,13 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (ids) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_id_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + if (item_id_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_id_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_id_match(item, text, exact, casematch, _action_replace); } } } @@ -595,12 +600,15 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (style) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_style_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_style_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_style_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_style_match(item, text, exact, casematch, _action_replace); } } } @@ -610,11 +618,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (attrname) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_attr_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_attr_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_attr_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_attr_match(item, text, exact, casematch, _action_replace); } } } @@ -624,11 +635,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (attrvalue) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_attrvalue_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_attrvalue_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_attrvalue_match(item, text, exact, casematch, _action_replace); } } } @@ -638,11 +652,14 @@ GSList *Find::filter_fields (GSList *l, bool exact, bool casematch) if (font) { for (GSList *i = in; i != NULL; i = i->next) { - if (item_font_match (SP_ITEM(i->data), text, exact, casematch)) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_font_match(item, text, exact, casematch)) { if (!g_slist_find(out, i->data)) { out = g_slist_prepend (out, i->data); if (_action_replace) { - item_font_match (SP_ITEM(i->data), text, exact, casematch, _action_replace); + item_font_match(item, text, exact, casematch, _action_replace); } } } @@ -661,34 +678,34 @@ bool Find::item_type_match (SPItem *item) { bool all =check_alltypes.get_active(); - if ( SP_IS_RECT(item)) { + if ( dynamic_cast<SPRect *>(item)) { return ( all ||check_rects.get_active()); - } else if (SP_IS_GENERICELLIPSE(item)) { + } else if (dynamic_cast<SPGenericEllipse *>(item)) { return ( all || check_ellipses.get_active()); - } else if (SP_IS_STAR(item) || SP_IS_POLYGON(item)) { + } else if (dynamic_cast<SPStar *>(item) || dynamic_cast<SPPolygon *>(item)) { return ( all || check_stars.get_active()); - } else if (SP_IS_SPIRAL(item)) { + } else if (dynamic_cast<SPSpiral *>(item)) { return ( all || check_spirals.get_active()); - } else if (SP_IS_PATH(item) || SP_IS_LINE(item) || SP_IS_POLYLINE(item)) { + } else if (dynamic_cast<SPPath *>(item) || dynamic_cast<SPLine *>(item) || dynamic_cast<SPPolyLine *>(item)) { return (all || check_paths.get_active()); - } else if (SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item)) { + } else if (dynamic_cast<SPText *>(item) || dynamic_cast<SPTSpan *>(item) || dynamic_cast<SPTRef *>(item) || dynamic_cast<SPString *>(item)) { return (all || check_texts.get_active()); - } else if (SP_IS_GROUP(item) && !desktop->isLayer(item) ) { // never select layers! + } else if (dynamic_cast<SPGroup *>(item) && !desktop->isLayer(item) ) { // never select layers! return (all || check_groups.get_active()); - } else if (SP_IS_USE(item)) { + } else if (dynamic_cast<SPUse *>(item)) { return (all || check_clones.get_active()); - } else if (SP_IS_IMAGE(item)) { + } else if (dynamic_cast<SPImage *>(item)) { return (all || check_images.get_active()); - } else if (SP_IS_OFFSET(item)) { + } else if (dynamic_cast<SPOffset *>(item)) { return (all || check_offsets.get_active()); } @@ -699,7 +716,10 @@ GSList *Find::filter_types (GSList *l) { GSList *n = NULL; for (GSList *i = l; i != NULL; i = i->next) { - if (item_type_match (SP_ITEM(i->data))) { + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item_type_match(item)) { n = g_slist_prepend (n, i->data); } } @@ -716,7 +736,7 @@ GSList *Find::filter_list (GSList *l, bool exact, bool casematch) GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked) { - if (SP_IS_DEFS(r)) { + if (dynamic_cast<SPDefs *>(r)) { return l; // we're not interested in items in defs } @@ -725,8 +745,8 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked) } for (SPObject *child = r->firstChild(); child; child = child->getNext()) { - if (SP_IS_ITEM(child) && !child->cloned && !desktop->isLayer(SP_ITEM(child))) { - SPItem *item = reinterpret_cast<SPItem *>(child); + SPItem *item = dynamic_cast<SPItem *>(child); + if (item && !child->cloned && !desktop->isLayer(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l = g_slist_prepend (l, child); } @@ -739,16 +759,18 @@ GSList *Find::all_items (SPObject *r, GSList *l, bool hidden, bool locked) GSList *Find::all_selection_items (Inkscape::Selection *s, GSList *l, SPObject *ancestor, bool hidden, bool locked) { for (GSList *i = (GSList *) s->itemList(); i != NULL; i = i->next) { - if (SP_IS_ITEM (i->data) && !reinterpret_cast<SPItem *>(i->data)->cloned && !desktop->isLayer(SP_ITEM(i->data))) { - SPItem *item = reinterpret_cast<SPItem *>(i->data); + SPObject *obj = reinterpret_cast<SPObject *>(i->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + if (item && !item->cloned && !desktop->isLayer(item)) { if (!ancestor || ancestor->isAncestorOf(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l = g_slist_prepend (l, i->data); } } } - if (!ancestor || ancestor->isAncestorOf(SP_OBJECT (i->data))) { - l = all_items (SP_OBJECT (i->data), l, hidden, locked); + if (!ancestor || ancestor->isAncestorOf(item)) { + l = all_items(item, l, hidden, locked); } } return l; @@ -831,7 +853,10 @@ void Find::onAction() Inkscape::Selection *selection = sp_desktop_selection (desktop); selection->clear(); selection->setList(n); - scroll_to_show_item (desktop, SP_ITEM(n->data)); + SPObject *obj = reinterpret_cast<SPObject *>(n->data); + SPItem *item = dynamic_cast<SPItem *>(obj); + g_assert(item != NULL); + scroll_to_show_item(desktop, item); if (_action_replace) { DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, _("Replace text or property")); diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 9a569725c..eb3857ee7 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -295,9 +295,8 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if ( item ) { - if ( SP_IS_LPE_ITEM(item) ) { - SPLPEItem *lpeitem = SP_LPE_ITEM(item); - + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item); + if ( lpeitem ) { effect_list_reload(lpeitem); current_lpeitem = lpeitem; @@ -318,25 +317,28 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) button_up.set_sensitive(false); button_down.set_sensitive(false); } - } else if ( SP_IS_USE(item) ) { - // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = SP_USE(item)->get_original(); - if ( SP_IS_SHAPE(orig) || - SP_IS_TEXT(orig) ) - { - // Note that an SP_USE cannot have an LPE applied, so we only need to worry about the "add effect" case. - set_sensitize_all(true); - showText(_("Click add button to convert clone")); - button_remove.set_sensitive(false); - button_up.set_sensitive(false); - button_down.set_sensitive(false); + } else { + SPUse *use = dynamic_cast<SPUse *>(item); + if ( use ) { + // test whether linked object is supported by the CLONE_ORIGINAL LPE + SPItem *orig = use->get_original(); + if ( dynamic_cast<SPShape *>(orig) || + dynamic_cast<SPText *>(orig) ) + { + // Note that an SP_USE cannot have an LPE applied, so we only need to worry about the "add effect" case. + set_sensitize_all(true); + showText(_("Click add button to convert clone")); + button_remove.set_sensitive(false); + button_up.set_sensitive(false); + button_down.set_sensitive(false); + } else { + showText(_("Select a path or shape")); + set_sensitize_all(false); + } } else { showText(_("Select a path or shape")); set_sensitize_all(false); } - } else { - showText(_("Select a path or shape")); - set_sensitize_all(false); } } else { showText(_("Only one item can be selected")); @@ -423,7 +425,7 @@ LivePathEffectEditor::onAdd() if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if (item) { - if ( SP_IS_LPE_ITEM(item) ) { + if ( dynamic_cast<SPLPEItem *>(item) ) { // show effectlist dialog using Inkscape::UI::Dialog::LivePathEffectAdd; LivePathEffectAdd::show(current_desktop); @@ -439,7 +441,7 @@ LivePathEffectEditor::onAdd() } // If item is a SPRect, convert it to path first: - if ( SP_IS_RECT(item) ) { + if ( dynamic_cast<SPRect *>(item) ) { sp_selected_path_to_curves(sel, current_desktop, false); item = sel->singleItem(); // get new item } @@ -451,41 +453,43 @@ LivePathEffectEditor::onAdd() lpe_list_locked = false; onSelectionChanged(sel); - } - else if ( SP_IS_USE(item) ) { - // item is a clone. do not show effectlist dialog. - // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path - - // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = SP_USE(item)->get_original(); - if ( SP_IS_SHAPE(orig) || - SP_IS_TEXT(orig) ) - { - // select original - sel->set(orig); - - // delete clone but remember its id and transform - gchar *id = g_strdup(item->getRepr()->attribute("id")); - gchar *transform = g_strdup(item->getRepr()->attribute("transform")); - item->deleteObject(false); - item = NULL; - - // run sp_selection_clone_original_path_lpe - sp_selection_clone_original_path_lpe(current_desktop); - SPItem *new_item = sel->singleItem(); - new_item->getRepr()->setAttribute("id", id); - new_item->getRepr()->setAttribute("transform", transform); - g_free(id); - g_free(transform); - - /// \todo Add the LPE stack of the original path? - - SPDocument *doc = current_desktop->doc(); - DocumentUndo::done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT, - _("Create and apply Clone original path effect")); - - lpe_list_locked = false; - onSelectionChanged(sel); + } else { + SPUse *use = dynamic_cast<SPUse *>(item); + if ( use ) { + // item is a clone. do not show effectlist dialog. + // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path + + // test whether linked object is supported by the CLONE_ORIGINAL LPE + SPItem *orig = use->get_original(); + if ( dynamic_cast<SPShape *>(orig) || + dynamic_cast<SPText *>(orig) ) + { + // select original + sel->set(orig); + + // delete clone but remember its id and transform + gchar *id = g_strdup(item->getRepr()->attribute("id")); + gchar *transform = g_strdup(item->getRepr()->attribute("transform")); + item->deleteObject(false); + item = NULL; + + // run sp_selection_clone_original_path_lpe + sp_selection_clone_original_path_lpe(current_desktop); + SPItem *new_item = sel->singleItem(); + new_item->getRepr()->setAttribute("id", id); + new_item->getRepr()->setAttribute("transform", transform); + g_free(id); + g_free(transform); + + /// \todo Add the LPE stack of the original path? + + SPDocument *doc = current_desktop->doc(); + DocumentUndo::done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Create and apply Clone original path effect")); + + lpe_list_locked = false; + onSelectionChanged(sel); + } } } } @@ -498,13 +502,14 @@ LivePathEffectEditor::onRemove() Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); - if ( item && SP_IS_LPE_ITEM(item) ) { - SP_LPE_ITEM(item)->removeCurrentPathEffect(false); + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item); + if ( lpeitem ) { + lpeitem->removeCurrentPathEffect(false); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Remove path effect") ); - effect_list_reload(SP_LPE_ITEM(item)); + effect_list_reload(lpeitem); } } @@ -515,7 +520,8 @@ void LivePathEffectEditor::onUp() Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); - if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) { + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item); + if ( lpeitem ) { lpeitem->upCurrentPathEffect(); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, @@ -531,7 +537,8 @@ void LivePathEffectEditor::onDown() Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); - if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) { + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item); + if ( lpeitem ) { lpeitem->downCurrentPathEffect(); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index fa909924d..55a19fc51 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -64,7 +64,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() _fillet_chamfer_chamfer_subdivisions.set_digits(0); _fillet_chamfer_chamfer_subdivisions.set_increments(1,1); //todo: get tha max aloable infinity freeze the widget - _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999); + _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999.0); _fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:")); _fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5); @@ -79,12 +79,15 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() _fillet_chamfer_type_inverse_fillet.set_group(_fillet_chamfer_type_group); _fillet_chamfer_type_chamfer.set_label(_("Chamfer")); _fillet_chamfer_type_chamfer.set_group(_fillet_chamfer_type_group); + _fillet_chamfer_type_inverse_chamfer.set_label(_("Inverse chamfer")); + _fillet_chamfer_type_inverse_chamfer.set_group(_fillet_chamfer_type_group); mainVBox->pack_start(_layout_table, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_fillet, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_inverse_fillet, true, true, 4); mainVBox->pack_start(_fillet_chamfer_type_chamfer, true, true, 4); + mainVBox->pack_start(_fillet_chamfer_type_inverse_chamfer, true, true, 4); // Buttons _close_button.set_use_stock(true); @@ -116,7 +119,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog() { - _setDesktop(NULL); + _set_desktop(NULL); } void FilletChamferPropertiesDialog::showDialog( @@ -125,16 +128,18 @@ void FilletChamferPropertiesDialog::showDialog( FilletChamferPointArrayParamKnotHolderEntity *pt, const gchar *unit, bool use_distance, - bool aprox_radius) + bool aprox_radius, + Glib::ustring const * documentUnit) { FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); - dialog->_setDesktop(desktop); - dialog->_setUnit(unit); + dialog->_set_desktop(desktop); + dialog->_set_unit(unit); dialog->_set_use_distance(use_distance); dialog->_set_aprox(aprox_radius); - dialog->_setKnotPoint(knotpoint); - dialog->_setPt(pt); + dialog->_set_document_unit(documentUnit); + dialog->_set_knot_point(knotpoint); + dialog->_set_pt(pt); dialog->set_title(_("Modify Fillet-Chamfer")); dialog->_apply_button.set_label(_("_Modify")); @@ -156,8 +161,10 @@ void FilletChamferPropertiesDialog::_apply() d_width = 1; } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { d_width = 2; + } else if (_fillet_chamfer_type_inverse_chamfer.get_active() == true) { + d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 4000; } else { - d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3; + d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3000; } if (_flexible) { if (d_pos > 99.99999 || d_pos < 0) { @@ -165,7 +172,7 @@ void FilletChamferPropertiesDialog::_apply() } d_pos = _index + (d_pos / 100); } else { - d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, "px"); + d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, *document_unit); d_pos = d_pos * -1; } _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); @@ -175,7 +182,7 @@ void FilletChamferPropertiesDialog::_apply() void FilletChamferPropertiesDialog::_close() { - _setDesktop(NULL); + _set_desktop(NULL); destroy_(); Glib::signal_idle().connect( sigc::bind_return( @@ -197,7 +204,7 @@ void FilletChamferPropertiesDialog::_handleButtonEvent(GdkEventButton *event) } } -void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) +void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint) { double position; std::string distance_or_radius = std::string(_("Radius ")); @@ -219,19 +226,24 @@ void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) std::string(_("(")) + std::string(unit) + std::string(")"); _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); position = knotpoint[Geom::X] * -1; - position = Inkscape::Util::Quantity::convert(position, "px", unit); + + position = Inkscape::Util::Quantity::convert(position, *document_unit, unit); } _fillet_chamfer_position_numeric.set_value(position); if (knotpoint.y() == 1) { _fillet_chamfer_type_fillet.set_active(true); } else if (knotpoint.y() == 2) { _fillet_chamfer_type_inverse_fillet.set_active(true); - } else if (knotpoint.y() >= 3) { - _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3); + } else if (knotpoint.y() >= 3000 && knotpoint.y() < 4000) { + _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3000); + _fillet_chamfer_type_chamfer.set_active(true); + } else if (knotpoint.y() >= 4000 && knotpoint.y() < 5000) { + _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 4000); + _fillet_chamfer_type_inverse_chamfer.set_active(true); } } -void FilletChamferPropertiesDialog::_setPt( +void FilletChamferPropertiesDialog::_set_pt( const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt) { @@ -240,11 +252,16 @@ void FilletChamferPropertiesDialog::_setPt( pt); } -void FilletChamferPropertiesDialog::_setUnit(const gchar *abbr) +void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr) { unit = abbr; } +void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring const *abbr) +{ + document_unit = abbr; +} + void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance) { use_distance = use_knot_distance; @@ -255,7 +272,7 @@ void FilletChamferPropertiesDialog::_set_aprox(bool aprox_radius) aprox = aprox_radius; } -void FilletChamferPropertiesDialog::_setDesktop(SPDesktop *desktop) +void FilletChamferPropertiesDialog::_set_desktop(SPDesktop *desktop) { if (desktop) { Inkscape::GC::anchor(desktop); diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index deae0cee0..3807e98c8 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -32,7 +32,8 @@ public: FilletChamferPointArrayParamKnotHolderEntity *pt, const gchar *unit, bool use_distance, - bool aprox_radius); + bool aprox_radius, + Glib::ustring const * documentUnit); protected: @@ -46,6 +47,7 @@ protected: Gtk::RadioButton _fillet_chamfer_type_fillet; Gtk::RadioButton _fillet_chamfer_type_inverse_fillet; Gtk::RadioButton _fillet_chamfer_type_chamfer; + Gtk::RadioButton _fillet_chamfer_type_inverse_chamfer; Gtk::Label _fillet_chamfer_chamfer_subdivisions_label; Gtk::SpinButton _fillet_chamfer_chamfer_subdivisions; @@ -63,19 +65,21 @@ protected: return instance; } - void _setDesktop(SPDesktop *desktop); - void _setPt(const Inkscape::LivePathEffect:: + void _set_desktop(SPDesktop *desktop); + void _set_pt(const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt); - void _setUnit(const gchar *abbr); + void _set_unit(const gchar *abbr); + void _set_document_unit(Glib::ustring const * abbr); void _set_use_distance(bool use_knot_distance); void _set_aprox(bool aprox_radius); void _apply(); void _close(); bool _flexible; const gchar *unit; + Glib::ustring const * document_unit; bool use_distance; bool aprox; - void _setKnotPoint(Geom::Point knotpoint); + void _set_knot_point(Geom::Point knotpoint); void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); bool _handleKeyEvent(GdkEventKey *event); diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 647753c4f..c9d9bb36c 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -298,8 +298,7 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : // This might need to be a global variable so setTargetDesktop can modify it SPDefs *defs = currentDocument->getDefs(); - sigc::connection defsModifiedConn = (SP_OBJECT(defs))->connectModified( - sigc::mem_fun(*this, &SymbolsDialog::defsModified)); + sigc::connection defsModifiedConn = defs->connectModified(sigc::mem_fun(*this, &SymbolsDialog::defsModified)); instanceConns.push_back(defsModifiedConn); sigc::connection selectionChangedConn = currentDesktop->selection->connectChanged( @@ -660,11 +659,11 @@ GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l) g_return_val_if_fail(r != NULL, l); // Stop multiple counting of same symbol - if( SP_IS_USE(r) ) { + if ( dynamic_cast<SPUse *>(r) ) { return l; } - if( SP_IS_SYMBOL(r) ) { + if ( dynamic_cast<SPSymbol *>(r) ) { l = g_slist_prepend (l, r); } @@ -686,7 +685,7 @@ GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l) { - if( SP_IS_USE(r) ) { + if ( dynamic_cast<SPUse *>(r) ) { l = g_slist_prepend (l, r); } @@ -711,8 +710,9 @@ gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* documen gchar const* style = 0; GSList* l = use_in_doc( document ); for( ; l != NULL; l = l->next ) { - SPObject* use = SP_OBJECT(l->data); - if( SP_IS_USE( use ) ) { + SPObject *obj = reinterpret_cast<SPObject *>(l->data); + SPUse *use = dynamic_cast<SPUse *>(obj); + if ( use ) { gchar const *href = use->getRepr()->attribute("xlink:href"); if( href ) { Glib::ustring href2(href); @@ -732,8 +732,9 @@ void SymbolsDialog::add_symbols( SPDocument* symbolDocument ) { GSList* l = symbols_in_doc( symbolDocument ); for( ; l != NULL; l = l->next ) { - SPObject* symbol = SP_OBJECT(l->data); - if (SP_IS_SYMBOL(symbol)) { + SPObject *obj = reinterpret_cast<SPObject *>(l->data); + SPSymbol *symbol = dynamic_cast<SPSymbol *>(obj); + if (symbol) { add_symbol( symbol ); } } @@ -822,7 +823,8 @@ SymbolsDialog::draw_symbol(SPObject *symbol) previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); previewDocument->ensureUpToDate(); - SPItem *item = SP_ITEM(object_temp); + SPItem *item = dynamic_cast<SPItem *>(object_temp); + g_assert(item != NULL); unsigned psize = SYMBOL_ICON_SIZES[pack_size]; Glib::RefPtr<Gdk::Pixbuf> pixbuf(NULL); diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 4abc901d2..8a1ca0b90 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -60,10 +60,10 @@ Inkscape::ControlType nodeTypeToCtrlType(Inkscape::UI::NodeType type) namespace Inkscape { namespace UI { -const double handleCubicGap = 0.01; +/*const double handleCubicGap = 0.01;*/ const double noPower = 0.0; const double defaultStartPower = 0.3334; -const double defaultEndPower = 0.6667; +/*const double defaultEndPower = 0.6667;*/ ControlPoint::ColorSet Node::node_colors = { {0xbfbfbf00, 0x000000ff}, // normal fill, stroke diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 6434c30d2..bd84e0efb 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -703,8 +703,8 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc) dc->selection->set(repr); Inkscape::GC::release(repr); item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - item->doWriteTransform(item->getRepr(), item->transform, NULL, true); item->updateRepr(); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); } DocumentUndo::done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL, diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index 99d60e2b7..838c2a884 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -310,7 +310,7 @@ void NodeTool::update_helperpath () { for (Inkscape::UI::ControlPointSelection::Set::iterator i = selectionNodes.begin(); i != selectionNodes.end(); ++i) { if ((*i)->selected()) { Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); - selectedNodesPositions.push_back(desktop->doc2dt(n->position())); + selectedNodesPositions.push_back(n->position()); } } lpe->setSelectedNodePoints(selectedNodesPositions); diff --git a/src/ui/tools/rect-tool.h b/src/ui/tools/rect-tool.h index a50fd7b24..a22f1caa8 100644 --- a/src/ui/tools/rect-tool.h +++ b/src/ui/tools/rect-tool.h @@ -6,6 +6,7 @@ * * Author: * Lauris Kaplinski <lauris@kaplinski.com> + * Jon A. Cruz <jon@joncruz.org> * * Copyright (C) 2000 Lauris Kaplinski * Copyright (C) 2000-2001 Ximian, Inc. @@ -21,9 +22,6 @@ #include "sp-rect.h" -#define SP_RECT_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::RectTool*>((Inkscape::UI::Tools::ToolBase*)obj)) -#define SP_IS_RECT_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::RectTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) - namespace Inkscape { namespace UI { namespace Tools { diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index 89b0b8f7e..32e357c57 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -311,8 +311,8 @@ PageSizer::PageSizer(Registry & _wr) SPDesktop *dt = SP_ACTIVE_DESKTOP; SPNamedView *nv = sp_desktop_namedview(dt); _wr.setUpdating (true); - if (nv->units) { - _dimensionUnits.setUnit(nv->units->abbr); + if (nv->page_size_units) { + _dimensionUnits.setUnit(nv->page_size_units->abbr); } else if (nv->doc_units) { _dimensionUnits.setUnit(nv->doc_units->abbr); } diff --git a/src/util/units.cpp b/src/util/units.cpp index eb4a313e0..3d635e2d2 100644 --- a/src/util/units.cpp +++ b/src/util/units.cpp @@ -206,7 +206,6 @@ bool Unit::compatibleWith(Unit const *u) const } bool Unit::compatibleWith(Glib::ustring const &u) const { - static UnitTable unit_table; return compatibleWith(unit_table.getUnit(u)); } diff --git a/src/widgets/rect-toolbar.cpp b/src/widgets/rect-toolbar.cpp index e1ce01eaf..b6b7e435d 100644 --- a/src/widgets/rect-toolbar.cpp +++ b/src/widgets/rect-toolbar.cpp @@ -404,7 +404,8 @@ static void rect_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolB { static sigc::connection changed; - if (SP_IS_RECT_CONTEXT(ec)) { + // TODO fixme: use of dynamic_cast<> seems wrong here. + if (dynamic_cast<Inkscape::UI::Tools::RectTool *>(ec)) { changed = sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), holder)); } else { if (changed) |
