diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2013-09-20 17:43:57 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2013-09-20 17:43:57 +0000 |
| commit | 0a836d1870bb87d5be3e4d900718f903371c8e56 (patch) | |
| tree | 7d218dc0e9d81e2f7d3eddcefad9640769dc89b3 /src | |
| parent | Compact of SVG icons whith the help of ~suv and Martin Owens (diff) | |
| parent | Merge Google Summer of Code unit improvement. (diff) | |
| download | inkscape-0a836d1870bb87d5be3e4d900718f903371c8e56.tar.gz inkscape-0a836d1870bb87d5be3e4d900718f903371c8e56.zip | |
Update to trunk
(bzr r11950.1.146)
Diffstat (limited to 'src')
120 files changed, 1290 insertions, 862 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a0c857aa3..a45a33932 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -268,7 +268,6 @@ XFAIL_TESTS = $(check_PROGRAMS) # including the the testsuites here ensures that they get distributed cxxtests_SOURCES = cxxtests.cpp $(CXXTEST_TESTSUITES) $(ink_common_sources) $(win32_sources) -cxxtests_LDFLAGS = -z muldefs cxxtests_LDADD = $(all_libs) cxxtests.cpp: $(CXXTEST_TESTSUITES) $(CXXTEST_TEMPLATE) diff --git a/src/arc-context.cpp b/src/arc-context.cpp index 10e56f621..350df908b 100644 --- a/src/arc-context.cpp +++ b/src/arc-context.cpp @@ -451,6 +451,7 @@ void SPArcContext::finishItem() { } this->arc->updateRepr(); + this->arc->doWriteTransform(this->arc->getRepr(), this->arc->transform, NULL, true); desktop->canvas->endForcedFullRedraws(); diff --git a/src/box3d.cpp b/src/box3d.cpp index 0f528a592..193051ee5 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -255,11 +255,8 @@ Inkscape::XML::Node* SPBox3D::write(Inkscape::XML::Document *xml_doc, Inkscape:: return repr; } -gchar* SPBox3D::description() { - SPBox3D* item = this; - - g_return_val_if_fail(SP_IS_BOX3D(item), NULL); - return g_strdup(_("<b>3D Box</b>")); +const char* SPBox3D::display_name() { + return _("3D Box"); } void box3d_position_set(SPBox3D *box) diff --git a/src/box3d.h b/src/box3d.h index 18d99d60a..be5f1926c 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -58,7 +58,7 @@ public: virtual void update(SPCtx *ctx, guint flags); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual gchar *description(); + virtual const char* display_name(); virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides(); }; diff --git a/src/connector-context.cpp b/src/connector-context.cpp index c79c58125..3d6a4f28e 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -998,6 +998,8 @@ spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) cc->newconn->updateRepr(); } + cc->newconn->doWriteTransform(cc->newconn->getRepr(), cc->newconn->transform, NULL, true); + // Only set the selection after we are finished with creating the attributes of // the connector. Otherwise, the selection change may alter the defaults for // values like curvature in the connector context, preventing subsequent lookup diff --git a/src/desktop.cpp b/src/desktop.cpp index 69d83d8da..d19a99da6 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -242,7 +242,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid // display rect and zoom are now handled in sp_desktop_widget_realize() Geom::Rect const d(Geom::Point(0.0, 0.0), - Geom::Point(document->getWidth(), document->getHeight())); + Geom::Point(document->getWidth().value("px"), document->getHeight().value("px"))); SP_CTRLRECT(page)->setRectangle(d); SP_CTRLRECT(page_border)->setRectangle(d); @@ -259,7 +259,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid /* Connect event for page resize */ - _doc2dt[5] = document->getHeight(); + _doc2dt[5] = document->getHeight().value("px"); sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -1108,7 +1108,7 @@ void SPDesktop::zoom_page() { Geom::Rect d(Geom::Point(0, 0), - Geom::Point(doc()->getWidth(), doc()->getHeight())); + Geom::Point(doc()->getWidth().value("px"), doc()->getHeight().value("px"))); if (d.minExtent() < 1.0) { return; @@ -1125,12 +1125,12 @@ SPDesktop::zoom_page_width() { Geom::Rect const a = get_display_area(); - if (doc()->getWidth() < 1.0) { + if (doc()->getWidth().value("px") < 1.0) { return; } Geom::Rect d(Geom::Point(0, a.midpoint()[Geom::Y]), - Geom::Point(doc()->getWidth(), a.midpoint()[Geom::Y])); + Geom::Point(doc()->getWidth().value("px"), a.midpoint()[Geom::Y])); set_display_area(d, 10); } diff --git a/src/document.cpp b/src/document.cpp index ec831745c..967d049c2 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -548,16 +548,20 @@ SPDocument *SPDocument::doUnref() return NULL; } -gdouble SPDocument::getWidth() const +Inkscape::Util::Quantity SPDocument::getWidth() const { - g_return_val_if_fail(this->priv != NULL, 0.0); - g_return_val_if_fail(this->root != NULL, 0.0); + g_return_val_if_fail(this->priv != NULL, Inkscape::Util::Quantity(0.0, Inkscape::Util::Unit())); + g_return_val_if_fail(this->root != NULL, Inkscape::Util::Quantity(0.0, Inkscape::Util::Unit())); - gdouble result = root->width.computed; + gdouble result = root->width.value; + SVGLength::Unit u = root->width.unit; if (root->width.unit == SVGLength::PERCENT && root->viewBox_set) { result = root->viewBox.width(); } - return result; + if (u == SVGLength::NONE) { + u = SVGLength::PX; + } + return Inkscape::Util::Quantity(result, unit_table.getUnit(u)); } void SPDocument::setWidth(const Inkscape::Util::Quantity &width) @@ -584,16 +588,20 @@ void SPDocument::setWidth(const Inkscape::Util::Quantity &width) root->updateRepr(); } -gdouble SPDocument::getHeight() const +Inkscape::Util::Quantity SPDocument::getHeight() const { - g_return_val_if_fail(this->priv != NULL, 0.0); - g_return_val_if_fail(this->root != NULL, 0.0); + g_return_val_if_fail(this->priv != NULL, Inkscape::Util::Quantity(0.0, Inkscape::Util::Unit())); + g_return_val_if_fail(this->root != NULL, Inkscape::Util::Quantity(0.0, Inkscape::Util::Unit())); - gdouble result = root->height.computed; + gdouble result = root->height.value; + SVGLength::Unit u = root->height.unit; if (root->height.unit == SVGLength::PERCENT && root->viewBox_set) { result = root->viewBox.height(); } - return result; + if (u == SVGLength::NONE) { + u = SVGLength::PX; + } + return Inkscape::Util::Quantity(result, unit_table.getUnit(u)); } void SPDocument::setHeight(const Inkscape::Util::Quantity &height) @@ -620,9 +628,16 @@ void SPDocument::setHeight(const Inkscape::Util::Quantity &height) root->updateRepr(); } +void SPDocument::setViewBox(const Geom::Rect &viewBox) +{ + root->viewBox_set = true; + root->viewBox = viewBox; + root->updateRepr(); +} + Geom::Point SPDocument::getDimensions() const { - return Geom::Point(getWidth(), getHeight()); + return Geom::Point(getWidth().value("px"), getHeight().value("px")); } Geom::OptRect SPDocument::preferredBounds() const @@ -644,7 +659,7 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double const w = rect.width(); double const h = rect.height(); - double const old_height = getHeight(); + double const old_height = getHeight().value("px"); Inkscape::Util::Unit const px = unit_table.getUnit("px"); /* in px */ @@ -979,7 +994,7 @@ void SPDocument::setupViewport(SPItemCtx *ctx) if (root->viewBox_set) { // if set, take from viewBox ctx->viewport = root->viewBox; } else { // as a last resort, set size to A4 - ctx->viewport = Geom::Rect::from_xywh(0, 0, 210 * Inkscape::Util::Quantity::convert(1, "mm", "px"), 297 * Inkscape::Util::Quantity::convert(1, "mm", "px")); + ctx->viewport = Geom::Rect::from_xywh(0, 0, Inkscape::Util::Quantity::convert(210, "mm", "px"), Inkscape::Util::Quantity::convert(297, "mm", "px")); } ctx->i2vp = Geom::identity(); } diff --git a/src/document.h b/src/document.h index 63332f431..948b5b867 100644 --- a/src/document.h +++ b/src/document.h @@ -227,12 +227,13 @@ public: SPDocument *doRef(); SPDocument *doUnref(); - gdouble getWidth() const; - gdouble getHeight() const; + Inkscape::Util::Quantity getWidth() const; + Inkscape::Util::Quantity getHeight() const; Geom::Point getDimensions() const; Geom::OptRect preferredBounds() const; void setWidth(const Inkscape::Util::Quantity &width); void setHeight(const Inkscape::Util::Quantity &height); + void setViewBox(const Geom::Rect &viewBox); void requestModified(); gint ensureUpToDate(); bool addResource(const gchar *key, SPObject *object); diff --git a/src/draw-context.cpp b/src/draw-context.cpp index 34b80e3eb..1a4383664 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -616,6 +616,7 @@ static void spdc_flush_white(SPDrawContext *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(); } diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 05ebc3a4a..3e35c0ac1 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -958,6 +958,10 @@ void SPDynaDrawContext::set_to_accumulated(bool unionize, bool subtract) { sp_desktop_selection(desktop)->set(this->repr); } } + + SPItem *item=SP_ITEM(desktop->doc()->getObjectByRepr(this->repr)); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + } else { if (this->repr) { sp_repr_unparent(this->repr); diff --git a/src/ege-adjustment-action.cpp b/src/ege-adjustment-action.cpp index 5a827096f..7f844ec4b 100644 --- a/src/ege-adjustment-action.cpp +++ b/src/ege-adjustment-action.cpp @@ -115,6 +115,7 @@ struct _EgeAdjustmentActionPrivate gchar* appearance; gchar* iconId; Inkscape::IconSize iconSize; + Inkscape::UI::Widget::UnitTracker *unitTracker; }; #define EGE_ADJUSTMENT_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_ADJUSTMENT_ACTION_TYPE, EgeAdjustmentActionPrivate ) ) @@ -128,7 +129,8 @@ enum { PROP_TOOL_POST, PROP_APPEARANCE, PROP_ICON_ID, - PROP_ICON_SIZE + PROP_ICON_SIZE, + PROP_UNIT_TRACKER }; enum { @@ -234,6 +236,13 @@ static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass ) (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + g_object_class_install_property( objClass, + PROP_UNIT_TRACKER, + g_param_spec_pointer( "unit_tracker", + "Unit Tracker", + "The widget that keeps track of the unit", + (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + g_type_class_add_private( klass, sizeof(EgeAdjustmentActionClass) ); } } @@ -263,6 +272,7 @@ static void ege_adjustment_action_init( EgeAdjustmentAction* action ) action->private_data->appearance = 0; action->private_data->iconId = 0; action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR; + action->private_data->unitTracker = NULL; } static void ege_adjustment_action_finalize( GObject* object ) @@ -292,7 +302,8 @@ EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment, const gchar *tooltip, const gchar *stock_id, gdouble climb_rate, - guint digits ) + guint digits, + Inkscape::UI::Widget::UnitTracker *unit_tracker ) { GObject* obj = (GObject*)g_object_new( EGE_ADJUSTMENT_ACTION_TYPE, "name", name, @@ -302,6 +313,7 @@ EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment, "adjustment", adjustment, "climb-rate", climb_rate, "digits", digits, + "unit_tracker", unit_tracker, NULL ); EgeAdjustmentAction* action = EGE_ADJUSTMENT_ACTION( obj ); @@ -349,6 +361,10 @@ static void ege_adjustment_action_get_property( GObject* obj, guint propId, GVal g_value_set_int( value, action->private_data->iconSize ); break; + case PROP_UNIT_TRACKER: + g_value_set_pointer( value, action->private_data->unitTracker ); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } @@ -450,6 +466,12 @@ void ege_adjustment_action_set_property( GObject* obj, guint propId, const GValu } break; + case PROP_UNIT_TRACKER: + { + action->private_data->unitTracker = (Inkscape::UI::Widget::UnitTracker*)g_value_get_pointer( value ); + } + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } @@ -812,7 +834,7 @@ static GtkWidget* create_tool_item( GtkAction* action ) gtk_scale_button_set_icons( GTK_SCALE_BUTTON(spinbutton), floogles ); } else { if ( gFactoryCb ) { - spinbutton = gFactoryCb( act->private_data->adj, act->private_data->climbRate, act->private_data->digits ); + spinbutton = gFactoryCb( act->private_data->adj, act->private_data->climbRate, act->private_data->digits, act->private_data->unitTracker ); } else { spinbutton = gtk_spin_button_new( act->private_data->adj, act->private_data->climbRate, act->private_data->digits ); } diff --git a/src/ege-adjustment-action.h b/src/ege-adjustment-action.h index f63d4ed3e..590035eb3 100644 --- a/src/ege-adjustment-action.h +++ b/src/ege-adjustment-action.h @@ -63,6 +63,14 @@ typedef struct _EgeAdjustmentAction EgeAdjustmentAction; typedef struct _EgeAdjustmentActionClass EgeAdjustmentActionClass; typedef struct _EgeAdjustmentActionPrivate EgeAdjustmentActionPrivate; +namespace Inkscape { + namespace UI { + namespace Widget { + class UnitTracker; + } + } +} + /** * Instance structure of EgeAdjustmentAction. */ @@ -95,7 +103,7 @@ GType ege_adjustment_action_get_type( void ); */ /** Callback type for widgets creation factory */ -typedef GtkWidget* (*EgeCreateAdjWidgetCB)( GtkAdjustment *adjustment, gdouble climb_rate, guint digits ); +typedef GtkWidget* (*EgeCreateAdjWidgetCB)( GtkAdjustment *adjustment, gdouble climb_rate, guint digits, Inkscape::UI::Widget::UnitTracker *unit_tracker ); /** * Sets a factory callback to be used to create the specific widget. @@ -117,6 +125,7 @@ void ege_adjustment_action_set_compact_tool_factory( EgeCreateAdjWidgetCB factor * @param stock_id Icon id to use. * @param climb_rate Used for created widgets. * @param digits Used for created widgets. + * @param unit_tracker Used to store unit. */ EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment, const gchar *name, @@ -124,7 +133,8 @@ EgeAdjustmentAction* ege_adjustment_action_new( GtkAdjustment* adjustment, const gchar *tooltip, const gchar *stock_id, gdouble climb_rate, - guint digits + guint digits, + Inkscape::UI::Widget::UnitTracker *unit_tracker ); /** * Returns a pointer to the GtkAdjustment represented by the given diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index b9125582a..0c314a576 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -197,7 +197,7 @@ CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, float new_bleedmargin_px = 0.; try { - new_bleedmargin_px = mod->get_param_float("bleed") * Inkscape::Util::Quantity::convert(1, "mm", "px"); + new_bleedmargin_px = Inkscape::Util::Quantity::convert(mod->get_param_float("bleed"), "mm", "px"); } catch(...) { g_warning("Parameter <bleed> might not exist"); diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index cace251cf..0a4c86f0b 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -463,8 +463,8 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) } // The width and height of the bitmap in pixels - unsigned width = ceil(bbox->width() * (res / Inkscape::Util::Quantity::convert(1, "in", "px"))); - unsigned height = ceil(bbox->height() * (res / Inkscape::Util::Quantity::convert(1, "in", "px"))); + unsigned width = ceil(bbox->width() * Inkscape::Util::Quantity::convert(res, "px", "in")); + unsigned height = ceil(bbox->height() * Inkscape::Util::Quantity::convert(res, "px", "in")); if (width == 0 || height == 0) return; @@ -638,9 +638,9 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page Geom::Affine tp( Geom::Translate( bleedmargin_px, bleedmargin_px ) ); ctx->transform(tp); } else { - double high = doc->getHeight(); + double high = doc->getHeight().value("px"); if (ctx->_vector_based_target) - high *= Inkscape::Util::Quantity::convert(1, "px", "pt"); + high = Inkscape::Util::Quantity::convert(high, "px", "pt"); // this transform translates the export drawing to a virtual page (0,0)-(width,height) Geom::Affine tp(Geom::Translate(-d.left() * (ctx->_vector_based_target ? Inkscape::Util::Quantity::convert(1, "pt", "px") : 1.0), diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp index b185d3348..ab8a1ab64 100644 --- a/src/extension/internal/emf-inout.cpp +++ b/src/extension/internal/emf-inout.cpp @@ -1799,8 +1799,8 @@ std::cout << "BEFORE DRAW" d->MMX = d->MM100InX / 100.0; d->MMY = d->MM100InY / 100.0; - d->PixelsOutX = d->MMX * Inkscape::Util::Quantity::convert(1, "mm", "px"); - d->PixelsOutY = d->MMY * Inkscape::Util::Quantity::convert(1, "mm", "px"); + d->PixelsOutX = Inkscape::Util::Quantity::convert(d->MMX, "mm", "px"); + d->PixelsOutY = Inkscape::Util::Quantity::convert(d->MMY, "mm", "px"); // Upper left corner, from header rclBounds, in device units, usually both 0, but not always d->ulCornerInX = pEmr->rclBounds.left; diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 770257978..0df643130 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -138,8 +138,8 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) // width and height in px - _width = doc->getWidth(); - _height = doc->getHeight(); + _width = doc->getWidth().value("px"); + _height = doc->getHeight().value("px"); // initialize a few global variables hbrush = hbrushOld = hpen = 0; @@ -243,7 +243,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) g_error("Fatal programming error in PrintEmf::begin at textcomment_set 1"); } - snprintf(buff, sizeof(buff) - 1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, dwInchesX * Inkscape::Util::Quantity::convert(1, "in", "mm"), dwInchesY * Inkscape::Util::Quantity::convert(1, "in", "mm")); + snprintf(buff, sizeof(buff) - 1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, Inkscape::Util::Quantity::convert(dwInchesX, "in", "mm"), Inkscape::Util::Quantity::convert(dwInchesY, "in", "mm")); rec = textcomment_set(buff); if (!rec || emf_append((PU_ENHMETARECORD)rec, et, U_REC_FREE)) { g_error("Fatal programming error in PrintEmf::begin at textcomment_set 1"); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 820d1c9d3..2f9d0ff25 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -35,6 +35,7 @@ #include "extension/effect.h" #include "extension/system.h" +#include "util/units.h" #include "grid.h" @@ -97,14 +98,14 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc /* get page size */ SPDocument * doc = document->doc(); bounding_area = Geom::Rect( Geom::Point(0,0), - Geom::Point(doc->getWidth(), doc->getHeight()) ); + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px")) ); } else { Geom::OptRect bounds = selection->visualBounds(); if (bounds) { bounding_area = *bounds; } - gdouble doc_height = (document->doc())->getHeight(); + gdouble doc_height = (document->doc())->getHeight().value("px"); Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]), Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y])); diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp index 2ece1ba87..c8e8e2f2e 100644 --- a/src/extension/internal/latex-pstricks.cpp +++ b/src/extension/internal/latex-pstricks.cpp @@ -117,8 +117,8 @@ unsigned int PrintLatex::begin (Inkscape::Extension::Print *mod, SPDocument *doc } // width and height in pt - _width = doc->getWidth() * Inkscape::Util::Quantity::convert(1, "px", "pt"); - _height = doc->getHeight() * Inkscape::Util::Quantity::convert(1, "px", "pt"); + _width = doc->getWidth().value("pt"); + _height = doc->getHeight().value("pt"); if (res >= 0) { @@ -128,10 +128,10 @@ unsigned int PrintLatex::begin (Inkscape::Extension::Print *mod, SPDocument *doc os << "\\psset{xunit=.5pt,yunit=.5pt,runit=.5pt}\n"; // from now on we can output px, but they will be treated as pt - os << "\\begin{pspicture}(" << doc->getWidth() << "," << doc->getHeight() << ")\n"; + os << "\\begin{pspicture}(" << doc->getWidth().value("px") << "," << doc->getHeight().value("px") << ")\n"; } - m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, doc->getHeight())); /// @fixme hardcoded doc2dt transform + m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, doc->getHeight().value("px"))); /// @fixme hardcoded doc2dt transform return fprintf(_stream, "%s", os.str().c_str()); } diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 7e6941232..398c9f061 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -633,7 +633,7 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, float bl } // flip y-axis - push_transform( Geom::Scale(1,-1) * Geom::Translate(0, doc->getHeight()) ); /// @fixme hardcoded desktop transform! + push_transform( Geom::Scale(1,-1) * Geom::Translate(0, doc->getHeight().value("px")) ); /// @fixme hardcoded desktop transform! // write the info to LaTeX Inkscape::SVGOStringStream os; @@ -642,7 +642,7 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, float bl // scaling of the image when including it in LaTeX os << " \\ifx\\svgwidth\\undefined%\n"; - os << " \\setlength{\\unitlength}{" << d.width() * Inkscape::Util::Quantity::convert(1, "px", "pt") << "bp}%\n"; // note: 'bp' is the Postscript pt unit in LaTeX, see LP bug #792384 + os << " \\setlength{\\unitlength}{" << Inkscape::Util::Quantity::convert(d.width(), "px", "pt") << "bp}%\n"; // note: 'bp' is the Postscript pt unit in LaTeX, see LP bug #792384 os << " \\ifx\\svgscale\\undefined%\n"; os << " \\relax%\n"; os << " \\else%\n"; diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index a7c14387f..fcabcc4b2 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -75,6 +75,7 @@ #include "sp-flowtext.h" #include "svg/svg.h" #include "text-editing.h" +#include "util/units.h" //# DOM-specific includes @@ -945,7 +946,7 @@ static Geom::Affine getODFTransform(const SPItem *item) //### Get SVG-to-ODF transform Geom::Affine tf (item->i2dt_affine()); //Flip Y into document coordinates - double doc_height = SP_ACTIVE_DOCUMENT->getHeight(); + double doc_height = SP_ACTIVE_DOCUMENT->getHeight().value("px"); Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0)); /// @fixme hardcoded desktop transform doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height)); tf = tf * doc2dt_tf; diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 6e57f6278..7edb758fd 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -279,14 +279,14 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui ignoreUndef = 0; operatorHistory = NULL; builder = builderA; - builder->setDocumentSize(state->getPageWidth()*Inkscape::Util::Quantity::convert(1, "pt", "px"), - state->getPageHeight()*Inkscape::Util::Quantity::convert(1, "pt", "px")); + builder->setDocumentSize(Inkscape::Util::Quantity::convert(state->getPageWidth(), "pt", "px"), + Inkscape::Util::Quantity::convert(state->getPageHeight(), "pt", "px")); double *ctm = state->getCTM(); double scaledCTM[6]; for (int i = 0; i < 6; ++i) { baseMatrix[i] = ctm[i]; - scaledCTM[i] = Inkscape::Util::Quantity::convert(1, "pt", "px") * ctm[i]; + scaledCTM[i] = Inkscape::Util::Quantity::convert(ctm[i], "pt", "px"); } saveState(); builder->setTransform((double*)&scaledCTM); diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index a1a309a87..b3f15bbff 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -793,7 +793,7 @@ gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix, bool for Geom::Affine pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); if ( !for_shading && _is_top_level ) { - Geom::Affine flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * Inkscape::Util::Quantity::convert(1, "px", "pt")); + Geom::Affine flip(1.0, 0.0, 0.0, -1.0, 0.0, Inkscape::Util::Quantity::convert(_height, "px", "pt")); pat_matrix *= flip; } gchar *transform_text = sp_svg_transform_write(pat_matrix); diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index 451d94c0e..373138187 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -1742,8 +1742,8 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK tmp_outdef << " version=\"1.0\"\n"; tmp_outdef << - " width=\"" << d->PixelsOutX/ Inkscape::Util::Quantity::convert(1, "mm", "px") << "mm\"\n" << - " height=\"" << d->PixelsOutY/ Inkscape::Util::Quantity::convert(1, "mm", "px") << "mm\">\n"; + " width=\"" << Inkscape::Util::Quantity::convert(d->PixelsOutX, "px", "mm") << "mm\"\n" << + " height=\"" << Inkscape::Util::Quantity::convert(d->PixelsOutY, "px", "mm") << "mm\">\n"; *(d->outdef) += tmp_outdef.str().c_str(); *(d->outdef) += "<defs>"; // temporary end of header diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 99262b109..cf0302b38 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -138,8 +138,8 @@ unsigned int PrintWmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) // WMF header the only things that can be set are the page size in inches (w,h) and the dpi // width and height in px - _width = doc->getWidth(); - _height = doc->getHeight(); + _width = doc->getWidth().value("px"); + _height = doc->getHeight().value("px"); // initialize a few global variables hbrush = hpen = 0; diff --git a/src/file.cpp b/src/file.cpp index 68e229e62..caea05d95 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -149,7 +149,7 @@ SPDesktop *sp_file_new(const Glib::ustring &templ) // If the current desktop is empty, open the document there doc->ensureUpToDate(); // TODO this will trigger broken link warnings, etc. desktop->change_document(doc); - doc->emitResizedSignal(doc->getWidth(), doc->getHeight()); + doc->emitResizedSignal(doc->getWidth().value("px"), doc->getHeight().value("px")); } else { // create a whole new desktop and window SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL)); // TODO this will trigger broken link warnings, etc. @@ -291,7 +291,7 @@ bool sp_file_open(const Glib::ustring &uri, // If the current desktop is empty, open the document there doc->ensureUpToDate(); // TODO this will trigger broken link warnings, etc. desktop->change_document(doc); - doc->emitResizedSignal(doc->getWidth(), doc->getHeight()); + doc->emitResizedSignal(doc->getWidth().value("px"), doc->getHeight().value("px")); } else { // create a whole new desktop and window SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL)); // TODO this will trigger broken link warnings, etc. diff --git a/src/flood-context.cpp b/src/flood-context.cpp index 1f2a240ca..28aedba6e 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -764,7 +764,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even unsigned int height = (int)ceil(screen.height() * zoom_scale * padding); Geom::Point origin(screen.min()[Geom::X], - document->getHeight() - screen.height() - screen.min()[Geom::Y]); + document->getHeight().value("px") - screen.height() - screen.min()[Geom::Y]); origin[Geom::X] += (screen.width() * ((1 - padding) / 2)); origin[Geom::Y] += (screen.height() * ((1 - padding) / 2)); @@ -874,7 +874,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even } for (unsigned int i = 0; i < fill_points.size(); i++) { - Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, document->getHeight() + (fill_points[i][Geom::Y] / zoom_scale)) * affine; + Geom::Point pw = Geom::Point(fill_points[i][Geom::X] / zoom_scale, document->getHeight().value("px") + (fill_points[i][Geom::Y] / zoom_scale)) * affine; pw[Geom::X] = (int)MIN(width - 1, MAX(0, pw[Geom::X])); pw[Geom::Y] = (int)MIN(height - 1, MAX(0, pw[Geom::Y])); diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index 8e611d197..cd4f539ec 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -115,12 +115,12 @@ Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*fi double padding = 1.0; Geom::Point origin(screen.min()[Geom::X], - doc->getHeight() - screen[Geom::Y].extent() - screen.min()[Geom::Y]); + doc->getHeight().value("px") - screen[Geom::Y].extent() - screen.min()[Geom::Y]); origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2)); origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2)); - Geom::Scale scale( (xdpi / Inkscape::Util::Quantity::convert(1, "in", "px")), (ydpi / Inkscape::Util::Quantity::convert(1, "in", "px"))); + Geom::Scale scale(Inkscape::Util::Quantity::convert(xdpi, "px", "in"), Inkscape::Util::Quantity::convert(ydpi, "px", "in")); Geom::Affine affine = scale * Geom::Translate(-origin * scale); /* Create ArenaItems and set transform */ diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index c43a207c8..b8b815b4c 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -34,6 +34,7 @@ #include "preferences.h" #include "rdf.h" #include "display/cairo-utils.h" +#include "util/units.h" /* This is an example of how to use libpng to read and write PNG files. * The file libpng.txt is much more verbose then this. If you have not @@ -415,7 +416,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename, doc->ensureUpToDate(); /* Calculate translation by transforming to document coordinates (flipping Y)*/ - Geom::Point translation = Geom::Point(-area[Geom::X][0], area[Geom::Y][1] - doc->getHeight()); + Geom::Point translation = Geom::Point(-area[Geom::X][0], area[Geom::Y][1] - doc->getHeight().value("px")); /* This calculation is only valid when assumed that (x0,y0)= area.corner(0) and (x1,y1) = area.corner(2) * 1) a[0] * x0 + a[2] * y1 + a[4] = 0.0 diff --git a/src/inkview.cpp b/src/inkview.cpp index fd7f6b608..e65638df6 100644 --- a/src/inkview.cpp +++ b/src/inkview.cpp @@ -54,6 +54,7 @@ #include "document.h" #include "svg-view.h" #include "svg-view-widget.h" +#include "util/units.h" #ifdef WITH_INKJAR #include "io/inkjar.h" @@ -308,8 +309,8 @@ main (int argc, const char **argv) w = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title( GTK_WINDOW(w), ss.doc->getName() ); gtk_window_set_default_size (GTK_WINDOW (w), - MIN ((int)(ss.doc)->getWidth (), (int)gdk_screen_width () - 64), - MIN ((int)(ss.doc)->getHeight (), (int)gdk_screen_height () - 64)); + MIN ((int)(ss.doc)->getWidth().value("px"), (int)gdk_screen_width() - 64), + MIN ((int)(ss.doc)->getHeight().value("px"), (int)gdk_screen_height() - 64)); ss.window = w; g_signal_connect (G_OBJECT (w), "delete_event", (GCallback) sp_svgview_main_delete, &ss); @@ -318,7 +319,7 @@ main (int argc, const char **argv) (ss.doc)->ensureUpToDate(); ss.view = sp_svg_view_widget_new (ss.doc); (ss.doc)->doUnref (); - SP_SVG_VIEW_WIDGET(ss.view)->setResize( false, ss.doc->getWidth(), ss.doc->getHeight() ); + SP_SVG_VIEW_WIDGET(ss.view)->setResize( false, ss.doc->getWidth().value("px"), ss.doc->getHeight().value("px") ); gtk_widget_show (ss.view); gtk_container_add (GTK_CONTAINER (w), ss.view); diff --git a/src/lpe-tool-context.cpp b/src/lpe-tool-context.cpp index 63707c1c5..14a536b7d 100644 --- a/src/lpe-tool-context.cpp +++ b/src/lpe-tool-context.cpp @@ -330,8 +330,8 @@ lpetool_context_switch_mode(SPLPEToolContext *lc, Inkscape::LivePathEffect::Effe void lpetool_get_limiting_bbox_corners(SPDocument *document, Geom::Point &A, Geom::Point &B) { - Geom::Coord w = document->getWidth(); - Geom::Coord h = document->getHeight(); + Geom::Coord w = document->getWidth().value("px"); + Geom::Coord h = document->getHeight().value("px"); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); double ulx = prefs->getDouble("/tools/lpetool/bbox_upperleftx", 0); diff --git a/src/main.cpp b/src/main.cpp index 27346a230..9a365424c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1535,7 +1535,7 @@ static int sp_do_export_png(SPDocument *doc) g_warning("Export width %lu out of range (1 - %lu). Nothing exported.", width, (unsigned long int)PNG_UINT_31_MAX); return 1; } - dpi = (gdouble) width * Inkscape::Util::Quantity::convert(1, "in", "px") / area.width(); + dpi = (gdouble) Inkscape::Util::Quantity::convert(width, "in", "px") / area.width(); } if (sp_export_height) { @@ -1545,15 +1545,15 @@ static int sp_do_export_png(SPDocument *doc) g_warning("Export height %lu out of range (1 - %lu). Nothing exported.", height, (unsigned long int)PNG_UINT_31_MAX); return 1; } - dpi = (gdouble) height * Inkscape::Util::Quantity::convert(1, "in", "px") / area.height(); + dpi = (gdouble) Inkscape::Util::Quantity::convert(height, "in", "px") / area.height(); } if (!sp_export_width) { - width = (unsigned long int) (area.width() * dpi / Inkscape::Util::Quantity::convert(1, "in", "px") + 0.5); + width = (unsigned long int) (Inkscape::Util::Quantity::convert(area.width(), "px", "in") * dpi + 0.5); } if (!sp_export_height) { - height = (unsigned long int) (area.height() * dpi / Inkscape::Util::Quantity::convert(1, "in", "px") + 0.5); + height = (unsigned long int) (Inkscape::Util::Quantity::convert(area.height(), "px", "in") * dpi + 0.5); } guint32 bgcolor = 0x00000000; diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 77ba3040f..c5a3e1e88 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -770,7 +770,7 @@ void Inkscape::ObjectSnapper::_clear_paths() const Geom::PathVector* Inkscape::ObjectSnapper::_getBorderPathv() const { - Geom::Rect const border_rect = Geom::Rect(Geom::Point(0,0), Geom::Point((_snapmanager->getDocument())->getWidth(),(_snapmanager->getDocument())->getHeight())); + Geom::Rect const border_rect = Geom::Rect(Geom::Point(0,0), Geom::Point((_snapmanager->getDocument())->getWidth().value("px"),(_snapmanager->getDocument())->getHeight().value("px"))); return _getPathvFromRect(border_rect); } @@ -787,8 +787,8 @@ Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const re void Inkscape::ObjectSnapper::_getBorderNodes(std::vector<SnapCandidatePoint> *points) const { - Geom::Coord w = (_snapmanager->getDocument())->getWidth(); - Geom::Coord h = (_snapmanager->getDocument())->getHeight(); + Geom::Coord w = (_snapmanager->getDocument())->getWidth().value("px"); + Geom::Coord h = (_snapmanager->getDocument())->getHeight().value("px"); points->push_back(SnapCandidatePoint(Geom::Point(0,0), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); points->push_back(SnapCandidatePoint(Geom::Point(0,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); points->push_back(SnapCandidatePoint(Geom::Point(w,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); diff --git a/src/persp3d.cpp b/src/persp3d.cpp index a0e6f1c02..530da0799 100644 --- a/src/persp3d.cpp +++ b/src/persp3d.cpp @@ -24,6 +24,7 @@ #include "desktop-handles.h" #include <glibmm/i18n.h> #include "verbs.h" +#include "util/units.h" using Inkscape::DocumentUndo; @@ -168,10 +169,10 @@ Persp3D *persp3d_create_xml_element(SPDocument *document, Persp3DImpl *dup) {// repr = xml_doc->createElement("inkscape:perspective"); repr->setAttribute("sodipodi:type", "inkscape:persp3d"); - Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, document->getHeight()/2, 1.0); + Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, document->getHeight().value("px")/2, 1.0); Proj::Pt2 proj_vp_y = Proj::Pt2 (0.0, 1000.0, 0.0); - Proj::Pt2 proj_vp_z = Proj::Pt2 (document->getWidth(), document->getHeight()/2, 1.0); - Proj::Pt2 proj_origin = Proj::Pt2 (document->getWidth()/2, document->getHeight()/3, 1.0); + Proj::Pt2 proj_vp_z = Proj::Pt2 (document->getWidth().value("px"), document->getHeight().value("px")/2, 1.0); + Proj::Pt2 proj_origin = Proj::Pt2 (document->getWidth().value("px")/2, document->getHeight().value("px")/3, 1.0); if (dup) { proj_vp_x = dup->tmat.column (Proj::X); diff --git a/src/rect-context.cpp b/src/rect-context.cpp index 8a7427928..599680190 100644 --- a/src/rect-context.cpp +++ b/src/rect-context.cpp @@ -478,6 +478,7 @@ void SPRectContext::finishItem() { } this->rect->updateRepr(); + this->rect->doWriteTransform(this->rect->getRepr(), this->rect->transform, NULL, true); this->desktop->canvas->endForcedFullRedraws(); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 91b99e3f4..0cb7123ae 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2809,7 +2809,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, doc->getHeight()) - *c; + Geom::Point move_p = Geom::Point(0, doc->getHeight().value("px")) - *c; move_p[Geom::Y] = -move_p[Geom::Y]; Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); @@ -3093,7 +3093,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } // calculate the transform to be applied to objects to move them to 0,0 - Geom::Point move_p = Geom::Point(0, doc->getHeight()) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); + Geom::Point move_p = Geom::Point(0, doc->getHeight().value("px")) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); move_p[Geom::Y] = -move_p[Geom::Y]; Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); @@ -3398,7 +3398,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) res = prefs_res; } else if (0 < prefs_min) { // If minsize is given, look up minimum bitmap size (default 250 pixels) and calculate resolution from it - res = Inkscape::Util::Quantity::convert(1, "in", "px") * prefs_min / MIN(bbox->width(), bbox->height()); + res = Inkscape::Util::Quantity::convert(prefs_min, "in", "px") / MIN(bbox->width(), bbox->height()); } else { float hint_xdpi = 0, hint_ydpi = 0; Glib::ustring hint_filename; @@ -3419,8 +3419,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) } // The width and height of the bitmap in pixels - unsigned width = (unsigned) floor(bbox->width() * res / Inkscape::Util::Quantity::convert(1, "in", "px")); - unsigned height =(unsigned) floor(bbox->height() * res / Inkscape::Util::Quantity::convert(1, "in", "px")); + unsigned width = (unsigned) floor(bbox->width() * Inkscape::Util::Quantity::convert(res, "px", "in")); + unsigned height =(unsigned) floor(bbox->height() * Inkscape::Util::Quantity::convert(res, "px", "in")); // Find out if we have to run an external filter gchar const *run = NULL; diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 4c2229667..fc6cb7f91 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -38,64 +38,22 @@ #include "sp-polyline.h" #include "sp-spiral.h" -// CPPIFY: this is ugly. -static const gchar * -type2term(SPItem *item) +// Returns a list of terms for the items to be used in the statusbar +const char* collect_terms (GSList *items) { -// GType type = G_OBJECT_TYPE( item ); -// if (type == SP_TYPE_ANCHOR) -// //TRANSLATORS: "Link" means internet link (anchor) -// { return C_("Web", "Link"); } -// if (type == SP_TYPE_CIRCLE) -// { return _("Circle"); } -// if (type == SP_TYPE_ELLIPSE) -// { return _("Ellipse"); } -// if (type == SP_TYPE_FLOWTEXT) -// { return _("Flowed text"); } -// if (type == SP_TYPE_GROUP) -// { return _("Group"); } -// if (type == SP_TYPE_IMAGE) -// { return _("Image"); } -// if (type == SP_TYPE_LINE) -// { return _("Line"); } -// if (type == SP_TYPE_PATH) -// { return _("Path"); } -// if (type == SP_TYPE_POLYGON) -// { return _("Polygon"); } -// if (type == SP_TYPE_POLYLINE) -// { return _("Polyline"); } -// if (type == SP_TYPE_RECT) -// { return _("Rectangle"); } -// if (type == SP_TYPE_BOX3D) -// { return _("3D Box"); } -// if (type == SP_TYPE_TEXT) -// { return C_("Object", "Text"); } -// if (type == SP_TYPE_USE) -// if (SP_IS_SYMBOL(item->firstChild())) -// { return C_("Object", "Symbol"); } -// // TRANSLATORS: "Clone" is a noun, type of object -// { return C_("Object", "Clone"); } -// if (type == SP_TYPE_ARC) -// { return _("Ellipse"); } -// if (type == SP_TYPE_OFFSET) -// { return _("Offset path"); } -// if (type == SP_TYPE_SPIRAL) -// { return _("Spiral"); } -// if (type == SP_TYPE_STAR) -// { return _("Star"); } -// return NULL; - return "Selektion-Describer ---"; -} - -static GSList *collect_terms (GSList *items) -{ - GSList *r = NULL; - for (GSList *i = items; i != NULL; i = i->next) { - const gchar *term = type2term ( SP_ITEM(i->data) ); - if (term != NULL && g_slist_find (r, term) == NULL) - r = g_slist_prepend (r, (void *) term); + GSList *check = NULL; + std::stringstream ss; + bool first = true; + + for (GSList *i = (GSList *)items; i != NULL; i = i->next) { + const char *term = SP_ITEM(i->data)->display_name(); + if (term != NULL && g_slist_find (check, term) == NULL) { + check = g_slist_prepend (check, (void *) term); + ss << (first ? "" : ", ") << "<b>" << term << "</b>"; + first = false; + } } - return r; + return ss.str().c_str(); } // Returns the number of filtered items in the list @@ -201,7 +159,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select g_free (parent_name); if (!items->next) { // one item - char *item_desc = item->description(); + char *item_desc = item->getDetailedDescription(); + if (SP_IS_USE(item) && SP_IS_SYMBOL(item->firstChild())) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, @@ -229,38 +188,11 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select g_free(item_desc); } else { // multiple items int object_count = g_slist_length((GSList *)items); + const char *terms = collect_terms ((GSList *)items); - gchar *objects_str = NULL; - GSList *terms = collect_terms ((GSList *)items); - int n_terms = g_slist_length(terms); - if (n_terms == 0) { - objects_str = g_strdup_printf ( - // this is only used with 2 or more objects - ngettext("<b>%i</b> object selected", "<b>%i</b> objects selected", object_count), - object_count); - } else if (n_terms == 1) { - objects_str = g_strdup_printf ( - // this is only used with 2 or more objects - ngettext("<b>%i</b> object of type <b>%s</b>", "<b>%i</b> objects of type <b>%s</b>", object_count), - object_count, (gchar *) terms->data); - } else if (n_terms == 2) { - objects_str = g_strdup_printf ( - // this is only used with 2 or more objects - ngettext("<b>%i</b> object of types <b>%s</b>, <b>%s</b>", "<b>%i</b> objects of types <b>%s</b>, <b>%s</b>", object_count), - object_count, (gchar *) terms->data, (gchar *) terms->next->data); - } else if (n_terms == 3) { - objects_str = g_strdup_printf ( - // this is only used with 2 or more objects - ngettext("<b>%i</b> object of types <b>%s</b>, <b>%s</b>, <b>%s</b>", "<b>%i</b> objects of types <b>%s</b>, <b>%s</b>, <b>%s</b>", object_count), - object_count, (gchar *) terms->data, (gchar *) terms->next->data, (gchar *) terms->next->next->data); - } else { - objects_str = g_strdup_printf ( - // this is only used with 2 or more objects - ngettext("<b>%i</b> object of <b>%i</b> types", "<b>%i</b> objects of <b>%i</b> types", object_count), - object_count, n_terms); - } - g_slist_free (terms); - + gchar *objects_str = + g_strdup_printf( "<b>%i</b> objects selected of types %s", + object_count, terms ); // indicate all, some, or none filtered gchar *filt_str = NULL; diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp index 71018d89b..59d43f24c 100644 --- a/src/shape-editor.cpp +++ b/src/shape-editor.cpp @@ -35,6 +35,8 @@ using Inkscape::createKnotHolder; +bool ShapeEditor::_blockSetItem = false; + ShapeEditor::ShapeEditor(SPDesktop *dt) { this->desktop = dt; this->knotholder = NULL; @@ -169,6 +171,10 @@ static Inkscape::XML::NodeEventVector shapeeditor_repr_events = { void ShapeEditor::set_item(SPItem *item, SubType type, bool keep_knotholder) { + if (_blockSetItem) { + return; + } + // this happens (and should only happen) when for an LPEItem having both knotholder and // nodepath the knotholder is adapted; in this case we don't want to delete the knotholder // since this freezes the handles diff --git a/src/shape-editor.h b/src/shape-editor.h index 206ff269b..9b3771fee 100644 --- a/src/shape-editor.h +++ b/src/shape-editor.h @@ -65,11 +65,14 @@ public: void shapeeditor_event_attr_changed(gchar const *name); bool knot_mouseover(); + + static void blockSetItem(bool b) {_blockSetItem = b;} private: bool has_knotholder (); void reset_item (SubType type, bool keep_knotholder = true); const SPItem *get_item (SubType type); + static bool _blockSetItem; SPDesktop *desktop; KnotHolder *knotholder; diff --git a/src/sp-anchor.cpp b/src/sp-anchor.cpp index d9a8c4142..3ed2c766c 100644 --- a/src/sp-anchor.cpp +++ b/src/sp-anchor.cpp @@ -115,14 +115,18 @@ Inkscape::XML::Node* SPAnchor::write(Inkscape::XML::Document *xml_doc, Inkscape: return repr; } +const char* SPAnchor::display_name() { + return _("Link"); +} + gchar* SPAnchor::description() { if (this->href) { char *quoted_href = xml_quote_strdup(this->href); - char *ret = g_strdup_printf(_("<b>Link</b> to %s"), quoted_href); + char *ret = g_strdup_printf(_("to %s"), quoted_href); g_free(quoted_href); return ret; } else { - return g_strdup (_("<b>Link</b> without URI")); + return g_strdup (_("without URI")); } } diff --git a/src/sp-anchor.h b/src/sp-anchor.h index cada9665e..a88778132 100644 --- a/src/sp-anchor.h +++ b/src/sp-anchor.h @@ -30,6 +30,7 @@ public: virtual void set(unsigned int key, gchar const* value); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual const char* display_name(); virtual gchar* description(); virtual gint event(SPEvent *event); }; diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index 7c6066054..cb39ef0ec 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -318,6 +318,59 @@ void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, } } +Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) +{ + /* Calculate ellipse start in parent coords. */ + Geom::Point pos( Geom::Point(this->cx.computed, this->cy.computed) * xform ); + + /* This function takes care of translation and scaling, we return whatever parts we can't + handle. */ + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); + gdouble const sw = hypot(ret[0], ret[1]); + gdouble const sh = hypot(ret[2], ret[3]); + if (sw > 1e-9) { + ret[0] /= sw; + ret[1] /= sw; + } else { + ret[0] = 1.0; + ret[1] = 0.0; + } + if (sh > 1e-9) { + ret[2] /= sh; + ret[3] /= sh; + } else { + ret[2] = 0.0; + ret[3] = 1.0; + } + + if (this->rx._set) { + this->rx = this->rx.computed * sw; + } + if (this->ry._set) { + this->ry = this->ry.computed * sh; + } + + /* Find start in item coords */ + pos = pos * ret.inverse(); + this->cx = pos[Geom::X]; + this->cy = pos[Geom::Y]; + + this->set_shape(); + + // Adjust stroke width + this->adjust_stroke(sqrt(fabs(sw * sh))); + + // Adjust pattern fill + this->adjust_pattern(xform * ret.inverse()); + + // Adjust gradient fill + this->adjust_gradient(xform * ret.inverse()); + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + + return ret; +} + void sp_genericellipse_normalize(SPGenericEllipse *ellipse) { @@ -427,8 +480,8 @@ void SPEllipse::set(unsigned int key, gchar const* value) { } } -gchar* SPEllipse::description() { - return g_strdup(_("<b>Ellipse</b>")); +const char* SPEllipse::display_name() { + return _("Ellipse"); } @@ -507,8 +560,8 @@ void SPCircle::set(unsigned int key, gchar const* value) { } } -gchar* SPCircle::description() { - return g_strdup(_("<b>Circle</b>")); +const char* SPCircle::display_name() { + return _("Circle"); } /* <path sodipodi:type="arc"> element */ @@ -681,7 +734,7 @@ void SPArc::modified(guint flags) { } -gchar* SPArc::description() { +const char* SPArc::display_name() { gdouble len = fmod(this->end - this->start, SP_2PI); if (len < 0.0) { @@ -690,12 +743,12 @@ gchar* SPArc::description() { if (!(fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8)) { if (this->closed) { - return g_strdup(_("<b>Segment</b>")); + return _("Segment"); } else { - return g_strdup(_("<b>Arc</b>")); + return _("Arc"); } } else { - return g_strdup(_("<b>Ellipse</b>")); + return _("Ellipse"); } } diff --git a/src/sp-ellipse.h b/src/sp-ellipse.h index 67e12006a..b74beeae0 100644 --- a/src/sp-ellipse.h +++ b/src/sp-ellipse.h @@ -39,6 +39,7 @@ public: virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); virtual void set_shape(); + virtual Geom::Affine set_transform(Geom::Affine const& xform); virtual void update_patheffect(bool write); }; @@ -58,7 +59,7 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); virtual void set(unsigned int key, gchar const* value); - virtual gchar* description(); + virtual const char* display_name(); }; void sp_ellipse_position_set (SPEllipse * ellipse, gdouble x, gdouble y, gdouble rx, gdouble ry); @@ -75,7 +76,7 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); virtual void set(unsigned int key, gchar const* value); - virtual gchar* description(); + virtual const char* display_name(); }; /* <path sodipodi:type="arc"> element */ @@ -90,7 +91,7 @@ public: virtual void build(SPDocument *document, Inkscape::XML::Node *repr); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); virtual void set(unsigned int key, gchar const* value); - virtual gchar* description(); + virtual const char* display_name(); virtual void modified(unsigned int flags); }; diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index 3a0aef6be..caa6aef76 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -188,14 +188,11 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc return repr; } -gchar* SPFlowregion::description() { +const char* SPFlowregion::display_name() { // TRANSLATORS: "Flow region" is an area where text is allowed to flow - return g_strdup_printf(_("Flow region")); + return _("Flow Region"); } -/* - * - */ SPFlowregionExclude::SPFlowregionExclude() : SPItem() { this->computed = NULL; } @@ -338,18 +335,14 @@ Inkscape::XML::Node *SPFlowregionExclude::write(Inkscape::XML::Document *xml_doc return repr; } -gchar* SPFlowregionExclude::description() { +const char* SPFlowregionExclude::display_name() { /* TRANSLATORS: A region "cut out of" a flow region; text is not allowed to flow inside the * flow excluded region. flowRegionExclude in SVG 1.2: see * http://www.w3.org/TR/2004/WD-SVG12-20041027/flow.html#flowRegion-elem and * http://www.w3.org/TR/2004/WD-SVG12-20041027/flow.html#flowRegionExclude-elem. */ - return g_strdup_printf(_("Flow excluded region")); + return _("Flow Excluded Region"); } -/* - * - */ - static void UnionShape(Shape **base_shape, Shape const *add_shape) { if (*base_shape == NULL) diff --git a/src/sp-flowregion.h b/src/sp-flowregion.h index 59818651a..600b2aa6e 100644 --- a/src/sp-flowregion.h +++ b/src/sp-flowregion.h @@ -31,7 +31,7 @@ public: virtual void update(SPCtx *ctx, unsigned int flags); virtual void modified(guint flags); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual gchar *description(); + virtual const char* display_name(); }; class SPFlowregionExclude : public SPItem { @@ -48,7 +48,7 @@ public: virtual void update(SPCtx *ctx, unsigned int flags); virtual void modified(guint flags); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual gchar *description(); + virtual const char* display_name(); }; #endif diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index c7ef579ac..d46a644cf 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -28,6 +28,7 @@ #include "text-tag-attributes.h" #include "text-chemistry.h" #include "text-editing.h" +#include "sp-text.h" #include "livarot/Shape.h" @@ -280,17 +281,20 @@ void SPFlowtext::print(SPPrintContext *ctx) { this->layout.print(ctx, pbox, dbox, bbox, ctm); } +const char* SPFlowtext::display_name() { + if (SP_FLOWTEXT(this)->has_internal_frame()) { + return _("Flowed Text"); + } else { + return _("Linked Flowed Text"); + } +} + gchar* SPFlowtext::description() { Inkscape::Text::Layout const &layout = SP_FLOWTEXT(this)->layout; int const nChars = layout.iteratorToCharIndex(layout.end()); - char const *trunc = (layout.inputTruncated()) ? _(" [truncated]") : ""; - if (SP_FLOWTEXT(this)->has_internal_frame()) { - return g_strdup_printf(ngettext("<b>Flowed text</b> (%d character%s)", "<b>Flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } else { - return g_strdup_printf(ngettext("<b>Linked flowed text</b> (%d character%s)", "<b>Linked flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } + return g_strdup_printf(ngettext(_("(%d character%s)"), _("(%d characters%s)"), nChars), nChars, trunc); } void SPFlowtext::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { @@ -645,6 +649,44 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, return ft_item; } +Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform) +{ + if ((this->_optimizeScaledText && !xform.withoutTranslation().isNonzeroUniformScale()) + || (!this->_optimizeScaledText && !xform.isNonzeroUniformScale())) { + this->_optimizeScaledText = false; + return xform; + } + this->_optimizeScaledText = false; + + SPText *text = reinterpret_cast<SPText *>(this); + + double const ex = xform.descrim(); + if (ex == 0) { + return xform; + } + + Geom::Affine ret(xform); + ret[0] /= ex; + ret[1] /= ex; + ret[2] /= ex; + ret[3] /= ex; + + // Adjust font size + text->_adjustFontsizeRecursive (this, ex); + + // Adjust stroke width + this->adjust_stroke_width_recursive (ex); + + // Adjust pattern fill + this->adjust_pattern(xform * ret.inverse()); + + // Adjust gradient fill + this->adjust_gradient(xform * ret.inverse()); + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); + + return ret; +} /* Local Variables: diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h index bd7c5990a..de328608f 100644 --- a/src/sp-flowtext.h +++ b/src/sp-flowtext.h @@ -43,6 +43,12 @@ public: double par_indent; + bool _optimizeScaledText; + + /** Optimize scaled flow text on next set_transform. */ + void optimizeScaledText() + {_optimizeScaledText = true;} + private: /** Recursively walks the xml tree adding tags and their contents. */ void _buildLayoutInput(SPObject *root, Shape const *exclusion_shape, std::list<Shape> *shapes, SPObject **pending_line_break_object); @@ -58,6 +64,7 @@ public: virtual void remove_child(Inkscape::XML::Node* child); virtual void set(unsigned int key, const gchar* value); + virtual Geom::Affine set_transform(Geom::Affine const& xform); virtual void update(SPCtx* ctx, unsigned int flags); virtual void modified(unsigned int flags); @@ -66,6 +73,7 @@ public: virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); virtual void print(SPPrintContext *ctx); + virtual const char* display_name(); virtual gchar* description(); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index 039edc90f..42a3b1ba7 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -287,7 +287,7 @@ sp_guide_create_guides_around_page(SPDesktop *dt) { std::list<std::pair<Geom::Point, Geom::Point> > pts; Geom::Point A(0, 0); - Geom::Point C(doc->getWidth(), doc->getHeight()); + Geom::Point C(doc->getWidth().value("px"), doc->getHeight().value("px")); Geom::Point B(C[Geom::X], 0); Geom::Point D(0, C[Geom::Y]); diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 80daf33c3..c3352fcf0 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -613,6 +613,10 @@ void SPImage::print(SPPrintContext *ctx) { } } +const char* SPImage::display_name() { + return _("Image"); +} + gchar* SPImage::description() { char *href_desc; @@ -626,8 +630,8 @@ gchar* SPImage::description() { } char *ret = ( this->pixbuf == NULL - ? g_strdup_printf(_("<b>Image with bad reference</b>: %s"), href_desc) - : g_strdup_printf(_("<b>Image</b> %d × %d: %s"), + ? g_strdup_printf(_("[bad reference]: %s"), href_desc) + : g_strdup_printf(_("%d × %d: %s"), this->pixbuf->width(), this->pixbuf->height(), href_desc) ); diff --git a/src/sp-image.h b/src/sp-image.h index bfc10e7f2..85eceac20 100644 --- a/src/sp-image.h +++ b/src/sp-image.h @@ -64,6 +64,7 @@ public: virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); virtual void print(SPPrintContext *ctx); + virtual const char* display_name(); virtual gchar* description(); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 010cc5449..720f6857a 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -50,6 +50,9 @@ #include "sp-switch.h" #include "sp-defs.h" #include "verbs.h" +#include "layer-model.h" +#include "sp-textpath.h" +#include "sp-flowtext.h" using Inkscape::DocumentUndo; @@ -325,12 +328,14 @@ void SPGroup::print(SPPrintContext *ctx) { } } +const char *SPGroup::display_name() { + return _("Group"); +} + gchar *SPGroup::description() { gint len = this->getItemCount(); return g_strdup_printf( - ngettext("<b>Group</b> of <b>%d</b> object", - "<b>Group</b> of <b>%d</b> objects", - len), len); + ngettext(_("of <b>%d</b> object"), _("of <b>%d</b> objects"), len), len); } void SPGroup::set(unsigned int key, gchar const* value) { @@ -642,6 +647,81 @@ void SPGroup::translateChildItems(Geom::Translate const &tr) } } +// Recursively scale child items around a point +void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p) +{ + if ( hasChildren() ) { + for (SPObject *o = firstChild() ; o ; o = o->getNext() ) { + if ( SP_IS_ITEM(o) ) { + if (SP_IS_GROUP(o) && !SP_IS_BOX3D(o)) { + SP_GROUP(o)->scaleChildItemsRec(sc, p); + } else { + SPItem *item = SP_ITEM(o); + Geom::OptRect bbox = item->desktopVisualBounds(); + if (bbox) { + // Scale item + Geom::Translate const s(p); + Geom::Affine final = s.inverse() * sc * s; + + Geom::Point old_center(0,0); + if (item->isCenterSet()) { + old_center = item->getCenter(); + } + + gchar const *conn_type = NULL; + if (SP_IS_TEXT_TEXTPATH(item)) { + SP_TEXT(item)->optimizeTextpathText(); + } else if (SP_IS_FLOWTEXT(item)) { + SP_FLOWTEXT(item)->optimizeScaledText(); + } else if (SP_IS_BOX3D(item)) { + // Force recalculation from perspective + box3d_position_set(SP_BOX3D(item)); + } else if (item->getAttribute("inkscape:connector-type") != NULL + && (item->getAttribute("inkscape:connection-start") == NULL + || item->getAttribute("inkscape:connection-end") == NULL)) { + // Remove and store connector type for transform if disconnected + conn_type = item->getAttribute("inkscape:connector-type"); + item->removeAttribute("inkscape:connector-type"); + } + + if (SP_IS_PERSP3D(item)) { + persp3d_apply_affine_transformation(SP_PERSP3D(item), final); + } else if ((SP_IS_TEXT_TEXTPATH(item) || SP_IS_FLOWTEXT(item)) && !item->transform.isIdentity()) { + // Save and reset current transform + Geom::Affine tmp(item->transform); + item->transform = Geom::Affine(); + // Apply scale + item->set_i2d_affine(item->i2dt_affine() * sc); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + // Scale translation and restore original transform + tmp[4] *= sc[0]; + tmp[5] *= sc[1]; + item->doWriteTransform(item->getRepr(), tmp, NULL, true); + } else if (SP_IS_USE(item)) { + // calculate the matrix we need to apply to the clone + // to cancel its induced transform from its original + Geom::Affine move = final.inverse() * item->transform * final; + item->doWriteTransform(item->getRepr(), move, &move, true); + } else { + item->set_i2d_affine(item->i2dt_affine() * final); + item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + } + + if (conn_type != NULL) { + item->setAttribute("inkscape:connector-type", conn_type); + } + + if (item->isCenterSet() && !(final.isTranslation() || final.isIdentity())) { + item->setCenter(old_center * final); + item->updateRepr(); + } + } + } + } + } + } +} + gint SPGroup::getItemCount() { gint len = 0; for (SPObject *o = this->firstChild() ; o ; o = o->getNext() ) { diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 88ca9657a..24c24abbd 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -52,6 +52,7 @@ public: LayerMode layerDisplayMode(unsigned int display_key) const; void setLayerDisplayMode(unsigned int display_key, LayerMode mode); void translateChildItems(Geom::Translate const &tr); + void scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p); gint getItemCount(); void _showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags); @@ -75,6 +76,7 @@ public: virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype); virtual void print(SPPrintContext *ctx); + virtual const char* display_name(); virtual gchar *description(); virtual Inkscape::DrawingItem *show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide (unsigned int key); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index e6991a1fa..a91d0e741 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -73,6 +73,8 @@ #include "live_effects/effect.h" #include "live_effects/lpeobject-reference.h" +#include "util/units.h" + #define noSP_ITEM_DEBUG_IDLE @@ -818,7 +820,7 @@ Geom::OptRect SPItem::desktopGeometricBounds() const Geom::OptRect SPItem::desktopVisualBounds() const { /// @fixme hardcoded desktop transform - Geom::Affine m = Geom::Scale(1, -1) * Geom::Translate(0, document->getHeight()); + Geom::Affine m = Geom::Scale(1, -1) * Geom::Translate(0, document->getHeight().value("px")); Geom::OptRect ret = documentVisualBounds(); if (ret) *ret *= m; return ret; @@ -931,9 +933,12 @@ void SPItem::invoke_print(SPPrintContext *ctx) } } -// CPPIFY: is it possible to combine this method with "SPItem::description()"? +const char* SPItem::display_name() { + return _("Object"); +} + gchar* SPItem::description() { - return g_strdup(_("Object")); + return g_strdup(""); } /** @@ -943,7 +948,8 @@ gchar* SPItem::description() { */ gchar *SPItem::getDetailedDescription() { - gchar* s = this->description(); + gchar* s = g_strdup_printf("<b>%s</b> %s", + this->display_name(), this->description()); if (s && clip_ref->getObject()) { gchar *snew = g_strdup_printf (_("%s; <i>clipped</i>"), s); @@ -1496,7 +1502,7 @@ Geom::Affine SPItem::i2dt_affine() const // TODO temp code to prevent crashing on command-line launch: ret = i2doc_affine() * Geom::Scale(1, -1) - * Geom::Translate(0, document->getHeight()); + * Geom::Translate(0, document->getHeight().value("px")); } return ret; } diff --git a/src/sp-item.h b/src/sp-item.h index 8dfb4142a..769af229e 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -236,6 +236,7 @@ public: virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); virtual void print(SPPrintContext *ctx); + virtual const char* display_name(); virtual gchar* description(); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); diff --git a/src/sp-line.cpp b/src/sp-line.cpp index 3963007de..c3a0b13db 100644 --- a/src/sp-line.cpp +++ b/src/sp-line.cpp @@ -122,8 +122,8 @@ Inkscape::XML::Node* SPLine::write(Inkscape::XML::Document *xml_doc, Inkscape::X return repr; } -gchar* SPLine::description() { - return g_strdup(_("<b>Line</b>")); +const char* SPLine::display_name() { + return _("Line"); } void SPLine::convert_to_guides() { diff --git a/src/sp-line.h b/src/sp-line.h index ebdfc9f04..7184b9401 100644 --- a/src/sp-line.h +++ b/src/sp-line.h @@ -34,7 +34,7 @@ public: virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); virtual void set(unsigned int key, gchar const* value); - virtual gchar* description(); + virtual const char* display_name(); virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides(); virtual void update(SPCtx* ctx, guint flags); diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 1ab3cade8..8c7a24a2b 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -61,6 +61,14 @@ using std::strstr; # define debug(f, a...) /* */ #endif +namespace { + SPObject* createObject() { + return new SPObject(); + } + + bool gridRegistered = SPFactory::instance().registerObject("inkscape:grid", createObject); +} + guint update_in_progress = 0; // guard against update-during-update Inkscape::XML::NodeEventVector object_event_vector = { diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index ef18acc8e..f9759cac1 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -339,18 +339,20 @@ void SPOffset::update(SPCtx *ctx, guint flags) { SPShape::update(ctx, flags); } -gchar* SPOffset::description() { +const char* SPOffset::display_name() { if ( this->sourceHref ) { - // TRANSLATORS COMMENT: %s is either "outset" or "inset" depending on sign - return g_strdup_printf(_("<b>Linked offset</b>, %s by %f pt"), - (this->rad >= 0)? _("outset") : _("inset"), fabs (this->rad)); + return _("Linked Offset"); } else { - // TRANSLATORS COMMENT: %s is either "outset" or "inset" depending on sign - return g_strdup_printf(_("<b>Dynamic offset</b>, %s by %f pt"), - (this->rad >= 0)? _("outset") : _("inset"), fabs (this->rad)); + return _("Dynamic Offset"); } } +gchar* SPOffset::description() { + // TRANSLATORS COMMENT: %s is either "outset" or "inset" depending on sign + return g_strdup_printf(_("%s by %f pt"), (this->rad >= 0) ? + _("outset") : _("inset"), fabs (this->rad)); +} + void SPOffset::set_shape() { if ( this->originalPath == NULL ) { // oops : no path?! (the offset object should do harakiri) diff --git a/src/sp-offset.h b/src/sp-offset.h index 7fe6a8a24..360bfbf94 100644 --- a/src/sp-offset.h +++ b/src/sp-offset.h @@ -82,6 +82,7 @@ public: virtual void release(); virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); + virtual const char* display_name(); virtual gchar* description(); virtual void set_shape(); diff --git a/src/sp-path.cpp b/src/sp-path.cpp index 105506d6e..49e40fd24 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -66,8 +66,13 @@ gint SPPath::nodesInPath() const return _curve ? _curve->nodes_in_path() : 0; } +const char* SPPath::display_name() { + return _("Path"); +} + gchar* SPPath::description() { int count = this->nodesInPath(); + char *lpe_desc = g_strdup(""); if (sp_lpe_item_has_path_effect(this)) { Glib::ustring s; @@ -87,13 +92,12 @@ gchar* SPPath::description() { s = s + ", " + lpeobj->get_lpe()->getName(); } } - - return g_strdup_printf(ngettext("<b>Path</b> (%i node, path effect: %s)", - "<b>Path</b> (%i nodes, path effect: %s)",count), count, s.c_str()); - } else { - return g_strdup_printf(ngettext("<b>Path</b> (%i node)", - "<b>Path</b> (%i nodes)",count), count); + lpe_desc = g_strdup_printf(_(", path effect: %s"), s.c_str()); } + char *ret = g_strdup_printf(ngettext( + _("%i node%s"), _("%i nodes%s"), count), count, lpe_desc); + g_free(lpe_desc); + return ret; } void SPPath::convert_to_guides() { diff --git a/src/sp-path.h b/src/sp-path.h index 42c0f22c8..ca25de33b 100644 --- a/src/sp-path.h +++ b/src/sp-path.h @@ -54,6 +54,7 @@ public: virtual void set(unsigned int key, gchar const* value); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual const char* display_name(); virtual gchar* description(); virtual Geom::Affine set_transform(Geom::Affine const &transform); virtual void convert_to_guides(); diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp index 519b7ba6e..6d5119e4c 100644 --- a/src/sp-rect.cpp +++ b/src/sp-rect.cpp @@ -159,8 +159,8 @@ Inkscape::XML::Node * SPRect::write(Inkscape::XML::Document *xml_doc, Inkscape:: return repr; } -gchar* SPRect::description() { - return g_strdup(_("<b>Rectangle</b>")); +const char* SPRect::display_name() { + return _("Rectangle"); } #define C1 0.554 diff --git a/src/sp-rect.h b/src/sp-rect.h index 28f74f9f9..e06833916 100644 --- a/src/sp-rect.h +++ b/src/sp-rect.h @@ -55,7 +55,7 @@ public: virtual void update(SPCtx* ctx, unsigned int flags); virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual gchar* description(); + virtual const char* display_name(); virtual void set_shape(); virtual Geom::Affine set_transform(Geom::Affine const& xform); diff --git a/src/sp-root.h b/src/sp-root.h index a9f64a53b..47a37029d 100644 --- a/src/sp-root.h +++ b/src/sp-root.h @@ -41,7 +41,7 @@ public: SVGLength height; /* viewBox; */ - unsigned int viewBox_set : 1; + bool viewBox_set : true; Geom::Rect viewBox; /* preserveAspectRatio */ diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp index 8d2954c6e..e4bfb8c76 100644 --- a/src/sp-spiral.cpp +++ b/src/sp-spiral.cpp @@ -28,7 +28,6 @@ #include "sp-spiral.h" - #include "sp-factory.h" namespace { @@ -227,12 +226,14 @@ void SPSpiral::update_patheffect(bool write) { shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -gchar* SPSpiral::description() { - SPSpiral* item = this; +const char* SPSpiral::display_name() { + return _("Spiral"); +} - // TRANSLATORS: since turn count isn't an integer, please adjust the +gchar* SPSpiral::description() { + // TRANSLATORS: since turn count isn't an integer, please adjust the // string as needed to deal with an localized plural forms. - return g_strdup_printf (_("<b>Spiral</b> with %3f turns"), SP_SPIRAL(item)->revo); + return g_strdup_printf (_("with %3f turns"), SP_SPIRAL(this)->revo); } /** @@ -433,6 +434,58 @@ void SPSpiral::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape } /** + * Set spiral transform + */ +Geom::Affine SPSpiral::set_transform(Geom::Affine const &xform) +{ + // Only set transform with proportional scaling + if (!xform.withoutTranslation().isUniformScale()) { + return xform; + } + + /* Calculate spiral start in parent coords. */ + Geom::Point pos( Geom::Point(this->cx, this->cy) * xform ); + + /* This function takes care of translation and scaling, we return whatever parts we can't + handle. */ + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); + gdouble const s = hypot(ret[0], ret[1]); + if (s > 1e-9) { + ret[0] /= s; + ret[1] /= s; + ret[2] /= s; + ret[3] /= s; + } else { + ret[0] = 1.0; + ret[1] = 0.0; + ret[2] = 0.0; + ret[3] = 1.0; + } + + this->rad *= s; + + /* Find start in item coords */ + pos = pos * ret.inverse(); + this->cx = pos[Geom::X]; + this->cy = pos[Geom::Y]; + + this->set_shape(); + + // Adjust stroke width + this->adjust_stroke(s); + + // Adjust pattern fill + this->adjust_pattern(xform * ret.inverse()); + + // Adjust gradient fill + this->adjust_gradient(xform * ret.inverse()); + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + + return ret; +} + +/** * Return one of the points on the spiral. * * \param t specifies how far along the spiral. diff --git a/src/sp-spiral.h b/src/sp-spiral.h index 1e9c2d2b4..a140d48f9 100644 --- a/src/sp-spiral.h +++ b/src/sp-spiral.h @@ -53,6 +53,7 @@ public: /* Lowlevel interface */ void setPosition(gdouble cx, gdouble cy, gdouble exp, gdouble revo, gdouble rad, gdouble arg, gdouble t0); + virtual Geom::Affine set_transform(Geom::Affine const& xform); Geom::Point getXY(gdouble t) const; @@ -71,6 +72,7 @@ public: virtual void set(unsigned int key, gchar const* value); virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); + virtual const char* display_name(); virtual gchar* description(); virtual void set_shape(); diff --git a/src/sp-star.cpp b/src/sp-star.cpp index 4a3a8cbe3..bc3155caf 100644 --- a/src/sp-star.cpp +++ b/src/sp-star.cpp @@ -251,19 +251,18 @@ void SPStar::update_patheffect(bool write) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +const char* SPStar::display_name() { + if (this->flatsided == false) + return _("Star"); + return _("Polygon"); +} + gchar* SPStar::description() { // while there will never be less than 3 vertices, we still need to // make calls to ngettext because the pluralization may be different // for various numbers >=3. The singular form is used as the index. - if (this->flatsided == false) { - return g_strdup_printf (ngettext("<b>Star</b> with %d vertex", - "<b>Star</b> with %d vertices", - this->sides), this->sides); - } else { - return g_strdup_printf (ngettext("<b>Polygon</b> with %d vertex", - "<b>Polygon</b> with %d vertices", - this->sides), this->sides); - } + return g_strdup_printf (ngettext(_("with %d vertex"), _("with %d vertices"), + this->sides), this->sides); } /** @@ -515,6 +514,55 @@ void SPStar::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape:: } } +Geom::Affine SPStar::set_transform(Geom::Affine const &xform) +{ + // Only set transform with proportional scaling + if (!xform.withoutTranslation().isUniformScale()) { + return xform; + } + + /* Calculate star start in parent coords. */ + Geom::Point pos( this->center * xform ); + + /* This function takes care of translation and scaling, we return whatever parts we can't + handle. */ + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); + gdouble const s = hypot(ret[0], ret[1]); + if (s > 1e-9) { + ret[0] /= s; + ret[1] /= s; + ret[2] /= s; + ret[3] /= s; + } else { + ret[0] = 1.0; + ret[1] = 0.0; + ret[2] = 0.0; + ret[3] = 1.0; + } + + this->r[0] *= s; + this->r[1] *= s; + + /* Find start in item coords */ + pos = pos * ret.inverse(); + this->center = pos; + + this->set_shape(); + + // Adjust stroke width + this->adjust_stroke(s); + + // Adjust pattern fill + this->adjust_pattern(xform * ret.inverse()); + + // Adjust gradient fill + this->adjust_gradient(xform * ret.inverse()); + + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + + return ret; +} + /** * sp_star_get_xy: Get X-Y value as item coordinate system * @star: star item diff --git a/src/sp-star.h b/src/sp-star.h index 0f1280139..3096862cd 100644 --- a/src/sp-star.h +++ b/src/sp-star.h @@ -50,11 +50,13 @@ public: virtual void set(unsigned int key, gchar const* value); virtual void update(SPCtx* ctx, guint flags); + virtual const char* display_name(); virtual gchar* description(); virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); virtual void update_patheffect(bool write); virtual void set_shape(); + virtual Geom::Affine set_transform(Geom::Affine const& xform); }; void sp_star_position_set (SPStar *star, gint sides, Geom::Point center, gdouble r1, gdouble r2, gdouble arg1, gdouble arg2, bool isflat, double rounded, double randomized); diff --git a/src/sp-switch.cpp b/src/sp-switch.cpp index cc50a8fef..c6dcf17e3 100644 --- a/src/sp-switch.cpp +++ b/src/sp-switch.cpp @@ -71,12 +71,14 @@ GSList *SPSwitch::_childList(bool add_ref, SPObject::Action action) { return g_slist_prepend (NULL, child); } +const char *SPSwitch::display_name() { + return _("Conditional Group"); +} + gchar *SPSwitch::description() { gint len = this->getItemCount(); return g_strdup_printf( - ngettext("<b>Conditional group</b> of <b>%d</b> object", - "<b>Conditional group</b> of <b>%d</b> objects", - len), len); + ngettext(_("of <b>%d</b> object"), _("of <b>%d</b> objects"), len), len); } void SPSwitch::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) { diff --git a/src/sp-switch.h b/src/sp-switch.h index 210cd0ddc..5627784cf 100644 --- a/src/sp-switch.h +++ b/src/sp-switch.h @@ -41,6 +41,7 @@ public: virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); virtual void remove_child(Inkscape::XML::Node *child); virtual void order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref); + virtual const char* display_name(); virtual gchar *description(); }; diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 85137e58d..927536dde 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -321,6 +321,9 @@ void SPText::hide(unsigned int key) { // SPItem::onHide(key); } +const char* SPText::display_name() { + return _("Text"); +} gchar* SPText::description() { SPStyle *style = this->style; @@ -350,8 +353,8 @@ gchar* SPText::description() { } char *ret = ( SP_IS_TEXT_TEXTPATH(this) - ? g_strdup_printf(_("<b>Text on path</b>%s (%s, %s)"), trunc, n, xs->str) - : g_strdup_printf(_("<b>Text</b>%s (%s, %s)"), trunc, n, xs->str) ); + ? g_strdup_printf(_("on path%s (%s, %s)"), trunc, n, xs->str) + : g_strdup_printf(_("%s (%s, %s)"), trunc, n, xs->str) ); g_free(n); return ret; } @@ -374,8 +377,13 @@ void SPText::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape:: Geom::Affine SPText::set_transform(Geom::Affine const &xform) { // we cannot optimize textpath because changing its fontsize will break its match to the path - if (SP_IS_TEXT_TEXTPATH (this)) - return xform; + if (SP_IS_TEXT_TEXTPATH (this)) { + if (!this->_optimizeTextpathText) { + return xform; + } else { + this->_optimizeTextpathText = false; + } + } /* This function takes care of scaling & translation only, we return whatever parts we can't handle. */ diff --git a/src/sp-text.h b/src/sp-text.h index 12f773ded..9b8afea6d 100644 --- a/src/sp-text.h +++ b/src/sp-text.h @@ -58,6 +58,8 @@ public: /** discards the drawing objects representing this text. */ void _clearFlow(Inkscape::DrawingGroup *in_arena); + bool _optimizeTextpathText; + private: /** Recursively walks the xml tree adding tags and their contents. The non-trivial code does two things: firstly, it manages the positioning @@ -67,6 +69,10 @@ private: unsigned _buildLayoutInput(SPObject *root, Inkscape::Text::Layout::OptionalTextTagAttrs const &parent_optional_attrs, unsigned parent_attrs_offset, bool in_textpath); public: + /** Optimize textpath text on next set_transform. */ + void optimizeTextpathText() + {_optimizeTextpathText = true;} + virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); virtual void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref); @@ -78,6 +84,7 @@ public: virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); virtual void print(SPPrintContext *ctx); + virtual const char* display_name(); virtual gchar* description(); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void hide(unsigned int key); diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index 1872cdf7c..f0a4af667 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -233,28 +233,30 @@ Geom::OptRect SPTRef::bbox(Geom::Affine const &transform, SPItem::BBoxType type) return bbox; } +const char* SPTRef::display_name() { + return _("Cloned Character Data"); +} + gchar* SPTRef::description() { - SPObject *referred = this->getObjectReferredTo(); + SPObject *referred = this->getObjectReferredTo(); - if (this->getObjectReferredTo()) { - char *child_desc; + if (this->getObjectReferredTo()) { + char *child_desc; - if (SP_IS_ITEM(referred)) { - child_desc = SP_ITEM(referred)->getDetailedDescription(); - } else { - child_desc = g_strdup(""); - } + if (SP_IS_ITEM(referred)) { + child_desc = SP_ITEM(referred)->getDetailedDescription(); + } else { + child_desc = g_strdup(""); + } - char *ret = g_strdup_printf( - _("<b>Cloned character data</b>%s%s"), - (SP_IS_ITEM(referred) ? _(" from ") : ""), - child_desc); - g_free(child_desc); + char *ret = g_strdup_printf("%s%s", + (SP_IS_ITEM(referred) ? _(" from ") : ""), child_desc); + g_free(child_desc); - return ret; - } + return ret; + } - return g_strdup(_("<b>Orphaned cloned character data</b>")); + return g_strdup(_("[orphaned]")); } diff --git a/src/sp-tref.h b/src/sp-tref.h index 451c6cb58..c82970a7f 100644 --- a/src/sp-tref.h +++ b/src/sp-tref.h @@ -58,6 +58,7 @@ public: virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); + virtual const char* display_name(); virtual gchar* description(); }; diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp index 63dcd07d8..43a9faa5e 100644 --- a/src/sp-tspan.cpp +++ b/src/sp-tspan.cpp @@ -216,8 +216,8 @@ Inkscape::XML::Node* SPTSpan::write(Inkscape::XML::Document *xml_doc, Inkscape:: return repr; } -gchar* SPTSpan::description() { - return g_strdup(_("<b>Text span</b>")); +const char* SPTSpan::display_name() { + return _("Text Span"); } diff --git a/src/sp-tspan.h b/src/sp-tspan.h index d1c6ec4bc..ee05073cd 100644 --- a/src/sp-tspan.h +++ b/src/sp-tspan.h @@ -34,7 +34,7 @@ public: virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type); - virtual gchar* description(); + virtual const char* display_name(); }; #endif /* !INKSCAPE_SP_TSPAN_H */ diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 44935e61d..05e1f0e66 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -226,12 +226,17 @@ void SPUse::print(SPPrintContext* ctx) { } } +const char* SPUse::display_name() { + if(this->child && SP_IS_SYMBOL( this->child )) { + return _("Symbol"); + } + return _("Clone"); +} + gchar* SPUse::description() { if (this->child) { if( SP_IS_SYMBOL( this->child ) ) { - char *symbol_desc = SP_ITEM(this->child)->title(); - return g_strdup_printf(_("<b>'%s' Symbol</b>"), symbol_desc ); - g_free(symbol_desc); + return g_strdup_printf(_("called %s"), SP_ITEM(this->child)->title()); } static unsigned recursion_depth = 0; @@ -248,12 +253,12 @@ gchar* SPUse::description() { char *child_desc = SP_ITEM(this->child)->getDetailedDescription(); --recursion_depth; - char *ret = g_strdup_printf(_("<b>Clone</b> of: %s"), child_desc); + char *ret = g_strdup_printf(_("of: %s"), child_desc); g_free(child_desc); return ret; } else { - return g_strdup(_("<b>Orphaned clone</b>")); + return g_strdup(_("[orphaned]")); } } diff --git a/src/sp-use.h b/src/sp-use.h index 37ff2cf66..568b8f7da 100644 --- a/src/sp-use.h +++ b/src/sp-use.h @@ -57,6 +57,7 @@ public: virtual void modified(unsigned int flags); virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype); + virtual const char* display_name(); virtual gchar* description(); virtual void print(SPPrintContext *ctx); virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); diff --git a/src/spiral-context.cpp b/src/spiral-context.cpp index f841fe6d6..24a3ea6de 100644 --- a/src/spiral-context.cpp +++ b/src/spiral-context.cpp @@ -417,6 +417,7 @@ void SPSpiralContext::finishItem() { spiral->set_shape(); spiral->updateRepr(SP_OBJECT_WRITE_EXT); + spiral->doWriteTransform(spiral->getRepr(), spiral->transform, NULL, true); this->desktop->canvas->endForcedFullRedraws(); diff --git a/src/star-context.cpp b/src/star-context.cpp index 1a04f823f..30112cbe9 100644 --- a/src/star-context.cpp +++ b/src/star-context.cpp @@ -443,6 +443,7 @@ void SPStarContext::finishItem() { this->star->setCenter(this->center); this->star->set_shape(); this->star->updateRepr(SP_OBJECT_WRITE_EXT); + this->star->doWriteTransform(this->star->getRepr(), this->star->transform, NULL, true); desktop->canvas->endForcedFullRedraws(); diff --git a/src/style.cpp b/src/style.cpp index e9cf22891..03c90bc09 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -2523,11 +2523,11 @@ sp_style_css_size_px_to_units(double size, int unit) case SP_CSS_UNIT_NONE: unit_size = size; break; case SP_CSS_UNIT_PX: unit_size = size; break; - case SP_CSS_UNIT_PT: unit_size = size * Inkscape::Util::Quantity::convert(1, "px", "pt"); break; - case SP_CSS_UNIT_PC: unit_size = size * (Inkscape::Util::Quantity::convert(1, "px", "pt") / Inkscape::Util::Quantity::convert(1, "pc", "pt")); break; - case SP_CSS_UNIT_MM: unit_size = size * Inkscape::Util::Quantity::convert(1, "px", "mm"); break; - case SP_CSS_UNIT_CM: unit_size = size * Inkscape::Util::Quantity::convert(1, "px", "cm"); break; - case SP_CSS_UNIT_IN: unit_size = size * Inkscape::Util::Quantity::convert(1, "px", "in"); break; + case SP_CSS_UNIT_PT: unit_size = Inkscape::Util::Quantity::convert(size, "px", "pt"); break; + case SP_CSS_UNIT_PC: unit_size = Inkscape::Util::Quantity::convert(size, "px", "pc"); break; + case SP_CSS_UNIT_MM: unit_size = Inkscape::Util::Quantity::convert(size, "px", "mm"); break; + case SP_CSS_UNIT_CM: unit_size = Inkscape::Util::Quantity::convert(size, "px", "cm"); break; + case SP_CSS_UNIT_IN: unit_size = Inkscape::Util::Quantity::convert(size, "px", "in"); break; case SP_CSS_UNIT_EM: unit_size = size / SP_CSS_FONT_SIZE_DEFAULT; break; case SP_CSS_UNIT_EX: unit_size = size * 2.0 / SP_CSS_FONT_SIZE_DEFAULT ; break; case SP_CSS_UNIT_PERCENT: unit_size = size * 100.0 / SP_CSS_FONT_SIZE_DEFAULT; break; @@ -3530,19 +3530,19 @@ sp_style_read_ilength(SPILength *val, gchar const *str) } else if (!strcmp(e, "pt")) { /* Userspace / DEVICESCALE */ val->unit = SP_CSS_UNIT_PT; - val->computed = value * Inkscape::Util::Quantity::convert(1, "pt", "px"); + val->computed = Inkscape::Util::Quantity::convert(value, "pt", "px"); } else if (!strcmp(e, "pc")) { val->unit = SP_CSS_UNIT_PC; - val->computed = value * Inkscape::Util::Quantity::convert(1, "pc", "px"); + val->computed = Inkscape::Util::Quantity::convert(value, "pc", "px"); } else if (!strcmp(e, "mm")) { val->unit = SP_CSS_UNIT_MM; - val->computed = value * Inkscape::Util::Quantity::convert(1, "mm", "px"); + val->computed = Inkscape::Util::Quantity::convert(value, "mm", "px"); } else if (!strcmp(e, "cm")) { val->unit = SP_CSS_UNIT_CM; - val->computed = value * Inkscape::Util::Quantity::convert(1, "cm", "px"); + val->computed = Inkscape::Util::Quantity::convert(value, "cm", "px"); } else if (!strcmp(e, "in")) { val->unit = SP_CSS_UNIT_IN; - val->computed = value * Inkscape::Util::Quantity::convert(1, "in", "px"); + val->computed = Inkscape::Util::Quantity::convert(value, "in", "px"); } else if (!strcmp(e, "em")) { /* EM square */ val->unit = SP_CSS_UNIT_EM; @@ -4204,23 +4204,23 @@ sp_style_write_ilength(gchar *p, gint const len, gchar const *const key, return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_PT: - os << key << ":" << val->computed * Inkscape::Util::Quantity::convert(1, "px", "pt") << "pt;"; + os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "pt") << "pt;"; return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_PC: - os << key << ":" << val->computed * Inkscape::Util::Quantity::convert(1, "px", "pt") / 12.0 << "pc;"; + os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "pc") << "pc;"; return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_MM: - os << key << ":" << val->computed * Inkscape::Util::Quantity::convert(1, "px", "mm") << "mm;"; + os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "mm") << "mm;"; return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_CM: - os << key << ":" << val->computed * Inkscape::Util::Quantity::convert(1, "px", "cm") << "cm;"; + os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "cm") << "cm;"; return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_IN: - os << key << ":" << val->computed * Inkscape::Util::Quantity::convert(1, "px", "in") << "in;"; + os << key << ":" << Inkscape::Util::Quantity::convert(val->computed, "px", "in") << "in;"; return g_strlcpy(p, os.str().c_str(), len); break; case SP_CSS_UNIT_EM: diff --git a/src/svg-view-widget.cpp b/src/svg-view-widget.cpp index d392943e0..567156fec 100644 --- a/src/svg-view-widget.cpp +++ b/src/svg-view-widget.cpp @@ -21,6 +21,7 @@ #include "document.h" #include "svg-view.h" #include "svg-view-widget.h" +#include "util/units.h" static void sp_svg_view_widget_class_init (SPSVGSPViewWidgetClass *klass); static void sp_svg_view_widget_init (SPSVGSPViewWidget *widget); @@ -175,8 +176,8 @@ static void sp_svg_view_widget_size_request(GtkWidget *widget, GtkRequisition *r gdouble width, height; svgv = static_cast<SPSVGView*> (v); - width = (v->doc())->getWidth () * svgv->_hscale; - height = (v->doc())->getHeight () * svgv->_vscale; + width = (v->doc())->getWidth().value("px") * svgv->_hscale; + height = (v->doc())->getHeight().value("px") * svgv->_vscale; if (width <= vw->maxwidth) { hpol = GTK_POLICY_NEVER; diff --git a/src/svg-view.cpp b/src/svg-view.cpp index 7559cbb24..f52608420 100644 --- a/src/svg-view.cpp +++ b/src/svg-view.cpp @@ -20,6 +20,7 @@ #include "sp-item.h" #include "svg-view.h" #include "sp-root.h" +#include "util/units.h" SPSVGView::SPSVGView(SPCanvasGroup *parent) { @@ -71,16 +72,16 @@ void SPSVGView::doRescale(bool event) if (!doc()) { return; } - if (doc()->getWidth () < 1e-9) { + if (doc()->getWidth().value("px") < 1e-9) { return; } - if (doc()->getHeight () < 1e-9) { + if (doc()->getHeight().value("px") < 1e-9) { return; } if (_rescale) { - _hscale = _width / doc()->getWidth (); - _vscale = _height / doc()->getHeight (); + _hscale = _width / doc()->getWidth().value("px"); + _vscale = _height / doc()->getHeight().value("px"); if (_keepaspect) { if (_hscale > _vscale) { _hscale = _vscale; @@ -95,8 +96,8 @@ void SPSVGView::doRescale(bool event) } if (event) { - emitResized (doc()->getWidth () * _hscale, - doc()->getHeight () * _vscale); + emitResized (doc()->getWidth().value("px") * _hscale, + doc()->getHeight().value("px") * _vscale); } } diff --git a/src/text-context.cpp b/src/text-context.cpp index 502973633..10973b7aa 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -441,6 +441,7 @@ static void sp_text_context_setup_text(SPTextContext *tc) text_item->transform = SP_ITEM(ec->desktop->currentLayer())->i2doc_affine().inverse(); text_item->updateRepr(); + text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); DocumentUndo::done(sp_desktop_document(ec->desktop), SP_VERB_CONTEXT_TEXT, _("Create text")); } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 8a7812494..1d91a3b4d 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -1087,8 +1087,8 @@ void ClipboardManagerImpl::_onGet(Gtk::SelectionData &sel, guint /*info*/) Geom::Point origin (_clipboardSPDoc->getRoot()->x.computed, _clipboardSPDoc->getRoot()->y.computed); Geom::Rect area = Geom::Rect(origin, origin + _clipboardSPDoc->getDimensions()); - unsigned long int width = (unsigned long int) (area.width() * dpi / Inkscape::Util::Quantity::convert(1, "in", "px") + 0.5); - unsigned long int height = (unsigned long int) (area.height() * dpi / Inkscape::Util::Quantity::convert(1, "in", "px") + 0.5); + unsigned long int width = (unsigned long int) (Inkscape::Util::Quantity::convert(area.width(), "px", "in") * dpi + 0.5); + unsigned long int height = (unsigned long int) (Inkscape::Util::Quantity::convert(area.height(), "in", "px") * dpi + 0.5); // read from namedview Inkscape::XML::Node *nv = sp_repr_lookup_name (_clipboardSPDoc->rroot, "sodipodi:namedview"); diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 6f1137e46..121773b6d 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -34,6 +34,7 @@ #include "svg-view-widget.h" #include "sp-text.h" #include "text-editing.h" +#include "util/units.h" #include "inkscape-version.h" @@ -175,8 +176,8 @@ Gtk::Widget *build_splash_widget() { GtkWidget *v=sp_svg_view_widget_new(doc); - double width=doc->getWidth(); - double height=doc->getHeight(); + double width=doc->getWidth().value("px"); + double height=doc->getHeight().value("px"); doc->doUnref(); diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 511e63d02..ec04f6d98 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -31,9 +31,12 @@ #include "inkscape.h" #include "io/sys.h" #include "preferences.h" +#include "shape-editor.h" #include "sp-namedview.h" #include "sp-root.h" #include "sp-script.h" +#include "svg/stringstream.h" +#include "tools-switch.h" #include "ui/widget/color-picker.h" #include "ui/widget/scalar-unit.h" #include "ui/dialog/filedialog.h" @@ -53,6 +56,8 @@ #include <gtkmm/stock.h> #include <gtkmm/table.h> +#include <2geom/transforms.h> + using std::pair; namespace Inkscape { @@ -168,6 +173,9 @@ DocumentProperties::DocumentProperties() signalDocumentReplaced().connect(sigc::mem_fun(*this, &DocumentProperties::_handleDocumentReplaced)); signalActivateDesktop().connect(sigc::mem_fun(*this, &DocumentProperties::_handleActivateDesktop)); signalDeactiveDesktop().connect(sigc::mem_fun(*this, &DocumentProperties::_handleDeactivateDesktop)); + + _rum_deflt._changed_connection.block(); + _rum_deflt.getUnitMenu()->signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::onDocUnitChange)); } void DocumentProperties::init() @@ -1432,9 +1440,17 @@ void DocumentProperties::update() if (nv->doc_units) _rum_deflt.setUnit (nv->doc_units->abbr); - double const doc_w_px = sp_desktop_document(dt)->getWidth(); - double const doc_h_px = sp_desktop_document(dt)->getHeight(); - _page_sizer.setDim (doc_w_px, doc_h_px); + double const doc_w = sp_desktop_document(dt)->getRoot()->width.value; + Glib::ustring doc_w_unit = unit_table.getUnit(sp_desktop_document(dt)->getRoot()->width.unit).abbr; + if (doc_w_unit == "") { + doc_w_unit = "px"; + } + double const doc_h = sp_desktop_document(dt)->getRoot()->height.value; + Glib::ustring doc_h_unit = unit_table.getUnit(sp_desktop_document(dt)->getRoot()->height.unit).abbr; + if (doc_h_unit == "") { + doc_h_unit = "px"; + } + _page_sizer.setDim(Inkscape::Util::Quantity(doc_w, doc_w_unit), Inkscape::Util::Quantity(doc_h, doc_h_unit)); _page_sizer.updateFitMarginsUI(nv->getRepr()); //-----------------------------------------------------------guide page @@ -1617,6 +1633,47 @@ void DocumentProperties::onRemoveGrid() } } +/** Callback for document unit change. */ +void DocumentProperties::onDocUnitChange() +{ + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Inkscape::XML::Node *repr = sp_desktop_namedview(getDesktop())->getRepr(); + Inkscape::Util::Unit old_doc_unit = unit_table.getUnit("px"); + if(repr->attribute("inkscape:document-units")) { + old_doc_unit = unit_table.getUnit(repr->attribute("inkscape:document-units")); + } + Inkscape::Util::Unit doc_unit = _rum_deflt.getUnit(); + + // Don't execute when change is being undone + if (!DocumentUndo::getUndoSensitive(doc)) { + return; + } + + // Set document unit + Inkscape::SVGOStringStream os; + os << doc_unit.abbr; + repr->setAttribute("inkscape:document-units", os.str().c_str()); + + // Set viewBox + Inkscape::Util::Quantity width = doc->getWidth(); + Inkscape::Util::Quantity height = doc->getHeight(); + doc->setViewBox(Geom::Rect::from_xywh(0, 0, width.value(doc_unit), height.value(doc_unit))); + + // TODO: Fix bug in nodes tool instead of switching away from it + if (tools_active(getDesktop()) == TOOLS_NODES) { + tools_switch(getDesktop(), TOOLS_SELECT); + } + + // Scale and translate objects + gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); + ShapeEditor::blockSetItem(true); + doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, doc->getHeight().value("px"))); + ShapeEditor::blockSetItem(false); + + doc->setModifiedSinceSave(); + + DocumentUndo::done(doc, SP_VERB_NONE, _("Changed document unit")); +} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 56fed30c4..e3ca91731 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -216,6 +216,9 @@ private: // callback methods for buttons on grids page. void onNewGrid(); void onRemoveGrid(); + + // callback for document unit change + void onDocUnitChange(); }; } // namespace Dialog diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 0b20c08a2..577793496 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -762,7 +762,7 @@ void Export::onAreaToggled () } case SELECTION_PAGE: bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth(), doc->getHeight())); + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); // std::cout << "Using selection: PAGE" << std::endl; key = SELECTION_PAGE; @@ -1475,8 +1475,8 @@ void Export::detectSize() { doc = sp_desktop_document (SP_ACTIVE_DESKTOP); Geom::Point x(0.0, 0.0); - Geom::Point y(doc->getWidth(), - doc->getHeight()); + Geom::Point y(doc->getWidth().value("px"), + doc->getHeight().value("px")); Geom::Rect bbox(x, y); if (bbox_equal(bbox,current_bbox)) { diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index 4c8c77f96..e6dae278b 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -49,8 +49,8 @@ static void draw_page( if (junk->_tab->as_bitmap()) { // Render as exported PNG - gdouble width = (junk->_doc)->getWidth(); - gdouble height = (junk->_doc)->getHeight(); + gdouble width = (junk->_doc)->getWidth().value("px"); + gdouble height = (junk->_doc)->getHeight().value("px"); gdouble dpi = junk->_tab->bitmap_dpi(); std::string tmp_png; std::string tmp_base = "inkscape-print-png-XXXXXX"; @@ -72,8 +72,8 @@ static void draw_page( sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0, width, height, - (unsigned long)(width * dpi / Inkscape::Util::Quantity::convert(1, "in", "px")), - (unsigned long)(height * dpi / Inkscape::Util::Quantity::convert(1, "in", "px")), + (unsigned long)(Inkscape::Util::Quantity::convert(width, "px", "in") * dpi), + (unsigned long)(Inkscape::Util::Quantity::convert(height, "px", "in") * dpi), dpi, dpi, bgcolor, NULL, NULL, true, NULL); // This doesn't seem to work: @@ -195,8 +195,8 @@ Print::Print(SPDocument *doc, SPItem *base) : // set up paper size to match the document size gtk_print_operation_set_unit (_printop, GTK_UNIT_POINTS); GtkPageSetup *page_setup = gtk_page_setup_new(); - gdouble doc_width = _doc->getWidth() * Inkscape::Util::Quantity::convert(1, "px", "pt"); - gdouble doc_height = _doc->getHeight() * Inkscape::Util::Quantity::convert(1, "px", "pt"); + gdouble doc_width = _doc->getWidth().value("pt"); + gdouble doc_height = _doc->getHeight().value("pt"); GtkPaperSize *paper_size; if (doc_width > doc_height) { gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_LANDSCAPE); diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 4a25f723b..9124681a0 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -401,7 +401,7 @@ void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); - double pt_size = sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit) * Inkscape::Util::Quantity::convert(1, "px", "pt"); + double pt_size = Inkscape::Util::Quantity::convert(sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit), "px", "pt"); // Pango font size is in 1024ths of a point // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE ); diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index 8287452d7..051937c43 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -442,6 +442,7 @@ PageSizer::init () _portrait_connection = _portraitButton.signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait)); _changedw_connection = _dimensionWidth.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); _changedh_connection = _dimensionHeight.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + _changedu_connection = _dimensionUnits.getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &PageSizer::on_units_changed)); _fitPageButton.signal_clicked().connect(sigc::mem_fun(*this, &PageSizer::fire_fit_canvas_to_selection_or_drawing)); show_all_children(); @@ -454,11 +455,11 @@ PageSizer::init () * 'changeList' is true, then adjust the paperSizeList to show the closest * standard page size. * - * \param w, h given in px + * \param w, h * \param changeList whether to modify the paper size list */ void -PageSizer::setDim (double w, double h, bool changeList) +PageSizer::setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool changeList) { static bool _called = false; if (_called) { @@ -475,12 +476,12 @@ PageSizer::setDim (double w, double h, bool changeList) if (SP_ACTIVE_DESKTOP && !_widgetRegistry->isUpdating()) { SPDocument *doc = sp_desktop_document(SP_ACTIVE_DESKTOP); - double const old_height = doc->getHeight(); - doc->setWidth (Inkscape::Util::Quantity(w, "px")); - doc->setHeight (Inkscape::Util::Quantity(h, "px")); + Inkscape::Util::Quantity const old_height = doc->getHeight(); + doc->setWidth (w); + doc->setHeight (h); // The origin for the user is in the lower left corner; this point should remain stationary when // changing the page size. The SVG's origin however is in the upper left corner, so we must compensate for this - Geom::Translate const vert_offset(Geom::Point(0, (old_height - h))); + Geom::Translate const vert_offset(Geom::Point(0, (old_height.value("px") - h.value("px")))); doc->getRoot()->translateChildItems(vert_offset); DocumentUndo::done(doc, SP_VERB_NONE, _("Set page size")); } @@ -503,9 +504,10 @@ PageSizer::setDim (double w, double h, bool changeList) _paperSizeListSelection->select(row); } - Unit const& unit = _dimensionUnits.getUnit(); - _dimensionWidth.setValue (w / unit.factor); - _dimensionHeight.setValue (h / unit.factor); + _dimensionWidth.setUnit(w.unit->abbr); + _dimensionWidth.setValue (w.quantity); + _dimensionHeight.setUnit(h.unit->abbr); + _dimensionHeight.setValue (h.quantity); _paper_size_list_connection.unblock(); _landscape_connection.unblock(); @@ -547,12 +549,12 @@ PageSizer::updateFitMarginsUI(Inkscape::XML::Node *nv_repr) * paperSizeListStore->children().end() if no such paper exists. */ Gtk::ListStore::iterator -PageSizer::find_paper_size (double w, double h) const +PageSizer::find_paper_size (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h) const { - double smaller = w; - double larger = h; + double smaller = w.quantity; + double larger = h.quantity; if ( h < w ) { - smaller = h; larger = w; + smaller = h.quantity; larger = w.quantity; } g_return_val_if_fail(smaller <= larger, _paperSizeListStore->children().end()); @@ -562,8 +564,8 @@ PageSizer::find_paper_size (double w, double h) const iter != _paperSizeTable.end() ; ++iter) { PaperSize paper = iter->second; Inkscape::Util::Unit const &i_unit = paper.unit; - double smallX = Inkscape::Util::Quantity::convert(paper.smaller, i_unit, "px"); - double largeX = Inkscape::Util::Quantity::convert(paper.larger, i_unit, "px"); + double smallX = Inkscape::Util::Quantity::convert(paper.smaller, i_unit, *w.unit); + double largeX = Inkscape::Util::Quantity::convert(paper.larger, i_unit, *w.unit); g_return_val_if_fail(smallX <= largeX, _paperSizeListStore->children().end()); @@ -643,8 +645,8 @@ PageSizer::on_paper_size_list_changed() return; } PaperSize paper = piter->second; - double w = paper.smaller; - double h = paper.larger; + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(paper.smaller, paper.unit); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(paper.larger, paper.unit); if (std::find(lscape_papers.begin(), lscape_papers.end(), paper.name.c_str()) != lscape_papers.end()) { // enforce landscape mode if this is desired for the given page format @@ -654,9 +656,6 @@ PageSizer::on_paper_size_list_changed() _landscape = _landscapeButton.get_active(); } - w = Inkscape::Util::Quantity::convert(w, paper.unit, "px"); - h = Inkscape::Util::Quantity::convert(h, paper.unit, "px"); - if (_landscape) setDim (h, w, false); else @@ -673,8 +672,8 @@ PageSizer::on_portrait() { if (!_portraitButton.get_active()) return; - double w = _dimensionWidth.getValue ("px"); - double h = _dimensionHeight.getValue ("px"); + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); if (h < w) { setDim (h, w); } @@ -689,8 +688,8 @@ PageSizer::on_landscape() { if (!_landscapeButton.get_active()) return; - double w = _dimensionWidth.getValue ("px"); - double h = _dimensionHeight.getValue ("px"); + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); if (w < h) { setDim (h, w); } @@ -703,11 +702,18 @@ void PageSizer::on_value_changed() { if (_widgetRegistry->isUpdating()) return; - - setDim (_dimensionWidth.getValue("px"), - _dimensionHeight.getValue("px")); + if (_unit != _dimensionUnits.getUnit().abbr) return; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit())); +} +void +PageSizer::on_units_changed() +{ + if (_widgetRegistry->isUpdating()) return; + _unit = _dimensionUnits.getUnit().abbr; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit())); } - } // namespace Widget } // namespace UI diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h index 34ed7592d..95836a005 100644 --- a/src/ui/widget/page-sizer.h +++ b/src/ui/widget/page-sizer.h @@ -161,7 +161,7 @@ public: * Set the page size to the given dimensions. If 'changeList' is * true, then reset the paper size list to the closest match */ - void setDim (double w, double h, bool changeList=true); + void setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool changeList=true); /** * Updates the scalar widgets for the fit margins. (Just changes the value @@ -179,7 +179,7 @@ protected: /** * Find the closest standard paper size in the table, to the */ - Gtk::ListStore::iterator find_paper_size (double w, double h) const; + Gtk::ListStore::iterator find_paper_size (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h) const; void fire_fit_canvas_to_selection_or_drawing(); @@ -252,13 +252,17 @@ protected: //callback void on_value_changed(); + void on_units_changed(); sigc::connection _changedw_connection; sigc::connection _changedh_connection; + sigc::connection _changedu_connection; Registry *_widgetRegistry; //### state - whether we are currently landscape or portrait bool _landscape; + + Glib::ustring _unit; }; diff --git a/src/ui/widget/spinbutton.cpp b/src/ui/widget/spinbutton.cpp index c107979a8..62c17f821 100644 --- a/src/ui/widget/spinbutton.cpp +++ b/src/ui/widget/spinbutton.cpp @@ -14,6 +14,7 @@ #include "spinbutton.h" #include "unit-menu.h" +#include "unit-tracker.h" #include "util/expression-evaluator.h" #include "event-context.h" @@ -32,16 +33,23 @@ SpinButton::connect_signals() { int SpinButton::on_input(double* newvalue) { try { - Inkscape::Util::GimpEevlQuantity result; - if (_unit_menu) { - Unit unit = _unit_menu->getUnit(); - result = Inkscape::Util::gimp_eevl_evaluate (get_text().c_str(), &unit); + Inkscape::Util::EvaluatorQuantity result; + if (_unit_menu || _unit_tracker) { + Unit unit; + if (_unit_menu) { + unit = _unit_menu->getUnit(); + } else { + unit = _unit_tracker->getActiveUnit(); + } + Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), &unit); + result = eval.evaluate(); // check if output dimension corresponds to input unit if (result.dimension != (unit.isAbsolute() ? 1 : 0) ) { throw Inkscape::Util::EvaluatorException("Input dimensions do not match with parameter dimensions.",""); } } else { - result = Inkscape::Util::gimp_eevl_evaluate (get_text().c_str(), NULL); + Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), NULL); + result = eval.evaluate(); } *newvalue = result.value; diff --git a/src/ui/widget/spinbutton.h b/src/ui/widget/spinbutton.h index fe5d699e7..c772fe2a2 100644 --- a/src/ui/widget/spinbutton.h +++ b/src/ui/widget/spinbutton.h @@ -25,6 +25,7 @@ namespace UI { namespace Widget { class UnitMenu; +class UnitTracker; /** * SpinButton widget, that allows entry of simple math expressions (also units, when linked with UnitMenu), @@ -50,14 +51,18 @@ public: _unit_menu(NULL) { connect_signals(); + _unit_tracker = NULL; }; virtual ~SpinButton() {}; void setUnitMenu(UnitMenu* unit_menu) { _unit_menu = unit_menu; }; + + void addUnitTracker(UnitTracker* ut) { _unit_tracker = ut; }; protected: UnitMenu *_unit_menu; /// Linked unit menu for unit conversion in entered expressions. + UnitTracker *_unit_tracker; // Linked unit tracker for unit conversion in entered expressions. void connect_signals(); diff --git a/src/util/expression-evaluator.cpp b/src/util/expression-evaluator.cpp index dc59c67f4..3b7e77c6c 100644 --- a/src/util/expression-evaluator.cpp +++ b/src/util/expression-evaluator.cpp @@ -6,6 +6,7 @@ * Copyright (C) 2008 Martin Nordholts <martinn@svn.gnome.org> * Modified for Inkscape by Johan Engelen * Copyright (C) 2011 Johan Engelen + * Copyright (C) 2013 Matthew Petroff * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,6 +28,7 @@ #include "util/expression-evaluator.h" #include "util/units.h" +#include <math.h> #include <string.h> using Inkscape::Util::unit_table; @@ -34,495 +36,353 @@ using Inkscape::Util::unit_table; namespace Inkscape { namespace Util { -enum +EvaluatorQuantity::EvaluatorQuantity(double value, unsigned int dimension) : + value(value), + dimension(dimension) { - GIMP_EEVL_TOKEN_NUM = 30000, - GIMP_EEVL_TOKEN_IDENTIFIER = 30001, - - GIMP_EEVL_TOKEN_ANY = 40000, - - GIMP_EEVL_TOKEN_END = 50000 -}; - -typedef int GimpEevlTokenType; - - -typedef struct -{ - GimpEevlTokenType type; - - union - { - gdouble fl; - - struct - { - const gchar *c; - gint size; - }; - - } value; - -} GimpEevlToken; +} -typedef struct +EvaluatorToken::EvaluatorToken() { - const gchar *string; - GimpEevlUnitResolverProc unit_resolver_proc; - Unit *unit; - - GimpEevlToken current_token; - const gchar *start_of_current_token; -} GimpEevl; + type = 0; + value.fl = 0; +} -/** Unit Resolver... - */ -static bool unitresolverproc (const gchar* identifier, GimpEevlQuantity *result, Unit* unit) +ExpressionEvaluator::ExpressionEvaluator(const char *string, Unit *unit) : + string(string), + unit(unit) { - if (!unit) { - result->value = 1; - result->dimension = 1; - return true; - }else if (!identifier) { - result->value = 1; - result->dimension = unit->isAbsolute() ? 1 : 0; - return true; - } else if (unit_table.hasUnit(identifier)) { - Unit identifier_unit = unit_table.getUnit(identifier); - - // Catch the case of zero or negative unit factors (error!) - if (identifier_unit.factor < 0.0000001) { - return false; - } - - result->value = unit->factor / identifier_unit.factor; - result->dimension = identifier_unit.isAbsolute() ? 1 : 0; - return true; - } else { - return false; - } + current_token.type = TOKEN_END; + + // Preload symbol + parseNextToken(); } -static void gimp_eevl_init (GimpEevl *eva, - const gchar *string, - GimpEevlUnitResolverProc unit_resolver_proc, - Unit *unit); -static GimpEevlQuantity gimp_eevl_complete (GimpEevl *eva); -static GimpEevlQuantity gimp_eevl_expression (GimpEevl *eva); -static GimpEevlQuantity gimp_eevl_term (GimpEevl *eva); -static GimpEevlQuantity gimp_eevl_signed_factor (GimpEevl *eva); -static GimpEevlQuantity gimp_eevl_factor (GimpEevl *eva); -static gboolean gimp_eevl_accept (GimpEevl *eva, - GimpEevlTokenType token_type, - GimpEevlToken *consumed_token); -static void gimp_eevl_lex (GimpEevl *eva); -static void gimp_eevl_lex_accept_count (GimpEevl *eva, - gint count, - GimpEevlTokenType token_type); -static void gimp_eevl_lex_accept_to (GimpEevl *eva, - gchar *to, - GimpEevlTokenType token_type); -static void gimp_eevl_move_past_whitespace (GimpEevl *eva); -static gboolean gimp_eevl_unit_identifier_start (gunichar c); -static gboolean gimp_eevl_unit_identifier_continue (gunichar c); -static gint gimp_eevl_unit_identifier_size (const gchar *s, - gint start); -static void gimp_eevl_expect (GimpEevl *eva, - GimpEevlTokenType token_type, - GimpEevlToken *value); -static void gimp_eevl_error (GimpEevl *eva, - const char *msg); - - /** * Evaluates the given arithmetic expression, along with an optional dimension * analysis, and basic unit conversions. * - * @param string The NULL-terminated string to be evaluated. - * @param unit_resolver_proc Unit resolver callback. - * * All units conversions factors are relative to some implicit - * base-unit (which in GIMP is inches). This is also the unit of the - * returned value. + * base-unit. This is also the unit of the returned value. * - * Returns: A #GimpEevlQuantity with a value given in the base unit along with - * the order of the dimension (i.e. if the base unit is inches, a dimension - * order of two menas in^2). + * Returns: An EvaluatorQuantity with a value given in the base unit along with + * the order of the dimension (e.g. if the base unit is inches, a dimension + * order of two means in^2). * * @return Result of evaluation. * @throws Inkscape::Util::EvaluatorException There was a parse error. **/ -GimpEevlQuantity -gimp_eevl_evaluate (const gchar* string, Unit* unit) +EvaluatorQuantity ExpressionEvaluator::evaluate() { - if (! g_utf8_validate (string, -1, NULL)) { + if (!g_utf8_validate(string, -1, NULL)) { throw EvaluatorException("Invalid UTF8 string", NULL); } - - GimpEevl eva; - gimp_eevl_init (&eva, string, unitresolverproc, unit); - - return gimp_eevl_complete(&eva); -} - -static void -gimp_eevl_init (GimpEevl *eva, - const gchar *string, - GimpEevlUnitResolverProc unit_resolver_proc, - Unit *unit) -{ - eva->string = string; - eva->unit_resolver_proc = unit_resolver_proc; - eva->unit = unit; - - eva->current_token.type = GIMP_EEVL_TOKEN_END; - - /* Preload symbol... */ - gimp_eevl_lex (eva); -} - -static GimpEevlQuantity -gimp_eevl_complete (GimpEevl *eva) -{ - GimpEevlQuantity result = {0, 0}; - GimpEevlQuantity default_unit_factor; - - /* Empty expression evaluates to 0 */ - if (gimp_eevl_accept (eva, GIMP_EEVL_TOKEN_END, NULL)) - return result; - - result = gimp_eevl_expression (eva); - - /* There should be nothing left to parse by now */ - gimp_eevl_expect (eva, GIMP_EEVL_TOKEN_END, 0); - - eva->unit_resolver_proc (NULL, &default_unit_factor, eva->unit); - - /* Entire expression is dimensionless, apply default unit if - * applicable - */ - if (result.dimension == 0 && default_unit_factor.dimension != 0) - { - result.value /= default_unit_factor.value; - result.dimension = default_unit_factor.dimension; + + EvaluatorQuantity result = EvaluatorQuantity(); + EvaluatorQuantity default_unit_factor; + + // Empty expression evaluates to 0 + if (acceptToken(TOKEN_END, NULL)) { + return result; + } + + result = evaluateExpression(); + + // There should be nothing left to parse by now + isExpected(TOKEN_END, 0); + + resolveUnit(NULL, &default_unit_factor, unit); + + // Entire expression is dimensionless, apply default unit if applicable + if ( result.dimension == 0 && default_unit_factor.dimension != 0 ) { + result.value /= default_unit_factor.value; + result.dimension = default_unit_factor.dimension; } - return result; + return result; } -static GimpEevlQuantity -gimp_eevl_expression (GimpEevl *eva) +EvaluatorQuantity ExpressionEvaluator::evaluateExpression() { - gboolean subtract; - GimpEevlQuantity evaluated_terms; - - evaluated_terms = gimp_eevl_term (eva); - - /* continue evaluating terms, chained with + or -. */ - for (subtract = FALSE; - gimp_eevl_accept (eva, '+', NULL) || - (subtract = gimp_eevl_accept (eva, '-', NULL)); - subtract = FALSE) + bool subtract; + EvaluatorQuantity evaluated_terms; + + evaluated_terms = evaluateTerm(); + + // Continue evaluating terms, chained with + or -. + for (subtract = FALSE; + acceptToken('+', NULL) || (subtract = acceptToken('-', NULL)); + subtract = FALSE) { - GimpEevlQuantity new_term = gimp_eevl_term (eva); - - /* If dimensions missmatch, attempt default unit assignent */ - if (new_term.dimension != evaluated_terms.dimension) - { - GimpEevlQuantity default_unit_factor; - - eva->unit_resolver_proc (NULL, - &default_unit_factor, - eva->unit); - - if (new_term.dimension == 0 && - evaluated_terms.dimension == default_unit_factor.dimension) + EvaluatorQuantity new_term = evaluateTerm(); + + // If dimensions mismatch, attempt default unit assignent + if ( new_term.dimension != evaluated_terms.dimension ) { + EvaluatorQuantity default_unit_factor; + + resolveUnit(NULL, &default_unit_factor, unit); + + if ( new_term.dimension == 0 + && evaluated_terms.dimension == default_unit_factor.dimension ) { - new_term.value /= default_unit_factor.value; - new_term.dimension = default_unit_factor.dimension; - } - else if (evaluated_terms.dimension == 0 && - new_term.dimension == default_unit_factor.dimension) + new_term.value /= default_unit_factor.value; + new_term.dimension = default_unit_factor.dimension; + } else if ( evaluated_terms.dimension == 0 + && new_term.dimension == default_unit_factor.dimension ) { - evaluated_terms.value /= default_unit_factor.value; - evaluated_terms.dimension = default_unit_factor.dimension; - } - else - { - gimp_eevl_error (eva, "Dimension missmatch during addition"); + evaluated_terms.value /= default_unit_factor.value; + evaluated_terms.dimension = default_unit_factor.dimension; + } else { + throwError("Dimension mismatch during addition"); } } - - evaluated_terms.value += (subtract ? -new_term.value : new_term.value); + + evaluated_terms.value += (subtract ? -new_term.value : new_term.value); } - - return evaluated_terms; + + return evaluated_terms; } -static GimpEevlQuantity -gimp_eevl_term (GimpEevl *eva) +EvaluatorQuantity ExpressionEvaluator::evaluateTerm() { - gboolean division; - GimpEevlQuantity evaluated_signed_factors; - - evaluated_signed_factors = gimp_eevl_signed_factor (eva); - - for (division = FALSE; - gimp_eevl_accept (eva, '*', NULL) || - (division = gimp_eevl_accept (eva, '/', NULL)); - division = FALSE) + bool division; + EvaluatorQuantity evaluated_exp_terms = evaluateExpTerm(); + + for ( division = false; + acceptToken('*', NULL) || (division = acceptToken('/', NULL)); + division = false ) { - GimpEevlQuantity new_signed_factor = gimp_eevl_signed_factor (eva); - - if (division) - { - evaluated_signed_factors.value /= new_signed_factor.value; - evaluated_signed_factors.dimension -= new_signed_factor.dimension; - - } - else - { - evaluated_signed_factors.value *= new_signed_factor.value; - evaluated_signed_factors.dimension += new_signed_factor.dimension; + EvaluatorQuantity new_exp_term = evaluateExpTerm(); + + if (division) { + evaluated_exp_terms.value /= new_exp_term.value; + evaluated_exp_terms.dimension -= new_exp_term.dimension; + } else { + evaluated_exp_terms.value *= new_exp_term.value; + evaluated_exp_terms.dimension += new_exp_term.dimension; } } - - return evaluated_signed_factors; -} - -static GimpEevlQuantity -gimp_eevl_signed_factor (GimpEevl *eva) -{ - GimpEevlQuantity result; - gboolean negate = FALSE; - - if (! gimp_eevl_accept (eva, '+', NULL)) - negate = gimp_eevl_accept (eva, '-', NULL); - - result = gimp_eevl_factor (eva); - - if (negate) result.value = -result.value; - - return result; + + return evaluated_exp_terms; } -static GimpEevlQuantity -gimp_eevl_factor (GimpEevl *eva) +EvaluatorQuantity ExpressionEvaluator::evaluateExpTerm() { - GimpEevlQuantity evaluated_factor = { 0, 0 }; - GimpEevlToken consumed_token; - - if (gimp_eevl_accept (eva, - GIMP_EEVL_TOKEN_NUM, - &consumed_token)) - { - evaluated_factor.value = consumed_token.value.fl; - } - else if (gimp_eevl_accept (eva, '(', NULL)) - { - evaluated_factor = gimp_eevl_expression (eva); - gimp_eevl_expect (eva, ')', 0); - } - else - { - gimp_eevl_error (eva, "Expected number or '('"); - } - - if (eva->current_token.type == GIMP_EEVL_TOKEN_IDENTIFIER) - { - gchar *identifier; - GimpEevlQuantity result; - - gimp_eevl_accept (eva, - GIMP_EEVL_TOKEN_ANY, - &consumed_token); - - identifier = g_newa (gchar, consumed_token.value.size + 1); - - strncpy (identifier, consumed_token.value.c, consumed_token.value.size); - identifier[consumed_token.value.size] = '\0'; - - if (eva->unit_resolver_proc (identifier, - &result, - eva->unit)) - { - evaluated_factor.value /= result.value; - evaluated_factor.dimension += result.dimension; - } - else - { - gimp_eevl_error (eva, "Unit was not resolved"); + EvaluatorQuantity evaluated_signed_factors = evaluateSignedFactor(); + + while(acceptToken('^', NULL)) { + EvaluatorQuantity new_signed_factor = evaluateSignedFactor(); + + if (new_signed_factor.dimension == 0) { + evaluated_signed_factors.value = pow(evaluated_signed_factors.value, + new_signed_factor.value); + evaluated_signed_factors.dimension *= new_signed_factor.value; + } else { + throwError("Unit in exponent"); } } - - return evaluated_factor; + + return evaluated_signed_factors; } -static gboolean -gimp_eevl_accept (GimpEevl *eva, - GimpEevlTokenType token_type, - GimpEevlToken *consumed_token) +EvaluatorQuantity ExpressionEvaluator::evaluateSignedFactor() { - gboolean existed = FALSE; - - if (token_type == eva->current_token.type || - token_type == GIMP_EEVL_TOKEN_ANY) - { - existed = TRUE; - - if (consumed_token) - *consumed_token = eva->current_token; - - /* Parse next token */ - gimp_eevl_lex (eva); + EvaluatorQuantity result; + bool negate = FALSE; + + if (!acceptToken('+', NULL)) { + negate = acceptToken ('-', NULL); } - - return existed; + + result = evaluateFactor(); + + if (negate) { + result.value = -result.value; + } + + return result; } -static void -gimp_eevl_lex (GimpEevl *eva) +EvaluatorQuantity ExpressionEvaluator::evaluateFactor() { - const gchar *s; - - gimp_eevl_move_past_whitespace (eva); - s = eva->string; - eva->start_of_current_token = s; - - if (! s || s[0] == '\0') - { - /* We're all done */ - eva->current_token.type = GIMP_EEVL_TOKEN_END; - } - else if (s[0] == '+' || s[0] == '-') - { - /* Snatch these before the g_strtod() does, othewise they might - * be used in a numeric conversion. - */ - gimp_eevl_lex_accept_count (eva, 1, s[0]); + EvaluatorQuantity evaluated_factor = EvaluatorQuantity(); + EvaluatorToken consumed_token = EvaluatorToken(); + + if (acceptToken(TOKEN_NUM, &consumed_token)) { + evaluated_factor.value = consumed_token.value.fl; + } else if (acceptToken('(', NULL)) { + evaluated_factor = evaluateExpression(); + isExpected(')', 0); + } else { + throwError("Expected number or '('"); } - else - { - /* Attempt to parse a numeric value */ - gchar *endptr = NULL; - gdouble value = g_strtod (s, &endptr); - - if (endptr && endptr != s) - { - /* A numeric could be parsed, use it */ - eva->current_token.value.fl = value; - - gimp_eevl_lex_accept_to (eva, endptr, GIMP_EEVL_TOKEN_NUM); + if ( current_token.type == TOKEN_IDENTIFIER ) { + char *identifier; + EvaluatorQuantity result; + + acceptToken(TOKEN_ANY, &consumed_token); + + identifier = g_newa(char, consumed_token.value.size + 1); + + strncpy(identifier, consumed_token.value.c, consumed_token.value.size); + identifier[consumed_token.value.size] = '\0'; + + if (resolveUnit(identifier, &result, unit)) { + evaluated_factor.value /= result.value; + evaluated_factor.dimension += result.dimension; + } else { + throwError("Unit was not resolved"); } - else if (gimp_eevl_unit_identifier_start (s[0])) - { - /* Unit identifier */ - eva->current_token.value.c = s; - eva->current_token.value.size = gimp_eevl_unit_identifier_size (s, 0); + } + + return evaluated_factor; +} - gimp_eevl_lex_accept_count (eva, - eva->current_token.value.size, - GIMP_EEVL_TOKEN_IDENTIFIER); - } - else - { - /* Everything else is a single character token */ - gimp_eevl_lex_accept_count (eva, 1, s[0]); +bool ExpressionEvaluator::acceptToken(TokenType token_type, + EvaluatorToken *consumed_token) +{ + bool existed = FALSE; + + if ( token_type == current_token.type || token_type == TOKEN_ANY ) { + existed = TRUE; + + if (consumed_token) { + *consumed_token = current_token; } + + // Parse next token + parseNextToken(); } + + return existed; } -static void -gimp_eevl_lex_accept_count (GimpEevl *eva, - gint count, - GimpEevlTokenType token_type) +void ExpressionEvaluator::parseNextToken() { - eva->current_token.type = token_type; - eva->string += count; + const char *s; + + movePastWhiteSpace(); + s = string; + start_of_current_token = s; + + if ( !s || s[0] == '\0' ) { + // We're all done + current_token.type = TOKEN_END; + } else if ( s[0] == '+' || s[0] == '-' ) { + // Snatch these before the g_strtod() does, othewise they might + // be used in a numeric conversion. + acceptTokenCount(1, s[0]); + } else { + // Attempt to parse a numeric value + char *endptr = NULL; + gdouble value = g_strtod(s, &endptr); + + if ( endptr && endptr != s ) { + // A numeric could be parsed, use it + current_token.value.fl = value; + + current_token.type = TOKEN_NUM; + string = endptr; + } else if (isUnitIdentifierStart(s[0])) { + // Unit identifier + current_token.value.c = s; + current_token.value.size = getIdentifierSize(s, 0); + + acceptTokenCount(current_token.value.size, TOKEN_IDENTIFIER); + } else { + // Everything else is a single character token + acceptTokenCount(1, s[0]); + } + } } -static void -gimp_eevl_lex_accept_to (GimpEevl *eva, - gchar *to, - GimpEevlTokenType token_type) +void ExpressionEvaluator::acceptTokenCount (int count, TokenType token_type) { - eva->current_token.type = token_type; - eva->string = to; + current_token.type = token_type; + string += count; } -static void -gimp_eevl_move_past_whitespace (GimpEevl *eva) +void ExpressionEvaluator::isExpected(TokenType token_type, + EvaluatorToken *value) { - if (! eva->string) - return; - - while (g_ascii_isspace (*eva->string)) - eva->string++; + if (!acceptToken(token_type, value)) { + throwError("Unexpected token"); + } } -static gboolean -gimp_eevl_unit_identifier_start (gunichar c) +void ExpressionEvaluator::movePastWhiteSpace() { - return (g_unichar_isalpha (c) || - c == (gunichar) '%' || - c == (gunichar) '\''); + if (!string) { + return; + } + + while (g_ascii_isspace(*string)) { + string++; + } } -static gboolean -gimp_eevl_unit_identifier_continue (gunichar c) +bool ExpressionEvaluator::isUnitIdentifierStart(gunichar c) { - return (gimp_eevl_unit_identifier_start (c) || - g_unichar_isdigit (c)); + return (g_unichar_isalpha (c) + || c == (gunichar) '%' + || c == (gunichar) '\''); } /** - * gimp_eevl_unit_identifier_size: + * getIdentifierSize: * @s: * @start: * * Returns: Size of identifier in bytes (not including NULL * terminator). **/ -static gint -gimp_eevl_unit_identifier_size (const gchar *string, - gint start_offset) +int ExpressionEvaluator::getIdentifierSize(const char *string, int start_offset) { - const gchar *start = g_utf8_offset_to_pointer (string, start_offset); - const gchar *s = start; - gunichar c = g_utf8_get_char (s); - gint length = 0; - - if (gimp_eevl_unit_identifier_start (c)) - { - s = g_utf8_next_char (s); - c = g_utf8_get_char (s); - length++; - - while (gimp_eevl_unit_identifier_continue (c)) - { - s = g_utf8_next_char (s); - c = g_utf8_get_char (s); - length++; + const char *start = g_utf8_offset_to_pointer(string, start_offset); + const char *s = start; + gunichar c = g_utf8_get_char(s); + int length = 0; + + if (isUnitIdentifierStart(c)) { + s = g_utf8_next_char (s); + c = g_utf8_get_char (s); + length++; + + while ( isUnitIdentifierStart (c) || g_unichar_isdigit (c) ) { + s = g_utf8_next_char(s); + c = g_utf8_get_char(s); + length++; } } - - return g_utf8_offset_to_pointer (start, length) - start; + + return g_utf8_offset_to_pointer(start, length) - start; } -static void -gimp_eevl_expect (GimpEevl *eva, - GimpEevlTokenType token_type, - GimpEevlToken *value) +bool ExpressionEvaluator::resolveUnit (const char* identifier, + EvaluatorQuantity *result, + Unit* unit) { - if (! gimp_eevl_accept (eva, token_type, value)) - gimp_eevl_error (eva, "Unexpected token"); + if (!unit) { + result->value = 1; + result->dimension = 1; + return true; + }else if (!identifier) { + result->value = 1; + result->dimension = unit->isAbsolute() ? 1 : 0; + return true; + } else if (unit_table.hasUnit(identifier)) { + Unit identifier_unit = unit_table.getUnit(identifier); + result->value = Quantity::convert(1, *unit, identifier_unit); + result->dimension = identifier_unit.isAbsolute() ? 1 : 0; + return true; + } else { + return false; + } } -static void -gimp_eevl_error (GimpEevl *eva, - const char *msg) +void ExpressionEvaluator::throwError(const char *msg) { - throw EvaluatorException(msg, eva->start_of_current_token); + throw EvaluatorException(msg, start_of_current_token); } } // namespace Util diff --git a/src/util/expression-evaluator.h b/src/util/expression-evaluator.h index 4b1065268..6412dfea7 100644 --- a/src/util/expression-evaluator.h +++ b/src/util/expression-evaluator.h @@ -6,6 +6,7 @@ * Copyright (C) 2008-2009 Martin Nordholts <martinn@svn.gnome.org> * Modified for Inkscape by Johan Engelen * Copyright (C) 2011 Johan Engelen + * Copyright (C) 2013 Matthew Petroff * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,8 +23,8 @@ * <http://www.gnu.org/licenses/>. */ -#ifndef SEEN_GIMP_EEVL_H -#define SEEN_GIMP_EEVL_H +#ifndef INKSCAPE_UTIL_EXPRESSION_EVALUATOR_H +#define INKSCAPE_UTIL_EXPRESSION_EVALUATOR_H #include "util/units.h" @@ -33,7 +34,7 @@ /** * @file - * Introducing eevl eva, the evaluator. A straightforward recursive + * Expression evaluator: A straightforward recursive * descent parser, no fuss, no new dependencies. The lexer is hand * coded, tedious, not extremely fast but works. It evaluates the * expression as it goes along, and does not create a parse tree or @@ -43,8 +44,8 @@ * * It relies on external unit resolving through a callback and does * elementary dimensionality constraint check (e.g. "2 mm + 3 px * 4 - * in" is an error, as L + L^2 is a missmatch). It uses g_strtod() for numeric - * conversions and it's non-destructive in terms of the paramters, and + * in" is an error, as L + L^2 is a mismatch). It uses g_strtod() for numeric + * conversions and it's non-destructive in terms of the parameters, and * it's reentrant. * * EBNF: @@ -52,7 +53,9 @@ * expression ::= term { ('+' | '-') term }* | * <empty string> ; * - * term ::= signed factor { ( '*' | '/' ) signed factor }* ; + * term ::= exponent { ( '*' | '/' ) exponent }* ; + * + * exponent ::= signed factor { '^' signed factor }* ; * * signed factor ::= ( '+' | '-' )? factor ; * @@ -79,37 +82,104 @@ namespace Util { class Unit; /** -* GimpEevlQuantity: -* @value: In reference units. -* @dimension: in has a dimension of 1, in^2 has a dimension of 2 etc -*/ -typedef struct + * EvaluatorQuantity: + * @param value In reference units. + * @param dimension mm has a dimension of 1, mm^2 has a dimension of 2, etc. + */ +class EvaluatorQuantity { +public: + EvaluatorQuantity(double value = 0, unsigned int dimension = 0); + double value; - gint dimension; -} GimpEevlQuantity; + unsigned int dimension; +}; -typedef bool (* GimpEevlUnitResolverProc) (const gchar *identifier, - GimpEevlQuantity *result, - Unit* unit); +/** + * TokenType + */ +enum { + TOKEN_NUM = 30000, + TOKEN_IDENTIFIER = 30001, + TOKEN_ANY = 40000, + TOKEN_END = 50000 +}; +typedef int TokenType; -GimpEevlQuantity gimp_eevl_evaluate (const gchar* string, Unit* unit = NULL); +/** + * EvaluatorToken + */ +class EvaluatorToken +{ +public: + EvaluatorToken(); + + TokenType type; + + union { + double fl; + struct { + const char *c; + int size; + }; + } value; +}; + +/** + * ExpressionEvaluator + * @param string NULL terminated input string to evaluate + * @param unit Unit output should be in + */ +class ExpressionEvaluator +{ +public: + ExpressionEvaluator(const char *string, Unit *unit = NULL); + + EvaluatorQuantity evaluate(); + +private: + const char *string; + Unit *unit; + + EvaluatorToken current_token; + const char *start_of_current_token; + + EvaluatorQuantity evaluateExpression(); + EvaluatorQuantity evaluateTerm(); + EvaluatorQuantity evaluateExpTerm(); + EvaluatorQuantity evaluateSignedFactor(); + EvaluatorQuantity evaluateFactor(); + + bool acceptToken(TokenType token_type, EvaluatorToken *consumed_token); + void parseNextToken(); + void acceptTokenCount(int count, TokenType token_type); + void isExpected(TokenType token_type, EvaluatorToken *value); + + void movePastWhiteSpace(); + + static bool isUnitIdentifierStart(gunichar c); + static int getIdentifierSize(const char *s, int start); + + static bool resolveUnit(const char *identifier, EvaluatorQuantity *result, Unit *unit); + + void throwError(const char *msg); +}; /** * Special exception class for the expression evaluator. */ class EvaluatorException : public std::exception { public: - EvaluatorException(const char * message, const char *at_position) { + EvaluatorException(const char *message, const char *at_position) { std::ostringstream os; - const char* token = at_position ? at_position : "<End of input>"; + const char *token = at_position ? at_position : "<End of input>"; os << "Expression evaluator error: " << message << " at '" << token << "'"; msgstr = os.str(); } virtual ~EvaluatorException() throw() {} // necessary to destroy the string object!!! - virtual const char* what() const throw () { + virtual const char *what() const throw () { return msgstr.c_str(); } protected: @@ -119,4 +189,4 @@ protected: } } -#endif // SEEN_GIMP_EEVL_H +#endif // INKSCAPE_UTIL_EXPRESSION_EVALUATOR_H diff --git a/src/util/units.cpp b/src/util/units.cpp index 3fdd77916..e5c6f74fb 100644 --- a/src/util/units.cpp +++ b/src/util/units.cpp @@ -114,6 +114,7 @@ Unit::Unit(UnitType type, abbr(abbr), description(description) { + g_return_if_fail(factor <= 0); } void Unit::clear() @@ -166,25 +167,25 @@ bool operator!= (const Unit &u1, const Unit &u2) int Unit::svgUnit() const { if (!abbr.compare("px")) - return 1; + return SVGLength::PX; if (!abbr.compare("pt")) - return 2; + return SVGLength::PT; if (!abbr.compare("pc")) - return 3; + return SVGLength::PC; if (!abbr.compare("mm")) - return 4; + return SVGLength::MM; if (!abbr.compare("cm")) - return 5; + return SVGLength::CM; if (!abbr.compare("in")) - return 6; + return SVGLength::INCH; if (!abbr.compare("ft")) - return 7; + return SVGLength::FOOT; if (!abbr.compare("em")) - return 8; + return SVGLength::EM; if (!abbr.compare("ex")) - return 9; + return SVGLength::EX; if (!abbr.compare("%")) - return 10; + return SVGLength::PERCENT; return 0; } @@ -220,6 +221,36 @@ Unit UnitTable::getUnit(Glib::ustring const &unit_abbr) const return Unit(); } } +Unit UnitTable::getUnit(SVGLength::Unit const u) const +{ + Glib::ustring u_str; + switch(u) { + case SVGLength::PX: + u_str = "px"; break; + case SVGLength::PT: + u_str = "pt"; break; + case SVGLength::PC: + u_str = "pc"; break; + case SVGLength::MM: + u_str = "mm"; break; + case SVGLength::CM: + u_str = "cm"; break; + case SVGLength::INCH: + u_str = "in"; break; + case SVGLength::FOOT: + u_str = "ft"; break; + case SVGLength::EM: + u_str = "em"; break; + case SVGLength::EX: + u_str = "ex"; break; + case SVGLength::PERCENT: + u_str = "%"; break; + default: + u_str = ""; + } + + return getUnit(u_str); +} Quantity UnitTable::getQuantity(Glib::ustring const& q) const { @@ -421,6 +452,27 @@ double Quantity::convert(const double from_dist, const Glib::ustring from, const return convert(from_dist, unit_table.getUnit(from), unit_table.getUnit(to)); } +bool operator< (const Quantity &ql, const Quantity &qr) +{ + if (ql.unit->type != qr.unit->type) { + g_warning("Incompatible units"); + return false; + } + return ql.quantity < qr.value(*ql.unit); +} +bool operator> (const Quantity &ql, const Quantity &qr) +{ + if (ql.unit->type != qr.unit->type) { + g_warning("Incompatible units"); + return false; + } + return ql.quantity > qr.value(*ql.unit); +} +bool operator!= (const Quantity &q1, const Quantity &q2) +{ + return (*q1.unit != *q2.unit) || (q1.quantity != q2.quantity); +} + } // namespace Util } // namespace Inkscape diff --git a/src/util/units.h b/src/util/units.h index bb202b96a..7ba6e1e86 100644 --- a/src/util/units.h +++ b/src/util/units.h @@ -1,5 +1,6 @@ /* * Inkscape Units + * These classes are used for defining different unit systems. * * Authors: * Matthew Petroff <matthew@mpetroff.net> @@ -9,25 +10,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -/* -This is a rough draft of a global 'units' thingee, to allow dialogs and -the ruler to share info about unit systems... Dunno if this is the -right kind of object though, so we may have to redo this or shift things -around later when it becomes clearer what we need. - -This object is used for defining different unit systems. - -This is intended to eventually replace inkscape/helper/units.*. - -Need to review the Units support that's in Gtkmm already... - -*/ - #ifndef INKSCAPE_UTIL_UNITS_H #define INKSCAPE_UTIL_UNITS_H #include <map> #include <glibmm/ustring.h> +#include "svg/svg-length.h" namespace Inkscape { namespace Util { @@ -112,6 +100,11 @@ public: static double convert(const double from_dist, const Glib::ustring from, const Unit &to); static double convert(const double from_dist, const Unit &from, const Glib::ustring to); static double convert(const double from_dist, const Glib::ustring from, const Glib::ustring to); + + /** Comparison operators. */ + friend bool operator< (const Quantity &ql, const Quantity &qr); + friend bool operator> (const Quantity &ql, const Quantity &qr); + friend bool operator!= (const Quantity &q1, const Quantity &q2); }; class UnitTable { @@ -132,6 +125,9 @@ class UnitTable { /** Retrieve a given unit based on its string identifier */ Unit getUnit(Glib::ustring const &name) const; + /** Retrieve a given unit based on its SVGLength unit */ + Unit getUnit(SVGLength::Unit const u) const; + /** Retrieve a quantity based on its string identifier */ Quantity getQuantity(Glib::ustring const &q) const; diff --git a/src/widgets/calligraphy-toolbar.cpp b/src/widgets/calligraphy-toolbar.cpp index 1f91b9fe2..12228ce56 100644 --- a/src/widgets/calligraphy-toolbar.cpp +++ b/src/widgets/calligraphy-toolbar.cpp @@ -450,7 +450,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-calligraphy", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_width_value_changed, 1, 0 ); + sp_ddc_width_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -467,7 +467,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, -100, 100, 1, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_velthin_value_changed, 1, 0); + sp_ddc_velthin_value_changed, NULL /*unit tracker*/, 1, 0); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } @@ -483,7 +483,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, TRUE, "calligraphy-angle", -90.0, 90.0, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_angle_value_changed, 1, 0 ); + sp_ddc_angle_value_changed, NULL /*unit tracker*/, 1, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); g_object_set_data( holder, "angle_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -501,7 +501,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_flatness_value_changed, 1, 0); + sp_ddc_flatness_value_changed, NULL /*unit tracker*/, 1, 0); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } @@ -518,7 +518,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 5.0, 0.01, 0.1, labels, values, G_N_ELEMENTS(labels), - sp_ddc_cap_rounding_value_changed, 0.01, 2 ); + sp_ddc_cap_rounding_value_changed, NULL /*unit tracker*/, 0.01, 2 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } @@ -534,7 +534,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 100, 1, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_tremor_value_changed, 1, 0); + sp_ddc_tremor_value_changed, NULL /*unit tracker*/, 1, 0); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); @@ -552,7 +552,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 100, 1, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_wiggle_value_changed, 1, 0); + sp_ddc_wiggle_value_changed, NULL /*unit tracker*/, 1, 0); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -569,7 +569,7 @@ void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 100, 1, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_ddc_mass_value_changed, 1, 0); + sp_ddc_mass_value_changed, NULL /*unit tracker*/, 1, 0); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); diff --git a/src/widgets/connector-toolbar.cpp b/src/widgets/connector-toolbar.cpp index 54344e446..2e5c2ade1 100644 --- a/src/widgets/connector-toolbar.cpp +++ b/src/widgets/connector-toolbar.cpp @@ -364,7 +364,7 @@ void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainActions, GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-curvature", 0, 100, 1.0, 10.0, 0, 0, 0, - connector_curvature_changed, 1, 0 ); + connector_curvature_changed, NULL /*unit tracker*/, 1, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); // Spacing spinbox @@ -375,7 +375,7 @@ void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainActions, GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-spacing", 0, 100, 1.0, 10.0, 0, 0, 0, - connector_spacing_changed, 1, 0 ); + connector_spacing_changed, NULL /*unit tracker*/, 1, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); // Graph (connector network) layout @@ -397,7 +397,7 @@ void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainActions, GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-length", 10, 1000, 10.0, 100.0, 0, 0, 0, - connector_length_changed, 1, 0 ); + connector_length_changed, NULL /*unit tracker*/, 1, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index e9c2e6ef3..e9a834db7 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -2135,8 +2135,8 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) /* The desktop region we always show unconditionally */ SPDocument *doc = dtw->desktop->doc(); - Geom::Rect darea ( Geom::Point(-doc->getWidth(), -doc->getHeight()), - Geom::Point(2 * doc->getWidth(), 2 * doc->getHeight()) ); + Geom::Rect darea ( Geom::Point(-doc->getWidth().value("px"), -doc->getHeight().value("px")), + Geom::Point(2 * doc->getWidth().value("px"), 2 * doc->getHeight().value("px")) ); Geom::OptRect deskarea; if (Inkscape::Preferences::get()->getInt("/tools/bounding_box") == 0) { diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp index 3f5e60780..1af574ed6 100644 --- a/src/widgets/eraser-toolbar.cpp +++ b/src/widgets/eraser-toolbar.cpp @@ -148,7 +148,7 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-eraser", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_erc_width_value_changed, 1, 0); + sp_erc_width_value_changed, NULL /*unit tracker*/, 1, 0); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index 5f29e8ed8..a68f3f451 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -1175,8 +1175,9 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0.0, 1.0, 0.01, 0.1, 0, 0, 0, - gr_stop_offset_adjustment_changed - , 0.01, 2, 1.0); + gr_stop_offset_adjustment_changed, + NULL /*unit tracker*/, + 0.01, 2, 1.0); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); g_object_set_data( holder, "offset_action", eact ); diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 50f092c43..23e9b9c72 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -42,6 +42,7 @@ #include "display/drawing.h" #include "io/sys.h" #include "sp-root.h" +#include "util/units.h" #include "icon.h" @@ -1138,7 +1139,7 @@ sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing, if ( object->parent == NULL ) { dbox = Geom::Rect(Geom::Point(0, 0), - Geom::Point(doc->getWidth(), doc->getHeight())); + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); } /* This is in document coordinates, i.e. pixels */ diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp index 37763ab34..582243870 100644 --- a/src/widgets/mesh-toolbar.cpp +++ b/src/widgets/mesh-toolbar.cpp @@ -265,7 +265,7 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 1, 20, 1, 1, labels, values, G_N_ELEMENTS(labels), - ms_row_changed, + ms_row_changed, NULL /*unit tracker*/, 1.0, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -281,7 +281,7 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 1, 20, 1, 1, labels, values, G_N_ELEMENTS(labels), - ms_col_changed, + ms_col_changed, NULL /*unit tracker*/, 1.0, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); diff --git a/src/widgets/node-toolbar.cpp b/src/widgets/node-toolbar.cpp index a9e298f1d..c3e5b22ce 100644 --- a/src/widgets/node-toolbar.cpp +++ b/src/widgets/node-toolbar.cpp @@ -595,7 +595,7 @@ void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-nodes", -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_node_path_x_value_changed ); + sp_node_path_x_value_changed, tracker ); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); g_object_set_data( holder, "nodes_x_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); @@ -613,7 +613,7 @@ void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_node_path_y_value_changed ); + sp_node_path_y_value_changed, tracker ); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); g_object_set_data( holder, "nodes_y_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); diff --git a/src/widgets/paintbucket-toolbar.cpp b/src/widgets/paintbucket-toolbar.cpp index 1d8ae7ae9..028753b59 100644 --- a/src/widgets/paintbucket-toolbar.cpp +++ b/src/widgets/paintbucket-toolbar.cpp @@ -169,7 +169,7 @@ void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions "/tools/paintbucket/threshold", 5, GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:paintbucket-threshold", 0, 100.0, 1.0, 10.0, 0, 0, 0, - paintbucket_threshold_changed, 1, 0 ); + paintbucket_threshold_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); @@ -197,7 +197,7 @@ void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions "/tools/paintbucket/offset", 0, GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:paintbucket-offset", -1e4, 1e4, 0.1, 0.5, 0, 0, 0, - paintbucket_offset_changed, 1, 2); + paintbucket_offset_changed, tracker, 1, 2); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp index 87a73712e..c1f2d246e 100644 --- a/src/widgets/pencil-toolbar.cpp +++ b/src/widgets/pencil-toolbar.cpp @@ -314,6 +314,7 @@ void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb 1, 100.0, 0.5, 1.0, labels, values, G_N_ELEMENTS(labels), sp_pencil_tb_tolerance_value_changed, + NULL /*unit tracker*/, 1, 2); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); diff --git a/src/widgets/rect-toolbar.cpp b/src/widgets/rect-toolbar.cpp index fb64ae14b..0d5d3a688 100644 --- a/src/widgets/rect-toolbar.cpp +++ b/src/widgets/rect-toolbar.cpp @@ -114,7 +114,7 @@ static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const * for (GSList const *items = selection->itemList(); items != NULL; items = items->next) { if (SP_IS_RECT(items->data)) { if (gtk_adjustment_get_value(adj) != 0) { - (SP_RECT(items->data)->*setter)(Quantity::convert(gtk_adjustment_get_value(adj), unit, "px")); + (SP_RECT(items->data)->*setter)(Quantity::convert(gtk_adjustment_get_value(adj), unit, *sp_desktop_namedview(desktop)->doc_units)); } else { SP_OBJECT(items->data)->getRepr()->setAttribute(value_name, NULL); } @@ -186,6 +186,7 @@ static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar con UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) ); Unit const unit = tracker->getActiveUnit(); + Unit const doc_unit = *sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units; gpointer item = g_object_get_data( tbl, "item" ); if (item && SP_IS_RECT(item)) { @@ -193,28 +194,28 @@ static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar con GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "rx" ) ); gdouble rx = SP_RECT(item)->getVisibleRx(); - gtk_adjustment_set_value(adj, Quantity::convert(rx, "px", unit)); + gtk_adjustment_set_value(adj, Quantity::convert(rx, doc_unit, unit)); } { GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "ry" ) ); gdouble ry = SP_RECT(item)->getVisibleRy(); - gtk_adjustment_set_value(adj, Quantity::convert(ry, "px", unit)); + gtk_adjustment_set_value(adj, Quantity::convert(ry, doc_unit, unit)); } { GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "width" ) ); gdouble width = SP_RECT(item)->getVisibleWidth(); - gtk_adjustment_set_value(adj, Quantity::convert(width, "px", unit)); + gtk_adjustment_set_value(adj, Quantity::convert(width, doc_unit, unit)); } { GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "height" ) ); gdouble height = SP_RECT(item)->getVisibleHeight(); - gtk_adjustment_set_value(adj, Quantity::convert(height, "px", unit)); + gtk_adjustment_set_value(adj, Quantity::convert(height, doc_unit, unit)); } } @@ -322,7 +323,7 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-rect", 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_rtb_width_value_changed ); + sp_rtb_width_value_changed, tracker); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); g_object_set_data( holder, "width_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); @@ -339,7 +340,7 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_rtb_height_value_changed ); + sp_rtb_height_value_changed, tracker); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); g_object_set_data( holder, "height_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); @@ -356,7 +357,7 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_rtb_rx_value_changed); + sp_rtb_rx_value_changed, tracker); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); } @@ -371,7 +372,7 @@ void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, labels, values, G_N_ELEMENTS(labels), - sp_rtb_ry_value_changed); + sp_rtb_ry_value_changed, tracker); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); } diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index e4a5a2905..590b0867f 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -273,7 +273,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } -static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRate, guint digits ) +static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRate, guint digits, Inkscape::UI::Widget::UnitTracker *unit_tracker ) { #if WITH_GTKMM_3_0 Glib::RefPtr<Gtk::Adjustment> adj = Glib::wrap(adjustment, true); @@ -281,6 +281,7 @@ static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRa #else Inkscape::UI::Widget::SpinButton *inkSpinner = new Inkscape::UI::Widget::SpinButton(*Glib::wrap(adjustment, true), climbRate, digits); #endif + inkSpinner->addUnitTracker(unit_tracker); inkSpinner = Gtk::manage( inkSpinner ); GtkWidget *widget = GTK_WIDGET( inkSpinner->gobj() ); return widget; @@ -313,7 +314,7 @@ static EgeAdjustmentAction * create_adjustment_action( gchar const *name, g_object_set_data( G_OBJECT(spw), data, adj ); } - EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, Q_(label), tooltip, 0, SPIN_STEP, 3 ); + EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, Q_(label), tooltip, 0, SPIN_STEP, 3, tracker ); if ( shortLabel ) { g_object_set( act, "short_label", Q_(shortLabel), NULL ); } diff --git a/src/widgets/spiral-toolbar.cpp b/src/widgets/spiral-toolbar.cpp index cccaf5154..b4e8e68a7 100644 --- a/src/widgets/spiral-toolbar.cpp +++ b/src/widgets/spiral-toolbar.cpp @@ -262,7 +262,7 @@ void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-spiral", 0.01, 1024.0, 0.1, 1.0, labels, values, G_N_ELEMENTS(labels), - sp_spl_tb_revolution_value_changed, 1, 2); + sp_spl_tb_revolution_value_changed, NULL /*unit tracker*/, 1, 2); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); } diff --git a/src/widgets/spray-toolbar.cpp b/src/widgets/spray-toolbar.cpp index fe221f695..247df53e2 100644 --- a/src/widgets/spray-toolbar.cpp +++ b/src/widgets/spray-toolbar.cpp @@ -130,7 +130,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-spray", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_width_value_changed, 1, 0 ); + sp_spray_width_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -146,7 +146,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "spray-mean", 0, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_mean_value_changed, 1, 0 ); + sp_spray_mean_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -162,7 +162,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "spray-standard_deviation", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_standard_deviation_value_changed, 1, 0 ); + sp_spray_standard_deviation_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -223,7 +223,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "spray-population", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_population_value_changed, 1, 0 ); + sp_spray_population_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -254,7 +254,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "spray-rotation", 0, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_rotation_value_changed, 1, 0 ); + sp_spray_rotation_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -272,7 +272,7 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "spray-scale", 0, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_spray_scale_value_changed, 1, 0 ); + sp_spray_scale_value_changed, NULL /*unit tracker*/, 1, 0 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); diff --git a/src/widgets/star-toolbar.cpp b/src/widgets/star-toolbar.cpp index 9f7dd95e0..9e26988ff 100644 --- a/src/widgets/star-toolbar.cpp +++ b/src/widgets/star-toolbar.cpp @@ -504,7 +504,7 @@ void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 3, 1024, 1, 5, labels, values, G_N_ELEMENTS(labels), - sp_stb_magnitude_value_changed, + sp_stb_magnitude_value_changed, NULL /*unit tracker*/, 1.0, 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -559,7 +559,7 @@ void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, -10.0, 10.0, 0.001, 0.01, labels, values, G_N_ELEMENTS(labels), - sp_stb_randomized_value_changed, 0.1, 3 ); + sp_stb_randomized_value_changed, NULL /*unit tracker*/, 0.1, 3 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 7554f4faf..6b9fc900c 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -1459,6 +1459,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje 0.0, 10.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_lineheight_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ @@ -1489,6 +1490,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_wordspacing_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ @@ -1519,6 +1521,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_letterspacing_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ @@ -1549,6 +1552,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje -100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_dx_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ @@ -1579,6 +1583,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje -100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_dy_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ @@ -1609,6 +1614,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje -180.0, 180.0, 0.1, 1.0, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_rotation_value_changed, /* callback */ + NULL, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index a171ce29b..81566bcf8 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -1012,7 +1012,7 @@ GtkWidget *ToolboxFactory::createSnapToolbox() return toolboxNewCommon( tb, BAR_SNAP, GTK_POS_LEFT ); } -static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRate, guint digits ) +static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRate, guint digits, Inkscape::UI::Widget::UnitTracker *unit_tracker) { #if WITH_GTKMM_3_0 Glib::RefPtr<Gtk::Adjustment> adj = Glib::wrap(adjustment, true); @@ -1020,6 +1020,7 @@ static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRa #else Inkscape::UI::Widget::SpinButton *inkSpinner = new Inkscape::UI::Widget::SpinButton(*Glib::wrap(adjustment, true), climbRate, digits); #endif + inkSpinner->addUnitTracker(unit_tracker); inkSpinner = Gtk::manage( inkSpinner ); GtkWidget *widget = GTK_WIDGET( inkSpinner->gobj() ); return widget; @@ -1034,6 +1035,7 @@ EgeAdjustmentAction * create_adjustment_action( gchar const *name, gdouble lower, gdouble upper, gdouble step, gdouble page, gchar const** descrLabels, gdouble const* descrValues, guint descrCount, void (*callback)(GtkAdjustment *, GObject *), + Inkscape::UI::Widget::UnitTracker *unit_tracker, gdouble climb/* = 0.1*/, guint digits/* = 3*/, double factor/* = 1.0*/ ) { static bool init = false; @@ -1048,7 +1050,7 @@ EgeAdjustmentAction * create_adjustment_action( gchar const *name, g_signal_connect( G_OBJECT(adj), "value-changed", G_CALLBACK(callback), dataKludge ); - EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits ); + EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits, unit_tracker ); if ( shortLabel ) { g_object_set( act, "short_label", shortLabel, NULL ); } diff --git a/src/widgets/toolbox.h b/src/widgets/toolbox.h index 0ae4d4630..e9ffcda4a 100644 --- a/src/widgets/toolbox.h +++ b/src/widgets/toolbox.h @@ -28,6 +28,10 @@ class SPEventContext; namespace Inkscape { namespace UI { +namespace Widget { + class UnitTracker; +} + /** * Main toolbox source. */ @@ -123,6 +127,7 @@ void delete_connection(GObject * /*obj*/, sigc::connection *connection); gdouble lower, gdouble upper, gdouble step, gdouble page, gchar const** descrLabels, gdouble const* descrValues, guint descrCount, void (*callback)(GtkAdjustment *, GObject *), + Inkscape::UI::Widget::UnitTracker *unit_tracker = NULL, gdouble climb = 0.1, guint digits = 3, double factor = 1.0 ); #endif /* !SEEN_TOOLBOX_H */ diff --git a/src/widgets/tweak-toolbar.cpp b/src/widgets/tweak-toolbar.cpp index d5fe67ef7..6da7608bd 100644 --- a/src/widgets/tweak-toolbar.cpp +++ b/src/widgets/tweak-toolbar.cpp @@ -144,7 +144,7 @@ void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-tweak", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_tweak_width_value_changed, 0.01, 0, 100 ); + sp_tweak_width_value_changed, NULL /*unit tracker*/, 0.01, 0, 100 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -161,7 +161,7 @@ void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "tweak-force", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_tweak_force_value_changed, 0.01, 0, 100 ); + sp_tweak_force_value_changed, NULL /*unit tracker*/, 0.01, 0, 100 ); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); @@ -370,7 +370,7 @@ void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj GTK_WIDGET(desktop->canvas), holder, TRUE, "tweak-fidelity", 1, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), - sp_tweak_fidelity_value_changed, 0.01, 0, 100 ); + sp_tweak_fidelity_value_changed, NULL /*unit tracker*/, 0.01, 0, 100 ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) { diff --git a/src/xml/quote-test.h b/src/xml/quote-test.h index bd5c1f54c..bc01ec4e9 100644 --- a/src/xml/quote-test.h +++ b/src/xml/quote-test.h @@ -7,10 +7,7 @@ #include <cstring> #include <functional> -/* mental disclaims all responsibility for this evil idea for testing - static functions. The main disadvantages are that we retain any - #define's and `using' directives of the included file. */ -#include "quote.cpp" +#include "quote.h" class XmlQuoteTest : public CxxTest::TestSuite { diff --git a/src/xml/quote.cpp b/src/xml/quote.cpp index 030a6c764..c9e001d05 100644 --- a/src/xml/quote.cpp +++ b/src/xml/quote.cpp @@ -19,7 +19,7 @@ /** \return strlen(xml_quote_strdup(\a val)) (without doing the malloc). * \pre val != NULL */ -static size_t +size_t xml_quoted_strlen(char const *val) { size_t ret = 0; @@ -43,11 +43,11 @@ xml_quoted_strlen(char const *val) static void xml_quote(char *dest, char const *src) { -#define COPY_LIT(_lit) do { \ - size_t cpylen = sizeof(_lit "") - 1; \ - memcpy(dest, _lit, cpylen); \ - dest += cpylen; \ - } while(0) +#define COPY_LIT(_lit) do { \ + size_t cpylen = sizeof(_lit "") - 1; \ + memcpy(dest, _lit, cpylen); \ + dest += cpylen; \ + } while(0) for (; *src != '\0'; ++src) { switch (*src) { diff --git a/src/xml/quote.h b/src/xml/quote.h index 597272cd3..8e3bca0eb 100644 --- a/src/xml/quote.h +++ b/src/xml/quote.h @@ -1,6 +1,9 @@ #ifndef SEEN_XML_QUOTE_H #define SEEN_XML_QUOTE_H +#include <stddef.h> + +size_t xml_quoted_strlen(char const *val); char *xml_quote_strdup(char const *src); |
