From f24f34bd713c7a26fbb6e13c2a44111223950738 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 16:02:09 +0000 Subject: Core Dbus files. Init creates interfaces on Inkscape startup. Application and document interface provide API functions over Dbus. service.in file makes sure Inkscape starts automatically when someone connects to it over Dbus. (bzr r8254.1.3) --- src/extension/dbus/Makefile_insert | 31 + src/extension/dbus/application-interface.cpp | 112 +++ src/extension/dbus/application-interface.h | 84 ++ src/extension/dbus/application-interface.xml | 65 ++ src/extension/dbus/dbus-init.cpp | 153 ++++ src/extension/dbus/dbus-init.h | 42 + src/extension/dbus/document-interface.cpp | 936 ++++++++++++++++++++ src/extension/dbus/document-interface.xml | 1223 ++++++++++++++++++++++++++ src/extension/dbus/org.inkscape.service.in | 4 + 9 files changed, 2650 insertions(+) create mode 100644 src/extension/dbus/Makefile_insert create mode 100644 src/extension/dbus/application-interface.cpp create mode 100644 src/extension/dbus/application-interface.h create mode 100644 src/extension/dbus/application-interface.xml create mode 100644 src/extension/dbus/dbus-init.cpp create mode 100644 src/extension/dbus/dbus-init.h create mode 100644 src/extension/dbus/document-interface.cpp create mode 100644 src/extension/dbus/document-interface.xml create mode 100644 src/extension/dbus/org.inkscape.service.in (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert new file mode 100644 index 000000000..c8bee0ca6 --- /dev/null +++ b/src/extension/dbus/Makefile_insert @@ -0,0 +1,31 @@ +## Makefile.am fragment sourced by src/Makefile.am. + +ink_common_sources += \ + extension/dbus/dbus-init.cpp \ + extension/dbus/dbus-init.h \ + extension/dbus/application-interface.cpp \ + extension/dbus/application-interface.h \ + extension/dbus/document-interface.cpp \ + extension/dbus/document-interface.h + +## Slightly concerned about this. +## Would use += but it has to be set first. +BUILT_SOURCES = \ + extension/dbus/application-server-glue.h \ + extension/dbus/document-server-glue.h + +extension/dbus/application-server-glue.h: extension/dbus/application-interface.xml + dbus-binding-tool --mode=glib-server --output=$@ --prefix=application_interface $^ + +extension/dbus/document-server-glue.h: extension/dbus/document-interface.xml + dbus-binding-tool --mode=glib-server --output=$@ --prefix=document_interface $^ + +# Dbus service file +servicedir = "/usr/share/dbus-1/services" +service_in_files = extension/dbus/org.inkscape.service.in +service_DATA = $(service_in_files:.service.in=.service) + +# Rule to make the service file with bindir expanded +$(service_DATA): $(service_in_files) Makefile + @sed -e "s|@bindir@|$(bindir)|" $<> $@ + diff --git a/src/extension/dbus/application-interface.cpp b/src/extension/dbus/application-interface.cpp new file mode 100644 index 000000000..06e41ecf3 --- /dev/null +++ b/src/extension/dbus/application-interface.cpp @@ -0,0 +1,112 @@ +#include "application-interface.h" +#include +#include "dbus-init.h" + +G_DEFINE_TYPE(ApplicationInterface, application_interface, G_TYPE_OBJECT) + +static void +application_interface_finalize (GObject *object) +{ + G_OBJECT_CLASS (application_interface_parent_class)->finalize (object); +} + + +static void +application_interface_class_init (ApplicationInterfaceClass *klass) +{ + GObjectClass *object_class; + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = application_interface_finalize; +} + +static void +application_interface_init (ApplicationInterface *object) +{ +} + + +ApplicationInterface * +application_interface_new (void) +{ + return (ApplicationInterface*)g_object_new (TYPE_APPLICATION_INTERFACE, NULL); +} + +/**************************************************************************** + DESKTOP FUNCTIONS +****************************************************************************/ + +gchar* +application_interface_desktop_new (ApplicationInterface *object, + GError **error) +{ + return (gchar*)Inkscape::Extension::Dbus::init_desktop(); +} + +gchar** +application_interface_get_desktop_list (ApplicationInterface *object) +{ + return NULL; +} + +gchar* +application_interface_get_active_desktop (ApplicationInterface *object, + GError **error) +{ + return NULL; +} + +gboolean +application_interface_set_active_desktop (ApplicationInterface *object, + gchar* document_name, + GError **error) +{ + return TRUE; +} + +gboolean +application_interface_desktop_close_all (ApplicationInterface *object, + GError **error) +{ + return TRUE; +} + +gboolean +application_interface_exit (ApplicationInterface *object, GError **error) +{ + return TRUE; +} + +/**************************************************************************** + DOCUMENT FUNCTIONS +****************************************************************************/ + +gchar* application_interface_document_new (ApplicationInterface *object, + GError **error) +{ + return (gchar*)Inkscape::Extension::Dbus::init_document(); +} + +gchar** +application_interface_get_document_list (ApplicationInterface *object) +{ + return NULL; +} + +gboolean +application_interface_document_close_all (ApplicationInterface *object, + GError **error) +{ + return TRUE; +} + +/* INTERESTING FUNCTIONS + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + g_assert(desktop != NULL); + + SPDocument *doc = sp_desktop_document(desktop); + g_assert(doc != NULL); + + Inkscape::XML::Node *repr = sp_document_repr_root(doc); + g_assert(repr != NULL); +*/ + diff --git a/src/extension/dbus/application-interface.h b/src/extension/dbus/application-interface.h new file mode 100644 index 000000000..a04c992c3 --- /dev/null +++ b/src/extension/dbus/application-interface.h @@ -0,0 +1,84 @@ +#ifndef INKSCAPE_EXTENSION_APPLICATION_INTERFACE_H_ +#define INKSCAPE_EXTENSION_APPLICATION_INTERFACE_H_ + +#include +#include +#include +#include + +#define DBUS_APPLICATION_INTERFACE_PATH "/org/inkscape/application" + +#define TYPE_APPLICATION_INTERFACE (application_interface_get_type ()) +#define APPLICATION_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_APPLICATION_INTERFACE, ApplicationInterface)) +#define APPLICATION_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_APPLICATION_INTERFACE, ApplicationInterfaceClass)) +#define IS_APPLICATION_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TYPE_APPLICATION_INTERFACE)) +#define IS_APPLICATION_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_APPLICATION_INTERFACE)) +#define APPLICATION_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_APPLICATION_INTERFACE, ApplicationInterfaceClass)) + +G_BEGIN_DECLS + +typedef struct _ApplicationInterface ApplicationInterface; +typedef struct _ApplicationInterfaceClass ApplicationInterfaceClass; + +struct _ApplicationInterface { + GObject parent; +}; + +struct _ApplicationInterfaceClass { + GObjectClass parent; +}; + +/**************************************************************************** + DESKTOP FUNCTIONS +****************************************************************************/ + +gchar* +application_interface_desktop_new (ApplicationInterface *object, + GError **error); + +gchar** +application_interface_get_desktop_list (ApplicationInterface *object); + +gchar* +application_interface_get_active_desktop (ApplicationInterface *object, + GError **error); + +gboolean +application_interface_set_active_desktop (ApplicationInterface *object, + gchar* document_name, + GError **error); + +gboolean +application_interface_desktop_close_all (ApplicationInterface *object, + GError **error); + +gboolean +application_interface_exit (ApplicationInterface *object, GError **error); + +/**************************************************************************** + DOCUMENT FUNCTIONS +****************************************************************************/ + +gchar* +application_interface_document_new (ApplicationInterface *object, + GError **error); + +gchar** +application_interface_get_document_list (ApplicationInterface *object); + +gboolean +application_interface_document_close_all (ApplicationInterface *object, + GError **error); + + +/**************************************************************************** + SETUP +****************************************************************************/ + +ApplicationInterface *application_interface_new (void); +GType application_interface_get_type (void); + + +G_END_DECLS + +#endif // INKSCAPE_EXTENSION_APPLICATION_INTERFACE_H_ diff --git a/src/extension/dbus/application-interface.xml b/src/extension/dbus/application-interface.xml new file mode 100644 index 000000000..9b55a9b2b --- /dev/null +++ b/src/extension/dbus/application-interface.xml @@ -0,0 +1,65 @@ + + + + + + + + + + This string can be used to connect to the new interface that was created. + + + + + Create a new document interface and return it's location. + + + + + + + + A list of interfaces being provided by Inkscape. + + + + + List all the interfaces that it is possible to connect to. + + + + + + + Close all document interfaces without saving. + + + + + + + Exit Inkscape without saving. Fairly straightforward. + + + + + + + + + + This string can be used to connect to the new interface that was created. + + + + + Originally, there were going to be two interfaces. A desktop and a document. Desktops would be used when the user wanted to see the result of their code and documents would be used when less overhead was desired. Unfortunately as more and more of the code can to rely on the desktop and it's associated support code (including selections and verbs) the document interface was looking more and more limited. Ultimately I decided to just go with the desktop interface since I didn't have a compelling reason for keeping the other one and having two similar interfaces could be very confusing. The desktop interface inherited the document name because I believe it's more familiar to people. + Perhaps it would be best to have an option as to whether or not to create a window and fail with a good error message when they call a function that requires one. Or have a second interface for different use cases but have it be completely different, rather than a subset of the first if there are use cases that support it. + + + + + diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp new file mode 100644 index 000000000..a30bb8fda --- /dev/null +++ b/src/extension/dbus/dbus-init.cpp @@ -0,0 +1,153 @@ + +#include +#include "dbus-init.h" + +#include "application-interface.h" +#include "application-server-glue.h" + +#include "document-interface.h" +#include "document-server-glue.h" + +#include "inkscape.h" +#include "document.h" +#include "desktop.h" +#include "file.h" +#include "verbs.h" +#include "helper/action.h" + +#include +#include +#include + + + + +namespace Inkscape { +namespace Extension { +namespace Dbus { + +/* PRIVATE get a connection to the session bus */ +DBusGConnection * +dbus_get_connection() { + GError *error = NULL; + DBusGConnection *connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (error) { + fprintf(stderr, "Failed to get connection"); + return NULL; + } + else + return connection; +} + +/* PRIVATE create a proxy object for a bus.*/ +DBusGProxy * +dbus_get_proxy(DBusGConnection *connection) { + return dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); +} + +/* PRIVATE register an object on a bus */ +static gpointer +dbus_register_object (DBusGConnection *connection, + DBusGProxy *proxy, + GType object_type, + const DBusGObjectInfo *info, + const gchar *path) +{ + GObject *object = (GObject*)g_object_new (object_type, NULL); + dbus_g_object_type_install_info (object_type, info); + dbus_g_connection_register_g_object (connection, path, object); + return object; +} + +/* Initialize a Dbus service */ +void +init (void) +{ + guint result; + GError *error = NULL; + DBusGConnection *connection; + DBusGProxy *proxy; + DocumentInterface *obj; + connection = dbus_get_connection(); + proxy = dbus_get_proxy(connection); + org_freedesktop_DBus_request_name (proxy, + "org.inkscape", + DBUS_NAME_FLAG_DO_NOT_QUEUE, &result, &error); + //create interface for application + dbus_register_object (connection, + proxy, + TYPE_APPLICATION_INTERFACE, + &dbus_glib_application_interface_object_info, + DBUS_APPLICATION_INTERFACE_PATH); +} //init + +gchar * +init_document (void) { + guint result; + GError *error = NULL; + DBusGConnection *connection; + DBusGProxy *proxy; + SPDocument *doc; + + doc = sp_document_new(NULL, 1, TRUE); + + std::string name("/org/inkscape/"); + name.append(doc->name); + std::replace(name.begin(), name.end(), ' ', '_'); + + connection = dbus_get_connection(); + proxy = dbus_get_proxy(connection); + + dbus_register_object (connection, + proxy, + TYPE_DOCUMENT_INTERFACE, + &dbus_glib_document_interface_object_info, + name.c_str()); + return strdup(name.c_str()); +} //init_document + +gchar * +dbus_init_desktop_interface (SPDesktop * dt) +{ + DBusGConnection *connection; + DBusGProxy *proxy; + DocumentInterface *obj; + + std::string name("/org/inkscape/desktop_"); + std::stringstream out; + out << dt->dkey; + name.append(out.str()); + + //printf("DKEY: %d\n, NUMBER %d\n NAME: %s\n", dt->dkey, dt->number, name.c_str()); + + connection = dbus_get_connection(); + proxy = dbus_get_proxy(connection); + + obj = (DocumentInterface*) dbus_register_object (connection, + proxy, TYPE_DOCUMENT_INTERFACE, + &dbus_glib_document_interface_object_info, name.c_str()); + obj->desk = dt; + obj->updates = TRUE; + + return strdup(name.c_str()); +} + +gchar * +init_desktop (void) { + //this function will create a new desktop and call + //dbus_init_desktop_interface. + SPDesktop * dt = sp_file_new_default(); + + std::string name("/org/inkscape/desktop_"); + std::stringstream out; + out << dt->dkey; + name.append(out.str()); + return strdup(name.c_str()); +} //init_desktop + + + +} } } /* namespace Inkscape::Extension::Dbus */ diff --git a/src/extension/dbus/dbus-init.h b/src/extension/dbus/dbus-init.h new file mode 100644 index 000000000..f76483170 --- /dev/null +++ b/src/extension/dbus/dbus-init.h @@ -0,0 +1,42 @@ +/* + * Authors: + * Soren Berg + * + * Copyright (C) 2004 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_EXTENSION_DBUS_INIT_H__ +#define INKSCAPE_EXTENSION_DBUS_INIT_H__ + +#include "desktop.h" + +namespace Inkscape { +namespace Extension { +namespace Dbus { + +/** \brief Dbus stuff. For registering objects on the bus. */ + +void init (void); + +gchar * init_document (void); + +gchar * init_desktop (void); + +gchar * dbus_init_desktop_interface (SPDesktop * dt); + +} } } /* namespace Dbus, Extension, Inkscape */ + +#endif /* INKSCAPE_EXTENSION_DBUS_INIT_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp new file mode 100644 index 000000000..94f442865 --- /dev/null +++ b/src/extension/dbus/document-interface.cpp @@ -0,0 +1,936 @@ +#include "document-interface.h" +#include + +#include "verbs.h" +#include "helper/action.h" //sp_action_perform + +#include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops + +#include "desktop-handles.h" //sp_desktop_document() +#include "xml/repr.h" //sp_repr_document_new + +#include "sp-object.h" + +#include "document.h" // sp_document_repr_doc + +#include "desktop-style.h" //sp_desktop_get_style + +#include "selection.h" //selection struct +#include "selection-chemistry.h"// lots of selection functions + +#include "sp-ellipse.h" + +#include "layer-fns.h" //LPOS_BELOW + +#include "style.h" //style_write + +/**************************************************************************** + HELPER / SHORTCUT FUNCTIONS +****************************************************************************/ + +const gchar* intToCString(int i) +{ + std::stringstream ss; + ss << i; + return ss.str().c_str(); +} + +SPObject * +get_object_by_name (SPDesktop *desk, gchar *name) +{ + return sp_desktop_document(desk)->getObjectById(name); +} + +const gchar * +get_name_from_object (SPObject * obj) +{ + return obj->repr->attribute("id"); +} + +void +desktop_ensure_active (SPDesktop* desk) { + if (desk != SP_ACTIVE_DESKTOP) + inkscape_activate_desktop (desk); + return; +} + +Inkscape::XML::Node * +document_retrive_node (SPDocument *doc, gchar *name) { + return (doc->getObjectById(name))->repr; +} + +gdouble +selection_get_center_x (Inkscape::Selection *sel){ + NRRect *box = g_new(NRRect, 1);; + box = sel->boundsInDocument(box); + return box->x0 + ((box->x1 - box->x0)/2); +} + +gdouble +selection_get_center_y (Inkscape::Selection *sel){ + NRRect *box = g_new(NRRect, 1);; + box = sel->boundsInDocument(box); + return box->y0 + ((box->y1 - box->y0)/2); +} +//move_to etc +const GSList * +selection_swap(SPDesktop *desk, gchar *name) +{ + Inkscape::Selection *sel = sp_desktop_selection(desk); + const GSList *oldsel = g_slist_copy((GSList *)sel->list()); + + sel->set(get_object_by_name(desk, name)); + return oldsel; +} + +void +selection_restore(SPDesktop *desk, const GSList * oldsel) +{ + Inkscape::Selection *sel = sp_desktop_selection(desk); + sel->setList(oldsel); +} + +Inkscape::XML::Node * +dbus_create_node (SPDesktop *desk, gboolean isrect) +{ + SPDocument * doc = sp_desktop_document (desk); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + gchar *type; + if (isrect) + type = (gchar *)"svg:rect"; + else + type = (gchar *)"svg:path"; + return xml_doc->createElement(type); +} + +gchar * +finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc) +{ + + SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE); + + if (style) { + newNode->setAttribute("style", sp_repr_css_write_string(style), TRUE); + } + else { + newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE); + } + + object->desk->currentLayer()->appendChildRepr(newNode); + object->desk->currentLayer()->updateRepr(); + + if (object->updates) + sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)desc); + else + document_interface_pause_updates(object, error); + + return strdup(newNode->attribute("id")); +} + +gboolean +dbus_call_verb (DocumentInterface *object, int verbid, GError **error) +{ + SPDesktop *desk2 = object->desk; + + if ( desk2 ) { + Inkscape::Verb *verb = Inkscape::Verb::get( verbid ); + if ( verb ) { + SPAction *action = verb->get_action(desk2); + if ( action ) { + sp_action_perform( action, NULL ); + if (object->updates) { + sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); + } + return TRUE; + } + } + } + return FALSE; +} + +/**************************************************************************** + DOCUMENT INTERFACE CLASS STUFF +****************************************************************************/ + +G_DEFINE_TYPE(DocumentInterface, document_interface, G_TYPE_OBJECT) + +static void +document_interface_finalize (GObject *object) +{ + G_OBJECT_CLASS (document_interface_parent_class)->finalize (object); +} + + +static void +document_interface_class_init (DocumentInterfaceClass *klass) +{ + GObjectClass *object_class; + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = document_interface_finalize; +} + +static void +document_interface_init (DocumentInterface *object) +{ + object->desk = NULL; +} + + +DocumentInterface * +document_interface_new (void) +{ + return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL); +} + +/**************************************************************************** + MISC FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_delete_all (DocumentInterface *object, GError **error) +{ + sp_edit_clear_all (object->desk); + return TRUE; +} + +void +document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error) +{ + SPDesktop *desk2 = object->desk; + desktop_ensure_active (object->desk); + if ( desk2 ) { + Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid ); + if ( verb ) { + SPAction *action = verb->get_action(desk2); + if ( action ) { + sp_action_perform( action, NULL ); + if (object->updates) { + sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); + } + } + } + } +} + + +/**************************************************************************** + CREATION FUNCTIONS +****************************************************************************/ + +gchar* +document_interface_rectangle (DocumentInterface *object, int x, int y, + int width, int height, GError **error) +{ + + + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, TRUE); + sp_repr_set_int(newNode, "x", x); //could also use newNode->setAttribute() + sp_repr_set_int(newNode, "y", y); + sp_repr_set_int(newNode, "width", width); + sp_repr_set_int(newNode, "height", height); + return finish_create_shape (object, error, newNode, (gchar *)"create rectangle"); +} + +gchar* +document_interface_ellipse_center (DocumentInterface *object, int cx, int cy, + int rx, int ry, GError **error) +{ + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + newNode->setAttribute("sodipodi:type", "arc"); + sp_repr_set_int(newNode, "sodipodi:cx", cx); + sp_repr_set_int(newNode, "sodipodi:cy", cy); + sp_repr_set_int(newNode, "sodipodi:rx", rx); + sp_repr_set_int(newNode, "sodipodi:ry", ry); + return finish_create_shape (object, error, newNode, (gchar *)"create circle"); +} + +gchar* +document_interface_polygon (DocumentInterface *object, int cx, int cy, + int radius, int rotation, int sides, + GError **error) +{ + gdouble rot = ((rotation / 180.0) * 3.14159265) - ( 3.14159265 / 2.0); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + newNode->setAttribute("inkscape:flatsided", "true"); + newNode->setAttribute("sodipodi:type", "star"); + sp_repr_set_int(newNode, "sodipodi:cx", cx); + sp_repr_set_int(newNode, "sodipodi:cy", cy); + sp_repr_set_int(newNode, "sodipodi:r1", radius); + sp_repr_set_int(newNode, "sodipodi:r2", radius); + sp_repr_set_int(newNode, "sodipodi:sides", sides); + sp_repr_set_int(newNode, "inkscape:randomized", 0); + sp_repr_set_svg_double(newNode, "sodipodi:arg1", rot); + sp_repr_set_svg_double(newNode, "sodipodi:arg2", rot); + sp_repr_set_svg_double(newNode, "inkscape:rounded", 0); + + return finish_create_shape (object, error, newNode, (gchar *)"create polygon"); +} + +gchar* +document_interface_star (DocumentInterface *object, int cx, int cy, + int r1, int r2, int sides, gdouble rounded, + gdouble arg1, gdouble arg2, GError **error) +{ + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + newNode->setAttribute("inkscape:flatsided", "false"); + newNode->setAttribute("sodipodi:type", "star"); + sp_repr_set_int(newNode, "sodipodi:cx", cx); + sp_repr_set_int(newNode, "sodipodi:cy", cy); + sp_repr_set_int(newNode, "sodipodi:r1", r1); + sp_repr_set_int(newNode, "sodipodi:r2", r2); + sp_repr_set_int(newNode, "sodipodi:sides", sides); + sp_repr_set_int(newNode, "inkscape:randomized", 0); + sp_repr_set_svg_double(newNode, "sodipodi:arg1", arg1); + sp_repr_set_svg_double(newNode, "sodipodi:arg2", arg2); + sp_repr_set_svg_double(newNode, "inkscape:rounded", rounded); + + return finish_create_shape (object, error, newNode, (gchar *)"create star"); +} + +gchar* +document_interface_ellipse (DocumentInterface *object, int x, int y, + int width, int height, GError **error) +{ + int rx = width/2; + int ry = height/2; + return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error); +} + +gchar* +document_interface_line (DocumentInterface *object, int x, int y, + int x2, int y2, GError **error) +{ + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + std::stringstream out; + printf("X2: %d\nY2 %d\n", x2, y2); + out << "m " << x << "," << y << " " << x2 << "," << y2; + printf ("PATH: %s\n", out.str().c_str()); + newNode->setAttribute("d", out.str().c_str()); + return finish_create_shape (object, error, newNode, (gchar *)"create line"); +} + +gchar* +document_interface_spiral (DocumentInterface *object, int cx, int cy, + int r, int revolutions, GError **error) +{ + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + newNode->setAttribute("sodipodi:type", "spiral"); + sp_repr_set_int(newNode, "sodipodi:cx", cx); + sp_repr_set_int(newNode, "sodipodi:cy", cy); + sp_repr_set_int(newNode, "sodipodi:radius", r); + sp_repr_set_int(newNode, "sodipodi:revolution", revolutions); + sp_repr_set_int(newNode, "sodipodi:t0", 0); + sp_repr_set_int(newNode, "sodipodi:argument", 0); + sp_repr_set_int(newNode, "sodipodi:expansion", 1); + gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral"); + newNode->setAttribute("style", "fill:none"); + return retval; +} + +gchar* +document_interface_text (DocumentInterface *object, gchar *text, GError **error) +{ + return NULL; +} + +gchar* +document_interface_node (DocumentInterface *object, gchar *type, GError **error) +{ + return NULL; +} + +/**************************************************************************** + ENVIORNMENT FUNCTIONS +****************************************************************************/ +gdouble +document_interface_document_get_width (DocumentInterface *object) +{ + return sp_document_width(sp_desktop_document(object->desk)); +} + +gdouble +document_interface_document_get_height (DocumentInterface *object) +{ + return sp_document_height(sp_desktop_document(object->desk)); +} + +gchar * +document_interface_document_get_css (DocumentInterface *object, GError **error) +{ + SPCSSAttr *current = (object->desk)->current; + return sp_repr_css_write_string(current); +} + +gboolean +document_interface_document_merge_css (DocumentInterface *object, + gchar *stylestring, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_document_set_css (DocumentInterface *object, + gchar *stylestring, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_document_resize_to_fit_selection (DocumentInterface *object, + GError **error) +{ + return FALSE; +} + +/**************************************************************************** + OBJECT FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_set_attribute (DocumentInterface *object, char *shape, + char *attribute, char *newval, GError **error) +{ + Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; + + /* ALTERNATIVE + Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); + */ + if (newNode) + { + newNode->setAttribute(attribute, newval, TRUE); + return TRUE; + } + return FALSE; +} + +void +document_interface_set_int_attribute (DocumentInterface *object, + char *shape, char *attribute, + int newval, GError **error) +{ + Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; + if (newNode) + sp_repr_set_int (newNode, attribute, newval); +} + + +void +document_interface_set_double_attribute (DocumentInterface *object, + char *shape, char *attribute, + double newval, GError **error) +{ + Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; + if (newNode) + sp_repr_set_svg_double (newNode, attribute, newval); +} + +gchar * +document_interface_get_attribute (DocumentInterface *object, char *shape, + char *attribute, GError **error) +{ + SPDesktop *desk2 = object->desk; + SPDocument * doc = sp_desktop_document (desk2); + + // FIXME: Not sure if this is the most efficient way. + Inkscape::XML::Node *newNode = doc->getObjectById(shape)->repr; + + /* WORKS + Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); + */ + if (newNode) + return g_strdup(newNode->attribute(attribute)); + return FALSE; +} + +gboolean +document_interface_move (DocumentInterface *object, gchar *name, gdouble x, + gdouble y, GError **error) +{ + const GSList *oldsel = selection_swap(object->desk, name); + sp_selection_move (object->desk, x, 0 - y); + selection_restore(object->desk, oldsel); + return TRUE; +} + +gboolean +document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x, + gdouble y, GError **error) +{ + const GSList *oldsel = selection_swap(object->desk, name); + Inkscape::Selection * sel = sp_desktop_selection(object->desk); + sp_selection_move (object->desk, x - selection_get_center_x(sel), + 0 - (y - selection_get_center_y(sel))); + selection_restore(object->desk, oldsel); + return TRUE; +} + +void +document_interface_object_to_path (DocumentInterface *object, + char *shape, GError **error) +{ + const GSList *oldsel = selection_swap(object->desk, shape); + dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error); + selection_restore(object->desk, oldsel); +} + +gboolean +document_interface_get_path (DocumentInterface *object, char *pathname, GError **error) +{ + Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); + if (node == NULL || node->attribute("d") == NULL) { + g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); + return FALSE; + } + gchar *pathstr = strdup(node->attribute("d")); + printf("PATH: %s\n", pathstr); + //gfree (pathstr); + std::istringstream iss(pathstr); + std::copy(std::istream_iterator(iss), + std::istream_iterator(), + std::ostream_iterator(std::cout, "\n")); + + return TRUE; +} + +gboolean +document_interface_transform (DocumentInterface *object, gchar *shape, + gchar *transformstr, GError **error) +{ + //FIXME: This should merge transformations. + gchar trans[] = "transform"; + document_interface_set_attribute (object, shape, trans, transformstr, error); + return TRUE; +} + +gchar * +document_interface_get_css (DocumentInterface *object, gchar *shape, + GError **error) +{ +return NULL; +} + +gboolean +document_interface_modify_css (DocumentInterface *object, gchar *shape, + gchar *cssattrb, gchar *newval, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_merge_css (DocumentInterface *object, gchar *shape, + gchar *stylestring, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_move_to_layer (DocumentInterface *object, gchar *shape, + gchar *layerstr, GError **error) +{ + return FALSE; +} + +DBUSPoint ** +document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) +{ + return NULL; +} + + +/**************************************************************************** + FILE I/O FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_save (DocumentInterface *object, GError **error){ + return FALSE; +} + +gboolean +document_interface_load (DocumentInterface *object, + gchar *filename, GError **error){ + return FALSE; +} + +gboolean +document_interface_save_as (DocumentInterface *object, + gchar *filename, GError **error){ + return FALSE; +} + +gboolean +document_interface_print (DocumentInterface *object, GError **error){ + return FALSE; +} + +/**************************************************************************** + PROGRAM CONTROL FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_close (DocumentInterface *object, GError **error){ + return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error); +} + +gboolean +document_interface_exit (DocumentInterface *object, GError **error){ + return dbus_call_verb (object, SP_VERB_FILE_QUIT, error); +} + +gboolean +document_interface_undo (DocumentInterface *object, GError **error){ + return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error); +} + +gboolean +document_interface_redo (DocumentInterface *object, GError **error){ + return dbus_call_verb (object, SP_VERB_EDIT_REDO, error); +} + + + +/**************************************************************************** + UPDATE FUNCTIONS +****************************************************************************/ + +void +document_interface_pause_updates (DocumentInterface *object, GError **error) +{ + object->updates = FALSE; + sp_desktop_document(object->desk)->root->uflags = FALSE; + sp_desktop_document(object->desk)->root->mflags = FALSE; +} + +void +document_interface_resume_updates (DocumentInterface *object, GError **error) +{ + object->updates = TRUE; + sp_desktop_document(object->desk)->root->uflags = TRUE; + sp_desktop_document(object->desk)->root->mflags = TRUE; + //sp_desktop_document(object->desk)->_updateDocument(); + sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); +} + +void +document_interface_update (DocumentInterface *object, GError **error) +{ + sp_desktop_document(object->desk)->root->uflags = TRUE; + sp_desktop_document(object->desk)->root->mflags = TRUE; + sp_desktop_document(object->desk)->_updateDocument(); + sp_desktop_document(object->desk)->root->uflags = FALSE; + sp_desktop_document(object->desk)->root->mflags = FALSE; + //sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); +} + +/**************************************************************************** + SELECTION FUNCTIONS FIXME: use call_verb where appropriate. +****************************************************************************/ + +gchar ** +document_interface_selection_get (DocumentInterface *object) +{ + Inkscape::Selection * sel = sp_desktop_selection(object->desk); + GSList const *oldsel = sel->list(); + + int size = g_slist_length((GSList *) oldsel); + int i; + printf("premalloc\n"); + gchar **list = (gchar **)malloc(size); + printf("postmalloc\n"); + for(i = 0; i < size; i++) + list[i] = (gchar *)malloc(sizeof(gchar) * 10); + printf("postmalloc2\n"); + i=0; + printf("prealloc\n"); + for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) { + strcpy (list[i], SP_OBJECT(iter->data)->repr->attribute("id")); + i++; + } + printf("postalloc\n"); + for (i=0; idesk); + Inkscape::Selection *selection = sp_desktop_selection(object->desk); + /* WORKS + Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); + selection->add(repr2, TRUE); + */ + selection->add(doc->getObjectById(name)); + return TRUE; +} + +gboolean +document_interface_selection_add_list (DocumentInterface *object, + char **names, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_selection_set (DocumentInterface *object, char *name, GError **error) +{ + SPDocument * doc = sp_desktop_document (object->desk); + Inkscape::Selection *selection = sp_desktop_selection(object->desk); + selection->set(doc->getObjectById(name)); + return TRUE; +} + +gboolean +document_interface_selection_set_list (DocumentInterface *object, + gchar **names, GError **error) +{ + sp_desktop_selection(object->desk)->clear(); + int i; + for (i=0;((i<30000) && (names[i] != NULL));i++) { + printf("NAME: %s\n", names[i]); + document_interface_selection_add(object, names[i], error); + } + return TRUE; +} + +gboolean +document_interface_selection_rotate (DocumentInterface *object, int angle, GError **error) +{ + Inkscape::Selection *selection = sp_desktop_selection(object->desk); + sp_selection_rotate(selection, angle); + return TRUE; +} + +gboolean +document_interface_selection_delete (DocumentInterface *object, GError **error) +{ + sp_selection_delete (object->desk); + return TRUE; +} + +gboolean +document_interface_selection_clear (DocumentInterface *object, GError **error) +{ + sp_desktop_selection(object->desk)->clear(); + return TRUE; +} + +gboolean +document_interface_select_all (DocumentInterface *object, GError **error) +{ + sp_edit_select_all (object->desk); + return TRUE; +} + +gboolean +document_interface_select_all_in_all_layers(DocumentInterface *object, + GError **error) +{ + sp_edit_select_all_in_all_layers (object->desk); +} + +gboolean +document_interface_selection_box (DocumentInterface *object, int x, int y, + int x2, int y2, gboolean replace, + GError **error) +{ + return FALSE; +} + +gboolean +document_interface_selection_invert (DocumentInterface *object, GError **error) +{ + sp_edit_invert (object->desk); + return TRUE; +} + +gboolean +document_interface_selection_group (DocumentInterface *object, GError **error) +{ + sp_selection_group (object->desk); + return TRUE; +} +gboolean +document_interface_selection_ungroup (DocumentInterface *object, GError **error) +{ + sp_selection_ungroup (object->desk); + return TRUE; +} + +gboolean +document_interface_selection_cut (DocumentInterface *object, GError **error) +{ + sp_selection_cut (object->desk); + return TRUE; +} +gboolean +document_interface_selection_copy (DocumentInterface *object, GError **error) +{ + desktop_ensure_active (object->desk); + sp_selection_copy (); + return TRUE; +} +gboolean +document_interface_selection_paste (DocumentInterface *object, GError **error) +{ + desktop_ensure_active (object->desk); + sp_selection_paste (object->desk, TRUE); + return TRUE; +} + +gboolean +document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error) +{ + Inkscape::Selection *selection = sp_desktop_selection(object->desk); + sp_selection_scale (selection, grow); + return TRUE; +} + +gboolean +document_interface_selection_move (DocumentInterface *object, gdouble x, gdouble y, GError **error) +{ + sp_selection_move (object->desk, x, 0 - y); //switching coordinate systems. + return TRUE; +} + +gboolean +document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdouble y, GError **error) +{ + Inkscape::Selection * sel = sp_desktop_selection(object->desk); + + Geom::OptRect sel_bbox = sel->bounds(); + if (sel_bbox) { + //Geom::Point m( (object->desk)->point() - sel_bbox->midpoint() ); + Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) ); + sp_selection_move_relative(sel, m, true); + + } + + //FIXME: dosn't work with transformations + //sp_selection_move (object->desk, x - selection_get_center_x(sel), + // 0 - (y - selection_get_center_y(sel))); + return TRUE; +} + +gboolean +document_interface_selection_move_to_layer (DocumentInterface *object, + gchar *layerstr, GError **error) +{ + return FALSE; +} + +gboolean +document_interface_selection_get_center (DocumentInterface *object) +{ + return FALSE; +} + +gboolean +document_interface_selection_to_path (DocumentInterface *object, GError **error) +{ + return dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error); +} + + +gchar * +document_interface_selection_combine (DocumentInterface *object, gchar *cmd, + GError **error) +{ + + if (strcmp(cmd, "union") == 0) + dbus_call_verb (object, SP_VERB_SELECTION_UNION, error); + else if (strcmp(cmd, "intersection") == 0) + dbus_call_verb (object, SP_VERB_SELECTION_INTERSECT, error); + else if (strcmp(cmd, "difference") == 0) + dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error); + else if (strcmp(cmd, "exclusion") == 0) + dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error); + else if (strcmp(cmd, "division") == 0) + dbus_call_verb (object, SP_VERB_SELECTION_CUT, error); + else + return NULL; + + //FIXME: this WILL cause problems with division + return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); +} + +gboolean +document_interface_selection_change_level (DocumentInterface *object, gchar *cmd, + GError **error) +{ + if (strcmp(cmd, "raise") == 0) + return dbus_call_verb (object, SP_VERB_SELECTION_RAISE, error); + if (strcmp(cmd, "lower") == 0) + return dbus_call_verb (object, SP_VERB_SELECTION_LOWER, error); + if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0)) + return dbus_call_verb (object, SP_VERB_SELECTION_TO_FRONT, error); + if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0)) + return dbus_call_verb (object, SP_VERB_SELECTION_TO_BACK, error); + return TRUE; +} + +/**************************************************************************** + LAYER FUNCTIONS +****************************************************************************/ + +gchar * +document_interface_layer_new (DocumentInterface *object, GError **error) +{ + SPDesktop * dt = object->desk; + SPObject *new_layer = Inkscape::create_layer(dt->currentRoot(), dt->currentLayer(), Inkscape::LPOS_BELOW); + dt->setCurrentLayer(new_layer); + return g_strdup(get_name_from_object (new_layer)); +} + +gboolean +document_interface_layer_set (DocumentInterface *object, + gchar *layerstr, GError **error) +{ + object->desk->setCurrentLayer (get_object_by_name (object->desk, layerstr)); + return TRUE; +} + +gchar ** +document_interface_layer_get_all (DocumentInterface *object) +{ + return NULL; +} + +gboolean +document_interface_layer_change_level (DocumentInterface *object, + gchar *cmd, GError **error) +{ + if (strcmp(cmd, "raise") == 0) + return dbus_call_verb (object, SP_VERB_LAYER_RAISE, error); + if (strcmp(cmd, "lower") == 0) + return dbus_call_verb (object, SP_VERB_LAYER_LOWER, error); + if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0)) + return dbus_call_verb (object, SP_VERB_LAYER_TO_TOP, error); + if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0)) + return dbus_call_verb (object, SP_VERB_LAYER_TO_BOTTOM, error); + return TRUE; +} + +gboolean +document_interface_layer_next (DocumentInterface *object, GError **error) +{ + return dbus_call_verb (object, SP_VERB_LAYER_NEXT, error); +} + +gboolean +document_interface_layer_previous (DocumentInterface *object, GError **error) +{ + return dbus_call_verb (object, SP_VERB_LAYER_PREV, error); +} + + + + + + diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml new file mode 100644 index 000000000..ba8c7e2b3 --- /dev/null +++ b/src/extension/dbus/document-interface.xml @@ -0,0 +1,1223 @@ + + + + + + + + + + + + + + The string id of a verb. For example: "EditSelectAll". + + + + + This method allows you to call any Inkscape verb using it's associated string. Every button and menu item has an associated verb, so this allows access to some extra functionality if one is willing to do the prerequisite research. The list of verbs can be found at: + + + + + + + + + + X coordinate for the top left corner of the rectangle. + + + + + Y coordinate for the top left corner of the rectangle. + + + + + Width of the rectangle. + + + + + Height of the rectangle. + + + + + + The name of the new rectangle. + + + + + This method creates a rectangle in the current layer using the current document style. + It is recommended that you save the return value if you will want to modify this particular shape later. + Additional variables include: + cx and cy: set these anywhere from zero to half the width or height respectively of the rectangle to give it rounded corners. + + Coordinate System + + + + + + + X coordinate for the top left corner of the ellipse. + + + + + Y coordinate for the top left corner of the ellipse. + + + + + Width of the ellipse. + + + + + Height of the ellipse. + + + + + + The name of the new ellipse. + + + + + This method creates a ellipse in the current layer using the current document style. + It is recommended that you save the return value if you will want to modify this particular shape later. + Additional variables include: + "sodipodi:start" and "sodipodi:end": set these between 0 and Pi to create wedges or Pacman like shapes. + + Coordinate System + + + + + + + X coordinate for the center of the polygon. + + + + + Y coordinate for the center of the polygon. + + + + + Radius from the center to one of the points. + + + + + Angle in degrees to rotate. 0 will have the first point pointing straight up. + + + + + Number of sides of the polygon. + + + + + + The name of the new polygon. + + + + + This method creates a polygon in the current layer using the current document style. + It is recommended that you save the return value if you will want to modify this particular shape later. + Note: this is actually a star with "sodipodi:flatsided" set to true, which causes it to ignore the arg2 and r2 values. + + Coordinate System + + + + + + + X coordinate for the center of the star. + + + + + Y coordinate for the center of the star. + + + + + distance from the center for the first point. + + + + + distance from the center for the second point. + + + + + Angle in radians for the first point. 0 is 90 degrees to the right of straight up. + + + + + Angle in radians for the second point. 0 is 90 degrees to the right of straight up. + + + + + Number of times to repeat the points around the star. + + + + + How rounded to make the star. 0 to 1 recommended for moderate to medium curves. 10 for extreme curves. + + + + + + The name of the new star. + + + + + This method creates a star in the current layer using the current document style. + It is recommended that you save the return value if you will want to modify this particular shape later. + Stars are quite complicated. Here is how they are represented: There are two points, represented by sodipodi:arg1 and sodipodi:arg2 for angle in radians and sodipodi:r1 and sodipodi:r2 for respective radius from the center point. The further one is a point of the star, the shorter one one of the valleys. This point and valley are repeated according to sodipodi:sides. sodipodi:rounded controls their control handles. + + Coordinate System + + + + + + + X coordinate for the center of the spiral. + + + + + Y coordinate for the center of the spiral. + + + + + Radius of the spiral. + + + + + Number of revolutions. + + + + + + The name of the new spiral. + + + + + This method creates a spiral in the current layer using the current document style. However, fill is automatically set to "none". Stroke is unmodified. + It is recommended that you save the return value if you will want to modify this particular shape later. + Additional variables include: + "sodipodi:expansion": at 1 the spiral gets bigger at a constant rate. Less than one and the loops get tighter and tighter as it goes. More than one and they get looser and looser. This affects the number of revolutions so that it might not actually match the "sodipodi:revolutions" argument. + "sodipodi:t0": at 0 the entire spiral is drawn, at 0.5 it is only drawn %50 of the way (starting from the outside) etc. + "sodipodi:argument": Rotates the spiral. In radians. + + Coordinate System + + + + + + + X coordinate for the first point. + + + + + Y coordinate for the first point. + + + + + X coordinate for the second point. + + + + + Y coordinate for the second point. + + + + + + The name of the new line. + + + + + This method creates a line in the current layer using the current document style. It's a path, so the only attribute it will pay any attention to is "transform". + + Coordinate System + + + + + + + The text you want. + + + + + + The name of the new text object. + + + + + This method creates some text in the current layer. + + + + + + + + The type of node, probably "svg:path" + + + + + + The name of the new node. + + + + + Make any kind of node you want. Mostly for making paths. (May need to allow updateRepr to be called for it to show up.) + + + + + + + + + + + Document width. + + + + + Retrieve the width of the current document. anything outside the boundary will not be printed or exported but will be saved. + + + + + + + + + Document height. + + + + + Retrieve the height of the current document. anything outside the boundary will not be printed or exported but will be saved. + + + + + + + + + CSS attribute string for the document. + + + + + Get the current style for the document. All new shapes will use this style if it exists. + + Style Strings + + + + + + + A new CSS attribute string for the document. + + + + + Set the current style for the document. All new shapes will use this style if it exists. + + Style Strings + + + + + + + A new CSS attribute string for the document. + + + + + Merge this this string with the current style for the document. All new shapes will use this style if it exists. + + Style Strings, merge_css() + + + + + + + Resize the document to contain all of the currently selected objects. + This ensures that the image is not clipped when printing or exporting. + + + + + + + + + + The id of an object. + + + + + The name of the attribute. + + + + + The new value of the attribute. This will overwrite anything already set. To merge styles, see merge_css(). + + + + + Set any attribute, the available attributes depend on what kind of shape the object node represents. See shape creation functions for more details. + + + + + + + + The id of an object. + + + + + The name of the attribute. + + + + + The new value of the attribute. This will overwrite anything already set. + + + + + Set any attribute, the available attributes depend on what kind of shape the object node represents. See shape creation functions for more details. + This is a convenience function for set_attribute(). + + + + + + + + The id of an object. + + + + + The name of the attribute. + + + + + The new value of the attribute. This will overwrite anything already set. + + + + + Set any attribute, the available attributes depend on what kind of shape the node represents. See shape creation functions for more details. + This is a convenience function for set_attribute(). + + + + + + + + The id of an object. + + + + + The name of the attribute. + + + + + + The current value of the attribute. String is a copy and must be freed. + + + + + Get the value of any attribute. Not all objects will have every attribute their type supports, some are optional. See shape creation functions for more details. + + + + + + + + The id of an object. + + + + + Distance to move along the x axis. + + + + + Distance to move along the y axis. + + + + + This will move a shape (or any object) relative to it's current location. + This may be accomplished with transformation attributes or by changing x and y attributes depending on the state of the object. + + Coordinate System + + + + + + + The id of an object. + + + + + the x coordinate of the desired location. + + + + + the y coordinate of the desired location. + + + + + This will move a shape (or any object) to an absolute location. The point moved is the center of the bounding box, which is usually similar to the center of the shape. + Note that creating a rectangle or ellipse at 100,100 and calling move_to to move it to 100,100 will not produce the same results. + This may be accomplished with transformation attributes or by changing x and y attributes depending on the state of the object. + + Coordinate System + + + + + + + The id of an object. + + + + + Turns an object into a path. Most objects contain paths (except rectangles) but are not paths themselves. + This will remove every attribute except d (the path attribute) style and id. id will not change. The appearance will be the same as well, it essentially encodes all information about the shape into the path. + After doing this you will no longer be able to modify the shape using shape specific attributes (cx, radius etc.) except transform + Required for certain functions that work on paths (not yet present in this API.) + + + + + + + + The id of any node or object. + + + + + A string that represents a transformation. + + + + + Takes a transformation string ("matrix(0.96629885,0.25742286,-0.25742286,0.96629885,0,0)" or "rotate(45)") and applies it to any shape or path. + Will merge with existing transformations. + + + + + + + + Any object with a style attribute. + + + + + + A CSS Style string + + + + + Retrieve the style of a object. Equivalent to calling get_attribute() for "style". + + Style Strings + + + + + + + Any object with a style attribute. + + + + + An attribute such as "fill" or "stroke-width". + + + + + The new value. + + + + + Set a particular attribute of a style string. Overwrites just that part of the style. + + Style Strings + + + + + + + Any object with a style attribute. + + + + + A full or partial CSS Style string. + + + + + Takes a CSS Style string and merges it with the objects current style, overwriting only the elements present in stylestring. + + Style Strings + + + + + + + The id of an object. + + + + + A layer name. + + + + + Moves an object to a different layer. + Will error if layer does not exist. + + layer_new() + + + + + + + A object that contains a path ("d") attribute. + + + + + + An array of points. + + + + + Returns an array of all of the X,Y coordinates of the points in the objects path. + If the path is a closed loop the first point is repeated at the end. + + + + + + + + + + Saves the current document with current name or a default name if has not been saved before. + Will overwrite without confirmation. + + + + + + + + The path for the file to be saved as. + + + + + Saves the current document as pathname. + Will overwrite without confirmation. + + + + + + + + The path to a valid svg file. + + + + + Loads the file at pathname. + Will lose all unsaved work in current document. + + + + + + + + Prints the current document with default settings. + Will only print things visible within the document boundaries. + + document_resize_to_fit_selection() + + + + + + + + + Close this document. + You will not be able to send any more commands on this interface. + + + + + + + + Exit Inkscape. + You will not be able to send any more commands on any interface. + + + + + + + + Undo the last action. + + + + + + + + Redo the last undone action. + + + + + + + + + + When updates are paused Inkscape will not draw every change as it is made. Also you will not be able to undo individual actions made while updates were paused and will only be able to undo them in a group. Inkscape may refresh the screen every couple of seconds even with updates off. + The advantage is a 2-5x speed increase, depending on the type of functions being called. This is most useful when creating large numbers of shapes. + + + + + + + + Resume updates after they have been paused. If undo is called at this point it will undo everything that happened since pause_updates() was called. + This will update the display to show any changes that happened while updates were paused, a separate call to update() is not necessary. + + + + + + + + This will update the document once if updates are paused but it will not resume updates. + This could be used to check on the progress of a complex drawing function, or to add in undo steps at certain points in a render. + + + + + + + + + + + List of the ids of currently selected objects. + + + + + Returns the current selection in the form of a list of ids of selected objects. + Manipulating this list will not affect the selection. + + + + + + + + A object to add to the selection. + + + + + Adds a single object to the selection. + + + + + + + + An array of object ids to add to the selection. + + + + + Adds a list of objects to the selection. + + + + + + + + A object to select. + + + + + Replaces the selection with one containing just this object. + + + + + + + + A list of objects to select. + + + + + Replaces the selection with one containing just these objects. + + + + + + + + Angle in degrees to rotate. + + + + + Rotates the selection around the center of it's bounding box. + + + + + + + + Delete all objects in the selection. + + + + + + + + Deselect everything. Selection will be empty. + + + + + + + + Select all objects in current layer. + + + + + + + + Select all objects in every layer. + + + + + + + + X coordinate for the first point. + + + + + Y coordinate for the first point. + + + + + X coordinate for the second point. + + + + + Y coordinate for the second point. + + + + + True to replace selection, false to add to selection. + + + + + This method finds all of the objects inside the box and adds them to the current selection. If replace is true it will clear the old selection first. + + + + + + + + Invert the selection in the current layer. + + + + + + + + Group the selection. + + Groups + + + + + + + Ungroup the selection. + + Groups + + + + + + + Cut the current selection. + + + + + + + + Copy the current selection. + + + + + + + + Paste the current selection at the same location it was cut from. + To paste to a particular location, simply use selection_paste() followed by selection_move_to(). + + + + + + + + The amount to scale the selection, 1 has no effect. Between 0 and 1 will shrink it proportionally. Greater than one will grow it proportionally. + + + + + Scale the selection relative to it's current size. + + + + + + + + Amount to move in the x direction. + + + + + Amount to move in the y direction. + + + + + This will move the selection relative to it's current location. + This may be accomplished with transformation attributes or by changing x and y attributes depending on the state of the objects in the selection. + + Coordinate System + + + + + + + X coordinate to move to. + + + + + Y coordinate to move to. + + + + + This will move the center of the selection to a specific location. + This may be accomplished with transformation attributes or by changing x and y attributes depending on the state of the objects in the selection. + + Coordinate System + + + + + + + layer to move the selection to. + + + + + Move every item in the selection to a different layer. + Will error if layer does not exist. + + Layers and Levels + + + + + + + + Center of the selection. + + + + + Gets the center of the selections bounding box in X,Y coordinates. + + Coordinate System + + + + + + + Turns all the objects in the selection into paths. + + object_to_path() + + + + + + + Type of combination. + + + + + + The new path created, if there is one. NULL otherwise. + + + + + Will erase all objects in the selection and replace with a single aggregate path. + There are 5 types that can be passed in: + Union: The new shape is all of the other shapes put together, even if they don't overlap (paths can have multiple non-contiguous areas.) + Intersection: The new shape is composed of the area where ALL the objects in the selection overlap. If there is no area where all shapes overlap the new shape will be empty. + Difference: The area of the second shape is subtracted from the first, only works with two objects. + Exclusion: The new shape is the area(s) where none of the objects in the selection overlaped. Only works with two objects. + Division: the first object is split into multiple segments by the second object. Only works with two objects and if multiple paths result they are grouped and the group id is returned. + + + + + + + + How to change the level + + + + + + True if the objects changed levels. False if they don't(if they were already on top when being raised for example.) + + + + + Will change the level of a selection, respective of other objects in the same layer. Will not affect the overlap of objects in different layers. Will do nothing if the selection contains objects in multiple layers. + There are 4 commands that can be passed in: + "raise" or "lower": Move the selection one level up, or one level down. + "to_top" of "to_bottom": Move the selection above all other objects or below all other objects. + + + + + + + + + + + The name of the new layer. + + + + + Turns all the objects in the selection into paths. + + Layers and Levels + + + + + + + The name of any layer. + + + + + Sets the layer given as the current layer + + Layers and Levels + + + + + + + + list of layers. + + + + + Get a list of all the layers in this document. + + Layers and Levels + + + + + + + How to change the level + + + + + + True if the layer was moved. False if it was not (if it was already on top when being raised for example.) + + + + + Will change the level of a layer, respective of other layers. Will not affect the relative level of objects within the layer. + There are 4 commands that can be passed in: + "raise" or "lower": Move the layer one level up, or one level down. + "to_top" of "to_bottom": Move the layer above all other layers or below all other layers. + + + + + + + + Sets the next (or higher) layer as active. + + Layers and Levels + + + + + + + Sets the previous (or lower) layer as active. + + Layers and Levels + + + + + + diff --git a/src/extension/dbus/org.inkscape.service.in b/src/extension/dbus/org.inkscape.service.in new file mode 100644 index 000000000..401d2d38e --- /dev/null +++ b/src/extension/dbus/org.inkscape.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.inkscape +Exec=/usr/local/bin/inkscape + -- cgit v1.2.3 From a747404be053f835da4c28a06a91503da115524d Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 16:52:57 +0000 Subject: Added code to initialize DBus (if enabled.) (bzr r8254.1.4) --- src/extension/init.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/extension/init.cpp b/src/extension/init.cpp index 84cc45de9..dc39ea430 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -55,6 +55,9 @@ #endif #include "preferences.h" #include "io/sys.h" +#ifdef WITH_DBUS +#include "dbus/dbus-init.h" +#endif #ifdef WITH_IMAGE_MAGICK #include "internal/bitmap/adaptiveThreshold.h" @@ -185,6 +188,10 @@ init() Internal::BlurEdge::init(); Internal::GimpGrad::init(); Internal::Grid::init(); + +#ifdef WITH_DBUS + Dbus::init(); +#endif /* Raster Effects */ #ifdef WITH_IMAGE_MAGICK -- cgit v1.2.3 From fce8e137470e83bbe1e8eb64afba819f36c33f5d Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 16:57:36 +0000 Subject: Added code to add a DBus interface for every desktop created. (bzr r8254.1.5) --- src/file.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/file.cpp b/src/file.cpp index 049c1acb4..7acd5fe5d 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -42,6 +42,7 @@ #include "extension/input.h" #include "extension/output.h" #include "extension/system.h" +#include "extension/dbus/dbus-init.h" #include "file.h" #include "helper/png-write.h" #include "id-clash.h" @@ -136,6 +137,7 @@ sp_file_new(const Glib::ustring &templ) sp_namedview_window_from_document(dt); sp_namedview_update_layers_from_document(dt); } + Inkscape::Extension::Dbus::dbus_init_desktop_interface(dt); return dt; } -- cgit v1.2.3 From af5da2b930e76796a69174b62b5f4c4064662729 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 16:59:19 +0000 Subject: Added some requested documentaion. (bzr r8254.1.6) --- src/selection.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/selection.h b/src/selection.h index ecb1ef45e..8eacf0d46 100644 --- a/src/selection.h +++ b/src/selection.h @@ -249,14 +249,16 @@ public: /** * @brief Returns the bounding rectangle of the selection * - * \todo how is this different from bounds()? + * Gives the coordinates in internal format, does not match onscreen guides. + * (0,0 is the upper left corner, not the lower left corner) */ NRRect *boundsInDocument(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; /** * @brief Returns the bounding rectangle of the selection * - * \todo how is this different from bounds()? + * Gives the coordinates in internal format, does not match onscreen guides. + * (0,0 is the upper left corner, not the lower left corner) */ Geom::OptRect boundsInDocument(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; -- cgit v1.2.3 From bda22333701d1af321937c5c66926c6ed5c5fe07 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 17:02:17 +0000 Subject: Made public some functions so they could be used by the DBus code. Similar functions were already public so I think it's okay. (bzr r8254.1.7) --- src/inkscape.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/inkscape.h b/src/inkscape.h index ca2894227..d82092754 100644 --- a/src/inkscape.h +++ b/src/inkscape.h @@ -42,6 +42,8 @@ Inkscape::XML::Node *inkscape_get_menus (Inkscape::Application * inkscape); Inkscape::Application *inkscape_get_instance(); +SPDesktop * inkscape_find_desktop_by_dkey (unsigned int dkey); + #define SP_ACTIVE_EVENTCONTEXT inkscape_active_event_context () SPEventContext * inkscape_active_event_context (void); @@ -57,6 +59,7 @@ gchar *homedir_path(const char *filename); gchar *profile_path(const char *filename); /* Inkscape desktop stuff */ +void inkscape_activate_desktop (SPDesktop * desktop); void inkscape_switch_desktops_next (); void inkscape_switch_desktops_prev (); void inkscape_get_all_desktops (std::list< SPDesktop* >& listbuf); -- cgit v1.2.3 From 779ee4b74a28eef8186d19d632d61f88fbe5b1e0 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sun, 12 Jul 2009 17:08:53 +0000 Subject: Added makefile_insert for DBus, if enabled. (bzr r8254.1.8) --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index bc5b2d839..90b0be28c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,6 +45,7 @@ all_libs = \ $(PYTHON_LIBS) \ $(INKBOARD_LIBS) \ $(LIBWPG_LIBS) \ + $(DBUS_LIBS) \ $(IMAGEMAGICK_LIBS) # Add sources common for Inkscape and Inkview to this variable. @@ -62,6 +63,7 @@ INCLUDES = \ $(IMAGEMAGICK_CFLAGS) \ $(INKBOARD_CFLAGS) \ $(LIBWPG_CFLAGS) \ + $(DBUS_CFLAGS) \ $(XFT_CFLAGS) \ $(LCMS_CFLAGS) \ $(POPPLER_CFLAGS) \ @@ -104,6 +106,7 @@ include dialogs/Makefile_insert include display/Makefile_insert include dom/Makefile_insert include extension/Makefile_insert +include extension/dbus/Makefile_insert include extension/implementation/Makefile_insert include extension/internal/Makefile_insert include extension/script/Makefile_insert -- cgit v1.2.3 From 745136f6c9423a0f0c8b020980ec0321049dbedb Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 13 Jul 2009 17:33:36 +0000 Subject: Documentation helper files. Building documentation is currently done by shell script, but will be integrated into the build system eventually. (bzr r8254.1.9) --- src/extension/dbus/doc/config.xsl | 7 + src/extension/dbus/doc/dbus-introspect-docs.dtd | 33 ++ src/extension/dbus/doc/docbook.css | 79 ++++ src/extension/dbus/doc/inkscapeDbusRef.xml | 81 ++++ src/extension/dbus/doc/inkscapeDbusTerms.xml | 131 ++++++ src/extension/dbus/doc/spec-to-docbook.xsl | 544 ++++++++++++++++++++++++ 6 files changed, 875 insertions(+) create mode 100644 src/extension/dbus/doc/config.xsl create mode 100644 src/extension/dbus/doc/dbus-introspect-docs.dtd create mode 100644 src/extension/dbus/doc/docbook.css create mode 100644 src/extension/dbus/doc/inkscapeDbusRef.xml create mode 100644 src/extension/dbus/doc/inkscapeDbusTerms.xml create mode 100644 src/extension/dbus/doc/spec-to-docbook.xsl (limited to 'src') diff --git a/src/extension/dbus/doc/config.xsl b/src/extension/dbus/doc/config.xsl new file mode 100644 index 000000000..26949c4ef --- /dev/null +++ b/src/extension/dbus/doc/config.xsl @@ -0,0 +1,7 @@ + + + + + diff --git a/src/extension/dbus/doc/dbus-introspect-docs.dtd b/src/extension/dbus/doc/dbus-introspect-docs.dtd new file mode 100644 index 000000000..47816713e --- /dev/null +++ b/src/extension/dbus/doc/dbus-introspect-docs.dtd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/extension/dbus/doc/docbook.css b/src/extension/dbus/doc/docbook.css new file mode 100644 index 000000000..aed08dce1 --- /dev/null +++ b/src/extension/dbus/doc/docbook.css @@ -0,0 +1,79 @@ +body +{ + font-family: sans-serif; +} +h1.title +{ +} +.permission +{ + color: #ee0000; + text-decoration: underline; +} +.synopsis, .classsynopsis +{ + background: #eeeeee; + border: solid 1px #aaaaaa; + padding: 0.5em; +} +.programlisting +{ + background: #eeeeff; + border: solid 1px #aaaaff; + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} +td.shortcuts +{ + color: #770000; + font-size: 80%; +} +div.refnamediv +{ + margin-top: 2em; +} +div.toc +{ + border: 2em; +} +a +{ + text-decoration: none; +} +a:hover +{ + text-decoration: underline; + color: #FF0000; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + border-style: solid; + border-color: #777777; + border-width: 1px; +} + +div.table table td, div.table table th +{ + border-style: solid; + border-color: #777777; + border-width: 1px; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + background-color: #eeeeee; +} + diff --git a/src/extension/dbus/doc/inkscapeDbusRef.xml b/src/extension/dbus/doc/inkscapeDbusRef.xml new file mode 100644 index 000000000..6bf134a60 --- /dev/null +++ b/src/extension/dbus/doc/inkscapeDbusRef.xml @@ -0,0 +1,81 @@ + + + + + + +]> + + + + Inkscape Dbus Documentation + Version 0.0 + 7 July, 2009 + + + Soren + Berg + +
+ glimmer07@gmail.com +
+
+
+
+
+ + + Introduction + +This is the documentation for scripting Inkscape using Dbus. This framework was developed to let users quickly and easily write scripts to create or manipulate images in a variety of languages. Once the API has stabilized there will also be a C library that encapsulates the Dbus functionality. + + +The guiding principles behind the design of this API were: + + +Easy to use: Use of insider terms was limited where possible, and many functions have been simplified to provide a easy entry point for beginning users. Ideally one should not need any experience with Inkscape or even vector graphics to begin using the interface. At the same time, functions that can call arbitrary verbs or manipulate nodes and their attributes directly give knowledgeable users some flexibility. + + +Interactive: Since Dbus ties in with the main loop, users can mix scripting and mouse driven actions seamlessly. This allows for some unique uses but more importantly makes it easier for people to learn the API since they can play around with it in a scripting console, or even a simple python shell. + + +Responsive: Since one of the advantages of scripting is the ability to repeat actions many times with great precision it is obvious that the system would have to be fairly fast. The amount of overhead has been limited where possible and functions have been tested for speed. A system to pause updates and only refresh the display after a large number of operations have been completed, ensures that even very complicated renders will not take too long. + + + + + Concepts + + &Terms; + + + + + Reference + + + D-Bus API Reference + + + + Inkscape provides a D-Bus API for programs to interactivly script vector graphics. + + + This API is not yet stable and is likely to change in the future. + + + + &dbus-Application; + &dbus-Document; + &dbus-Proposed; + + + + + + Index + + +
+ diff --git a/src/extension/dbus/doc/inkscapeDbusTerms.xml b/src/extension/dbus/doc/inkscapeDbusTerms.xml new file mode 100644 index 000000000..cd41195a9 --- /dev/null +++ b/src/extension/dbus/doc/inkscapeDbusTerms.xml @@ -0,0 +1,131 @@ + + Connecting to the API + + + Overview + +There are really two Dbus interfaces provided by Inkscape. One is the application interface, which is constant, and allows one to control the Inkscape application as a whole and create new documents or windows. The second is the document interface. A document interface is automatically generated for every open window, and the commands sent to that interface will affect that particular window. + + +So the basic way of connecting goes like this: Connect to the session bus. Connect to the application interface. Request a new document. Connect to the newly created document interface using the name returned in the last step. Manipulate the document however you want (load files, create shapes, save, etc.) After the connection example there is a shortcut that will shorten this process somewhat in certain circumstances. + + + + Connection example + +Here is a basic example of connecting to the Bus and getting a new document. (In python for now because it's easy to read.) + + + +import dbus + +#get the session bus. +bus = dbus.SessionBus() + +#get the object for the application. +inkapp = bus.get_object('org.inkscape', + '/org/inkscape/application') + +#request a new desktop. +desk2 = inkapp.desktop_new(dbus_interface='org.inkscape.application') + +#get the object for that desktop. +inkdoc1 = bus.get_object('org.inkscape', desk2) + +#tell it what interface it is using so we don't have to type it for every method. +doc1 = dbus.Interface(inkdoc1, dbus_interface="org.inkscape.document") + +#use! +doc1.rectangle (0,0,100,100) + + + + + + Shortcut + +Here is a quicker way if you don't need multiple documents open at once. Since Inkscape starts automatically, and it always creates a blank document we can just connect to that. + + +WARNING: This may not always work, it also might connect you to a document that is in use if Inkscape was already running. Only recommended for testing/experimenting. + + + +import dbus + +#get the session bus. +bus = dbus.SessionBus() + +#get object +inkdoc1 = bus.get_object('org.inkscape', '/org/inkscape/desktop_0') + +#get interface +doc1 = dbus.Interface(inkdoc1, dbus_interface="org.inkscape.document") + +#ta-da +doc1.rectangle (0,0,100,100) + + + + + + + + Terminology + + + + Coordinate System + +The coordinate system used by this API may be different than what you are used to (although it is standard in the computer graphics industry.) Simply put the origin (0,0) is in the upper left hand corner of the document. X increases to the right and Y increases downwards. Therefore everything with positive coordinates is in the document. + + +For example: (100,100) would be just below and to the right of the top left corner of the document. + + + + + + Selections + +Selections are extremely useful ways of managing groups of objects and applying effects to all of them at once. Since much of Inkscapes core functionality is built around manipulating selections they are the key to much of this APIs utility. Manipulate the list of selected objects with selection_set(), selection_add(), and selection_box() and then call whatever selection function you need. + + + + + + Groups + +Groups are collections of objects that are treated as a single object. Groups have their own id and can be passed to any function that accepts an object, though some will not have any effect (groups ignore style for instance.) Groups can be transformed and occupy a single level in their layer. Objects within a group can still be modified using their ids, but this will not have any affect on the other group members. Functions like move_to may not work as expected if used on an object that is part of a group that has a transformation applied. + + + + + + Layers and Levels + +The basic idea is that things on top cover up things beneath them. The potentially confusing part is that Inkscape implements this in two ways: layers and levels. Levels are what order objects are in within a single layer. So the highest level object is still below all of the objects in the layer above it. layer_change_level() changes the order of layers and selection_change_level() changes the order of objects within a layer. + + +Changing the level of a selection also deserves some explanation. The selection_change_level() function can work in two ways. It can be absolute, "to_top" and "to_bottom" work like you'd expect, sending the entire selection to the top or bottom of that layer. But it can also be relative. "raise" and "lower" only work if there is another shape overlaping above or beneath the selection at the moment. Also if you have two objects selected and they are both occluded by a third, raising the selection once will only raise the first object in the selection above the third object. In other words selections don't move as a group. + + + + + + Style Strings + +Style strings look something like this: "fill:#ff0000;fill-opacity:1;stroke:#0000ff;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none". It is a string of key value pairs that determines the style of a particular object. Style strings affect most objects. They can be set all at once or specific key value pairs can be added one by one. Style strings can also be merged, with the new string replacing key/value pairs that it contains and leaving the rest as they were. One could also think of it as the new string taking any attributes it does not have and adopting them from the old string. + + + + + + Nodes and Paths + +To be written. + + + + + diff --git a/src/extension/dbus/doc/spec-to-docbook.xsl b/src/extension/dbus/doc/spec-to-docbook.xsl new file mode 100644 index 000000000..e200a05e0 --- /dev/null +++ b/src/extension/dbus/doc/spec-to-docbook.xsl @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + interface + + + + Methods + + + + + + + + + + + Signals + + + + + + + + + + + Implemented Interfaces + + Objects implementing also implements + org.freedesktop.DBus.Introspectable, + org.freedesktop.DBus.Properties + + + + + + + Properties + + + + + + + + + + + Description + + + + + + + Details + + + + + + + + + Signal Details + + + + + + + + + + + Property Details + + + + + + + + + + + + + + + + +: + + + + + + + + + + + + + + + + + + + + + + <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property + +'' + + + + + + + + + + + + + +: + + + + + + + + + + + + + + + + + + + + + <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal + + () + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Since + + + + + + + + /> + + + + + + + is deprecated since version and should not be used in newly-written code. Use + + + + + : + + + :: + + + . + + + + + + + + + + + + + + + +instead. + + + + + + + + + + + + + + + + + +See also: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +: + + + + + + + + + + + + Errors + + + + : + + + + + + + + + + + + Permissions + + + + + + + + + + + + + + + + + + <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> () + + () + + + + + + + + + + + + + + + + +:'' + + + + + + + + + + + + +::() + + + + + + + + + + + + +.() + + + + + +'' +, + + + + + +'' +, + + + + + + +'' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 5045b4248d6c274a5787476889b9332c19940507 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 13 Jul 2009 17:54:55 +0000 Subject: TEMPORARY Added a shell script to build documentation until it's integrated into the build system. (bzr r8254.1.10) --- src/extension/dbus/builddocs.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 src/extension/dbus/builddocs.sh (limited to 'src') diff --git a/src/extension/dbus/builddocs.sh b/src/extension/dbus/builddocs.sh new file mode 100755 index 000000000..2c16daf41 --- /dev/null +++ b/src/extension/dbus/builddocs.sh @@ -0,0 +1,6 @@ +xsltproc doc/spec-to-docbook.xsl application-interface.xml > doc/org.inkscape.application.ref.xml && +xsltproc doc/spec-to-docbook.xsl document-interface.xml > doc/org.inkscape.document.ref.xml && +xsltproc doc/spec-to-docbook.xsl proposed-interface.xml > doc/org.inkscape.proposed.ref.xml && +xmlto --skip-validation xhtml-nochunks -o doc -m doc/config.xsl doc/inkscapeDbusRef.xml && +firefox doc/inkscapeDbusRef.html + -- cgit v1.2.3 From fc46b3cb436a03d787778e0e462f89e45038b716 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 13 Jul 2009 22:42:41 +0000 Subject: Implemented all the CSS style functions. Worked on some layer functions. (bzr r8254.1.11) --- src/extension/dbus/document-interface.cpp | 62 +++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 94f442865..f73d319f5 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -365,21 +365,30 @@ gboolean document_interface_document_merge_css (DocumentInterface *object, gchar *stylestring, GError **error) { - return FALSE; + SPCSSAttr * style = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string (style, stylestring); + sp_desktop_set_style (object->desk, style); + return TRUE; } +//FIXME this actually merges gboolean document_interface_document_set_css (DocumentInterface *object, gchar *stylestring, GError **error) { - return FALSE; + SPCSSAttr * style = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string (style, stylestring); + sp_desktop_set_style (object->desk, style); + return TRUE; } gboolean document_interface_document_resize_to_fit_selection (DocumentInterface *object, GError **error) { - return FALSE; + dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); + //verb_fit_canvas_to_selection(object->desk); + return TRUE; } /**************************************************************************** @@ -506,28 +515,46 @@ gchar * document_interface_get_css (DocumentInterface *object, gchar *shape, GError **error) { -return NULL; + gchar style[] = "style"; + return document_interface_get_attribute (object, shape, style, error); } gboolean document_interface_modify_css (DocumentInterface *object, gchar *shape, gchar *cssattrb, gchar *newval, GError **error) { - return FALSE; + gchar style[] = "style"; + Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; + SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); + sp_repr_css_set_property(oldstyle, cssattrb, newval); + node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); + return TRUE; } gboolean document_interface_merge_css (DocumentInterface *object, gchar *shape, gchar *stylestring, GError **error) { - return FALSE; + SPCSSAttr * newstyle = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string (newstyle, stylestring); + + gchar style[] = "style"; + Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; + SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); + + sp_repr_css_merge(oldstyle, newstyle); + node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); + return TRUE; } gboolean document_interface_move_to_layer (DocumentInterface *object, gchar *shape, gchar *layerstr, GError **error) { - return FALSE; + const GSList *oldsel = selection_swap(object->desk, shape); + document_interface_selection_move_to_layer(object, layerstr, error); + selection_restore(object->desk, oldsel); + return TRUE; } DBUSPoint ** @@ -818,11 +845,30 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou return TRUE; } +//FIXME: does not paste in new layer. gboolean document_interface_selection_move_to_layer (DocumentInterface *object, gchar *layerstr, GError **error) { - return FALSE; + SPDesktop * dt = object->desk; + + Inkscape::Selection *selection = sp_desktop_selection(dt); + + // check if something is selected + if (selection->isEmpty()) + return FALSE; + + SPObject *next = get_object_by_name(object->desk, layerstr); + + if (next && (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0)) { + + sp_selection_cut(dt); + + dt->setCurrentLayer(next); + + sp_selection_paste(dt, TRUE); + } + return TRUE; } gboolean -- cgit v1.2.3 From 103aff597d89ef273a5d9cd12a0148c57f6a6435 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Wed, 15 Jul 2009 17:06:03 +0000 Subject: implemented a number of functions, including save/load functions. Removed the print function because I can see no way of doing it without bringing up a dialog. (bzr r8254.1.12) --- src/extension/dbus/document-interface.cpp | 107 +++++++++++++++++++++++------- src/extension/dbus/document-interface.xml | 5 +- 2 files changed, 86 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index f73d319f5..1cdff0133 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -24,6 +24,14 @@ #include "style.h" //style_write +#include "file.h" //IO + +#include "extension/system.h" //IO + +#include "extension/output.h" //IO + +#include "print.h" //IO + /**************************************************************************** HELPER / SHORTCUT FUNCTIONS ****************************************************************************/ @@ -330,13 +338,27 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy, gchar* document_interface_text (DocumentInterface *object, gchar *text, GError **error) { + //FIXME: implement. return NULL; } gchar* document_interface_node (DocumentInterface *object, gchar *type, GError **error) { - return NULL; + SPDocument * doc = sp_desktop_document (object->desk); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + + Inkscape::XML::Node *newNode = xml_doc->createElement(type); + + object->desk->currentLayer()->appendChildRepr(newNode); + object->desk->currentLayer()->updateRepr(); + + if (object->updates) + sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node"); + else + document_interface_pause_updates(object, error); + + return strdup(newNode->attribute("id")); } /**************************************************************************** @@ -371,14 +393,14 @@ document_interface_document_merge_css (DocumentInterface *object, return TRUE; } -//FIXME this actually merges gboolean document_interface_document_set_css (DocumentInterface *object, gchar *stylestring, GError **error) { SPCSSAttr * style = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string (style, stylestring); - sp_desktop_set_style (object->desk, style); + //Memory leak? + object->desk->current = style; return TRUE; } @@ -387,7 +409,6 @@ document_interface_document_resize_to_fit_selection (DocumentInterface *object, GError **error) { dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); - //verb_fit_canvas_to_selection(object->desk); return TRUE; } @@ -440,7 +461,6 @@ document_interface_get_attribute (DocumentInterface *object, char *shape, SPDesktop *desk2 = object->desk; SPDocument * doc = sp_desktop_document (desk2); - // FIXME: Not sure if this is the most efficient way. Inkscape::XML::Node *newNode = doc->getObjectById(shape)->repr; /* WORKS @@ -560,6 +580,7 @@ document_interface_move_to_layer (DocumentInterface *object, gchar *shape, DBUSPoint ** document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { + //FIXME: implement. return NULL; } @@ -569,48 +590,86 @@ document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape ****************************************************************************/ gboolean -document_interface_save (DocumentInterface *object, GError **error){ +document_interface_save (DocumentInterface *object, GError **error) +{ + SPDocument * doc = sp_desktop_document(object->desk); + printf("1: %s\n2: %s\n3: %s\n", doc->uri, doc->base, doc->name); + if (doc->uri) + return document_interface_save_as (object, doc->uri, error); return FALSE; } gboolean document_interface_load (DocumentInterface *object, - gchar *filename, GError **error){ - return FALSE; + gchar *filename, GError **error) +{ + desktop_ensure_active (object->desk); + const Glib::ustring file(filename); + sp_file_open(file, NULL, TRUE, TRUE); + if (object->updates) + sp_document_done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File"); + return TRUE; } gboolean document_interface_save_as (DocumentInterface *object, - gchar *filename, GError **error){ - return FALSE; -} + gchar *filename, GError **error) +{ + SPDocument * doc = sp_desktop_document(object->desk); + #ifdef WITH_GNOME_VFS + const Glib::ustring file(filename); + return file_save_remote(doc, file, NULL, TRUE, TRUE); + #endif + if (!doc || strlen(filename)<1) //Safety check + return false; + + try { + Inkscape::Extension::save(NULL, doc, filename, + false, false, true); + } catch (...) { + //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved.")); + return false; + } + //SP_ACTIVE_DESKTOP->event_log->rememberFileSave(); + //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved."); + return true; +} +/* gboolean -document_interface_print (DocumentInterface *object, GError **error){ - return FALSE; +document_interface_print_to_file (DocumentInterface *object, GError **error) +{ + SPDocument * doc = sp_desktop_document(object->desk); + sp_print_document_to_file (doc, g_strdup("/home/soren/test.pdf")); + + return TRUE; } - +*/ /**************************************************************************** PROGRAM CONTROL FUNCTIONS ****************************************************************************/ gboolean -document_interface_close (DocumentInterface *object, GError **error){ +document_interface_close (DocumentInterface *object, GError **error) +{ return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error); } gboolean -document_interface_exit (DocumentInterface *object, GError **error){ +document_interface_exit (DocumentInterface *object, GError **error) +{ return dbus_call_verb (object, SP_VERB_FILE_QUIT, error); } gboolean -document_interface_undo (DocumentInterface *object, GError **error){ +document_interface_undo (DocumentInterface *object, GError **error) +{ return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error); } gboolean -document_interface_redo (DocumentInterface *object, GError **error){ +document_interface_redo (DocumentInterface *object, GError **error) +{ return dbus_call_verb (object, SP_VERB_EDIT_REDO, error); } @@ -686,7 +745,6 @@ document_interface_selection_add (DocumentInterface *object, char *name, GError { if (name == NULL) return FALSE; - //FIXME: This gets called a lot. Efficient? SPDocument * doc = sp_desktop_document (object->desk); Inkscape::Selection *selection = sp_desktop_selection(object->desk); /* WORKS @@ -701,6 +759,7 @@ gboolean document_interface_selection_add_list (DocumentInterface *object, char **names, GError **error) { + //FIXME: implement. return FALSE; } @@ -717,6 +776,7 @@ gboolean document_interface_selection_set_list (DocumentInterface *object, gchar **names, GError **error) { + //FIXME: broken array passing. sp_desktop_selection(object->desk)->clear(); int i; for (i=0;((i<30000) && (names[i] != NULL));i++) { @@ -760,6 +820,7 @@ document_interface_select_all_in_all_layers(DocumentInterface *object, GError **error) { sp_edit_select_all_in_all_layers (object->desk); + return TRUE; } gboolean @@ -767,6 +828,7 @@ document_interface_selection_box (DocumentInterface *object, int x, int y, int x2, int y2, gboolean replace, GError **error) { + //FIXME: implement. return FALSE; } @@ -836,12 +898,7 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou //Geom::Point m( (object->desk)->point() - sel_bbox->midpoint() ); Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) ); sp_selection_move_relative(sel, m, true); - } - - //FIXME: dosn't work with transformations - //sp_selection_move (object->desk, x - selection_get_center_x(sel), - // 0 - (y - selection_get_center_y(sel))); return TRUE; } @@ -874,6 +931,7 @@ document_interface_selection_move_to_layer (DocumentInterface *object, gboolean document_interface_selection_get_center (DocumentInterface *object) { + //FIXME: implement: pass struct. return FALSE; } @@ -945,6 +1003,7 @@ document_interface_layer_set (DocumentInterface *object, gchar ** document_interface_layer_get_all (DocumentInterface *object) { + //FIXME: implement. return NULL; } diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index ba8c7e2b3..f79816de1 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -719,8 +719,8 @@ - - + -- cgit v1.2.3 From c819feae71738f973920724e60029397dd1c92a1 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Thu, 16 Jul 2009 16:01:55 +0000 Subject: Added missing (and very important) file. Added get_path method. Added documentation on paths. (bzr r8254.1.13) --- src/extension/dbus/doc/inkscapeDbusTerms.xml | 15 +- src/extension/dbus/document-interface.cpp | 43 ++-- src/extension/dbus/document-interface.h | 353 +++++++++++++++++++++++++++ src/extension/dbus/document-interface.xml | 24 +- 4 files changed, 407 insertions(+), 28 deletions(-) create mode 100644 src/extension/dbus/document-interface.h (limited to 'src') diff --git a/src/extension/dbus/doc/inkscapeDbusTerms.xml b/src/extension/dbus/doc/inkscapeDbusTerms.xml index cd41195a9..507fcbf24 100644 --- a/src/extension/dbus/doc/inkscapeDbusTerms.xml +++ b/src/extension/dbus/doc/inkscapeDbusTerms.xml @@ -119,9 +119,20 @@ Style strings look something like this: "fill:#ff0000;fill-opacity:1;stroke:#000 - + - Nodes and Paths + Paths + +A path is a string representing a series of points, and how the line curves between the points. It looks something like this: "m 351.42857,296.64789 a 54.285713,87.14286 0 1 1 -108.57143,0 54.285713,87.14286 0 1 1 108.57143,0 z" and is usually found as an attribute of a shape with the label "d". All shapes except rectangles have this "d" attribute. + + +Just because a shape has a path does not mean it IS a path however. A path object has no attributes except the path and a style. Calling object_to_path() will convert any object to a path, stripping away any other attributes except id and style which stay the same. This will not change the visual appearance but you will no longer be able to use shape handles or affect it by changing any attributes except for "style", "d", and "transform". Some functions may require paths. + + + + + + Nodes To be written. diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 1cdff0133..e3573989a 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -422,8 +422,8 @@ document_interface_set_attribute (DocumentInterface *object, char *shape, { Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; - /* ALTERNATIVE - Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); + /* ALTERNATIVE (is this faster?) + Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name); */ if (newNode) { @@ -458,14 +458,8 @@ gchar * document_interface_get_attribute (DocumentInterface *object, char *shape, char *attribute, GError **error) { - SPDesktop *desk2 = object->desk; - SPDocument * doc = sp_desktop_document (desk2); - - Inkscape::XML::Node *newNode = doc->getObjectById(shape)->repr; + Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; - /* WORKS - Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); - */ if (newNode) return g_strdup(newNode->attribute(attribute)); return FALSE; @@ -493,16 +487,17 @@ document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x, return TRUE; } -void +gboolean document_interface_object_to_path (DocumentInterface *object, char *shape, GError **error) { const GSList *oldsel = selection_swap(object->desk, shape); dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error); selection_restore(object->desk, oldsel); + return TRUE; } -gboolean +gchar * document_interface_get_path (DocumentInterface *object, char *pathname, GError **error) { Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); @@ -510,15 +505,7 @@ document_interface_get_path (DocumentInterface *object, char *pathname, GError * g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); return FALSE; } - gchar *pathstr = strdup(node->attribute("d")); - printf("PATH: %s\n", pathstr); - //gfree (pathstr); - std::istringstream iss(pathstr); - std::copy(std::istream_iterator(iss), - std::istream_iterator(), - std::ostream_iterator(std::cout, "\n")); - - return TRUE; + return strdup(node->attribute("d")); } gboolean @@ -580,7 +567,14 @@ document_interface_move_to_layer (DocumentInterface *object, gchar *shape, DBUSPoint ** document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { - //FIXME: implement. + //FIXME: not implemented. + Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); + if (node == NULL || node->attribute("d") == NULL) { + g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); + return FALSE; + } + char * path = strdup(node->attribute("d")); + return NULL; } @@ -712,8 +706,8 @@ document_interface_update (DocumentInterface *object, GError **error) SELECTION FUNCTIONS FIXME: use call_verb where appropriate. ****************************************************************************/ -gchar ** -document_interface_selection_get (DocumentInterface *object) +gboolean +document_interface_selection_get (DocumentInterface *object, GSList const * listy, GError **error) { Inkscape::Selection * sel = sp_desktop_selection(object->desk); GSList const *oldsel = sel->list(); @@ -737,7 +731,8 @@ document_interface_selection_get (DocumentInterface *object) printf("%d = %s\n", i, list[i]); } - return list; + listy = oldsel; + return TRUE; } gboolean diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h new file mode 100644 index 000000000..ba60a6599 --- /dev/null +++ b/src/extension/dbus/document-interface.h @@ -0,0 +1,353 @@ +#ifndef INKSCAPE_EXTENSION_DOCUMENT_INTERFACE_H_ +#define INKSCAPE_EXTENSION_DOCUMENT_INTERFACE_H_ + +#include +#include +#include +#include +#include "desktop.h" + +#define DBUS_DOCUMENT_INTERFACE_PATH "/org/inkscape/document" + +#define TYPE_DOCUMENT_INTERFACE (document_interface_get_type ()) +#define DOCUMENT_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_DOCUMENT_INTERFACE, DocumentInterface)) +#define DOCUMENT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DOCUMENT_INTERFACE, DocumentInterfaceClass)) +#define IS_DOCUMENT_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TYPE_DOCUMENT_INTERFACE)) +#define IS_DOCUMENT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DOCUMENT_INTERFACE)) +#define DOCUMENT_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DOCUMENT_INTERFACE, DocumentInterfaceClass)) + +G_BEGIN_DECLS + +typedef struct _DocumentInterface DocumentInterface; +typedef struct _DocumentInterfaceClass DocumentInterfaceClass; + +struct _DocumentInterface { + GObject parent; + SPDesktop *desk; + gboolean updates; +}; + +struct _DocumentInterfaceClass { + GObjectClass parent; +}; + +struct DBUSPoint { + int x; + int y; +}; +/**************************************************************************** + MISC FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_delete_all (DocumentInterface *object, GError **error); + +void +document_interface_call_verb (DocumentInterface *object, + gchar *verbid, GError **error); + +/**************************************************************************** + CREATION FUNCTIONS +****************************************************************************/ + +gchar* +document_interface_rectangle (DocumentInterface *object, int x, int y, + int width, int height, GError **error); + +gchar* +document_interface_ellipse (DocumentInterface *object, int x, int y, + int width, int height, GError **error); + +gchar* +document_interface_polygon (DocumentInterface *object, int cx, int cy, + int radius, int rotation, int sides, + GError **error); + +gchar* +document_interface_star (DocumentInterface *object, int cx, int cy, + int r1, int r2, int sides, gdouble rounded, + gdouble arg1, gdouble arg2, GError **error); + +gchar* +document_interface_spiral (DocumentInterface *object, int cx, int cy, + int r, int revolutions, GError **error); + +gchar* +document_interface_line (DocumentInterface *object, int x, int y, + int x2, int y2, GError **error); + +gchar* +document_interface_text (DocumentInterface *object, gchar *text, + GError **error); + +gchar* +document_interface_node (DocumentInterface *object, gchar *svgtype, + GError **error); + + +/**************************************************************************** + ENVIORNMENT FUNCTIONS +****************************************************************************/ +gdouble +document_interface_document_get_width (DocumentInterface *object); + +gdouble +document_interface_document_get_height (DocumentInterface *object); + +gchar * +document_interface_document_get_css (DocumentInterface *object, GError **error); + +gboolean +document_interface_document_merge_css (DocumentInterface *object, + gchar *stylestring, GError **error); + +gboolean +document_interface_document_set_css (DocumentInterface *object, + gchar *stylestring, GError **error); + +gboolean +document_interface_document_resize_to_fit_selection (DocumentInterface *object, + GError **error); + +/**************************************************************************** + OBJECT FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_set_attribute (DocumentInterface *object, + char *shape, char *attribute, + char *newval, GError **error); + +void +document_interface_set_int_attribute (DocumentInterface *object, + char *shape, char *attribute, + int newval, GError **error); + +void +document_interface_set_double_attribute (DocumentInterface *object, + char *shape, char *attribute, + double newval, GError **error); + +gchar * +document_interface_get_attribute (DocumentInterface *object, + char *shape, char *attribute, GError **error); + +gboolean +document_interface_move (DocumentInterface *object, gchar *name, + gdouble x, gdouble y, GError **error); + +gboolean +document_interface_move_to (DocumentInterface *object, gchar *name, + gdouble x, gdouble y, GError **error); + +gboolean +document_interface_object_to_path (DocumentInterface *object, + char *shape, GError **error); + +gchar * +document_interface_get_path (DocumentInterface *object, + char *pathname, GError **error); + +gboolean +document_interface_transform (DocumentInterface *object, gchar *shape, + gchar *transformstr, GError **error); + +gchar * +document_interface_get_css (DocumentInterface *object, gchar *shape, + GError **error); + +gboolean +document_interface_modify_css (DocumentInterface *object, gchar *shape, + gchar *cssattrb, gchar *newval, GError **error); + +gboolean +document_interface_merge_css (DocumentInterface *object, gchar *shape, + gchar *stylestring, GError **error); + +gboolean +document_interface_move_to_layer (DocumentInterface *object, gchar *shape, + gchar *layerstr, GError **error); + + +DBUSPoint ** +document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape); + +/**************************************************************************** + FILE I/O FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_save (DocumentInterface *object, GError **error); + +gboolean +document_interface_load (DocumentInterface *object, + gchar *filename, GError **error); + +gboolean +document_interface_save_as (DocumentInterface *object, + gchar *filename, GError **error); +/* +gboolean +document_interface_print_to_file (DocumentInterface *object, GError **error); +*/ + +/**************************************************************************** + PROGRAM CONTROL FUNCTIONS +****************************************************************************/ + +gboolean +document_interface_close (DocumentInterface *object, GError **error); + +gboolean +document_interface_exit (DocumentInterface *object, GError **error); + +gboolean +document_interface_undo (DocumentInterface *object, GError **error); + +gboolean +document_interface_redo (DocumentInterface *object, GError **error); + + +/**************************************************************************** + UPDATE FUNCTIONS +****************************************************************************/ +void +document_interface_pause_updates (DocumentInterface *object, GError **error); + +void +document_interface_resume_updates (DocumentInterface *object, GError **error); + +void +document_interface_update (DocumentInterface *object, GError **error); + +/**************************************************************************** + SELECTION FUNCTIONS +****************************************************************************/ +gboolean +document_interface_selection_get (DocumentInterface *object, GSList const * listy, GError **error); + +gboolean +document_interface_selection_add (DocumentInterface *object, + char *name, GError **error); + +gboolean +document_interface_selection_add_list (DocumentInterface *object, + char **names, GError **error); + +gboolean +document_interface_selection_set (DocumentInterface *object, + char *name, GError **error); + +gboolean +document_interface_selection_set_list (DocumentInterface *object, + gchar **names, GError **error); + +gboolean +document_interface_selection_rotate (DocumentInterface *object, + int angle, GError **error); + +gboolean +document_interface_selection_delete(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_clear(DocumentInterface *object, GError **error); + +gboolean +document_interface_select_all(DocumentInterface *object, GError **error); + +gboolean +document_interface_select_all_in_all_layers(DocumentInterface *object, + GError **error); + +gboolean +document_interface_selection_box (DocumentInterface *object, int x, int y, + int x2, int y2, gboolean replace, + GError **error); + +gboolean +document_interface_selection_invert (DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_group(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_ungroup(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_cut(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_copy(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_paste(DocumentInterface *object, GError **error); + +gboolean +document_interface_selection_scale (DocumentInterface *object, + gdouble grow, GError **error); + +gboolean +document_interface_selection_move (DocumentInterface *object, gdouble x, + gdouble y, GError **error); + +gboolean +document_interface_selection_move_to (DocumentInterface *object, gdouble x, + gdouble y, GError **error); + +gboolean +document_interface_selection_move_to_layer (DocumentInterface *object, + gchar *layerstr, GError **error); + +gboolean +document_interface_selection_get_center (DocumentInterface *object); + +gboolean +document_interface_selection_to_path (DocumentInterface *object, GError **error); + +gchar * +document_interface_selection_combine (DocumentInterface *object, gchar *cmd, + GError **error); + + +gboolean +document_interface_selection_change_level (DocumentInterface *object, gchar *cmd, + GError **error); + +/**************************************************************************** + LAYER FUNCTIONS +****************************************************************************/ + +gchar * +document_interface_layer_new (DocumentInterface *object, GError **error); + +gboolean +document_interface_layer_set (DocumentInterface *object, + gchar *layerstr, GError **error); + +gchar ** +document_interface_layer_get_all (DocumentInterface *object); + +gboolean +document_interface_layer_change_level (DocumentInterface *object, + gchar *cmd, GError **error); + +gboolean +document_interface_layer_next (DocumentInterface *object, GError **error); + +gboolean +document_interface_layer_previous (DocumentInterface *object, GError **error); + + + + + + + + +DocumentInterface *document_interface_new (void); +GType document_interface_get_type (void); + + +G_END_DECLS + +#endif // INKSCAPE_EXTENSION_DOCUMENT_INTERFACE_H_ diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index f79816de1..14be0312b 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -556,6 +556,27 @@ After doing this you will no longer be able to modify the shape using shape specific attributes (cx, radius etc.) except transform Required for certain functions that work on paths (not yet present in this API.) + Paths + + + + + + + The id of an object. + + + + + + The path of the object. NULL if the object has no path. + + + + + Get the path value of an object. Equivilent to calling get_attribte() with argument "d". Will not turn object into a path if it is not already. + + Paths @@ -799,8 +820,7 @@ - - + List of the ids of currently selected objects. -- cgit v1.2.3 From 0c4a64e7df83742bb6d7a17f31985eed9d06ef26 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Thu, 16 Jul 2009 16:28:50 +0000 Subject: Whoops, fixed a bug in an incomplete method. (bzr r8254.1.14) --- src/extension/dbus/document-interface.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index e3573989a..914303a91 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -567,14 +567,15 @@ document_interface_move_to_layer (DocumentInterface *object, gchar *shape, DBUSPoint ** document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { - //FIXME: not implemented. + //FIXME: Needs lot's of work. +/* Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); if (node == NULL || node->attribute("d") == NULL) { g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); return FALSE; } - char * path = strdup(node->attribute("d")); - + //char * path = strdup(node->attribute("d")); +*/ return NULL; } -- cgit v1.2.3 From 88870910722f4cef3a929b49479d2fa721e4f715 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 20 Jul 2009 20:34:13 +0000 Subject: Fixed selection_get() (bzr r8254.1.15) --- src/extension/dbus/document-interface.cpp | 49 +++++++++++++------------------ src/extension/dbus/document-interface.h | 2 +- src/extension/dbus/document-interface.xml | 1 + 3 files changed, 22 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 914303a91..b9d8848cc 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -671,7 +671,7 @@ document_interface_redo (DocumentInterface *object, GError **error) /**************************************************************************** - UPDATE FUNCTIONS + UPDATE FUNCTIONS FIXME: test update system again. ****************************************************************************/ void @@ -689,6 +689,7 @@ document_interface_resume_updates (DocumentInterface *object, GError **error) sp_desktop_document(object->desk)->root->uflags = TRUE; sp_desktop_document(object->desk)->root->mflags = TRUE; //sp_desktop_document(object->desk)->_updateDocument(); + //FIXME: use better verb than rect. sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); } @@ -708,31 +709,22 @@ document_interface_update (DocumentInterface *object, GError **error) ****************************************************************************/ gboolean -document_interface_selection_get (DocumentInterface *object, GSList const * listy, GError **error) +document_interface_selection_get (DocumentInterface *object, char ***out, GError **error) { Inkscape::Selection * sel = sp_desktop_selection(object->desk); GSList const *oldsel = sel->list(); int size = g_slist_length((GSList *) oldsel); - int i; - printf("premalloc\n"); - gchar **list = (gchar **)malloc(size); - printf("postmalloc\n"); - for(i = 0; i < size; i++) - list[i] = (gchar *)malloc(sizeof(gchar) * 10); - printf("postmalloc2\n"); - i=0; - printf("prealloc\n"); + + *out = g_new0 (char *, size + 1); + + int i = 0; for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) { - strcpy (list[i], SP_OBJECT(iter->data)->repr->attribute("id")); + (*out)[i] = g_strdup(SP_OBJECT(iter->data)->repr->attribute("id")); i++; } - printf("postalloc\n"); - for (i=0; idesk); Inkscape::Selection *selection = sp_desktop_selection(object->desk); - /* WORKS - Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); - selection->add(repr2, TRUE); - */ - selection->add(doc->getObjectById(name)); + + selection->add(get_object_by_name(object->desk, name)); return TRUE; } @@ -755,8 +743,12 @@ gboolean document_interface_selection_add_list (DocumentInterface *object, char **names, GError **error) { - //FIXME: implement. - return FALSE; + int i; + for (i=0;names[i] != NULL;i++) { + //printf("NAME: %s\n", names[i]); + document_interface_selection_add(object, names[i], error); + } + return TRUE; } gboolean @@ -772,11 +764,10 @@ gboolean document_interface_selection_set_list (DocumentInterface *object, gchar **names, GError **error) { - //FIXME: broken array passing. sp_desktop_selection(object->desk)->clear(); int i; - for (i=0;((i<30000) && (names[i] != NULL));i++) { - printf("NAME: %s\n", names[i]); + for (i=0;names[i] != NULL;i++) { + //printf("NAME: %s\n", names[i]); document_interface_selection_add(object, names[i], error); } return TRUE; diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index ba60a6599..53fcacaaa 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -224,7 +224,7 @@ document_interface_update (DocumentInterface *object, GError **error); SELECTION FUNCTIONS ****************************************************************************/ gboolean -document_interface_selection_get (DocumentInterface *object, GSList const * listy, GError **error); +document_interface_selection_get (DocumentInterface *object, char ***out, GError **error); gboolean document_interface_selection_add (DocumentInterface *object, diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 14be0312b..5db3de763 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -821,6 +821,7 @@ + List of the ids of currently selected objects. -- cgit v1.2.3 From 40d5732d5a327c51e04c6aaab97725d0d61b2327 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 20 Jul 2009 22:55:35 +0000 Subject: Fixed selection_get_center and selection_combine. Added selection_divide. (bzr r8254.1.16) --- src/extension/dbus/document-interface.cpp | 37 +++++++++++++++++++++++-------- src/extension/dbus/document-interface.h | 6 ++++- src/extension/dbus/document-interface.xml | 17 +++++++++++++- 3 files changed, 49 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index b9d8848cc..a939064e1 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -745,7 +745,6 @@ document_interface_selection_add_list (DocumentInterface *object, { int i; for (i=0;names[i] != NULL;i++) { - //printf("NAME: %s\n", names[i]); document_interface_selection_add(object, names[i], error); } return TRUE; @@ -767,7 +766,6 @@ document_interface_selection_set_list (DocumentInterface *object, sp_desktop_selection(object->desk)->clear(); int i; for (i=0;names[i] != NULL;i++) { - //printf("NAME: %s\n", names[i]); document_interface_selection_add(object, names[i], error); } return TRUE; @@ -882,7 +880,6 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou Geom::OptRect sel_bbox = sel->bounds(); if (sel_bbox) { - //Geom::Point m( (object->desk)->point() - sel_bbox->midpoint() ); Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) ); sp_selection_move_relative(sel, m, true); } @@ -915,11 +912,23 @@ document_interface_selection_move_to_layer (DocumentInterface *object, return TRUE; } -gboolean +GArray * document_interface_selection_get_center (DocumentInterface *object) { - //FIXME: implement: pass struct. - return FALSE; + Inkscape::Selection * sel = sp_desktop_selection(object->desk); + + if (sel) + { + gdouble x = selection_get_center_x(sel); + gdouble y = selection_get_center_y(sel); + GArray * intArr = g_array_new (TRUE, TRUE, sizeof(double)); + + g_array_append_val (intArr, x); + g_array_append_val (intArr, y); + return intArr; + } + + return NULL; } gboolean @@ -933,7 +942,6 @@ gchar * document_interface_selection_combine (DocumentInterface *object, gchar *cmd, GError **error) { - if (strcmp(cmd, "union") == 0) dbus_call_verb (object, SP_VERB_SELECTION_UNION, error); else if (strcmp(cmd, "intersection") == 0) @@ -947,8 +955,19 @@ document_interface_selection_combine (DocumentInterface *object, gchar *cmd, else return NULL; - //FIXME: this WILL cause problems with division - return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); + if (sp_desktop_selection(object->desk)->singleRepr() != NULL) + return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); + + //Division will have a list of things selected, should have it's own function. + return NULL; +} + +gboolean +document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error) +{ + dbus_call_verb (object, SP_VERB_SELECTION_CUT, error); + + return document_interface_selection_get (object, out, error); } gboolean diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index 53fcacaaa..afad56f59 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -298,7 +298,7 @@ gboolean document_interface_selection_move_to_layer (DocumentInterface *object, gchar *layerstr, GError **error); -gboolean +GArray * document_interface_selection_get_center (DocumentInterface *object); gboolean @@ -308,6 +308,10 @@ gchar * document_interface_selection_combine (DocumentInterface *object, gchar *cmd, GError **error); +gboolean +document_interface_selection_divide (DocumentInterface *object, + char ***out, GError **error); + gboolean document_interface_selection_change_level (DocumentInterface *object, gchar *cmd, diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 5db3de763..171508dcd 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -1084,7 +1084,7 @@ - + Center of the selection. @@ -1132,6 +1132,21 @@ + + + + + List of the ids of resulting paths. + + + + + Returns the result of cutting the bottom object by all other intersecting paths. + This may make many seperate layers. + + + + -- cgit v1.2.3 From c30b66d5e5f875384b4fa13f93ceb6bea8054830 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Tue, 21 Jul 2009 01:48:22 +0000 Subject: Worked on text, now works with limited capability. Started work on node_get_coordinates. (bzr r8254.1.17) --- src/extension/dbus/document-interface.cpp | 40 ++++++++++++++++++------------- src/extension/dbus/document-interface.h | 8 +++---- src/extension/dbus/document-interface.xml | 16 ++++++++----- 3 files changed, 38 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index a939064e1..a28bb92fa 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -32,6 +32,11 @@ #include "print.h" //IO +#include "live_effects/parameter/text.h" //text +#include "display/canvas-text.h" //text + +#include "2geom/svg-path-parser.h" //get_node_coordinates + /**************************************************************************** HELPER / SHORTCUT FUNCTIONS ****************************************************************************/ @@ -335,11 +340,17 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy, return retval; } -gchar* -document_interface_text (DocumentInterface *object, gchar *text, GError **error) +gboolean +document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error) { - //FIXME: implement. - return NULL; + //FIXME: Not selectable. + + SPDesktop *desktop = object->desk; + SPCanvasText * canvas_text = (SPCanvasText *) sp_canvastext_new(sp_desktop_tempgroup(desktop), desktop, Geom::Point(0,0), ""); + sp_canvastext_set_text (canvas_text, text); + sp_canvastext_set_coords (canvas_text, x, y); + + return TRUE; } gchar* @@ -564,18 +575,19 @@ document_interface_move_to_layer (DocumentInterface *object, gchar *shape, return TRUE; } -DBUSPoint ** +GArray * document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { //FIXME: Needs lot's of work. -/* - Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); - if (node == NULL || node->attribute("d") == NULL) { - g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); + + Inkscape::XML::Node *shapenode = document_retrive_node (sp_desktop_document (object->desk), shape); + if (shapenode == NULL || shapenode->attribute("d") == NULL) { return FALSE; } - //char * path = strdup(node->attribute("d")); -*/ + const char * path = strdup(shapenode->attribute("d")); + printf("PATH: %s\n", path); + + Geom::parse_svg_path (path); return NULL; } @@ -705,7 +717,7 @@ document_interface_update (DocumentInterface *object, GError **error) } /**************************************************************************** - SELECTION FUNCTIONS FIXME: use call_verb where appropriate. + SELECTION FUNCTIONS FIXME: use call_verb where appropriate (once update system is tested.) ****************************************************************************/ gboolean @@ -950,15 +962,11 @@ document_interface_selection_combine (DocumentInterface *object, gchar *cmd, dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error); else if (strcmp(cmd, "exclusion") == 0) dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error); - else if (strcmp(cmd, "division") == 0) - dbus_call_verb (object, SP_VERB_SELECTION_CUT, error); else return NULL; if (sp_desktop_selection(object->desk)->singleRepr() != NULL) return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); - - //Division will have a list of things selected, should have it's own function. return NULL; } diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index afad56f59..9b56da417 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -76,9 +76,9 @@ gchar* document_interface_line (DocumentInterface *object, int x, int y, int x2, int y2, GError **error); -gchar* -document_interface_text (DocumentInterface *object, gchar *text, - GError **error); +gboolean +document_interface_text (DocumentInterface *object, int x, int y, + gchar *text, GError **error); gchar* document_interface_node (DocumentInterface *object, gchar *svgtype, @@ -169,7 +169,7 @@ document_interface_move_to_layer (DocumentInterface *object, gchar *shape, gchar *layerstr, GError **error); -DBUSPoint ** +GArray * document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape); /**************************************************************************** diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 171508dcd..7126887af 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -276,15 +276,19 @@ - + - The text you want. + The x coordinate to put the text at. - - + - The name of the new text object. + The y coordinate to put the text at. + + + + + The text you want. @@ -688,7 +692,7 @@ A object that contains a path ("d") attribute. - + An array of points. -- cgit v1.2.3 From f09b3a57c8a6259ef82db7be0786ff2959874a24 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Tue, 21 Jul 2009 17:50:12 +0000 Subject: worked on path parsing. (bzr r8254.1.18) --- src/extension/dbus/document-interface.cpp | 5 ++++- src/extension/dbus/document-interface.xml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index a28bb92fa..9a900e0ee 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -52,6 +52,9 @@ SPObject * get_object_by_name (SPDesktop *desk, gchar *name) { return sp_desktop_document(desk)->getObjectById(name); + /* ALTERNATIVE (is this faster if only repr is needed?) + Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name); + */ } const gchar * @@ -584,7 +587,7 @@ document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape if (shapenode == NULL || shapenode->attribute("d") == NULL) { return FALSE; } - const char * path = strdup(shapenode->attribute("d")); + char * path = strdup(shapenode->attribute("d")); printf("PATH: %s\n", path); Geom::parse_svg_path (path); diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 7126887af..37749c932 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -578,7 +578,7 @@ - Get the path value of an object. Equivilent to calling get_attribte() with argument "d". Will not turn object into a path if it is not already. + Get the path value of an object. Equivilent to calling get_attribte() with argument "d". Will not turn object into a path if it is not already. Paths -- cgit v1.2.3 From 4caca0b9edefb8470c058fdfed95ff50e0324499 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Wed, 22 Jul 2009 06:22:59 +0000 Subject: Fixed GErrors. Added many GErrors, especially for unfound objects. transfered many functions to using verbs instead of the function the verb calls to make error reporting easier. (bzr r8254.1.19) --- src/extension/dbus/dbus-init.cpp | 3 + src/extension/dbus/document-interface.cpp | 285 +++++++++++++++++++++-------- src/extension/dbus/document-interface.h | 23 ++- src/extension/dbus/document-interface.xml | 9 + src/extension/dbus/org.inkscape.service.in | 1 + 5 files changed, 244 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp index a30bb8fda..dfd69d9fa 100644 --- a/src/extension/dbus/dbus-init.cpp +++ b/src/extension/dbus/dbus-init.cpp @@ -115,6 +115,9 @@ dbus_init_desktop_interface (SPDesktop * dt) DBusGConnection *connection; DBusGProxy *proxy; DocumentInterface *obj; + dbus_g_error_domain_register (INKSCAPE_ERROR, + NULL, + INKSCAPE_TYPE_ERROR); std::string name("/org/inkscape/desktop_"); std::stringstream out; diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 9a900e0ee..664655f0e 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -35,7 +35,7 @@ #include "live_effects/parameter/text.h" //text #include "display/canvas-text.h" //text -#include "2geom/svg-path-parser.h" //get_node_coordinates +//#include "2geom/svg-path-parser.h" //get_node_coordinates /**************************************************************************** HELPER / SHORTCUT FUNCTIONS @@ -48,19 +48,48 @@ const gchar* intToCString(int i) return ss.str().c_str(); } -SPObject * -get_object_by_name (SPDesktop *desk, gchar *name) +Inkscape::XML::Node * +get_repr_by_name (SPDesktop *desk, gchar *name, GError **error) { - return sp_desktop_document(desk)->getObjectById(name); /* ALTERNATIVE (is this faster if only repr is needed?) - Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name); + Inkscape::XML::Node *node = sp_repr_lookup_name((doc->root)->repr, name); */ + Inkscape::XML::Node * node = sp_desktop_document(desk)->getObjectById(name)->repr; + if (!node) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name); + return NULL; + } + return node; +} + +SPObject * +get_object_by_name (SPDesktop *desk, gchar *name, GError **error) +{ + SPObject * obj = sp_desktop_document(desk)->getObjectById(name); + if (!obj) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name); + return NULL; + } + return obj; +} + +gboolean +dbus_check_string (gchar *string, GError ** error, gchar * errorstr) +{ + if (string == NULL) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "%s", errorstr); + return FALSE; + } + return TRUE; } const gchar * get_name_from_object (SPObject * obj) { - return obj->repr->attribute("id"); + return obj->repr->attribute("id"); } void @@ -70,11 +99,6 @@ desktop_ensure_active (SPDesktop* desk) { return; } -Inkscape::XML::Node * -document_retrive_node (SPDocument *doc, gchar *name) { - return (doc->getObjectById(name))->repr; -} - gdouble selection_get_center_x (Inkscape::Selection *sel){ NRRect *box = g_new(NRRect, 1);; @@ -90,12 +114,12 @@ selection_get_center_y (Inkscape::Selection *sel){ } //move_to etc const GSList * -selection_swap(SPDesktop *desk, gchar *name) +selection_swap(SPDesktop *desk, gchar *name, GError **error) { Inkscape::Selection *sel = sp_desktop_selection(desk); const GSList *oldsel = g_slist_copy((GSList *)sel->list()); - sel->set(get_object_by_name(desk, name)); + sel->set(get_object_by_name(desk, name, error)); return oldsel; } @@ -147,7 +171,8 @@ gboolean dbus_call_verb (DocumentInterface *object, int verbid, GError **error) { SPDesktop *desk2 = object->desk; - + desktop_ensure_active (desk2); + if ( desk2 ) { Inkscape::Verb *verb = Inkscape::Verb::get( verbid ); if ( verb ) { @@ -161,6 +186,7 @@ dbus_call_verb (DocumentInterface *object, int verbid, GError **error) } } } + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb failed to execute"); return FALSE; } @@ -198,6 +224,42 @@ document_interface_new (void) return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL); } +GQuark +inkscape_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("inkscape_error"); + + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +inkscape_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) + { + static const GEnumValue values[] = + { + + ENUM_ENTRY (INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"), + ENUM_ENTRY (INKSCAPE_ERROR_OBJECT, "Incompatible_Object"), + ENUM_ENTRY (INKSCAPE_ERROR_VERB, "Failed_Verb"), + ENUM_ENTRY (INKSCAPE_ERROR_OTHER, "Generic_Error"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("InkscapeError", values); + } + + return etype; +} + /**************************************************************************** MISC FUNCTIONS ****************************************************************************/ @@ -209,7 +271,7 @@ document_interface_delete_all (DocumentInterface *object, GError **error) return TRUE; } -void +gboolean document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error) { SPDesktop *desk2 = object->desk; @@ -226,6 +288,8 @@ document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError * } } } + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb '%s' failed to execute or was not found.", verbid); + return FALSE; } @@ -422,7 +486,7 @@ gboolean document_interface_document_resize_to_fit_selection (DocumentInterface *object, GError **error) { - dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); + return dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); return TRUE; } @@ -434,56 +498,72 @@ gboolean document_interface_set_attribute (DocumentInterface *object, char *shape, char *attribute, char *newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error); /* ALTERNATIVE (is this faster?) Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name); */ - if (newNode) - { - newNode->setAttribute(attribute, newval, TRUE); - return TRUE; - } - return FALSE; + if (!dbus_check_string(newval, error, "New value string was empty.")) + return FALSE; + + if (!newNode) + return FALSE; + + newNode->setAttribute(attribute, newval, TRUE); + return TRUE; } -void +gboolean document_interface_set_int_attribute (DocumentInterface *object, char *shape, char *attribute, int newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; - if (newNode) - sp_repr_set_int (newNode, attribute, newval); + Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error); + if (!newNode) + return FALSE; + + sp_repr_set_int (newNode, attribute, newval); + return TRUE; } -void +gboolean document_interface_set_double_attribute (DocumentInterface *object, char *shape, char *attribute, double newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; - if (newNode) - sp_repr_set_svg_double (newNode, attribute, newval); + Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error); + + if (!dbus_check_string (attribute, error, "New value string was empty.")) + return FALSE; + if (!newNode) + return FALSE; + + sp_repr_set_svg_double (newNode, attribute, newval); + return TRUE; } gchar * document_interface_get_attribute (DocumentInterface *object, char *shape, char *attribute, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error); - if (newNode) - return g_strdup(newNode->attribute(attribute)); - return FALSE; + if (!dbus_check_string (attribute, error, "Attribute name empty.")) + return NULL; + if (!newNode) + return NULL; + + return g_strdup(newNode->attribute(attribute)); } gboolean document_interface_move (DocumentInterface *object, gchar *name, gdouble x, gdouble y, GError **error) { - const GSList *oldsel = selection_swap(object->desk, name); + const GSList *oldsel = selection_swap(object->desk, name, error); + if (!oldsel) + return FALSE; sp_selection_move (object->desk, x, 0 - y); selection_restore(object->desk, oldsel); return TRUE; @@ -493,7 +573,9 @@ gboolean document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x, gdouble y, GError **error) { - const GSList *oldsel = selection_swap(object->desk, name); + const GSList *oldsel = selection_swap(object->desk, name, error); + if (!oldsel) + return FALSE; Inkscape::Selection * sel = sp_desktop_selection(object->desk); sp_selection_move (object->desk, x - selection_get_center_x(sel), 0 - (y - selection_get_center_y(sel))); @@ -505,7 +587,9 @@ gboolean document_interface_object_to_path (DocumentInterface *object, char *shape, GError **error) { - const GSList *oldsel = selection_swap(object->desk, shape); + const GSList *oldsel = selection_swap(object->desk, shape, error); + if (!oldsel) + return FALSE; dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error); selection_restore(object->desk, oldsel); return TRUE; @@ -514,10 +598,15 @@ document_interface_object_to_path (DocumentInterface *object, gchar * document_interface_get_path (DocumentInterface *object, char *pathname, GError **error) { - Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); - if (node == NULL || node->attribute("d") == NULL) { - g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); - return FALSE; + Inkscape::XML::Node *node = get_repr_by_name(object->desk, pathname, error); + + if (!node) + return NULL; + + if (node->attribute("d") == NULL) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object is not a path."); + return NULL; } return strdup(node->attribute("d")); } @@ -544,8 +633,15 @@ gboolean document_interface_modify_css (DocumentInterface *object, gchar *shape, gchar *cssattrb, gchar *newval, GError **error) { + // Doesn't like non-variable strings for some reason. gchar style[] = "style"; - Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error); + + if (!dbus_check_string (cssattrb, error, "Attribute string empty.")) + return FALSE; + if (!node) + return FALSE; + SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_set_property(oldstyle, cssattrb, newval); node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); @@ -556,11 +652,18 @@ gboolean document_interface_merge_css (DocumentInterface *object, gchar *shape, gchar *stylestring, GError **error) { + gchar style[] = "style"; + + Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error); + + if (!dbus_check_string (stylestring, error, "Style string empty.")) + return FALSE; + if (!node) + return FALSE; + SPCSSAttr * newstyle = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string (newstyle, stylestring); - gchar style[] = "style"; - Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_merge(oldstyle, newstyle); @@ -572,7 +675,10 @@ gboolean document_interface_move_to_layer (DocumentInterface *object, gchar *shape, gchar *layerstr, GError **error) { - const GSList *oldsel = selection_swap(object->desk, shape); + const GSList *oldsel = selection_swap(object->desk, shape, error); + if (!oldsel) + return FALSE; + document_interface_selection_move_to_layer(object, layerstr, error); selection_restore(object->desk, oldsel); return TRUE; @@ -582,8 +688,8 @@ GArray * document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { //FIXME: Needs lot's of work. - - Inkscape::XML::Node *shapenode = document_retrive_node (sp_desktop_document (object->desk), shape); +/* + Inkscape::XML::Node *shapenode = get_repr_by_name (object->desk, shape, error); if (shapenode == NULL || shapenode->attribute("d") == NULL) { return FALSE; } @@ -592,6 +698,7 @@ document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape Geom::parse_svg_path (path); return NULL; + */ } @@ -645,6 +752,16 @@ document_interface_save_as (DocumentInterface *object, //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved."); return true; } + +gboolean +document_interface_mark_as_unmodified (DocumentInterface *object, GError **error) +{ + SPDocument * doc = sp_desktop_document(object->desk); + if (doc) + doc->modified_since_save = FALSE; + return TRUE; +} + /* gboolean document_interface_print_to_file (DocumentInterface *object, GError **error) @@ -686,7 +803,10 @@ document_interface_redo (DocumentInterface *object, GError **error) /**************************************************************************** - UPDATE FUNCTIONS FIXME: test update system again. + UPDATE FUNCTIONS + FIXME: This would work better by adding a flag to SPDesktop to prevent + updating but that would be very intrusive so for now there is a workaround. + Need to make sure it plays well with verbs because they are used so much. ****************************************************************************/ void @@ -746,11 +866,13 @@ document_interface_selection_get (DocumentInterface *object, char ***out, GError gboolean document_interface_selection_add (DocumentInterface *object, char *name, GError **error) { - if (name == NULL) + SPObject * obj = get_object_by_name(object->desk, name, error); + if (!obj) return FALSE; + Inkscape::Selection *selection = sp_desktop_selection(object->desk); - selection->add(get_object_by_name(object->desk, name)); + selection->add(obj); return TRUE; } @@ -797,8 +919,8 @@ document_interface_selection_rotate (DocumentInterface *object, int angle, GErro gboolean document_interface_selection_delete (DocumentInterface *object, GError **error) { - sp_selection_delete (object->desk); - return TRUE; + //sp_selection_delete (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_DELETE, error); } gboolean @@ -811,16 +933,16 @@ document_interface_selection_clear (DocumentInterface *object, GError **error) gboolean document_interface_select_all (DocumentInterface *object, GError **error) { - sp_edit_select_all (object->desk); - return TRUE; + //sp_edit_select_all (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL, error); } gboolean document_interface_select_all_in_all_layers(DocumentInterface *object, GError **error) { - sp_edit_select_all_in_all_layers (object->desk); - return TRUE; + //sp_edit_select_all_in_all_layers (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, error); } gboolean @@ -835,48 +957,55 @@ document_interface_selection_box (DocumentInterface *object, int x, int y, gboolean document_interface_selection_invert (DocumentInterface *object, GError **error) { - sp_edit_invert (object->desk); - return TRUE; + //sp_edit_invert (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_INVERT, error); } gboolean document_interface_selection_group (DocumentInterface *object, GError **error) { - sp_selection_group (object->desk); - return TRUE; + //sp_selection_group (object->desk); + return dbus_call_verb (object, SP_VERB_SELECTION_GROUP, error); } gboolean document_interface_selection_ungroup (DocumentInterface *object, GError **error) { - sp_selection_ungroup (object->desk); - return TRUE; + //sp_selection_ungroup (object->desk); + return dbus_call_verb (object, SP_VERB_SELECTION_UNGROUP, error); } gboolean document_interface_selection_cut (DocumentInterface *object, GError **error) { - sp_selection_cut (object->desk); - return TRUE; + //desktop_ensure_active (object->desk); + //sp_selection_cut (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_CUT, error); } + gboolean document_interface_selection_copy (DocumentInterface *object, GError **error) { - desktop_ensure_active (object->desk); - sp_selection_copy (); - return TRUE; + //desktop_ensure_active (object->desk); + //sp_selection_copy (); + return dbus_call_verb (object, SP_VERB_EDIT_COPY, error); } + gboolean document_interface_selection_paste (DocumentInterface *object, GError **error) { - desktop_ensure_active (object->desk); - sp_selection_paste (object->desk, TRUE); - return TRUE; + //desktop_ensure_active (object->desk); + //sp_selection_paste (object->desk, TRUE); + return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error); } gboolean document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error) { Inkscape::Selection *selection = sp_desktop_selection(object->desk); + if (!selection) + { + return FALSE; + } sp_selection_scale (selection, grow); return TRUE; } @@ -914,9 +1043,12 @@ document_interface_selection_move_to_layer (DocumentInterface *object, if (selection->isEmpty()) return FALSE; - SPObject *next = get_object_by_name(object->desk, layerstr); + SPObject *next = get_object_by_name(object->desk, layerstr, error); + + if (!next) + return FALSE; - if (next && (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0)) { + if (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0) { sp_selection_cut(dt); @@ -1013,7 +1145,12 @@ gboolean document_interface_layer_set (DocumentInterface *object, gchar *layerstr, GError **error) { - object->desk->setCurrentLayer (get_object_by_name (object->desk, layerstr)); + SPObject * obj = get_object_by_name (object->desk, layerstr, error); + + if (!obj) + return FALSE; + + object->desk->setCurrentLayer (obj); return TRUE; } diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index 9b56da417..ff0452a14 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -31,6 +31,20 @@ struct _DocumentInterfaceClass { GObjectClass parent; }; +typedef enum +{ + INKSCAPE_ERROR_SELECTION, + INKSCAPE_ERROR_OBJECT, + INKSCAPE_ERROR_VERB, + INKSCAPE_ERROR_OTHER +} InkscapeError; + +#define INKSCAPE_ERROR (inkscape_error_quark ()) +#define INKSCAPE_TYPE_ERROR (inkscape_error_get_type ()) + +GQuark inkscape_error_quark (void); +GType inkscape_error_get_type (void); + struct DBUSPoint { int x; int y; @@ -42,7 +56,7 @@ struct DBUSPoint { gboolean document_interface_delete_all (DocumentInterface *object, GError **error); -void +gboolean document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error); @@ -118,12 +132,12 @@ document_interface_set_attribute (DocumentInterface *object, char *shape, char *attribute, char *newval, GError **error); -void +gboolean document_interface_set_int_attribute (DocumentInterface *object, char *shape, char *attribute, int newval, GError **error); -void +gboolean document_interface_set_double_attribute (DocumentInterface *object, char *shape, char *attribute, double newval, GError **error); @@ -186,6 +200,9 @@ document_interface_load (DocumentInterface *object, gboolean document_interface_save_as (DocumentInterface *object, gchar *filename, GError **error); + +gboolean +document_interface_mark_as_unmodified (DocumentInterface *object, GError **error); /* gboolean document_interface_print_to_file (DocumentInterface *object, GError **error); diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 37749c932..7c16c6d1e 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -744,6 +744,15 @@ + + + + + Marks the document as unmodified/saved. + Will prevent save confirmation on close if called at end of script. + + + + + * + * Copyright (C) 2009 Soren Berg + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + #include "document-interface.h" #include @@ -41,13 +58,16 @@ HELPER / SHORTCUT FUNCTIONS ****************************************************************************/ -const gchar* intToCString(int i) -{ - std::stringstream ss; - ss << i; - return ss.str().c_str(); -} - +/* + * This function or the one below it translates the user input for an object + * into Inkscapes internal representation. It is called by almost every + * method so it should be as fast as possible. + * + * (eg turns "rect2234" to an SPObject or Inkscape::XML::Node) + * + * If the internal representation changes (No more 'id' attributes) this is the + * place to adjust things. + */ Inkscape::XML::Node * get_repr_by_name (SPDesktop *desk, gchar *name, GError **error) { @@ -63,6 +83,9 @@ get_repr_by_name (SPDesktop *desk, gchar *name, GError **error) return node; } +/* + * See comment for get_repr_by_name, above. + */ SPObject * get_object_by_name (SPDesktop *desk, gchar *name, GError **error) { @@ -75,6 +98,11 @@ get_object_by_name (SPDesktop *desk, gchar *name, GError **error) return obj; } +/* + * Tests for NULL strings and throws an appropriate error. + * Every method that takes a string parameter (other than the + * name of an object, that's tested seperatly) should call this. + */ gboolean dbus_check_string (gchar *string, GError ** error, const gchar * errorstr) { @@ -86,12 +114,19 @@ dbus_check_string (gchar *string, GError ** error, const gchar * errorstr) return TRUE; } +/* + * This is used to return object values to the user + */ const gchar * get_name_from_object (SPObject * obj) { return obj->repr->attribute("id"); } +/* + * Some verbs (cut, paste) only work on the active layer. + * This makes sure that the document that is about to recive a command is active. + */ void desktop_ensure_active (SPDesktop* desk) { if (desk != SP_ACTIVE_DESKTOP) @@ -112,7 +147,21 @@ selection_get_center_y (Inkscape::Selection *sel){ box = sel->boundsInDocument(box); return box->y0 + ((box->y1 - box->y0)/2); } -//move_to etc + +/* + * This function is used along with selection_restore to + * take advantage of functionality provided by a selection + * for a single object. + * + * It saves the current selection and sets the selection to + * the object specified. Any selection verb can be used on the + * object and then selection_restore is called, restoring the + * original selection. + * + * This should be mostly transparent to the user who need never + * know we never bothered to implement it seperatly. Although + * they might see the selection box flicker if used in a loop. + */ const GSList * selection_swap(SPDesktop *desk, gchar *name, GError **error) { @@ -123,6 +172,9 @@ selection_swap(SPDesktop *desk, gchar *name, GError **error) return oldsel; } +/* + * See selection_swap, above + */ void selection_restore(SPDesktop *desk, const GSList * oldsel) { @@ -130,6 +182,9 @@ selection_restore(SPDesktop *desk, const GSList * oldsel) sel->setList(oldsel); } +/* + * Shortcut for creating a Node. + */ Inkscape::XML::Node * dbus_create_node (SPDesktop *desk, const gchar *type) { @@ -139,6 +194,13 @@ dbus_create_node (SPDesktop *desk, const gchar *type) return xml_doc->createElement(type); } +/* + * Called by the shape creation functions. Gets the default style for the doc + * or sets it arbitrarily if none. + * + * There is probably a better way to do this (use the shape tools default styles) + * but I'm not sure how. + */ gchar * finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc) { @@ -163,6 +225,14 @@ finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::N return strdup(newNode->attribute("id")); } +/* + * This is the code used internally to call all the verbs. + * + * It handles error reporting and update pausing (which needs some work.) + * This is a good place to improve efficiency as it is called a lot. + * + * document_interface_call_verb is similar but is called by the user. + */ gboolean dbus_call_verb (DocumentInterface *object, int verbid, GError **error) { @@ -223,6 +293,11 @@ document_interface_new (void) return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL); } +/* + * Error stuff... + * + * To add a new error type, edit here and in the .h InkscapeError enum. + */ GQuark inkscape_error_quark (void) { @@ -233,7 +308,6 @@ inkscape_error_quark (void) return quark; } -/* This should really be standard. */ #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType @@ -409,7 +483,7 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy, gboolean document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error) { - //FIXME: Not selectable. + //FIXME: Not selectable (aka broken). Needs to be rewritten completely. SPDesktop *desktop = object->desk; SPCanvasText * canvas_text = (SPCanvasText *) sp_canvastext_new(sp_desktop_tempgroup(desktop), desktop, Geom::Point(0,0), ""); @@ -1094,6 +1168,8 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou } //FIXME: does not paste in new layer. +// This needs to use lower level cut_impl and paste_impl (messy) +// See the built-in sp_selection_to_next_layer and duplicate. gboolean document_interface_selection_move_to_layer (DocumentInterface *object, gchar *layerstr, GError **error) diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index 436f6b118..8cf9b7ec1 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -1,3 +1,20 @@ +/* + * This is where the implementation of the DBus based document API lives. + * All the methods in here (except in the helper section) are + * designed to be called remotly via DBus. application-interface.cpp + * has the methods used to connect to the bus and get a document instance. + * + * Documentation for these methods is in document-interface.xml + * which is the "gold standard" as to how the interface should work. + * + * Authors: + * Soren Berg + * + * Copyright (C) 2009 Soren Berg + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + #ifndef INKSCAPE_EXTENSION_DOCUMENT_INTERFACE_H_ #define INKSCAPE_EXTENSION_DOCUMENT_INTERFACE_H_ diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index c9cd8aa69..2f1549488 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -1,3 +1,21 @@ + + +#include // (static.*(\n[^}]*)*(async)+.*(\n[^}]*)*})|typedef void .*; // http://www.josephkahn.com/music/index.xml @@ -50,6 +52,11 @@ dbus_register_object (DBusGConnection *connection, DOCUMENT INTERFACE CLASS STUFF ****************************************************************************/ +struct _DocumentInterface { + GObject parent; + DBusGProxy * proxy; +}; + G_DEFINE_TYPE(DocumentInterface, document_interface, G_TYPE_OBJECT) static void @@ -111,7 +118,7 @@ inkscape_desktop_init_dbus () } -static +//static gboolean inkscape_delete_all (DocumentInterface *doc, GError **error) { @@ -119,7 +126,7 @@ inkscape_delete_all (DocumentInterface *doc, GError **error) return org_inkscape_document_delete_all (proxy, error); } -static +//static gboolean inkscape_call_verb (DocumentInterface *doc, const char * IN_verbid, GError **error) { @@ -128,7 +135,7 @@ inkscape_call_verb (DocumentInterface *doc, const char * IN_verbid, GError **err } -static +//static gchar * inkscape_rectangle (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_width, const gint IN_height, GError **error) { @@ -138,7 +145,7 @@ inkscape_rectangle (DocumentInterface *doc, const gint IN_x, const gint IN_y, co return OUT_object_name; } -static +//static char * inkscape_ellipse (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_width, const gint IN_height, GError **error) { @@ -148,7 +155,7 @@ inkscape_ellipse (DocumentInterface *doc, const gint IN_x, const gint IN_y, cons return OUT_object_name; } -static +//static char * inkscape_polygon (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_radius, const gint IN_rotation, const gint IN_sides, GError **error) { @@ -158,7 +165,7 @@ inkscape_polygon (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, co return OUT_object_name; } -static +//static char * inkscape_star (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_r1, const gint IN_r2, const gdouble IN_arg1, const gdouble IN_arg2, const gint IN_sides, const gdouble IN_rounded, GError **error) { @@ -168,7 +175,7 @@ inkscape_star (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const return OUT_object_name; } -static +//static char * inkscape_spiral (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_r, const gint IN_revolutions, GError **error) { @@ -178,7 +185,7 @@ inkscape_spiral (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, con return OUT_object_name; } -static +//static char * inkscape_line (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_x2, const gint IN_y2, GError **error) { @@ -188,7 +195,7 @@ inkscape_line (DocumentInterface *doc, const gint IN_x, const gint IN_y, const g return OUT_object_name; } -static +//static gboolean inkscape_text (DocumentInterface *doc, const gint IN_x, const gint IN_y, const char * IN_text, GError **error) { @@ -196,7 +203,7 @@ inkscape_text (DocumentInterface *doc, const gint IN_x, const gint IN_y, const c return org_inkscape_document_text (proxy, IN_x, IN_y, IN_text, error); } -static +//static char * inkscape_image (DocumentInterface *doc, const gint IN_x, const gint IN_y, const char * IN_text, GError **error) { @@ -206,7 +213,7 @@ inkscape_image (DocumentInterface *doc, const gint IN_x, const gint IN_y, const return OUT_object_name; } -static +//static char * inkscape_node (DocumentInterface *doc, const char * IN_svgtype, GError **error) { @@ -216,7 +223,7 @@ inkscape_node (DocumentInterface *doc, const char * IN_svgtype, GError **error) return OUT_node_name; } -static +//static gdouble inkscape_document_get_width (DocumentInterface *doc, GError **error) { @@ -226,7 +233,7 @@ inkscape_document_get_width (DocumentInterface *doc, GError **error) return OUT_val; } -static +//static gdouble inkscape_document_get_height (DocumentInterface *doc, GError **error) { @@ -236,7 +243,7 @@ inkscape_document_get_height (DocumentInterface *doc, GError **error) return OUT_val; } -static +//static char * inkscape_document_get_css (DocumentInterface *doc, GError **error) { @@ -246,7 +253,7 @@ inkscape_document_get_css (DocumentInterface *doc, GError **error) return OUT_css; } -static +//static gboolean inkscape_document_set_css (DocumentInterface *doc, const char * IN_stylestring, GError **error) { @@ -254,7 +261,7 @@ inkscape_document_set_css (DocumentInterface *doc, const char * IN_stylestring, return org_inkscape_document_document_document_set_css (proxy, IN_stylestring, error); } -static +//static gboolean inkscape_document_merge_css (DocumentInterface *doc, const char * IN_stylestring, GError **error) { @@ -262,7 +269,7 @@ inkscape_document_merge_css (DocumentInterface *doc, const char * IN_stylestring return org_inkscape_document_document_document_merge_css (proxy, IN_stylestring, error); } -static +//static gboolean inkscape_document_resize_to_fit_selection (DocumentInterface *doc, GError **error) { @@ -270,7 +277,7 @@ inkscape_document_resize_to_fit_selection (DocumentInterface *doc, GError **erro return org_inkscape_document_document_document_resize_to_fit_selection (proxy, error); } -static +//static gboolean inkscape_set_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const char * IN_newval, GError **error) { @@ -278,7 +285,7 @@ inkscape_set_attribute (DocumentInterface *doc, const char * IN_shape, const cha return org_inkscape_document_set_attribute (proxy, IN_shape, IN_attribute, IN_newval, error); } -static +//static gboolean inkscape_set_int_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const gint IN_newval, GError **error) { @@ -286,7 +293,7 @@ inkscape_set_int_attribute (DocumentInterface *doc, const char * IN_shape, const return org_inkscape_document_set_int_attribute (proxy, IN_shape, IN_attribute, IN_newval, error); } -static +//static gboolean inkscape_set_double_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const gdouble IN_newval, GError **error) { @@ -294,7 +301,7 @@ inkscape_set_double_attribute (DocumentInterface *doc, const char * IN_shape, co return org_inkscape_document_set_double_attribute (proxy, IN_shape, IN_attribute, IN_newval, error); } -static +//static char * inkscape_get_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, GError **error) { @@ -304,7 +311,7 @@ inkscape_get_attribute (DocumentInterface *doc, const char * IN_shape, const cha return OUT_val; } -static +//static gboolean inkscape_move (DocumentInterface *doc, const char * IN_shape, const gdouble IN_x, const gdouble IN_y, GError **error) { @@ -312,7 +319,7 @@ inkscape_move (DocumentInterface *doc, const char * IN_shape, const gdouble IN_x return org_inkscape_document_move (proxy, IN_shape, IN_x, IN_y, error); } -static +//static gboolean inkscape_move_to (DocumentInterface *doc, const char * IN_shape, const gdouble IN_x, const gdouble IN_y, GError **error) { @@ -320,7 +327,7 @@ inkscape_move_to (DocumentInterface *doc, const char * IN_shape, const gdouble I return org_inkscape_document_move_to (proxy, IN_shape, IN_x, IN_y, error); } -static +//static gboolean inkscape_object_to_path (DocumentInterface *doc, const char * IN_objectname, GError **error) { @@ -328,7 +335,7 @@ inkscape_object_to_path (DocumentInterface *doc, const char * IN_objectname, GEr return org_inkscape_document_object_to_path (proxy, IN_objectname, error); } -static +//static char * inkscape_get_path (DocumentInterface *doc, const char * IN_shape, GError **error) { @@ -338,7 +345,7 @@ inkscape_get_path (DocumentInterface *doc, const char * IN_shape, GError **error return OUT_val; } -static +//static gboolean inkscape_transform (DocumentInterface *doc, const char * IN_shape, const char * IN_transformstr, GError **error) { @@ -346,7 +353,7 @@ inkscape_transform (DocumentInterface *doc, const char * IN_shape, const char * return org_inkscape_document_transform (proxy, IN_shape, IN_transformstr, error); } -static +//static char * inkscape_get_css (DocumentInterface *doc, const char * IN_shape, GError **error) { @@ -356,7 +363,7 @@ inkscape_get_css (DocumentInterface *doc, const char * IN_shape, GError **error) return OUT_css; } -static +//static gboolean inkscape_modify_css (DocumentInterface *doc, const char * IN_shape, const char * IN_cssattrib, const char * IN_newval, GError **error) { @@ -364,7 +371,7 @@ inkscape_modify_css (DocumentInterface *doc, const char * IN_shape, const char * return org_inkscape_document_modify_css (proxy, IN_shape, IN_cssattrib, IN_newval, error); } -static +//static gboolean inkscape_merge_css (DocumentInterface *doc, const char * IN_shape, const char * IN_stylestring, GError **error) { @@ -372,7 +379,7 @@ inkscape_merge_css (DocumentInterface *doc, const char * IN_shape, const char * return org_inkscape_document_merge_css (proxy, IN_shape, IN_stylestring, error); } -static +//static gboolean inkscape_set_color (DocumentInterface *doc, const char * IN_shape, const gint IN_red, const gint IN_green, const gint IN_blue, const gboolean IN_fill, GError **error) { @@ -380,7 +387,7 @@ inkscape_set_color (DocumentInterface *doc, const char * IN_shape, const gint IN return org_inkscape_document_set_color (proxy, IN_shape, IN_red, IN_green, IN_blue, IN_fill, error); } -static +//static gboolean inkscape_move_to_layer (DocumentInterface *doc, const char * IN_objectname, const char * IN_layername, GError **error) { @@ -388,7 +395,7 @@ inkscape_move_to_layer (DocumentInterface *doc, const char * IN_objectname, cons return org_inkscape_document_move_to_layer (proxy, IN_objectname, IN_layername, error); } -static +//static GArray* inkscape_get_node_coordinates (DocumentInterface *doc, const char * IN_shape, GError **error) { @@ -398,7 +405,7 @@ inkscape_get_node_coordinates (DocumentInterface *doc, const char * IN_shape, GE return OUT_points; } -static +//static gboolean inkscape_save (DocumentInterface *doc, GError **error) { @@ -406,7 +413,7 @@ inkscape_save (DocumentInterface *doc, GError **error) return org_inkscape_document_save (proxy, error); } -static +//static gboolean inkscape_save_as (DocumentInterface *doc, const char * IN_pathname, GError **error) { @@ -414,7 +421,7 @@ inkscape_save_as (DocumentInterface *doc, const char * IN_pathname, GError **err return org_inkscape_document_save_as (proxy, IN_pathname, error); } -static +//static gboolean inkscape_load (DocumentInterface *doc, const char * IN_pathname, GError **error) { @@ -422,7 +429,7 @@ inkscape_load (DocumentInterface *doc, const char * IN_pathname, GError **error) return org_inkscape_document_load (proxy, IN_pathname, error); } -static +//static gboolean inkscape_mark_as_unmodified (DocumentInterface *doc, GError **error) { @@ -430,7 +437,7 @@ inkscape_mark_as_unmodified (DocumentInterface *doc, GError **error) return org_inkscape_document_mark_as_unmodified (proxy, error); } -static +//static gboolean inkscape_close (DocumentInterface *doc, GError **error) { @@ -438,7 +445,7 @@ inkscape_close (DocumentInterface *doc, GError **error) return org_inkscape_document_close (proxy, error); } -static +//static gboolean inkscape_inkscape_exit (DocumentInterface *doc, GError **error) { @@ -446,7 +453,7 @@ inkscape_inkscape_exit (DocumentInterface *doc, GError **error) return org_inkscape_document_exit (proxy, error); } -static +//static gboolean inkscape_undo (DocumentInterface *doc, GError **error) { @@ -454,7 +461,7 @@ inkscape_undo (DocumentInterface *doc, GError **error) return org_inkscape_document_undo (proxy, error); } -static +//static gboolean inkscape_redo (DocumentInterface *doc, GError **error) { @@ -462,7 +469,7 @@ inkscape_redo (DocumentInterface *doc, GError **error) return org_inkscape_document_redo (proxy, error); } -static +//static gboolean inkscape_pause_updates (DocumentInterface *doc, GError **error) { @@ -470,7 +477,7 @@ inkscape_pause_updates (DocumentInterface *doc, GError **error) return org_inkscape_document_pause_updates (proxy, error); } -static +//static gboolean inkscape_resume_updates (DocumentInterface *doc, GError **error) { @@ -478,7 +485,7 @@ inkscape_resume_updates (DocumentInterface *doc, GError **error) return org_inkscape_document_resume_updates (proxy, error); } -static +//static gboolean inkscape_update (DocumentInterface *doc, GError **error) { @@ -486,7 +493,7 @@ inkscape_update (DocumentInterface *doc, GError **error) return org_inkscape_document_update (proxy, error); } -static +//static char ** inkscape_selection_get (DocumentInterface *doc, GError **error) { @@ -496,7 +503,7 @@ inkscape_selection_get (DocumentInterface *doc, GError **error) return OUT_listy; } -static +//static gboolean inkscape_selection_add (DocumentInterface *doc, const char * IN_name, GError **error) { @@ -504,7 +511,7 @@ inkscape_selection_add (DocumentInterface *doc, const char * IN_name, GError **e return org_inkscape_document_selection_add (proxy, IN_name, error); } -static +//static gboolean inkscape_selection_add_list (DocumentInterface *doc, const char ** IN_name, GError **error) { @@ -512,7 +519,7 @@ inkscape_selection_add_list (DocumentInterface *doc, const char ** IN_name, GErr return org_inkscape_document_selection_add_list (proxy, IN_name, error); } -static +//static gboolean inkscape_selection_set (DocumentInterface *doc, const char * IN_name, GError **error) { @@ -520,7 +527,7 @@ inkscape_selection_set (DocumentInterface *doc, const char * IN_name, GError **e return org_inkscape_document_selection_set (proxy, IN_name, error); } -static +//static gboolean inkscape_selection_set_list (DocumentInterface *doc, const char ** IN_name, GError **error) { @@ -528,7 +535,7 @@ inkscape_selection_set_list (DocumentInterface *doc, const char ** IN_name, GErr return org_inkscape_document_selection_set_list (proxy, IN_name, error); } -static +//static gboolean inkscape_selection_rotate (DocumentInterface *doc, const gint IN_angle, GError **error) { @@ -536,7 +543,7 @@ inkscape_selection_rotate (DocumentInterface *doc, const gint IN_angle, GError * return org_inkscape_document_selection_rotate (proxy, IN_angle, error); } -static +//static gboolean inkscape_selection_delete (DocumentInterface *doc, GError **error) { @@ -544,7 +551,7 @@ inkscape_selection_delete (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_delete (proxy, error); } -static +//static gboolean inkscape_selection_clear (DocumentInterface *doc, GError **error) { @@ -552,7 +559,7 @@ inkscape_selection_clear (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_clear (proxy, error); } -static +//static gboolean inkscape_select_all (DocumentInterface *doc, GError **error) { @@ -560,7 +567,7 @@ inkscape_select_all (DocumentInterface *doc, GError **error) return org_inkscape_document_select_all (proxy, error); } -static +//static gboolean inkscape_select_all_in_all_layers (DocumentInterface *doc, GError **error) { @@ -568,7 +575,7 @@ inkscape_select_all_in_all_layers (DocumentInterface *doc, GError **error) return org_inkscape_document_select_all_in_all_layers (proxy, error); } -static +//static gboolean inkscape_selection_box (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_x2, const gint IN_y2, const gboolean IN_replace, GError **error) { @@ -576,7 +583,7 @@ inkscape_selection_box (DocumentInterface *doc, const gint IN_x, const gint IN_y return org_inkscape_document_selection_box (proxy, IN_x, IN_y, IN_x2, IN_y2, IN_replace, error); } -static +//static gboolean inkscape_selection_invert (DocumentInterface *doc, GError **error) { @@ -584,7 +591,7 @@ inkscape_selection_invert (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_invert (proxy, error); } -static +//static gboolean inkscape_selection_group (DocumentInterface *doc, GError **error) { @@ -592,7 +599,7 @@ inkscape_selection_group (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_group (proxy, error); } -static +//static gboolean inkscape_selection_ungroup (DocumentInterface *doc, GError **error) { @@ -600,7 +607,7 @@ inkscape_selection_ungroup (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_ungroup (proxy, error); } -static +//static gboolean inkscape_selection_cut (DocumentInterface *doc, GError **error) { @@ -608,7 +615,7 @@ inkscape_selection_cut (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_cut (proxy, error); } -static +//static gboolean inkscape_selection_copy (DocumentInterface *doc, GError **error) { @@ -616,7 +623,7 @@ inkscape_selection_copy (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_copy (proxy, error); } -static +//static gboolean inkscape_selection_paste (DocumentInterface *doc, GError **error) { @@ -624,7 +631,7 @@ inkscape_selection_paste (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_paste (proxy, error); } -static +//static gboolean inkscape_selection_scale (DocumentInterface *doc, const gdouble IN_grow, GError **error) { @@ -632,7 +639,7 @@ inkscape_selection_scale (DocumentInterface *doc, const gdouble IN_grow, GError return org_inkscape_document_selection_scale (proxy, IN_grow, error); } -static +//static gboolean inkscape_selection_move (DocumentInterface *doc, const gdouble IN_x, const gdouble IN_y, GError **error) { @@ -640,7 +647,7 @@ inkscape_selection_move (DocumentInterface *doc, const gdouble IN_x, const gdoub return org_inkscape_document_selection_move (proxy, IN_x, IN_y, error); } -static +//static gboolean inkscape_selection_move_to (DocumentInterface *doc, const gdouble IN_x, const gdouble IN_y, GError **error) { @@ -648,7 +655,7 @@ inkscape_selection_move_to (DocumentInterface *doc, const gdouble IN_x, const gd return org_inkscape_document_selection_move_to (proxy, IN_x, IN_y, error); } -static +//static gboolean inkscape_selection_move_to_layer (DocumentInterface *doc, const char * IN_layer, GError **error) { @@ -656,7 +663,7 @@ inkscape_selection_move_to_layer (DocumentInterface *doc, const char * IN_layer, return org_inkscape_document_selection_move_to_layer (proxy, IN_layer, error); } -static +//static GArray * inkscape_selection_get_center (DocumentInterface *doc, GError **error) { @@ -666,7 +673,7 @@ inkscape_selection_get_center (DocumentInterface *doc, GError **error) return OUT_centerpoint; } -static +//static gboolean inkscape_selection_to_path (DocumentInterface *doc, GError **error) { @@ -674,7 +681,7 @@ inkscape_selection_to_path (DocumentInterface *doc, GError **error) return org_inkscape_document_selection_to_path (proxy, error); } -static +//static char * inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error) { @@ -684,7 +691,7 @@ inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError return OUT_newpath; } -static +//static char ** inkscape_selection_divide (DocumentInterface *doc, GError **error) { @@ -694,7 +701,7 @@ inkscape_selection_divide (DocumentInterface *doc, GError **error) return OUT_pieces; } -static +//static gboolean inkscape_selection_change_level (DocumentInterface *doc, const char * IN_command, GError **error) { @@ -704,7 +711,7 @@ inkscape_selection_change_level (DocumentInterface *doc, const char * IN_command return OUT_objectsmoved; } -static +//static char * inkscape_layer_new (DocumentInterface *doc, GError **error) { @@ -714,7 +721,7 @@ inkscape_layer_new (DocumentInterface *doc, GError **error) return OUT_layername; } -static +//static gboolean inkscape_layer_set (DocumentInterface *doc, const char * IN_layer, GError **error) { @@ -722,7 +729,7 @@ inkscape_layer_set (DocumentInterface *doc, const char * IN_layer, GError **erro return org_inkscape_document_layer_set (proxy, IN_layer, error); } -static +//static char ** inkscape_layer_get_all (DocumentInterface *doc, GError **error) { @@ -732,7 +739,7 @@ inkscape_layer_get_all (DocumentInterface *doc, GError **error) return OUT_layers; } -static +//static gboolean inkscape_layer_change_level (DocumentInterface *doc, const char * IN_command, GError **error) { @@ -742,7 +749,7 @@ inkscape_layer_change_level (DocumentInterface *doc, const char * IN_command, GE return OUT_layermoved; } -static +//static gboolean inkscape_layer_next (DocumentInterface *doc, GError **error) { @@ -750,7 +757,7 @@ inkscape_layer_next (DocumentInterface *doc, GError **error) return org_inkscape_document_layer_next (proxy, error); } -static +//static gboolean inkscape_layer_previous (DocumentInterface *doc, GError **error) { diff --git a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h index c48a712b4..c314bf6f8 100644 --- a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h +++ b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h @@ -4,8 +4,6 @@ #include #include -#include - //#include "document-client-glue-mod.h" //#include @@ -25,10 +23,7 @@ G_BEGIN_DECLS typedef struct _DocumentInterface DocumentInterface; typedef struct _DocumentInterfaceClass DocumentInterfaceClass; -struct _DocumentInterface { - GObject parent; - DBusGProxy * proxy; -}; +struct _DocumentInterface; struct _DocumentInterfaceClass { GObjectClass parent; @@ -40,305 +35,307 @@ GType document_interface_get_type (void); -DocumentInterface * inkscape_desktop_init_dbus (); -static +DocumentInterface * +inkscape_desktop_init_dbus (); + +//static gboolean inkscape_delete_all (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_call_verb (DocumentInterface *doc, const char * IN_verbid, GError **error); -static +//static gchar * inkscape_rectangle (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_width, const gint IN_height, GError **error); -static +//static char * inkscape_ellipse (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_width, const gint IN_height, GError **error); -static +//static char * inkscape_polygon (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_radius, const gint IN_rotation, const gint IN_sides, GError **error); -static +//static char * inkscape_star (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_r1, const gint IN_r2, const gdouble IN_arg1, const gdouble IN_arg2, const gint IN_sides, const gdouble IN_rounded, GError **error); -static +//static char * inkscape_spiral (DocumentInterface *doc, const gint IN_cx, const gint IN_cy, const gint IN_r, const gint IN_revolutions, GError **error); -static +//static char * inkscape_line (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_x2, const gint IN_y2, GError **error); -static +//static gboolean inkscape_text (DocumentInterface *doc, const gint IN_x, const gint IN_y, const char * IN_text, GError **error); -static +//static char * inkscape_image (DocumentInterface *doc, const gint IN_x, const gint IN_y, const char * IN_text, GError **error); -static +//static char * inkscape_node (DocumentInterface *doc, const char * IN_svgtype, GError **error); -static +//static gdouble inkscape_document_get_width (DocumentInterface *doc, GError **error); -static +//static gdouble inkscape_document_get_height (DocumentInterface *doc, GError **error); -static +//static char * inkscape_document_get_css (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_document_set_css (DocumentInterface *doc, const char * IN_stylestring, GError **error); -static +//static gboolean inkscape_document_merge_css (DocumentInterface *doc, const char * IN_stylestring, GError **error); -static +//static gboolean inkscape_document_resize_to_fit_selection (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_set_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const char * IN_newval, GError **error); -static +//static gboolean inkscape_set_int_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const gint IN_newval, GError **error); -static +//static gboolean inkscape_set_double_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, const gdouble IN_newval, GError **error); -static +//static char * inkscape_get_attribute (DocumentInterface *doc, const char * IN_shape, const char * IN_attribute, GError **error); -static +//static gboolean inkscape_move (DocumentInterface *doc, const char * IN_shape, const gdouble IN_x, const gdouble IN_y, GError **error); -static +//static gboolean inkscape_move_to (DocumentInterface *doc, const char * IN_shape, const gdouble IN_x, const gdouble IN_y, GError **error); -static +//static gboolean inkscape_object_to_path (DocumentInterface *doc, const char * IN_objectname, GError **error); -static +//static char * inkscape_get_path (DocumentInterface *doc, const char * IN_shape, GError **error); -static +//static gboolean inkscape_transform (DocumentInterface *doc, const char * IN_shape, const char * IN_transformstr, GError **error); -static +//static char * inkscape_get_css (DocumentInterface *doc, const char * IN_shape, GError **error); -static +//static gboolean inkscape_modify_css (DocumentInterface *doc, const char * IN_shape, const char * IN_cssattrib, const char * IN_newval, GError **error); -static +//static gboolean inkscape_inkscape_merge_css (DocumentInterface *doc, const char * IN_shape, const char * IN_stylestring, GError **error); -static +//static gboolean inkscape_set_color (DocumentInterface *doc, const char * IN_shape, const gint IN_red, const gint IN_green, const gint IN_blue, const gboolean IN_fill, GError **error); -static +//static gboolean inkscape_move_to_layer (DocumentInterface *doc, const char * IN_objectname, const char * IN_layername, GError **error); -static +//static GArray* inkscape_get_node_coordinates (DocumentInterface *doc, const char * IN_shape, GError **error); -static +//static gboolean inkscape_save (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_save_as (DocumentInterface *doc, const char * IN_pathname, GError **error); -static +//static gboolean inkscape_load (DocumentInterface *doc, const char * IN_pathname, GError **error); -static +//static gboolean inkscape_mark_as_unmodified (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_close (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_inkscape_exit (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_undo (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_redo (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_pause_updates (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_resume_updates (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_update (DocumentInterface *doc, GError **error); -static +//static char ** inkscape_selection_get (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_add (DocumentInterface *doc, const char * IN_name, GError **error); -static +//static gboolean inkscape_selection_add_list (DocumentInterface *doc, const char ** IN_name, GError **error); -static +//static gboolean inkscape_selection_set (DocumentInterface *doc, const char * IN_name, GError **error); -static +//static gboolean inkscape_selection_set_list (DocumentInterface *doc, const char ** IN_name, GError **error); -static +//static gboolean inkscape_selection_rotate (DocumentInterface *doc, const gint IN_angle, GError **error); -static +//static gboolean inkscape_selection_delete (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_clear (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_select_all (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_select_all_in_all_layers (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_box (DocumentInterface *doc, const gint IN_x, const gint IN_y, const gint IN_x2, const gint IN_y2, const gboolean IN_replace, GError **error); -static +//static gboolean inkscape_selection_invert (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_group (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_ungroup (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_cut (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_copy (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_paste (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_scale (DocumentInterface *doc, const gdouble IN_grow, GError **error); -static +//static gboolean inkscape_selection_move (DocumentInterface *doc, const gdouble IN_x, const gdouble IN_y, GError **error); -static +//static gboolean inkscape_selection_move_to (DocumentInterface *doc, const gdouble IN_x, const gdouble IN_y, GError **error); -static +//static gboolean inkscape_selection_move_to_layer (DocumentInterface *doc, const char * IN_layer, GError **error); -static +//static GArray * inkscape_selection_get_center (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_to_path (DocumentInterface *doc, GError **error); -static +//static char * inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error); -static +//static char ** inkscape_selection_divide (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_selection_change_level (DocumentInterface *doc, const char * IN_command, GError **error); -static +//static char * inkscape_layer_new (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_layer_set (DocumentInterface *doc, const char * IN_layer, GError **error); -static +//static char ** inkscape_layer_get_all (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_layer_change_level (DocumentInterface *doc, const char * IN_command, GError **error); -static +//static gboolean inkscape_layer_next (DocumentInterface *doc, GError **error); -static +//static gboolean inkscape_layer_previous (DocumentInterface *doc, GError **error); -- cgit v1.2.3 From babbc935015ef0e1bce562b22bb771e8aba8a784 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Thu, 13 Aug 2009 20:57:14 +0000 Subject: Added file with some current issues listed for coders. (bzr r8254.1.25) --- src/extension/dbus/Notes.txt | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/extension/dbus/Notes.txt (limited to 'src') diff --git a/src/extension/dbus/Notes.txt b/src/extension/dbus/Notes.txt new file mode 100644 index 000000000..d91dc4039 --- /dev/null +++ b/src/extension/dbus/Notes.txt @@ -0,0 +1,35 @@ +BUGS: + *Inkscape crashes if widow is closed while code is running, + need better error handling. + + *Pause updates needs work. + + *The following methods are broken: + -document_interface_selection_move_to_layer + + *The following are not implemented: + -document_interface_layer_get_all + -document_interface_selection_box + -document_interface_get_node_coordinates + + *The following do not behave like the documentation: + -document_interface_transform + -document_interface_text + +EFFICIENCY: + *Need better way to retrive objects by name. + Switch to GQuark codes for object retrival? + + *Rethink how often activate_desktop needs to be called. + + + +FEATURES: + *Find out more about extension API. + *API compatibility for plugins? + +CLEANUP: + + + + -- cgit v1.2.3 From 3237876b9543c6ec900089dd0ffbd9e0a0bedfa3 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Thu, 13 Aug 2009 21:30:21 +0000 Subject: Added an intro to coders interested in modifing the code. (bzr r8254.1.26) --- src/extension/dbus/Notes.txt | 49 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Notes.txt b/src/extension/dbus/Notes.txt index d91dc4039..95b07a958 100644 --- a/src/extension/dbus/Notes.txt +++ b/src/extension/dbus/Notes.txt @@ -1,3 +1,47 @@ +INTRO: +For people that are interested in improving the DBus API here is a +intro to how everything is layed out. + +First read the documentation for a general idea of how the different interfaces +fit together and how Dbus is used in this application. + +Here are short descriptions of the relevent files: + +document-interface.cpp: This has most of the "meat" of the interface, this is where +most functions are implemented. + +application-interface.cpp: This is where the application interface is implemented. + +(document/application)-interface.xml: These files are the master record of the interfaces. +All of the documentation is generated from these files as is a lot of glue code. +Any changes MUST be reflected here. + +dbus-init.cpp: This is where the interface is exposed when Inkscape starts up. +Here is where the names given to the various interfaces are set. The application interface is constant but the document interfaces are generated on the fly. + +org.inkscape.service.in: This sets where DBus looks for the Inkscape executable +if it is not running when someone tries to connect. Needs work. + +pytester.py: A python script that tests a lot of dbus functions. + +doc/builddocs.sh: builds documentation out of the XML files and some others. + +config.xsl, dbus-introspect-docs.dtd, spec-to-docbook.xsl, docbook.css: I borrowed +these files, they set how the documentation looks, I have no idea how to edit them. + +doc/inkscapeDbusRef.xml: This is the top level file for laying out th documentation, +it also includes the introduction. + +doc/inkscapeDbusTerms.xml: This containes the terms sections of the documentation. +Also the overview and all the tutorials. + +*.ref.xml: These are intermediate files, do not edit. + +wrapper/inkscape-dbus-wrapper.c: This is actually completely seperate from inkscape. +It has a wrapper for each function in the document interface and includes the +client generated bindings. It is used to create a shared object that will allow +people to use the interface without even knowing anything about Dbus. + BUGS: *Inkscape crashes if widow is closed while code is running, need better error handling. @@ -15,14 +59,15 @@ BUGS: *The following do not behave like the documentation: -document_interface_transform -document_interface_text + + *Service file should point to wherever the inkscape executable + was placed. EFFICIENCY: *Need better way to retrive objects by name. Switch to GQuark codes for object retrival? *Rethink how often activate_desktop needs to be called. - - FEATURES: *Find out more about extension API. -- cgit v1.2.3 From 28c0df8446a7442667b2a2a938f544f5508ef0a0 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sat, 15 Aug 2009 18:26:08 +0000 Subject: Added proposed interface file. Fixed other xml files to have xml file declaration before comments. (bzr r8254.1.27) --- src/extension/dbus/application-interface.xml | 3 +- src/extension/dbus/document-interface.xml | 3 +- src/extension/dbus/proposed-interface.xml | 176 +++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 src/extension/dbus/proposed-interface.xml (limited to 'src') diff --git a/src/extension/dbus/application-interface.xml b/src/extension/dbus/application-interface.xml index e942117d6..ee2c4837b 100644 --- a/src/extension/dbus/application-interface.xml +++ b/src/extension/dbus/application-interface.xml @@ -1,3 +1,4 @@ + - - diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml index 2f1549488..8b0252765 100644 --- a/src/extension/dbus/document-interface.xml +++ b/src/extension/dbus/document-interface.xml @@ -1,3 +1,4 @@ + - + diff --git a/src/extension/dbus/proposed-interface.xml b/src/extension/dbus/proposed-interface.xml new file mode 100644 index 000000000..e82e433b4 --- /dev/null +++ b/src/extension/dbus/proposed-interface.xml @@ -0,0 +1,176 @@ + + + + + + + + Signals would undoubtedly be a useful thing to have in many circumstances. They are in proposed for two reasons: One, they complicate things for script writers and may conflict with the proposed C wrapper library. Two, I'm not sure how much coding it would take to implement them because I am familiar with neither Dbus signals or Inkscape events. Until I have done more experimenting I don't want to promise anything I'm not sure can be implemented in a timely fashion. + + + + + + + + The id of the object. + + + + + Emitted when an object has been resized. + + + + + + + + The id of the object. + + + + + Emitted when an object has been moved. + + + + + + + + The id of the object. + + + + + Emitted when the style of an object has been changed. + + + + + + + + The id of the object. + + + + + Emitted when an object has been created. Possibly useful for working in conjunction with a live user. + + + + + + + + The id of the object. + + + + + Emitted when an object has been added to the selection. Possibly useful for working in conjunction with a live user. + + + + + + + + The x value to begin the path. + + + + + The y value to begin the path. + + + + + Begins a new path, extra nodes can be added with path_append(). + + + + + + + + The name of the path to append to. + + + + + A single letter denoting what type of node is beeing appended. + + + + + An array of numbers that describe the position and attributes of the path node. + + + + + Adds to an existing path. Close the path by sending "z" and no arguments. + You can no longer append to a path if it is closed. + + + + + + + + + + Any node with an "id" attribute. + + + + + + The id of this nodes parent, NULL if toplevel. + + + + + Returns the parent of any node. This function along with get_children() can be used to navigate the XML tree. In proposed because I think it might confuse users who don't know about the SVG tree structure. In the main API I have de-emphasized nodes and required no knowledge of internal representation. + + + + + + + + Any node with an "id" attribute. + + + + + + The ids of this nodes children, NULL if bottom level. + + + + + Returns the children of any node. This function along with get_parent() can be used to navigate the XML tree. In proposed because I think it might confuse users who don't know about the SVG tree structure. In the main API I have de-emphasized nodes and required no knowledge of internal representation. + + + + + + + + A object to remove from the selection. + + + + + Removes a single object from the selection. In proposed because I already have a ton of selection functions and am not sure people would need this. + + + + + + -- cgit v1.2.3 From 4335cee54fa4f142babf3d764e72feae9485b10a Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sat, 15 Aug 2009 18:29:16 +0000 Subject: Added copyright info to proposed interface. (bzr r8254.1.28) --- src/extension/dbus/proposed-interface.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/extension/dbus/proposed-interface.xml b/src/extension/dbus/proposed-interface.xml index e82e433b4..c281aff96 100644 --- a/src/extension/dbus/proposed-interface.xml +++ b/src/extension/dbus/proposed-interface.xml @@ -1,4 +1,19 @@ + -- cgit v1.2.3 From e28a44a795264136f7bd26e0f8926ed49b53473f Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sat, 15 Aug 2009 18:31:06 +0000 Subject: Fixed service file! Service file will now point to $(prefix) of most recently installed inkscape. (bzr r8254.1.29) --- src/extension/dbus/Makefile_insert | 2 +- src/extension/dbus/org.inkscape.service.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index a10dcdeba..00dba3b20 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -36,5 +36,5 @@ service_DATA = $(service_in_files:.service.in=.service) # Rule to make the service file with bindir expanded $(service_DATA): $(service_in_files) Makefile - @sed -e "s|@bindir@|$(bindir)|" $<> $@ #Fix bindir + @sed -e "s|bindir|$(prefix)|" $<> $@ diff --git a/src/extension/dbus/org.inkscape.service.in b/src/extension/dbus/org.inkscape.service.in index 60d5b6b43..dcfff2ff2 100644 --- a/src/extension/dbus/org.inkscape.service.in +++ b/src/extension/dbus/org.inkscape.service.in @@ -1,5 +1,5 @@ [D-BUS Service] Name=org.inkscape -Exec=/usr/local/bin/inkscape +Exec=bindir/inkscape -- cgit v1.2.3 From 1617fe112eeaa0c2a0e1b861b53bb956df379e9b Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Sat, 15 Aug 2009 19:24:51 +0000 Subject: Updated notes. (bzr r8254.1.30) --- src/extension/dbus/Notes.txt | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Notes.txt b/src/extension/dbus/Notes.txt index 95b07a958..25c3f35b5 100644 --- a/src/extension/dbus/Notes.txt +++ b/src/extension/dbus/Notes.txt @@ -1,11 +1,11 @@ INTRO: For people that are interested in improving the DBus API here is a -intro to how everything is layed out. +intro to how everything is laid out. First read the documentation for a general idea of how the different interfaces fit together and how Dbus is used in this application. -Here are short descriptions of the relevent files: +Here are short descriptions of the relevant files: document-interface.cpp: This has most of the "meat" of the interface, this is where most functions are implemented. @@ -20,7 +20,7 @@ dbus-init.cpp: This is where the interface is exposed when Inkscape starts up. Here is where the names given to the various interfaces are set. The application interface is constant but the document interfaces are generated on the fly. org.inkscape.service.in: This sets where DBus looks for the Inkscape executable -if it is not running when someone tries to connect. Needs work. +if it is not running when someone tries to connect. pytester.py: A python script that tests a lot of dbus functions. @@ -29,15 +29,15 @@ doc/builddocs.sh: builds documentation out of the XML files and some others. config.xsl, dbus-introspect-docs.dtd, spec-to-docbook.xsl, docbook.css: I borrowed these files, they set how the documentation looks, I have no idea how to edit them. -doc/inkscapeDbusRef.xml: This is the top level file for laying out th documentation, +doc/inkscapeDbusRef.xml: This is the top level file for laying out the documentation, it also includes the introduction. -doc/inkscapeDbusTerms.xml: This containes the terms sections of the documentation. +doc/inkscapeDbusTerms.xml: This contains the terms sections of the documentation. Also the overview and all the tutorials. *.ref.xml: These are intermediate files, do not edit. -wrapper/inkscape-dbus-wrapper.c: This is actually completely seperate from inkscape. +wrapper/inkscape-dbus-wrapper.c: This is actually completely separate from inkscape. It has a wrapper for each function in the document interface and includes the client generated bindings. It is used to create a shared object that will allow people to use the interface without even knowing anything about Dbus. @@ -48,6 +48,8 @@ BUGS: *Pause updates needs work. + *Default style for new shapes is occasionally strange. + *The following methods are broken: -document_interface_selection_move_to_layer @@ -59,13 +61,10 @@ BUGS: *The following do not behave like the documentation: -document_interface_transform -document_interface_text - - *Service file should point to wherever the inkscape executable - was placed. EFFICIENCY: - *Need better way to retrive objects by name. - Switch to GQuark codes for object retrival? + *Need better way to retrieve objects by name. + Switch to GQuark codes for object retrieval? *Rethink how often activate_desktop needs to be called. -- cgit v1.2.3 From a2c6f05866dff7112c551e875ce9b3760f6cdd0e Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 17 Aug 2009 18:51:36 +0000 Subject: Fixed directory for inkscape executable. Now points to $(prefix)/bin/inkscape (bin added.) (bzr r8254.1.31) --- src/extension/dbus/org.inkscape.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/org.inkscape.service.in b/src/extension/dbus/org.inkscape.service.in index dcfff2ff2..484c8e516 100644 --- a/src/extension/dbus/org.inkscape.service.in +++ b/src/extension/dbus/org.inkscape.service.in @@ -1,5 +1,5 @@ [D-BUS Service] Name=org.inkscape -Exec=bindir/inkscape +Exec=bindir/bin/inkscape -- cgit v1.2.3 From f8c188ba29f18db8bf7af03ed8f80841f613bbc0 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 17 Aug 2009 18:52:11 +0000 Subject: More documentation. (bzr r8254.1.32) --- src/extension/dbus/Notes.txt | 1 + src/extension/dbus/dbus-init.cpp | 16 +++++++++++++++- src/extension/dbus/dbus-init.h | 2 +- src/extension/dbus/document-interface.cpp | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Notes.txt b/src/extension/dbus/Notes.txt index 25c3f35b5..d7c34aac0 100644 --- a/src/extension/dbus/Notes.txt +++ b/src/extension/dbus/Notes.txt @@ -61,6 +61,7 @@ BUGS: *The following do not behave like the documentation: -document_interface_transform -document_interface_text + -document_interface_line EFFICIENCY: *Need better way to retrieve objects by name. diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp index dfd69d9fa..253d6b938 100644 --- a/src/extension/dbus/dbus-init.cpp +++ b/src/extension/dbus/dbus-init.cpp @@ -1,4 +1,18 @@ - +/* + * This is where Inkscape connects to the DBus when it starts and + * registers the main interface. + * + * Also where new interfaces are registered when a new document is created. + * (Not called directly by application-interface but called indirectly.) + * + * Authors: + * Soren Berg + * + * Copyright (C) 2009 Soren Berg + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + #include #include "dbus-init.h" diff --git a/src/extension/dbus/dbus-init.h b/src/extension/dbus/dbus-init.h index f76483170..4b07acfb4 100644 --- a/src/extension/dbus/dbus-init.h +++ b/src/extension/dbus/dbus-init.h @@ -2,7 +2,7 @@ * Authors: * Soren Berg * - * Copyright (C) 2004 Authors + * Copyright (C) 2009 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index e7af7096c..05dd2925e 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -449,6 +449,7 @@ document_interface_ellipse (DocumentInterface *object, int x, int y, return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error); } +/* FIXME: makes line but gets one endpoint wrong.*/ gchar* document_interface_line (DocumentInterface *object, int x, int y, int x2, int y2, GError **error) -- cgit v1.2.3 From aa3973adee525143989826b16d47c48c8d737cef Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 17 Aug 2009 19:05:00 +0000 Subject: Fixed document_interface_line (Warning: I don't know why it works this way, it just does.) (bzr r8254.1.33) --- src/extension/dbus/Notes.txt | 1 - src/extension/dbus/document-interface.cpp | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Notes.txt b/src/extension/dbus/Notes.txt index d7c34aac0..25c3f35b5 100644 --- a/src/extension/dbus/Notes.txt +++ b/src/extension/dbus/Notes.txt @@ -61,7 +61,6 @@ BUGS: *The following do not behave like the documentation: -document_interface_transform -document_interface_text - -document_interface_line EFFICIENCY: *Need better way to retrieve objects by name. diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 05dd2925e..ff691bab6 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -449,16 +449,14 @@ document_interface_ellipse (DocumentInterface *object, int x, int y, return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error); } -/* FIXME: makes line but gets one endpoint wrong.*/ gchar* document_interface_line (DocumentInterface *object, int x, int y, int x2, int y2, GError **error) { Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); std::stringstream out; - printf("X2: %d\nY2 %d\n", x2, y2); - out << "m " << x << "," << y << " " << x2 << "," << y2; - printf ("PATH: %s\n", out.str().c_str()); + // Not sure why this works. + out << "m " << x << "," << y << " " << x2 - x << "," << y2 - y; newNode->setAttribute("d", out.str().c_str()); return finish_create_shape (object, error, newNode, (gchar *)"create line"); } -- cgit v1.2.3 From 5c45322163136ff2390a441ecf95dcf2c73f01b3 Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Mon, 17 Aug 2009 19:23:12 +0000 Subject: Fixed spirals. (bzr r8254.1.34) --- src/extension/dbus/document-interface.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index ff691bab6..e2d7a41a2 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -475,7 +475,10 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy, sp_repr_set_int(newNode, "sodipodi:argument", 0); sp_repr_set_int(newNode, "sodipodi:expansion", 1); gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral"); - newNode->setAttribute("style", "fill:none"); + //Makes sure there is no fill for spirals by default. + gchar* newString = g_strconcat(newNode->attribute("style"), ";fill:none", NULL); + newNode->setAttribute("style", newString); + g_free(newString); return retval; } -- cgit v1.2.3 From 581760b8e2d2dac04182afd55f44199f631788dd Mon Sep 17 00:00:00 2001 From: Soren Berg Date: Thu, 20 Aug 2009 16:51:01 +0000 Subject: Added test script I thought was already added. (bzr r8254.1.35) --- src/extension/dbus/pytester.py | 290 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 src/extension/dbus/pytester.py (limited to 'src') diff --git a/src/extension/dbus/pytester.py b/src/extension/dbus/pytester.py new file mode 100644 index 000000000..d4c41fb47 --- /dev/null +++ b/src/extension/dbus/pytester.py @@ -0,0 +1,290 @@ +##################################################################### +# Python test script for Inkscape DBus API. +# +# Contains many examples of functions and various stress tests etc. +# Multiple tests can be run at once but the output will be a bit chaotic. +# List of test functions can be found at the bottom of the script. +##################################################################### + +import dbus +import random + +##################################################################### +# Various test functions, called at bottom of script +##################################################################### + +def randomrect (document): + document.rectangle( random.randint(0,1000), + random.randint(0,1000), + random.randint(1,100), + random.randint(1,100)) + +def lottarects ( document ): + document.pause_updates() + listy = [] + for x in range(1,2000): + if x == 1000: + print "HALFWAY" + if x == 1: + print "BEGUN" + document.rectangle( 0, 0, 100, 100) + #randomrect(document) + print "DONE" + for x in listy: + print x + selection_set(x) + document.resume_updates() + +def lottaverbs (doc): + doc.pause_updates() + doc.document_set_css ("fill:#ff0000;fill-opacity:.5;stroke:#0000ff;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none") + doc.rectangle( 0, 0, 100, 100) + doc.select_all() + doc.selection_copy() + for x in range(1,2000): + if x == 1000: + print "HALFWAY" + if x == 1: + print "BEGUN" + doc.selection_paste() + #doc.rectangle( 0, 0, 100, 100) + doc.resume_updates() + +def testDrawing (doc): + doc.document_set_css ("fill:#000000;fill-opacity:.5;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none") + doc.ellipse( 0, 0, 100, 100) + doc.select_all() + doc.selection_copy() + for x in range(1,2000): + if x == 1000: + print "HALFWAY" + if x == 1: + print "BEGUN" + doc.selection_paste() + newrect = doc.selection_get()[0] + doc.set_color(newrect, 255 - x%255, 0, 200, True) + doc.set_color(newrect, 0, 255 - x%75, x%75, False) + doc.mark_as_unmodified() + + +def testcopypaste (document ): + #document.pause_updates() + print document.rectangle (400, 500, 100, 100) + print document.rectangle (200, 200, 100, 100) + document.select_all() + document.selection_copy() + document.selection_paste() + #document.resume_updates() + +def testShapes (doc): + doc.rectangle (0, 0, 100, 100) + doc.ellipse (100, 100, 100, 100) + doc.star (250, 250, 50, 25, 5, False, .9, 1.4) + doc.polygon (350, 350, 50, 0, 5) + doc.line (400,400,500,500) + doc.spiral (550,550,50,3) + +def testMovement (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (0, 100, 100, 100) + rect3 = doc.rectangle (0, 200, 100, 100) + doc.select_all() + doc.move(rect2, 100,100) + +def testImport (doc): + # CHANGE TO LOCAL SVG FILE! + img1 = doc.image(0,0, "/home/soren/chavatar.jpg") + doc.selection_add(img1) + doc.selection_scale(500) + doc.transform(img1, "rotate(30)") + +def testSelections (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (0, 100, 100, 100) + rect3 = doc.rectangle (0, 200, 100, 100) + rect4 = doc.rectangle (0, 300, 100, 100) + + doc.selection_add (rect1) + center = doc.selection_get_center() + for d in center: + print d + doc.selection_to_path() + doc.get_path(rect1) + doc.selection_move(100.0, 100.0) + doc.selection_set(rect2) + doc.selection_move_to(0.0,0.0) + doc.selection_set(rect3) + doc.move(rect4, 500.0, 500.0) + doc.select_all() + doc.selection_to_path() + result = doc.selection_get() + print len(result) + for d in result: + print d + +def testLevels (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + rect4 = doc.rectangle (60, 60, 100, 100) + + doc.selection_set(rect1) + doc.selection_change_level("raise") + + doc.selection_set(rect4) + doc.selection_change_level("to_bottom") + +def testCombinations (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + rect4 = doc.rectangle (60, 60, 100, 100) + rect5 = doc.rectangle (80, 80, 100, 100) + rect6 = doc.rectangle (100, 100, 100, 100) + rect7 = doc.rectangle (120, 120, 100, 100) + rect8 = doc.rectangle (140, 140, 100, 100) + rect9 = doc.rectangle (160, 160, 100, 100) + rect10 = doc.rectangle (180, 180, 100, 100) + + doc.selection_set_list([rect1, rect2]) + print doc.selection_combine("union") + doc.selection_set_list([rect3, rect4]) + print doc.selection_combine("intersection") + doc.selection_set_list([rect5, rect6]) + print doc.selection_combine("difference") + doc.selection_set_list([rect7, rect8]) + print doc.selection_combine("exclusion") + doc.selection_set_list([rect9, rect10]) + for d in doc.selection_divide(): + print d + +def testTransforms (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + doc.set_attribute(rect1, "transform", "matrix(0.08881734,0.94288151,-0.99604793,0.68505564,245.36153,118.60315)") + doc.selection_set(rect1) + + doc.selection_move_to(200, 200) + +def testLayer (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + print doc.new_layer() + rect2 = doc.rectangle (20, 20, 100, 100) + +def testGetSelection (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + doc.select_all() + result = doc.selection_get() + print result + print len(result) + for d in result: + print d + + +def testDocStyle (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + doc.document_set_css ("fill:#ff0000;fill-opacity:.5;stroke:#0000ff;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none") + rect2 = doc.rectangle (20, 20, 100, 100) + doc.document_set_css ("fill:#ffff00;fill-opacity:1;stroke:#009002;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none") + rect3 = doc.rectangle (40, 40, 100, 100) + doc.document_set_css ("fill:#00ff00;fill-opacity:1") + rect4 = doc.rectangle (60, 60, 100, 100) + +def testStyle (doc): + doc.document_set_css ("fill:#ffff00;fill-opacity:1;stroke:#009002;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none") + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + rect4 = doc.rectangle (60, 60, 100, 100) + + doc.modify_css (rect3, "fill-opacity", ".5") + doc.merge_css (rect4, "fill:#0000ff;fill-opacity:.25;") + print doc.get_css (rect4) + +def testLayers (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + layer1 = doc.layer_new() + layer2 = doc.layer_new() + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + doc.selection_add(rect3) + doc.selection_move_to_layer(layer1) + +def testLoadSave (doc): + doc.load("/home/soren/testfile.svg") + rect2 = doc.rectangle (0, 0, 200, 200) + doc.save_as("/home/soren/testsave.svg") + rect1 = doc.rectangle (20, 20, 200, 200) + doc.save() + rect3 = doc.rectangle (40, 40, 200, 200) + doc.save_as("/home/soren/testsave2.svg") + +def testArray (doc): + rect1 = doc.rectangle (0, 0, 100, 100) + rect2 = doc.rectangle (20, 20, 100, 100) + rect3 = doc.rectangle (40, 40, 100, 100) + doc.selection_set_list([rect1, rect2, rect3]) + +def testPath (doc): + cr1 = doc.ellipse(0,0,50,50) + print doc.get_path(cr1) + doc.object_to_path(cr1) + print doc.get_path(cr1) + #doc.get_node_coordinates(cr1) + +# Needs work. +def testText(doc): + print doc.text(200, 200, "svg:text") + + +##################################################################### +# Setup bus connection, create documents. +##################################################################### + +# Connect to bus +bus = dbus.SessionBus() + +# Get interface for default document +inkdoc1 = bus.get_object('org.inkscape', '/org/inkscape/desktop_0') +doc1 = dbus.Interface(inkdoc1, dbus_interface="org.inkscape.document") + +# Create new window and get the interface for that. (optional) +inkapp = bus.get_object('org.inkscape', + '/org/inkscape/application') +desk2 = inkapp.desktop_new(dbus_interface='org.inkscape.application') +inkdoc2 = bus.get_object('org.inkscape', desk2) +doc2 = dbus.Interface(inkdoc2, dbus_interface="org.inkscape.document") + + +##################################################################### +# Call desired test functions +##################################################################### + +#lottaverbs (doc1) +#lottarects (doc1) +#testDrawing (doc1) + +#doc1.pause_updates() + +testShapes(doc1) +#testMovement(doc1) +#testImport(doc1) # EDIT FUNCTION TO OPEN EXISTING FILE! +#testcopypaste (doc1) +#testTransforms (doc1) +#testDocStyle(doc1) +#testLayers(doc1) +#testLoadSave(doc1) +#testArray(doc1) +#testSelections(doc1) +#testCombinations(doc1) +#testText(doc1) +#testPath(doc1) + +#doc1.resume_updates + + +# Prevents asking if you want to save when closing document. +doc1.mark_as_unmodified() + -- cgit v1.2.3 From 1493fb8cfd802dd4566b933d4ad255ee64787b09 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 27 Aug 2009 21:20:57 -0500 Subject: Add the build dir dbus directory to grab some headerfiles for distcheck. (bzr r8254.1.36) --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 90b0be28c..e1fe86535 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ INCLUDES = \ $(WIN32_CFLAGS) \ -I$(srcdir)/bind/javainc \ -I$(srcdir)/bind/javainc/linux \ + -I$(builddir)/extension/dbus \ $(AM_CPPFLAGS) CXXTEST_TEMPLATE = $(srcdir)/cxxtest-template.tpl -- cgit v1.2.3 From 70a057a9c77a7e977bf6abe0d7029400a66cbd9e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 30 Dec 2009 23:57:49 -0600 Subject: Making BUILT_SOURCES an append (bzr r8254.1.39) --- src/Makefile.am | 2 ++ src/extension/dbus/Makefile_insert | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 3b2dfeeb6..7fa869012 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,6 +54,8 @@ ink_common_sources = inkscape_SOURCES = # Add Inkview-only sources here. inkview_SOURCES = +# Add sources that are built from meta files +BUILT_SOURCES = INCLUDES = \ $(PERL_CFLAGS) $(PYTHON_CFLAGS) \ diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index 00dba3b20..3a8dc9ee6 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -10,7 +10,7 @@ ink_common_sources += \ ## Slightly concerned about this. ## Would use += but it has to be set first. -BUILT_SOURCES = \ +BUILT_SOURCES += \ extension/dbus/application-server-glue.h \ extension/dbus/document-server-glue.h \ extension/dbus/document-client-glue.h -- cgit v1.2.3 From 36a20383a3c581ebb32087d369a18a76a195f0e1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 00:08:50 -0600 Subject: Installing the service files into the dbus service directory (bzr r8254.1.41) --- src/extension/dbus/Makefile_insert | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index 3a8dc9ee6..8293a5e4d 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -30,7 +30,7 @@ extension/dbus/document-client-glue.h: extension/dbus/document-interface.xml # ld -shared -soname libinkdbus.so.1 -o extension/dbus/wrapper/libinkdbus.so.1.0 -lc extension/dbus/wrapper/inkscape-dbus-wrapper.o # Dbus service file -servicedir = "/usr/share/dbus-1/services" +servicedir = $(DBUSSERVICEDIR) service_in_files = extension/dbus/org.inkscape.service.in service_DATA = $(service_in_files:.service.in=.service) -- cgit v1.2.3 From c84c93abfd99947d87e4f9865d4c0c43cf74c2d2 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 00:12:50 -0600 Subject: Adding dbus descriptions to EXTRA_DIST (bzr r8254.1.42) --- src/extension/dbus/Makefile_insert | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index 8293a5e4d..cc363b7ce 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -25,6 +25,10 @@ extension/dbus/document-server-glue.h: extension/dbus/document-interface.xml extension/dbus/document-client-glue.h: extension/dbus/document-interface.xml dbus-binding-tool --mode=glib-client --output=$@ --prefix=document_interface $^ +EXTRA_DIST += \ + extension/dbus/application-interface.xml \ + extension/dbus/document-interface.xml + #extension/dbus/wrapper/libinkdbus.so.1.0: extension/dbus/wrapper/inkscape-dbus-wrapper.c extension/dbus/wrapper/inkscape-dbus-wrapper.h extension/dbus/document-interface.xml # gcc -fPIC -c extension/dbus/wrapper/inkscape-dbus-wrapper.c -o extension/dbus/wrapper/inkscape-dbus-wrapper.o $(shell pkg-config --cflags --libs glib-2.0 gobject-2.0 dbus-glib-1) # ld -shared -soname libinkdbus.so.1 -o extension/dbus/wrapper/libinkdbus.so.1.0 -lc extension/dbus/wrapper/inkscape-dbus-wrapper.o -- cgit v1.2.3 From 1b5d271f226e3eeb2011d8762cc000e8a02eda1b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 00:23:23 -0600 Subject: Updating interface to add save type (bzr r8254.1.43) --- src/extension/dbus/document-interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index e2d7a41a2..b8b0c2ade 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -862,7 +862,7 @@ document_interface_save_as (DocumentInterface *object, try { Inkscape::Extension::save(NULL, doc, filename, - false, false, true); + false, false, true, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); } catch (...) { //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved.")); return false; -- cgit v1.2.3 From c22fb6c4e0b23c806ade6e42a8025384cc380f91 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 00:23:42 -0600 Subject: Clearing up EXTRA_DIST lifecycle (bzr r8254.1.44) --- src/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 7fa869012..a064496ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,8 @@ inkscape_SOURCES = inkview_SOURCES = # Add sources that are built from meta files BUILT_SOURCES = +# Extra files to distribute +EXTRA_DIST = INCLUDES = \ $(PERL_CFLAGS) $(PYTHON_CFLAGS) \ @@ -147,7 +149,7 @@ include trace/Makefile_insert include 2geom/Makefile_insert # Extra files not mentioned as sources to include in the source tarball -EXTRA_DIST = \ +EXTRA_DIST += \ $(top_srcdir)/Doxyfile \ sp-skeleton.cpp sp-skeleton.h \ algorithms/makefile.in \ -- cgit v1.2.3 From 56060b950f32a8227f5dd7f084a7468bd80938a4 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 21:45:03 -0600 Subject: Cleaning up the Makefile so it's easier to read (bzr r8254.1.45) --- src/extension/dbus/Makefile_insert | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index cc363b7ce..65ead8c93 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -1,5 +1,9 @@ ## Makefile.am fragment sourced by src/Makefile.am. +############################# +# Sources for DBus interface +############################# + ink_common_sources += \ extension/dbus/dbus-init.cpp \ extension/dbus/dbus-init.h \ @@ -8,13 +12,9 @@ ink_common_sources += \ extension/dbus/document-interface.cpp \ extension/dbus/document-interface.h -## Slightly concerned about this. -## Would use += but it has to be set first. -BUILT_SOURCES += \ - extension/dbus/application-server-glue.h \ - extension/dbus/document-server-glue.h \ - extension/dbus/document-client-glue.h -# extension/dbus/wrapper/libinkdbus.so.1.0 this probably belongs somewhere else +########################### +# Build DBus wrapper files +########################### extension/dbus/application-server-glue.h: extension/dbus/application-interface.xml dbus-binding-tool --mode=glib-server --output=$@ --prefix=application_interface $^ @@ -25,13 +25,22 @@ extension/dbus/document-server-glue.h: extension/dbus/document-interface.xml extension/dbus/document-client-glue.h: extension/dbus/document-interface.xml dbus-binding-tool --mode=glib-client --output=$@ --prefix=document_interface $^ +BUILT_SOURCES += \ + extension/dbus/application-server-glue.h \ + extension/dbus/document-server-glue.h \ + extension/dbus/document-client-glue.h + +########################### +# Distribut DBus interface +########################### + EXTRA_DIST += \ extension/dbus/application-interface.xml \ extension/dbus/document-interface.xml -#extension/dbus/wrapper/libinkdbus.so.1.0: extension/dbus/wrapper/inkscape-dbus-wrapper.c extension/dbus/wrapper/inkscape-dbus-wrapper.h extension/dbus/document-interface.xml -# gcc -fPIC -c extension/dbus/wrapper/inkscape-dbus-wrapper.c -o extension/dbus/wrapper/inkscape-dbus-wrapper.o $(shell pkg-config --cflags --libs glib-2.0 gobject-2.0 dbus-glib-1) -# ld -shared -soname libinkdbus.so.1 -o extension/dbus/wrapper/libinkdbus.so.1.0 -lc extension/dbus/wrapper/inkscape-dbus-wrapper.o +########################### +# DBus Activation Service +########################### # Dbus service file servicedir = $(DBUSSERVICEDIR) -- cgit v1.2.3 From e588e1f405fa74d8e14735172570f1a542513625 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 22:30:23 -0600 Subject: Adding all of the library stuff in. Including libtool in configure and libtoolize in autogen.sh (bzr r8254.1.46) --- src/extension/dbus/Makefile_insert | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index 65ead8c93..aa4d17f22 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -51,3 +51,31 @@ service_DATA = $(service_in_files:.service.in=.service) $(service_DATA): $(service_in_files) Makefile @sed -e "s|bindir|$(prefix)|" $<> $@ +############################ +# DBus Interface Helper Lib +############################ + +lib_LTLIBRARIES = \ + libinkdbus.la + +libinkdbusincludedir = $(includedir)/libinkdbus-0.48/libinkdbus +libinkdbusinclude_HEADERS = \ + extension/dbus/wrapper/inkscape-dbus-wrapper.h + +libinkdbus_la_SOURCES = \ + extension/dbus/wrapper/inkscape-dbus-wrapper.h \ + extension/dbus/wrapper/inkscape-dbus-wrapper.c + +libinkdbus_la_LDFLAGS = \ + -version-info 0:0:0 \ + -no-undefined \ + -export-symbols-regex "^[^_d].*" + +libinkdbus_la_CFLAGS = \ + $(DBUS_CFLAGS) \ + $(INKSCAPE_CFLAGS) \ + -Wall -Werror + +libinkdbus_la_LIBADD = \ + $(DBUS_LIBS) \ + $(INKSCAPE_LIBS) -- cgit v1.2.3 From 8d5161054d0e7bb3c1b2172898f09aa000d2f1d9 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 22:33:04 -0600 Subject: Fixing includes (bzr r8254.1.47) --- src/extension/dbus/Makefile_insert | 1 + src/extension/dbus/wrapper/inkscape-dbus-wrapper.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index aa4d17f22..35b7c6fff 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -74,6 +74,7 @@ libinkdbus_la_LDFLAGS = \ libinkdbus_la_CFLAGS = \ $(DBUS_CFLAGS) \ $(INKSCAPE_CFLAGS) \ + -I$(builddir)/extension/dbus \ -Wall -Werror libinkdbus_la_LIBADD = \ diff --git a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c index e6d2818a2..5184affdf 100644 --- a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c +++ b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c @@ -5,7 +5,7 @@ -#include "../document-client-glue.h" +#include "document-client-glue.h" #include #include -- cgit v1.2.3 From b3d2e4c24cc409f0eedba79c890aefb60f43e7da Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 31 Dec 2009 22:38:19 -0600 Subject: Fixing some warnings/errors (bzr r8254.1.48) --- src/extension/dbus/wrapper/inkscape-dbus-wrapper.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c index 5184affdf..b59ee746b 100644 --- a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c +++ b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c @@ -34,10 +34,11 @@ dbus_get_proxy(DBusGConnection *connection) { DBUS_INTERFACE_DBUS); } +#if 0 /* PRIVATE register an object on a bus */ static gpointer dbus_register_object (DBusGConnection *connection, - DBusGProxy *proxy, + DBusGProxy * proxy, GType object_type, const DBusGObjectInfo *info, const gchar *path) @@ -47,6 +48,7 @@ dbus_register_object (DBusGConnection *connection, dbus_g_connection_register_g_object (connection, path, object); return object; } +#endif /**************************************************************************** DOCUMENT INTERFACE CLASS STUFF @@ -229,7 +231,7 @@ inkscape_document_get_width (DocumentInterface *doc, GError **error) { gdouble OUT_val; DBusGProxy *proxy = doc->proxy; - org_inkscape_document_document_document_get_width (proxy, &OUT_val, error); + org_inkscape_document_document_get_width (proxy, &OUT_val, error); return OUT_val; } @@ -239,7 +241,7 @@ inkscape_document_get_height (DocumentInterface *doc, GError **error) { gdouble OUT_val; DBusGProxy *proxy = doc->proxy; - org_inkscape_document_document_document_get_height (proxy, &OUT_val, error); + org_inkscape_document_document_get_height (proxy, &OUT_val, error); return OUT_val; } @@ -249,7 +251,7 @@ inkscape_document_get_css (DocumentInterface *doc, GError **error) { char * OUT_css; DBusGProxy *proxy = doc->proxy; - org_inkscape_document_document_document_get_css (proxy, &OUT_css, error); + org_inkscape_document_document_get_css (proxy, &OUT_css, error); return OUT_css; } @@ -258,7 +260,7 @@ gboolean inkscape_document_set_css (DocumentInterface *doc, const char * IN_stylestring, GError **error) { DBusGProxy *proxy = doc->proxy; - return org_inkscape_document_document_document_set_css (proxy, IN_stylestring, error); + return org_inkscape_document_document_set_css (proxy, IN_stylestring, error); } //static @@ -266,7 +268,7 @@ gboolean inkscape_document_merge_css (DocumentInterface *doc, const char * IN_stylestring, GError **error) { DBusGProxy *proxy = doc->proxy; - return org_inkscape_document_document_document_merge_css (proxy, IN_stylestring, error); + return org_inkscape_document_document_merge_css (proxy, IN_stylestring, error); } //static @@ -274,7 +276,7 @@ gboolean inkscape_document_resize_to_fit_selection (DocumentInterface *doc, GError **error) { DBusGProxy *proxy = doc->proxy; - return org_inkscape_document_document_document_resize_to_fit_selection (proxy, error); + return org_inkscape_document_document_resize_to_fit_selection (proxy, error); } //static -- cgit v1.2.3 From 915b47e2dec38c79388446548288291d4c973766 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 1 Jan 2010 00:09:50 -0600 Subject: Removing extra makefile (bzr r8254.1.50) --- src/extension/dbus/wrapper/Makefile | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/extension/dbus/wrapper/Makefile (limited to 'src') diff --git a/src/extension/dbus/wrapper/Makefile b/src/extension/dbus/wrapper/Makefile deleted file mode 100644 index 692f4fa19..000000000 --- a/src/extension/dbus/wrapper/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -wrapper: #inkscape-dbus-wrapper.c inkscape-dbus-wrapper.h - gcc -fPIC -c inkscape-dbus-wrapper.c $(shell pkg-config --cflags --libs glib-2.0 gobject-2.0 dbus-glib-1 dbus-1) - ld -shared -soname libinkdbus.so.1 -o libinkdbus.so.1.0 -lc inkscape-dbus-wrapper.o - ln -sf libinkdbus.so.1.0 libinkdbus.so - ln -sf libinkdbus.so.1.0 libinkdbus.so.1 - -test: wrapper tester.c - gcc -Wall -L. tester.c -linkdbus -o test $(shell pkg-config --cflags --libs glib-2.0 gobject-2.0) - -- cgit v1.2.3 From 2b0e6573d59004745df33e309f08e70e4de79e37 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 1 Jan 2010 00:22:15 -0600 Subject: Adding in building of the pkgconfig file. (bzr r8254.1.51) --- src/extension/dbus/wrapper/inkdbus.pc.in | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/extension/dbus/wrapper/inkdbus.pc.in (limited to 'src') diff --git a/src/extension/dbus/wrapper/inkdbus.pc.in b/src/extension/dbus/wrapper/inkdbus.pc.in new file mode 100644 index 000000000..2bdfb75eb --- /dev/null +++ b/src/extension/dbus/wrapper/inkdbus.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +bindir=@bindir@ +includedir=@includedir@ + +Cflags: -I${includedir}/libinkdbus-0.1 +Requires: gobject-2.0 dbus-glib-1 +Libs: -L${libdir} -linkdbus + +Name: inkdbus +Description: Inkscape DBus Interface Wrapper +Version: @VERSION@ + -- cgit v1.2.3 From 4b04615e34476d7a073df30482417e2f75f21ada Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 1 Jan 2010 00:26:17 -0600 Subject: Installing the pkgconfig file (bzr r8254.1.52) --- src/extension/dbus/Makefile_insert | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index 35b7c6fff..ce733364c 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -80,3 +80,11 @@ libinkdbus_la_CFLAGS = \ libinkdbus_la_LIBADD = \ $(DBUS_LIBS) \ $(INKSCAPE_LIBS) + +############################ +# DBus Pkgconfig file +############################ + +pkgconfig_DATA = extension/dbus/wrapper/inkdbus.pc +pkgconfigdir = $(libdir)/pkgconfig + -- cgit v1.2.3 From efa82e348fcc921fc3d6dc5065c933a2f0f67f6b Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 23 Jun 2010 00:23:28 +0200 Subject: fix wrong transform for dot drawing with pen or pencil tool Fixed bugs: - https://launchpad.net/bugs/597136 (bzr r9529) --- src/draw-context.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/draw-context.cpp b/src/draw-context.cpp index da22c8a7a..3049f3a6a 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -837,7 +837,7 @@ void spdc_create_single_dot(SPEventContext *ec, Geom::Point const &pt, char cons Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Geom::Matrix const i2d (sp_item_i2d_affine (item)); - Geom::Point pp = pt; + Geom::Point pp = pt * i2d.inverse(); double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0); if (event_state & GDK_MOD1_MASK) { /* TODO: We vary the dot size between 0.5*rad and 1.5*rad, where rad is the dot size @@ -856,7 +856,6 @@ void spdc_create_single_dot(SPEventContext *ec, Geom::Point const &pt, char cons sp_repr_set_svg_double (repr, "sodipodi:rx", rad * stroke_width); sp_repr_set_svg_double (repr, "sodipodi:ry", rad * stroke_width); item->updateRepr(); - sp_item_set_item_transform(item, i2d.inverse()); sp_desktop_selection(desktop)->set(item); -- cgit v1.2.3 From b95ac6836414620f191c592c31e263bf9a036bf8 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Fri, 25 Jun 2010 23:56:06 +0200 Subject: throw exception when sbasis is empty (bzr r9537) --- src/2geom/sbasis-to-bezier.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/2geom/sbasis-to-bezier.cpp b/src/2geom/sbasis-to-bezier.cpp index ce5bf89bc..0a5441254 100644 --- a/src/2geom/sbasis-to-bezier.cpp +++ b/src/2geom/sbasis-to-bezier.cpp @@ -99,6 +99,10 @@ int sgn(unsigned int j, unsigned int k) */ void sbasis_to_bezier (Bezier & bz, SBasis const& sb, size_t sz) { + if (sb.size() == 0) { + THROW_RANGEERROR("size of sb is too small"); + } + size_t q, n; bool even; if (sz == 0) -- cgit v1.2.3 From 1c5c6e9027b036185394728c6687a58adee530aa Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 26 Jun 2010 16:29:36 -0700 Subject: Implementing the "Convert" popup menu item for gradients/swatches. Part of bug #59441. Fixed bugs: - https://launchpad.net/bugs/594441 (bzr r9541) --- src/ui/dialog/swatches.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++-- src/ui/dialog/swatches.h | 3 +- 2 files changed, 82 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 6f013f4f3..b0d027ae9 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -44,6 +44,7 @@ #include "swatches.h" #include "style.h" #include "ui/previewholder.h" +#include "widgets/desktop-widget.h" #include "widgets/gradient-vector.h" #include "widgets/eek-preview.h" #include "display/nr-plain-stuff.h" @@ -68,6 +69,11 @@ static std::vector docTrackings; static std::map docPerPanel; +class SwatchesPanelHook : public SwatchesPanel +{ +public: + static void convertGradient( GtkMenuItem * menuitem, gpointer userData ); +}; static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { ColorItem* item = reinterpret_cast(callback_data); @@ -84,6 +90,9 @@ static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer } static GtkWidget* popupMenu = 0; +static GtkWidget *popupSubHolder = 0; +static GtkWidget *popupSub = 0; +static std::vector popupItems; static std::vector popupExtras; static ColorItem* bounceTarget = 0; static SwatchesPanel* bouncePanel = 0; @@ -159,6 +168,33 @@ static void addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) } } +void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) +{ + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + SPDocument *doc = desktop ? desktop->doc() : 0; + gint index = GPOINTER_TO_INT(userData); + if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { + Glib::ustring targetName = popupItems[index]; + + const GSList *gradients = sp_document_get_resource_list(doc, "gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + grad->repr->setAttribute("osb:paint", "solid"); + + sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, + _("Add gradient stop")); + + handleGradientsChange(doc); // work-around for signal not being emmitted + break; + } + } + } + } +} + static SwatchesPanel* findContainingPanel( GtkWidget *widget ) { SwatchesPanel *swp = 0; @@ -177,7 +213,12 @@ static SwatchesPanel* findContainingPanel( GtkWidget *widget ) return swp; } -gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data) +static void removeit( GtkWidget *widget, gpointer data ) +{ + gtk_container_remove( GTK_CONTAINER(data), widget ); +} + +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) { gboolean handled = FALSE; @@ -237,7 +278,12 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g child = gtk_menu_item_new_with_label(_("Convert")); gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); //popupExtras.push_back(child); - gtk_widget_set_sensitive( child, FALSE ); + //gtk_widget_set_sensitive( child, FALSE ); + { + popupSubHolder = child; + popupSub = gtk_menu_new(); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub ); + } gtk_widget_show_all(popupMenu); } @@ -251,7 +297,39 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g bounceTarget = item; bouncePanel = swp; + popupItems.clear(); if ( popupMenu ) { + gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub); + bool processed = false; + GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); + if ( wdgt ) { + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); + if ( dtw && dtw->desktop ) { + // Pick up all gradients with vectors + const GSList *gradients = sp_document_get_resource_list(dtw->desktop->doc(), "gradient"); + gint index = 0; + for (const GSList *curr = gradients; curr; curr = curr->next) { + SPGradient* grad = SP_GRADIENT(curr->data); + if (SP_GRADIENT_HAS_STOPS(grad) && !grad->isSwatch()) { + //gl = g_slist_prepend(gl, curr->data); + processed = true; + GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); + gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child); + + popupItems.push_back(grad->getId()); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(SwatchesPanelHook::convertGradient), + GINT_TO_POINTER(index) ); + index++; + } + } + + gtk_widget_show_all(popupSub); + } + } + gtk_widget_set_sensitive( popupSubHolder, processed ); + gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time); handled = TRUE; } diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index b18fd6cad..93bbe81d8 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -43,6 +43,8 @@ public: virtual int getSelectedIndex() {return _currentIndex;} // temporary protected: + static void handleGradientsChange(SPDocument *document); + virtual void _updateFromSelection(); virtual void _handleAction( int setId, int itemId ); virtual void _setDocument( SPDocument *document ); @@ -55,7 +57,6 @@ private: SwatchesPanel &operator=(SwatchesPanel const &); // no assign static void _trackDocument( SwatchesPanel *panel, SPDocument *document ); - static void handleGradientsChange(SPDocument *document); static void handleDefsModified(SPDocument *document); PreviewHolder* _holder; -- cgit v1.2.3 From 7e8ffe9fb3b42470802ed080dc827fdda32165b3 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 27 Jun 2010 20:16:09 -0700 Subject: Partial C++-ification of SPGradient (bzr r9542) --- src/extension/internal/cairo-render-context.cpp | 10 +- src/gradient-chemistry.cpp | 29 +- src/gradient-context.cpp | 2 +- src/gradient-drag.cpp | 2 +- src/interface.cpp | 2 +- src/sp-gradient-fns.h | 16 - src/sp-gradient.cpp | 464 ++++++++++++------------ src/sp-gradient.h | 42 ++- src/sp-paint-server.cpp | 9 +- src/tweak-context.cpp | 18 +- src/ui/dialog/swatches.cpp | 17 +- src/widgets/fill-style.cpp | 8 +- src/widgets/gradient-selector.cpp | 2 +- src/widgets/gradient-toolbar.cpp | 6 +- src/widgets/gradient-vector.cpp | 12 +- src/widgets/paint-selector.cpp | 4 +- src/widgets/swatch-selector.cpp | 2 +- 17 files changed, 335 insertions(+), 310 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index cf3c72432..28d1db9a4 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1120,11 +1120,11 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain SPLinearGradient *lg=SP_LINEARGRADIENT(paintserver); - sp_gradient_ensure_vector(SP_GRADIENT(lg)); // when exporting from commandline, vector is not built + SP_GRADIENT(lg)->ensureVector(); // when exporting from commandline, vector is not built Geom::Point p1 (lg->x1.computed, lg->y1.computed); Geom::Point p2 (lg->x2.computed, lg->y2.computed); - if (pbox && SP_GRADIENT(lg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + if (pbox && SP_GRADIENT(lg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { // convert to userspace Geom::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); p1 *= bbox2user; @@ -1144,12 +1144,12 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain SPRadialGradient *rg=SP_RADIALGRADIENT(paintserver); - sp_gradient_ensure_vector(SP_GRADIENT(rg)); // when exporting from commandline, vector is not built + SP_GRADIENT(rg)->ensureVector(); // when exporting from commandline, vector is not built Geom::Point c (rg->cx.computed, rg->cy.computed); Geom::Point f (rg->fx.computed, rg->fy.computed); double r = rg->r.computed; - if (pbox && SP_GRADIENT(rg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) + if (pbox && SP_GRADIENT(rg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) apply_bbox2user = true; // create radial gradient pattern @@ -1172,7 +1172,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain SPGradient *g = SP_GRADIENT(paintserver); // set extend type - SPGradientSpread spread = sp_gradient_get_spread(g); + SPGradientSpread spread = g->fetchSpread(); switch (spread) { case SP_GRADIENT_SPREAD_REPEAT: { cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index c95c1b2c5..979b53f1b 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -67,9 +67,9 @@ sp_gradient_ensure_vector_normalized(SPGradient *gr) } /* First make sure we have vector directly defined (i.e. gr has its own stops) */ - if (!gr->has_stops) { + if ( !gr->hasStops() ) { /* We do not have stops ourselves, so flatten stops as well */ - sp_gradient_ensure_vector(gr); + gr->ensureVector(); g_assert(gr->vector.built); // this adds stops from gr->vector as children to gr sp_gradient_repr_write_vector (gr); @@ -97,7 +97,7 @@ sp_gradient_get_private_normalized(SPDocument *document, SPGradient *vector, SPG g_return_val_if_fail(document != NULL, NULL); g_return_val_if_fail(vector != NULL, NULL); g_return_val_if_fail(SP_IS_GRADIENT(vector), NULL); - g_return_val_if_fail(SP_GRADIENT_HAS_STOPS(vector), NULL); + g_return_val_if_fail(vector->hasStops(), NULL); SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document); @@ -177,8 +177,9 @@ sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector, // Orphaned gradient, no vector with stops at the end of the line; this used to be an assert // but i think we should not abort on this - maybe just write a validity warning into some sort // of log - if (!vector || !SP_GRADIENT_HAS_STOPS(vector)) + if ( !vector || !vector->hasStops() ) { return (gr); + } // user is the object that uses this gradient; normally it's item but for tspans, we // check its ancestor text so that tspans don't get different gradients from their @@ -202,7 +203,7 @@ sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector, SPDocument *doc = SP_OBJECT_DOCUMENT(gr); SPObject *defs = SP_DOCUMENT_DEFS(doc); - if ((gr->has_stops) || + if ((gr->hasStops()) || (gr->state != SP_GRADIENT_STATE_UNKNOWN) || (SP_OBJECT_PARENT(gr) != SP_OBJECT(defs)) || (SP_OBJECT_HREFCOUNT(gr) > 1)) { @@ -339,7 +340,7 @@ sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *prop gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(), SP_IS_RADIALGRADIENT(gr) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, SP_OBJECT(item)); - if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); @@ -817,7 +818,7 @@ sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom // using X-coordinates only to determine the offset, assuming p has been snapped to the vector from begin to end. double offset = get_offset_between_points (p, Geom::Point(lg->x1.computed, lg->y1.computed), Geom::Point(lg->x2.computed, lg->y2.computed)); SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (lg, false); - sp_gradient_ensure_vector(lg); + lg->ensureVector(); lg->vector.stops.at(point_i).offset = offset; SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; @@ -911,7 +912,7 @@ sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom Geom::Point end = Geom::Point (rg->cx.computed + rg->r.computed, rg->cy.computed); double offset = get_offset_between_points (p, start, end); SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (rg, false); - sp_gradient_ensure_vector(rg); + rg->ensureVector(); rg->vector.stops.at(point_i).offset = offset; SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; @@ -927,7 +928,7 @@ sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom Geom::Point end = Geom::Point (rg->cx.computed, rg->cy.computed - rg->r.computed); double offset = get_offset_between_points (p, start, end); SPGradient *vector = sp_gradient_get_forked_vector_if_necessary(rg, false); - sp_gradient_ensure_vector(rg); + rg->ensureVector(); rg->vector.stops.at(point_i).offset = offset; SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; @@ -967,11 +968,13 @@ sp_item_gradient_get_vector (SPItem *item, bool fill_or_stroke) SPGradientSpread sp_item_gradient_get_spread (SPItem *item, bool fill_or_stroke) { + SPGradientSpread spread = SP_GRADIENT_SPREAD_PAD; SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); - if (gradient) - return sp_gradient_get_spread (gradient); - return SP_GRADIENT_SPREAD_PAD; + if (gradient) { + spread = gradient->fetchSpread(); + } + return spread; } @@ -1036,7 +1039,7 @@ sp_item_gradient_get_coords (SPItem *item, guint point_type, guint point_i, bool } } - if (SP_GRADIENT(gradient)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + if (SP_GRADIENT(gradient)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { sp_document_ensure_up_to_date(SP_OBJECT_DOCUMENT(item)); Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if (bbox) { diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index ddb153ffd..6d6ea8761 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -381,7 +381,7 @@ sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc) if (SP_IS_GRADIENT (parent)) { doc = SP_OBJECT_DOCUMENT (parent); sp_vector_add_stop (SP_GRADIENT (parent), this_stop, next_stop, offset); - sp_gradient_ensure_vector (SP_GRADIENT (parent)); + SP_GRADIENT(parent)->ensureVector(); } } diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 11de93d68..227a5f003 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -348,7 +348,7 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance) SPStop *newstop = sp_vector_add_stop (vector, prev_stop, next_stop, offset); - sp_gradient_ensure_vector (gradient); + gradient->ensureVector(); updateDraggers(); return newstop; diff --git a/src/interface.cpp b/src/interface.cpp index 47563238a..b33443d1b 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1367,7 +1367,7 @@ sp_ui_drag_data_received(GtkWidget *widget, for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( color.descr == grad->getId() ) { - if ( grad->has_stops ) { + if ( grad->hasStops() ) { matches = grad; break; } diff --git a/src/sp-gradient-fns.h b/src/sp-gradient-fns.h index dafa1646f..aabc3eda7 100644 --- a/src/sp-gradient-fns.h +++ b/src/sp-gradient-fns.h @@ -13,22 +13,6 @@ class SPGradient; -#define SP_GRADIENT_STATE_IS_SET(g) (SP_GRADIENT(g)->state != SP_GRADIENT_STATE_UNKNOWN) -#define SP_GRADIENT_IS_VECTOR(g) (SP_GRADIENT(g)->state == SP_GRADIENT_STATE_VECTOR) -#define SP_GRADIENT_IS_PRIVATE(g) (SP_GRADIENT(g)->state == SP_GRADIENT_STATE_PRIVATE) -#define SP_GRADIENT_HAS_STOPS(g) (SP_GRADIENT(g)->has_stops) -#define SP_GRADIENT_SPREAD(g) (SP_GRADIENT(g)->spread) -#define SP_GRADIENT_UNITS(g) (SP_GRADIENT(g)->units) - -/** Forces vector to be built, if not present (i.e. changed) */ -void sp_gradient_ensure_vector(SPGradient *gradient); - -/** Ensures that color array is populated */ -void sp_gradient_ensure_colors(SPGradient *gradient); - -void sp_gradient_set_units(SPGradient *gr, SPGradientUnits units); -void sp_gradient_set_spread(SPGradient *gr, SPGradientSpread spread); - SPGradientSpread sp_gradient_get_spread (SPGradient *gradient); /* Gradient repr methods */ diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 3d4d69672..0c0c94784 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -1,5 +1,3 @@ -#define __SP_GRADIENT_C__ - /** \file * SPGradient, SPStop, SPLinearGradient, SPRadialGradient. */ @@ -38,6 +36,7 @@ #include "svg/css-ostringstream.h" #include "attributes.h" #include "document-private.h" +#include "sp-gradient.h" #include "gradient-chemistry.h" #include "sp-gradient-reference.h" #include "sp-linear-gradient.h" @@ -62,6 +61,29 @@ static Inkscape::XML::Node *sp_stop_write(SPObject *object, Inkscape::XML::Docum static SPObjectClass *stop_parent_class; +class SPGradientImpl +{ + friend class SPGradient; + + static void classInit(SPGradientClass *klass); + + static void init(SPGradient *gr); + static void build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); + static void release(SPObject *object); + static void modified(SPObject *object, guint flags); + static Inkscape::XML::Node *write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + + static void gradientRefModified(SPObject *href, guint flags, SPGradient *gradient); + static void gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr); + + static void childAdded(SPObject *object, + Inkscape::XML::Node *child, + Inkscape::XML::Node *ref); + static void removeChild(SPObject *object, Inkscape::XML::Node *child); + + static void setGradientAttr(SPObject *object, unsigned key, gchar const *value); +}; + /** * Registers SPStop class and returns its type. */ @@ -240,6 +262,32 @@ sp_stop_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML: return repr; } + +bool SPGradient::hasStops() const +{ + return has_stops; +} + +bool SPGradient::isUnitsSet() const +{ + return units_set; +} + +SPGradientUnits SPGradient::getUnits() const +{ + return units; +} + +bool SPGradient::isSpreadSet() const +{ + return spread_set; +} + +SPGradientSpread SPGradient::getSpread() const +{ + return spread; +} + /** * Return stop's color as 32bit value. */ @@ -291,48 +339,23 @@ sp_stop_get_color(SPStop const *const stop) * Gradient */ -static void sp_gradient_class_init(SPGradientClass *klass); -static void sp_gradient_init(SPGradient *gr); - -static void sp_gradient_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); -static void sp_gradient_release(SPObject *object); -static void sp_gradient_set(SPObject *object, unsigned key, gchar const *value); -static void sp_gradient_child_added(SPObject *object, - Inkscape::XML::Node *child, - Inkscape::XML::Node *ref); -static void sp_gradient_remove_child(SPObject *object, Inkscape::XML::Node *child); -static void sp_gradient_modified(SPObject *object, guint flags); -static Inkscape::XML::Node *sp_gradient_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, - guint flags); - -static void gradient_ref_modified(SPObject *href, guint flags, SPGradient *gradient); - -static bool sp_gradient_invalidate_vector(SPGradient *gr); -static void sp_gradient_rebuild_vector(SPGradient *gr); - -static void gradient_ref_changed(SPObject *old_ref, SPObject *ref, SPGradient *gradient); - -SPGradientSpread sp_gradient_get_spread(SPGradient *gradient); -SPGradientUnits sp_gradient_get_units(SPGradient *gradient); - static SPPaintServerClass *gradient_parent_class; /** * Registers SPGradient class and returns its type. */ -GType -sp_gradient_get_type() +GType SPGradient::getType() { static GType gradient_type = 0; if (!gradient_type) { GTypeInfo gradient_info = { sizeof(SPGradientClass), NULL, NULL, - (GClassInitFunc) sp_gradient_class_init, + (GClassInitFunc) SPGradientImpl::classInit, NULL, NULL, sizeof(SPGradient), 16, - (GInstanceInitFunc) sp_gradient_init, + (GInstanceInitFunc) SPGradientImpl::init, NULL, /* value_table */ }; gradient_type = g_type_register_static(SP_TYPE_PAINT_SERVER, "SPGradient", @@ -344,30 +367,28 @@ sp_gradient_get_type() /** * SPGradient vtable initialization. */ -static void -sp_gradient_class_init(SPGradientClass *klass) +void SPGradientImpl::classInit(SPGradientClass *klass) { SPObjectClass *sp_object_class = (SPObjectClass *) klass; gradient_parent_class = (SPPaintServerClass *)g_type_class_ref(SP_TYPE_PAINT_SERVER); - sp_object_class->build = sp_gradient_build; - sp_object_class->release = sp_gradient_release; - sp_object_class->set = sp_gradient_set; - sp_object_class->child_added = sp_gradient_child_added; - sp_object_class->remove_child = sp_gradient_remove_child; - sp_object_class->modified = sp_gradient_modified; - sp_object_class->write = sp_gradient_write; + sp_object_class->build = SPGradientImpl::build; + sp_object_class->release = SPGradientImpl::release; + sp_object_class->set = SPGradientImpl::setGradientAttr; + sp_object_class->child_added = SPGradientImpl::childAdded; + sp_object_class->remove_child = SPGradientImpl::removeChild; + sp_object_class->modified = SPGradientImpl::modified; + sp_object_class->write = SPGradientImpl::write; } /** * Callback for SPGradient object initialization. */ -static void -sp_gradient_init(SPGradient *gr) +void SPGradientImpl::init(SPGradient *gr) { gr->ref = new SPGradientReference(SP_OBJECT(gr)); - gr->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(gradient_ref_changed), gr)); + gr->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(SPGradientImpl::gradientRefChanged), gr)); /** \todo * Fixme: reprs being rearranged (e.g. via the XML editor) @@ -397,8 +418,7 @@ sp_gradient_init(SPGradient *gr) /** * Virtual build: set gradient attributes from its associated repr. */ -static void -sp_gradient_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) +void SPGradientImpl::build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) { SPGradient *gradient = SP_GRADIENT(object); @@ -425,8 +445,7 @@ sp_gradient_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *r /** * Virtual release of SPGradient members before destruction. */ -static void -sp_gradient_release(SPObject *object) +void SPGradientImpl::release(SPObject *object) { SPGradient *gradient = (SPGradient *) object; @@ -460,8 +479,7 @@ sp_gradient_release(SPObject *object) /** * Set gradient attribute to value. */ -static void -sp_gradient_set(SPObject *object, unsigned key, gchar const *value) +void SPGradientImpl::setGradientAttr(SPObject *object, unsigned key, gchar const *value) { SPGradient *gr = SP_GRADIENT(object); @@ -529,8 +547,7 @@ sp_gradient_set(SPObject *object, unsigned key, gchar const *value) /** * Gets called when the gradient is (re)attached to another gradient. */ -static void -gradient_ref_changed(SPObject *old_ref, SPObject *ref, SPGradient *gr) +void SPGradientImpl::gradientRefChanged(SPObject *old_ref, SPObject *ref, SPGradient *gr) { if (old_ref) { gr->modified_connection.disconnect(); @@ -538,31 +555,32 @@ gradient_ref_changed(SPObject *old_ref, SPObject *ref, SPGradient *gr) if ( SP_IS_GRADIENT(ref) && ref != gr ) { - gr->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&gradient_ref_modified), gr)); + gr->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&SPGradientImpl::gradientRefModified), gr)); } // Per SVG, all unset attributes must be inherited from linked gradient. // So, as we're now (re)linked, we assign linkee's values to this gradient if they are not yet set - // but without setting the _set flags. // FIXME: do the same for gradientTransform too - if (!gr->units_set) - gr->units = sp_gradient_get_units (gr); - if (!gr->spread_set) - gr->spread = sp_gradient_get_spread (gr); + if (!gr->units_set) { + gr->units = gr->fetchUnits(); + } + if (!gr->spread_set) { + gr->spread = gr->fetchSpread(); + } /// \todo Fixme: what should the flags (second) argument be? */ - gradient_ref_modified(ref, 0, gr); + gradientRefModified(ref, 0, gr); } /** * Callback for child_added event. */ -static void -sp_gradient_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref) +void SPGradientImpl::childAdded(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref) { SPGradient *gr = SP_GRADIENT(object); - sp_gradient_invalidate_vector(gr); + gr->invalidateVector(); if (((SPObjectClass *) gradient_parent_class)->child_added) (* ((SPObjectClass *) gradient_parent_class)->child_added)(object, child, ref); @@ -579,15 +597,15 @@ sp_gradient_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape:: /** * Callback for remove_child event. */ -static void -sp_gradient_remove_child(SPObject *object, Inkscape::XML::Node *child) +void SPGradientImpl::removeChild(SPObject *object, Inkscape::XML::Node *child) { SPGradient *gr = SP_GRADIENT(object); - sp_gradient_invalidate_vector(gr); + gr->invalidateVector(); - if (((SPObjectClass *) gradient_parent_class)->remove_child) + if (((SPObjectClass *) gradient_parent_class)->remove_child) { (* ((SPObjectClass *) gradient_parent_class)->remove_child)(object, child); + } gr->has_stops = FALSE; SPObject *ochild; @@ -605,17 +623,16 @@ sp_gradient_remove_child(SPObject *object, Inkscape::XML::Node *child) /** * Callback for modified event. */ -static void -sp_gradient_modified(SPObject *object, guint flags) +void SPGradientImpl::modified(SPObject *object, guint flags) { SPGradient *gr = SP_GRADIENT(object); if (flags & SP_OBJECT_CHILD_MODIFIED_FLAG) { - sp_gradient_invalidate_vector(gr); + gr->invalidateVector(); } if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - sp_gradient_ensure_colors(gr); + gr->ensureColors(); } if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; @@ -663,8 +680,7 @@ int SPGradient::getStopCount() const /** * Write gradient attributes to repr. */ -static Inkscape::XML::Node * -sp_gradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +Inkscape::XML::Node *SPGradientImpl::write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPGradient *gr = SP_GRADIENT(object); @@ -710,7 +726,7 @@ sp_gradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape:: if ((flags & SP_OBJECT_WRITE_ALL) || gr->spread_set) { /* FIXME: Ensure that gr->spread is the inherited value - * if !gr->spread_set. Not currently happening: see sp_gradient_modified. + * if !gr->spread_set. Not currently happening: see SPGradient::modified. */ switch (gr->spread) { case SP_GRADIENT_SPREAD_REFLECT: @@ -733,40 +749,34 @@ sp_gradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape:: * * \pre SP_IS_GRADIENT(gradient). */ -void -sp_gradient_ensure_vector(SPGradient *gradient) +void SPGradient::ensureVector() { - g_return_if_fail(gradient != NULL); - g_return_if_fail(SP_IS_GRADIENT(gradient)); - - if (!gradient->vector.built) { - sp_gradient_rebuild_vector(gradient); + if ( !vector.built ) { + rebuildVector(); } } /** * Set units property of gradient and emit modified. */ -void -sp_gradient_set_units(SPGradient *gr, SPGradientUnits units) +void SPGradient::setUnits(SPGradientUnits units) { - if (units != gr->units) { - gr->units = units; - gr->units_set = TRUE; - SP_OBJECT(gr)->requestModified(SP_OBJECT_MODIFIED_FLAG); + if (units != this->units) { + this->units = units; + units_set = TRUE; + requestModified(SP_OBJECT_MODIFIED_FLAG); } } /** * Set spread property of gradient and emit modified. */ -void -sp_gradient_set_spread(SPGradient *gr, SPGradientSpread spread) +void SPGradient::setSpread(SPGradientSpread spread) { - if (spread != gr->spread) { - gr->spread = spread; - gr->spread_set = TRUE; - SP_OBJECT(gr)->requestModified(SP_OBJECT_MODIFIED_FLAG); + if (spread != this->spread) { + this->spread = spread; + spread_set = TRUE; + requestModified(SP_OBJECT_MODIFIED_FLAG); } } @@ -817,16 +827,15 @@ chase_hrefs(SPGradient *const src, bool (*match)(SPGradient const *)) */ static bool has_stopsFN(SPGradient const *gr) { - return SP_GRADIENT_HAS_STOPS(gr); + return gr->hasStops(); } /** * True if gradient has spread set. */ -static bool -has_spread_set(SPGradient const *gr) +static bool has_spread_set(SPGradient const *gr) { - return gr->spread_set; + return gr->isSpreadSet(); } /** @@ -835,7 +844,7 @@ has_spread_set(SPGradient const *gr) static bool has_units_set(SPGradient const *gr) { - return gr->units_set; + return gr->isUnitsSet(); } @@ -854,12 +863,9 @@ SPGradient *SPGradient::getVector(bool force_vector) * * \pre SP_IS_GRADIENT(gradient). */ -SPGradientSpread -sp_gradient_get_spread(SPGradient *gradient) +SPGradientSpread SPGradient::fetchSpread() { - g_return_val_if_fail(SP_IS_GRADIENT(gradient), SP_GRADIENT_SPREAD_PAD); - - SPGradient const *src = chase_hrefs(gradient, has_spread_set); + SPGradient const *src = chase_hrefs(this, has_spread_set); return ( src ? src->spread : SP_GRADIENT_SPREAD_PAD ); // pad is the default @@ -870,12 +876,9 @@ sp_gradient_get_spread(SPGradient *gradient) * * \pre SP_IS_GRADIENT(gradient). */ -SPGradientUnits -sp_gradient_get_units(SPGradient *gradient) +SPGradientUnits SPGradient::fetchUnits() { - g_return_val_if_fail(SP_IS_GRADIENT(gradient), SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX); - - SPGradient const *src = chase_hrefs(gradient, has_units_set); + SPGradient const *src = chase_hrefs(this, has_units_set); return ( src ? src->units : SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ); // bbox is the default @@ -950,30 +953,28 @@ sp_gradient_repr_write_vector(SPGradient *gr) } -static void -gradient_ref_modified(SPObject */*href*/, guint /*flags*/, SPGradient *gradient) +void SPGradientImpl::gradientRefModified(SPObject */*href*/, guint /*flags*/, SPGradient *gradient) { - if (sp_gradient_invalidate_vector(gradient)) { + if ( gradient->invalidateVector() ) { SP_OBJECT(gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); - /* Conditional to avoid causing infinite loop if there's a cycle in the href chain. */ + // Conditional to avoid causing infinite loop if there's a cycle in the href chain. } } -/** Return true iff change made. */ -static bool -sp_gradient_invalidate_vector(SPGradient *gr) +/** Return true if change made. */ +bool SPGradient::invalidateVector() { bool ret = false; - if (gr->color != NULL) { - g_free(gr->color); - gr->color = NULL; + if (color != NULL) { + g_free(color); + color = NULL; ret = true; } - if (gr->vector.built) { - gr->vector.built = false; - gr->vector.stops.clear(); + if (vector.built) { + vector.built = false; + vector.stops.clear(); ret = true; } @@ -981,11 +982,10 @@ sp_gradient_invalidate_vector(SPGradient *gr) } /** Creates normalized color vector */ -static void -sp_gradient_rebuild_vector(SPGradient *gr) +void SPGradient::rebuildVector() { gint len = 0; - for ( SPObject *child = sp_object_first_child(SP_OBJECT(gr)) ; + for ( SPObject *child = sp_object_first_child(SP_OBJECT(this)) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_STOP(child)) { @@ -993,36 +993,36 @@ sp_gradient_rebuild_vector(SPGradient *gr) } } - gr->has_stops = (len != 0); + has_stops = (len != 0); - gr->vector.stops.clear(); + vector.stops.clear(); - SPGradient *ref = gr->ref->getObject(); - if ( !gr->has_stops && ref ) { + SPGradient *reffed = ref->getObject(); + if ( !hasStops() && reffed ) { /* Copy vector from referenced gradient */ - gr->vector.built = true; // Prevent infinite recursion. - sp_gradient_ensure_vector(ref); - if (!ref->vector.stops.empty()) { - gr->vector.built = ref->vector.built; - gr->vector.stops.assign(ref->vector.stops.begin(), ref->vector.stops.end()); + vector.built = true; // Prevent infinite recursion. + reffed->ensureVector(); + if (!reffed->vector.stops.empty()) { + vector.built = reffed->vector.built; + vector.stops.assign(reffed->vector.stops.begin(), reffed->vector.stops.end()); return; } } - for (SPObject *child = sp_object_first_child(SP_OBJECT(gr)) ; + for (SPObject *child = sp_object_first_child(SP_OBJECT(this)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_STOP(child)) { SPStop *stop = SP_STOP(child); SPGradientStop gstop; - if (gr->vector.stops.size() > 0) { + if (vector.stops.size() > 0) { // "Each gradient offset value is required to be equal to or greater than the // previous gradient stop's offset value. If a given gradient stop's offset // value is not equal to or greater than all previous offset values, then the // offset value is adjusted to be equal to the largest of all previous offset // values." - gstop.offset = MAX(stop->offset, gr->vector.stops.back().offset); + gstop.offset = MAX(stop->offset, vector.stops.back().offset); } else { gstop.offset = stop->offset; } @@ -1035,12 +1035,12 @@ sp_gradient_rebuild_vector(SPGradient *gr) gstop.color = sp_stop_get_color(stop); gstop.opacity = stop->opacity; - gr->vector.stops.push_back(gstop); + vector.stops.push_back(gstop); } } // Normalize per section 13.2.4 of SVG 1.1. - if (gr->vector.stops.size() == 0) { + if (vector.stops.size() == 0) { /* "If no stops are defined, then painting shall occur as if 'none' were specified as the * paint style." */ @@ -1049,72 +1049,71 @@ sp_gradient_rebuild_vector(SPGradient *gr) gstop.offset = 0.0; gstop.color.set( 0x00000000 ); gstop.opacity = 0.0; - gr->vector.stops.push_back(gstop); + vector.stops.push_back(gstop); } { SPGradientStop gstop; gstop.offset = 1.0; gstop.color.set( 0x00000000 ); gstop.opacity = 0.0; - gr->vector.stops.push_back(gstop); + vector.stops.push_back(gstop); } } else { /* "If one stop is defined, then paint with the solid color fill using the color defined * for that gradient stop." */ - if (gr->vector.stops.front().offset > 0.0) { + if (vector.stops.front().offset > 0.0) { // If the first one is not at 0, then insert a copy of the first at 0. SPGradientStop gstop; gstop.offset = 0.0; - gstop.color = gr->vector.stops.front().color; - gstop.opacity = gr->vector.stops.front().opacity; - gr->vector.stops.insert(gr->vector.stops.begin(), gstop); + gstop.color = vector.stops.front().color; + gstop.opacity = vector.stops.front().opacity; + vector.stops.insert(vector.stops.begin(), gstop); } - if (gr->vector.stops.back().offset < 1.0) { + if (vector.stops.back().offset < 1.0) { // If the last one is not at 1, then insert a copy of the last at 1. SPGradientStop gstop; gstop.offset = 1.0; - gstop.color = gr->vector.stops.back().color; - gstop.opacity = gr->vector.stops.back().opacity; - gr->vector.stops.push_back(gstop); + gstop.color = vector.stops.back().color; + gstop.opacity = vector.stops.back().opacity; + vector.stops.push_back(gstop); } } - gr->vector.built = true; + vector.built = true; } /** * The gradient's color array is newly created and set up from vector. */ -void -sp_gradient_ensure_colors(SPGradient *gr) +void SPGradient::ensureColors() { - if (!gr->vector.built) { - sp_gradient_rebuild_vector(gr); + if (!vector.built) { + rebuildVector(); } - g_return_if_fail(!gr->vector.stops.empty()); + g_return_if_fail(!vector.stops.empty()); /// \todo Where is the memory freed? - if (!gr->color) { - gr->color = g_new(guchar, 4 * NCOLORS); + if (!color) { + color = g_new(guchar, 4 * NCOLORS); } - // This assumes that gr->vector is a zero-order B-spline (box function) approximation of the "true" gradient. + // This assumes that vector is a zero-order B-spline (box function) approximation of the "true" gradient. // This means that the "true" gradient must be prefiltered using a zero order B-spline and then sampled. // Furthermore, the first element corresponds to offset="0" and the last element to offset="1". double remainder[4] = {0,0,0,0}; double remainder_for_end[4] = {0,0,0,0}; // Used at the end - switch(gr->spread) { + switch(spread) { case SP_GRADIENT_SPREAD_PAD: - remainder[0] = 0.5*gr->vector.stops[0].color.v.c[0]; // Half of the first cell uses the color of the first stop - remainder[1] = 0.5*gr->vector.stops[0].color.v.c[1]; - remainder[2] = 0.5*gr->vector.stops[0].color.v.c[2]; - remainder[3] = 0.5*gr->vector.stops[0].opacity; - remainder_for_end[0] = 0.5*gr->vector.stops[gr->vector.stops.size() - 1].color.v.c[0]; // Half of the first cell uses the color of the last stop - remainder_for_end[1] = 0.5*gr->vector.stops[gr->vector.stops.size() - 1].color.v.c[1]; - remainder_for_end[2] = 0.5*gr->vector.stops[gr->vector.stops.size() - 1].color.v.c[2]; - remainder_for_end[3] = 0.5*gr->vector.stops[gr->vector.stops.size() - 1].opacity; + remainder[0] = 0.5*vector.stops[0].color.v.c[0]; // Half of the first cell uses the color of the first stop + remainder[1] = 0.5*vector.stops[0].color.v.c[1]; + remainder[2] = 0.5*vector.stops[0].color.v.c[2]; + remainder[3] = 0.5*vector.stops[0].opacity; + remainder_for_end[0] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[0]; // Half of the first cell uses the color of the last stop + remainder_for_end[1] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[1]; + remainder_for_end[2] = 0.5*vector.stops[vector.stops.size() - 1].color.v.c[2]; + remainder_for_end[3] = 0.5*vector.stops[vector.stops.size() - 1].opacity; break; case SP_GRADIENT_SPREAD_REFLECT: case SP_GRADIENT_SPREAD_REPEAT: @@ -1123,17 +1122,17 @@ sp_gradient_ensure_colors(SPGradient *gr) default: g_error("Spread type not supported!"); }; - for (unsigned int i = 0; i < gr->vector.stops.size() - 1; i++) { - double r0 = gr->vector.stops[i].color.v.c[0]; - double g0 = gr->vector.stops[i].color.v.c[1]; - double b0 = gr->vector.stops[i].color.v.c[2]; - double a0 = gr->vector.stops[i].opacity; - double r1 = gr->vector.stops[i+1].color.v.c[0]; - double g1 = gr->vector.stops[i+1].color.v.c[1]; - double b1 = gr->vector.stops[i+1].color.v.c[2]; - double a1 = gr->vector.stops[i+1].opacity; - double o0 = gr->vector.stops[i].offset * (NCOLORS-1); - double o1 = gr->vector.stops[i + 1].offset * (NCOLORS-1); + for (unsigned int i = 0; i < vector.stops.size() - 1; i++) { + double r0 = vector.stops[i].color.v.c[0]; + double g0 = vector.stops[i].color.v.c[1]; + double b0 = vector.stops[i].color.v.c[2]; + double a0 = vector.stops[i].opacity; + double r1 = vector.stops[i+1].color.v.c[0]; + double g1 = vector.stops[i+1].color.v.c[1]; + double b1 = vector.stops[i+1].color.v.c[2]; + double a1 = vector.stops[i+1].opacity; + double o0 = vector.stops[i].offset * (NCOLORS-1); + double o1 = vector.stops[i + 1].offset * (NCOLORS-1); unsigned int ob = (unsigned int) floor(o0+.5); // These are the first and last element that might be affected by this interval. unsigned int oe = (unsigned int) floor(o1+.5); // These need to be computed the same to ensure that ob will be covered by the next interval if oe==ob @@ -1156,10 +1155,10 @@ sp_gradient_ensure_colors(SPGradient *gr) double df = 1. / (o1-o0); for (unsigned int j = ob+1; j < oe; j++) { f += df; - gr->color[4 * j + 0] = (unsigned char) floor(255*(r0 + f*(r1-r0)) + .5); - gr->color[4 * j + 1] = (unsigned char) floor(255*(g0 + f*(g1-g0)) + .5); - gr->color[4 * j + 2] = (unsigned char) floor(255*(b0 + f*(b1-b0)) + .5); - gr->color[4 * j + 3] = (unsigned char) floor(255*(a0 + f*(a1-a0)) + .5); + color[4 * j + 0] = (unsigned char) floor(255*(r0 + f*(r1-r0)) + .5); + color[4 * j + 1] = (unsigned char) floor(255*(g0 + f*(g1-g0)) + .5); + color[4 * j + 2] = (unsigned char) floor(255*(b0 + f*(b1-b0)) + .5); + color[4 * j + 3] = (unsigned char) floor(255*(a0 + f*(a1-a0)) + .5); } // Now handle the beginning @@ -1171,13 +1170,13 @@ sp_gradient_ensure_colors(SPGradient *gr) // = (ob+.5-o0)*(c0+(ob+.5-o0)*df*(c1-c0)/2) double dt = ob+.5-o0; f = 0.5*dt*df; - if (ob==0 && gr->spread==SP_GRADIENT_SPREAD_REFLECT) { + if (ob==0 && spread==SP_GRADIENT_SPREAD_REFLECT) { // The first half of the first cell is just a mirror image of the second half, so simply multiply it by 2. - gr->color[4 * ob + 0] = (unsigned char) floor(2*255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5); - gr->color[4 * ob + 1] = (unsigned char) floor(2*255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5); - gr->color[4 * ob + 2] = (unsigned char) floor(2*255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5); - gr->color[4 * ob + 3] = (unsigned char) floor(2*255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5); - } else if (ob==0 && gr->spread==SP_GRADIENT_SPREAD_REPEAT) { + color[4 * ob + 0] = (unsigned char) floor(2*255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5); + color[4 * ob + 1] = (unsigned char) floor(2*255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5); + color[4 * ob + 2] = (unsigned char) floor(2*255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5); + color[4 * ob + 3] = (unsigned char) floor(2*255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5); + } else if (ob==0 && spread==SP_GRADIENT_SPREAD_REPEAT) { // The first cell is the same as the last cell, so save whatever is in the second half here and deal with the rest later. remainder_for_end[0] = remainder[0] + dt*(r0 + f*(r1-r0)); remainder_for_end[1] = remainder[1] + dt*(g0 + f*(g1-g0)); @@ -1185,10 +1184,10 @@ sp_gradient_ensure_colors(SPGradient *gr) remainder_for_end[3] = remainder[3] + dt*(a0 + f*(a1-a0)); } else { // The first half of the cell was already in remainder. - gr->color[4 * ob + 0] = (unsigned char) floor(255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5); - gr->color[4 * ob + 1] = (unsigned char) floor(255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5); - gr->color[4 * ob + 2] = (unsigned char) floor(255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5); - gr->color[4 * ob + 3] = (unsigned char) floor(255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5); + color[4 * ob + 0] = (unsigned char) floor(255*(remainder[0] + dt*(r0 + f*(r1-r0))) + .5); + color[4 * ob + 1] = (unsigned char) floor(255*(remainder[1] + dt*(g0 + f*(g1-g0))) + .5); + color[4 * ob + 2] = (unsigned char) floor(255*(remainder[2] + dt*(b0 + f*(b1-b0))) + .5); + color[4 * ob + 3] = (unsigned char) floor(255*(remainder[3] + dt*(a0 + f*(a1-a0))) + .5); } // Now handle the end, which should end up in remainder @@ -1204,26 +1203,26 @@ sp_gradient_ensure_colors(SPGradient *gr) remainder[3] = dt*(a0 + f*(a1-a0)); } } - switch(gr->spread) { + switch(spread) { case SP_GRADIENT_SPREAD_PAD: - gr->color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5); - gr->color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5); - gr->color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5); - gr->color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5); + color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5); + color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5); + color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5); + color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5); break; case SP_GRADIENT_SPREAD_REFLECT: // The second half is the same as the first half, so multiply by 2. - gr->color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(2*255*remainder[0] + .5); - gr->color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(2*255*remainder[1] + .5); - gr->color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(2*255*remainder[2] + .5); - gr->color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(2*255*remainder[3] + .5); + color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(2*255*remainder[0] + .5); + color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(2*255*remainder[1] + .5); + color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(2*255*remainder[2] + .5); + color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(2*255*remainder[3] + .5); break; case SP_GRADIENT_SPREAD_REPEAT: // The second half is the same as the second half of the first cell (which was saved in remainder_for_end). - gr->color[0] = gr->color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5); - gr->color[1] = gr->color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5); - gr->color[2] = gr->color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5); - gr->color[3] = gr->color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5); + color[0] = color[4 * (NCOLORS-1) + 0] = (unsigned char) floor(255*(remainder[0]+remainder_for_end[0]) + .5); + color[1] = color[4 * (NCOLORS-1) + 1] = (unsigned char) floor(255*(remainder[1]+remainder_for_end[1]) + .5); + color[2] = color[4 * (NCOLORS-1) + 2] = (unsigned char) floor(255*(remainder[2]+remainder_for_end[2]) + .5); + color[3] = color[4 * (NCOLORS-1) + 3] = (unsigned char) floor(255*(remainder[3]+remainder_for_end[3]) + .5); break; } } @@ -1250,7 +1249,7 @@ sp_gradient_render_vector_line_rgba(SPGradient *const gradient, guchar *buf, g_return_if_fail(span > 0); if (!gradient->color) { - sp_gradient_ensure_colors(gradient); + gradient->ensureColors(); } gint idx = (pos * 1024 << 8) / span; @@ -1359,7 +1358,7 @@ sp_gradient_render_vector_block_rgb(SPGradient *gradient, guchar *buf, Geom::Matrix sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox) { - if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { return ( Geom::Scale(bbox.dimensions()) * Geom::Translate(bbox.min()) * Geom::Matrix(ctm) ); @@ -1371,7 +1370,7 @@ sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom:: Geom::Matrix sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox) { - if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { + if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { return ( gr->gradientTransform * Geom::Scale(bbox.dimensions()) * Geom::Translate(bbox.min()) @@ -1386,7 +1385,7 @@ sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox, Geom::Matrix const &gs2d) { gr->gradientTransform = gs2d * ctm.inverse(); - if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) { + if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) { gr->gradientTransform = ( gr->gradientTransform * Geom::Translate(-bbox.min()) * Geom::Scale(bbox.dimensions()).inverse() ); @@ -1408,6 +1407,11 @@ struct SPLGPainter { SPLinearGradient *lg; NRLGradientRenderer lgr; + + static SPPainter * painter_new(SPPaintServer *ps, + Geom::Matrix const &full_transform, + Geom::Matrix const &parent_transform, + NRRect const *bbox); }; static void sp_lineargradient_class_init(SPLinearGradientClass *klass); @@ -1420,10 +1424,6 @@ static void sp_lineargradient_set(SPObject *object, unsigned key, gchar const *v static Inkscape::XML::Node *sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static SPPainter *sp_lineargradient_painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &parent_transform, - NRRect const *bbox); static void sp_lineargradient_painter_free(SPPaintServer *ps, SPPainter *painter); static void sp_lg_fill(SPPainter *painter, NRPixBlock *pb); @@ -1467,7 +1467,7 @@ static void sp_lineargradient_class_init(SPLinearGradientClass *klass) sp_object_class->set = sp_lineargradient_set; sp_object_class->write = sp_lineargradient_write; - ps_class->painter_new = sp_lineargradient_painter_new; + ps_class->painter_new = SPLGPainter::painter_new; ps_class->painter_free = sp_lineargradient_painter_free; } @@ -1573,16 +1573,17 @@ sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks * \todo (point 1 above) fixme: I do not know how to deal with start > 0 * and end < 1. */ -static SPPainter * -sp_lineargradient_painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &/*parent_transform*/, - NRRect const *bbox) +SPPainter * SPLGPainter::painter_new(SPPaintServer *ps, + Geom::Matrix const &full_transform, + Geom::Matrix const &/*parent_transform*/, + NRRect const *bbox) { SPLinearGradient *lg = SP_LINEARGRADIENT(ps); SPGradient *gr = SP_GRADIENT(ps); - if (!gr->color) sp_gradient_ensure_colors(gr); + if (!gr->color) { + gr->ensureColors(); + } SPLGPainter *lgp = g_new(SPLGPainter, 1); @@ -1623,7 +1624,7 @@ sp_lineargradient_painter_new(SPPaintServer *ps, } // TODO: remove color2px_nr after converting to 2geom NR::Matrix color2px_nr = from_2geom(color2px); - nr_lgradient_renderer_setup(&lgp->lgr, gr->color, sp_gradient_get_spread(gr), &color2px_nr, + nr_lgradient_renderer_setup(&lgp->lgr, gr->color, gr->fetchSpread(), &color2px_nr, lg->x1.computed, lg->y1.computed, lg->x2.computed, lg->y2.computed); @@ -1665,7 +1666,7 @@ sp_lg_fill(SPPainter *painter, NRPixBlock *pb) SPLGPainter *lgp = (SPLGPainter *) painter; if (lgp->lg->color == NULL) { - sp_gradient_ensure_colors (lgp->lg); + lgp->lg->ensureColors(); lgp->lgr.vector = lgp->lg->color; } @@ -1683,6 +1684,11 @@ struct SPRGPainter { SPPainter painter; SPRadialGradient *rg; NRRGradientRenderer rgr; + + static SPPainter *painter_new(SPPaintServer *ps, + Geom::Matrix const &full_transform, + Geom::Matrix const &parent_transform, + NRRect const *bbox); }; static void sp_radialgradient_class_init(SPRadialGradientClass *klass); @@ -1694,11 +1700,6 @@ static void sp_radialgradient_build(SPObject *object, static void sp_radialgradient_set(SPObject *object, unsigned key, gchar const *value); static Inkscape::XML::Node *sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); - -static SPPainter *sp_radialgradient_painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &parent_transform, - NRRect const *bbox); static void sp_radialgradient_painter_free(SPPaintServer *ps, SPPainter *painter); static void sp_rg_fill(SPPainter *painter, NRPixBlock *pb); @@ -1742,7 +1743,7 @@ static void sp_radialgradient_class_init(SPRadialGradientClass *klass) sp_object_class->set = sp_radialgradient_set; sp_object_class->write = sp_radialgradient_write; - ps_class->painter_new = sp_radialgradient_painter_new; + ps_class->painter_new = SPRGPainter::painter_new; ps_class->painter_free = sp_radialgradient_painter_free; } @@ -1856,16 +1857,17 @@ sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks /** * Create radial gradient context. */ -static SPPainter * -sp_radialgradient_painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &/*parent_transform*/, - NRRect const *bbox) +SPPainter *SPRGPainter::painter_new(SPPaintServer *ps, + Geom::Matrix const &full_transform, + Geom::Matrix const &/*parent_transform*/, + NRRect const *bbox) { SPRadialGradient *rg = SP_RADIALGRADIENT(ps); SPGradient *gr = SP_GRADIENT(ps); - if (!gr->color) sp_gradient_ensure_colors(gr); + if (!gr->color) { + gr->ensureColors(); + } SPRGPainter *rgp = g_new(SPRGPainter, 1); @@ -1899,7 +1901,7 @@ sp_radialgradient_painter_new(SPPaintServer *ps, } // TODO: remove gs2px_nr after converting to 2geom NR::Matrix gs2px_nr = from_2geom(gs2px); - nr_rgradient_renderer_setup(&rgp->rgr, gr->color, sp_gradient_get_spread(gr), + nr_rgradient_renderer_setup(&rgp->rgr, gr->color, gr->fetchSpread(), &gs2px_nr, rg->cx.computed, rg->cy.computed, rg->fx.computed, rg->fy.computed, @@ -1943,7 +1945,7 @@ sp_rg_fill(SPPainter *painter, NRPixBlock *pb) SPRGPainter *rgp = (SPRGPainter *) painter; if (rgp->rg->color == NULL) { - sp_gradient_ensure_colors (rgp->rg); + rgp->rg->ensureColors(); rgp->rgr.vector = rgp->rg->color; } diff --git a/src/sp-gradient.h b/src/sp-gradient.h index e7488673d..7e6afe052 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -29,14 +29,12 @@ struct SPGradientReference; -#define SP_TYPE_GRADIENT (sp_gradient_get_type()) +#define SP_TYPE_GRADIENT (SPGradient::getType()) #define SP_GRADIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_GRADIENT, SPGradient)) #define SP_GRADIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_GRADIENT, SPGradientClass)) #define SP_IS_GRADIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_GRADIENT)) #define SP_IS_GRADIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_GRADIENT)) -GType sp_gradient_get_type(); - typedef enum { SP_GRADIENT_TYPE_UNKNOWN, SP_GRADIENT_TYPE_LINEAR, @@ -78,20 +76,24 @@ struct SPGradient : public SPPaintServer { /** State in Inkscape gradient system */ guint state : 2; +private: /** gradientUnits attribute */ SPGradientUnits units; guint units_set : 1; +public: /** gradientTransform attribute */ Geom::Matrix gradientTransform; guint gradientTransform_set : 1; +private: /** spreadMethod attribute */ SPGradientSpread spread; guint spread_set : 1; /** Gradient stops */ guint has_stops : 1; +public: /** Composed vector */ SPGradientVector vector; @@ -101,10 +103,20 @@ struct SPGradient : public SPPaintServer { sigc::connection modified_connection; + bool hasStops() const; SPStop* getFirstStop(); int getStopCount() const; + + bool isUnitsSet() const; + SPGradientUnits getUnits() const; + void setUnits(SPGradientUnits units); + + + bool isSpreadSet() const; + SPGradientSpread getSpread() const; + /** * Returns private vector of given gradient (the gradient at the end of the href chain which has * stops), optionally normalizing it. @@ -113,6 +125,30 @@ struct SPGradient : public SPPaintServer { * \pre There exists a gradient in the chain that has stops. */ SPGradient *getVector(bool force_private = false); + + static GType getType(); + + /** Forces vector to be built, if not present (i.e. changed) */ + void ensureVector(); + + /** Ensures that color array is populated */ + void ensureColors(); + + /** + * Set spread property of gradient and emit modified. + */ + void setSpread(SPGradientSpread spread); + + SPGradientSpread fetchSpread(); + SPGradientUnits fetchUnits(); + +private: + bool invalidateVector(); + void rebuildVector(); + + friend class SPGradientImpl; + friend class SPLGPainter; + friend class SPRGPainter; }; /** diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp index 258323a93..5858f9a0e 100644 --- a/src/sp-paint-server.cpp +++ b/src/sp-paint-server.cpp @@ -160,12 +160,7 @@ bool SPPaintServer::isSwatch() const bool swatch = false; if (SP_IS_GRADIENT(this)) { SPGradient *grad = SP_GRADIENT(this); - if ( SP_GRADIENT_HAS_STOPS(grad) ) { - gchar const * attr = repr->attribute("osb:paint"); - if (attr && !strcmp(attr, "solid")) { - swatch = true; - } - } + swatch = grad->hasStops() && repr->attribute("osb:paint"); } return swatch; } @@ -175,7 +170,7 @@ bool SPPaintServer::isSolid() const bool solid = false; if (SP_IS_GRADIENT(this)) { SPGradient *grad = SP_GRADIENT(this); - if ( SP_GRADIENT_HAS_STOPS(grad) && (grad->getStopCount() == 0) ) { + if ( grad->hasStops() && (grad->getStopCount() == 0) ) { gchar const * attr = repr->attribute("osb:paint"); if (attr && !strcmp(attr, "solid")) { solid = true; diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 13299b5a4..904d0cb23 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -837,20 +837,24 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, // Normalize pos to 0..1, taking into accound gradient spread: double pos_e = pos; - if (gradient->spread == SP_GRADIENT_SPREAD_PAD) { - if (pos > 1) + if (gradient->getSpread() == SP_GRADIENT_SPREAD_PAD) { + if (pos > 1) { pos_e = 1; - if (pos < 0) + } + if (pos < 0) { pos_e = 0; - } else if (gradient->spread == SP_GRADIENT_SPREAD_REPEAT) { - if (pos > 1 || pos < 0) + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REPEAT) { + if (pos > 1 || pos < 0) { pos_e = pos - floor(pos); - } else if (gradient->spread == SP_GRADIENT_SPREAD_REFLECT) { + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REFLECT) { if (pos > 1 || pos < 0) { bool odd = ((int)(floor(pos)) % 2 == 1); pos_e = pos - floor(pos); - if (odd) + if (odd) { pos_e = 1 - pos_e; + } } } diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index b0d027ae9..90e9e5f7b 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -182,12 +182,12 @@ void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer us for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( targetName == grad->getId() ) { - grad->repr->setAttribute("osb:paint", "solid"); + grad->repr->setAttribute("osb:paint", "solid"); // TODO make conditional sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop")); - handleGradientsChange(doc); // work-around for signal not being emmitted + handleGradientsChange(doc); // work-around for signal not being emitted break; } } @@ -310,7 +310,7 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g gint index = 0; for (const GSList *curr = gradients; curr; curr = curr->next) { SPGradient* grad = SP_GRADIENT(curr->data); - if (SP_GRADIENT_HAS_STOPS(grad) && !grad->isSwatch()) { + if ( grad->hasStops() && !grad->isSwatch() ) { //gl = g_slist_prepend(gl, curr->data); processed = true; GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); @@ -809,7 +809,7 @@ static void recalcSwatchContents(SPDocument* doc, for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) { SPGradient* grad = *it; - sp_gradient_ensure_vector( grad ); + grad->ensureVector(); SPGradientStop first = grad->vector.stops[0]; SPColor color = first.color; guint32 together = color.toRGBA32(first.opacity); @@ -938,11 +938,12 @@ void SwatchesPanel::_updateFromSelection() if ( SP_IS_GRADIENT(server) ) { SPGradient* target = 0; SPGradient* grad = SP_GRADIENT(server); - if (grad->repr->attribute("osb:paint")) { + + if ( grad->isSwatch() ) { target = grad; } else if ( grad->ref ) { SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->repr->attribute("osb:paint") ) { + if ( tmp && tmp->isSwatch() ) { target = tmp; } } @@ -969,11 +970,11 @@ void SwatchesPanel::_updateFromSelection() if ( SP_IS_GRADIENT(server) ) { SPGradient* target = 0; SPGradient* grad = SP_GRADIENT(server); - if (grad->repr->attribute("osb:paint")) { + if ( grad->isSwatch() ) { target = grad; } else if ( grad->ref ) { SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->repr->attribute("osb:paint") ) { + if ( tmp && tmp->isSwatch() ) { target = tmp; } } diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 15d8b6cc2..5a7256d83 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -268,15 +268,15 @@ void FillNStroke::performUpdate() psel->setGradientLinear( vector ); SPLinearGradient *lg = SP_LINEARGRADIENT(server); - psel->setGradientProperties( SP_GRADIENT_UNITS(lg), - SP_GRADIENT_SPREAD(lg) ); + psel->setGradientProperties( lg->getUnits(), + lg->getSpread() ); } else if (SP_IS_RADIALGRADIENT(server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); psel->setGradientRadial( vector ); SPRadialGradient *rg = SP_RADIALGRADIENT(server); - psel->setGradientProperties( SP_GRADIENT_UNITS(rg), - SP_GRADIENT_SPREAD(rg) ); + psel->setGradientProperties( rg->getUnits(), + rg->getSpread() ); } else if (SP_IS_PATTERN(server)) { SPPattern *pat = pattern_getroot(SP_PATTERN(server)); psel->updatePatternList( pat ); diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 9aa72164b..77defa5c9 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -262,7 +262,7 @@ void SPGradientSelector::setVector(SPDocument *doc, SPGradient *vector) g_return_if_fail(!vector || SP_IS_GRADIENT(vector)); g_return_if_fail(!vector || (SP_OBJECT_DOCUMENT(vector) == doc)); - if (vector && !SP_GRADIENT_HAS_STOPS(vector)) { + if (vector && !vector->hasStops()) { return; } diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index 077e038e7..1d3187985 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -175,7 +175,7 @@ GtkWidget *gr_vector_list(SPDesktop *desktop, bool selection_empty, SPGradient * const GSList *gradients = sp_document_get_resource_list (document, "gradient"); for (const GSList *i = gradients; i != NULL; i = i->next) { SPGradient *grad = SP_GRADIENT(i->data); - if (SP_GRADIENT_HAS_STOPS(grad) && !grad->isSolid()) { + if ( grad->hasStops() && !grad->isSolid() ) { gl = g_slist_prepend (gl, i->data); } } @@ -316,7 +316,7 @@ void gr_read_selection( Inkscape::Selection *selection, SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); if (SP_IS_GRADIENT(server)) { SPGradient *gradient = SP_GRADIENT(server)->getVector(); - SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server)); + SPGradientSpread spread = SP_GRADIENT(server)->fetchSpread(); if (gradient && gradient->isSolid()) { gradient = 0; @@ -342,7 +342,7 @@ void gr_read_selection( Inkscape::Selection *selection, SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); if (SP_IS_GRADIENT(server)) { SPGradient *gradient = SP_GRADIENT(server)->getVector(); - SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server)); + SPGradientSpread spread = SP_GRADIENT(server)->fetchSpread(); if (gradient && gradient->isSolid()) { gradient = 0; diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 7bfe27310..454c12001 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -181,7 +181,7 @@ void sp_gradient_vector_selector_set_gradient(SPGradientVectorSelector *gvs, SPD g_return_if_fail(!gr || (doc != NULL)); g_return_if_fail(!gr || SP_IS_GRADIENT(gr)); g_return_if_fail(!gr || (SP_OBJECT_DOCUMENT(gr) == doc)); - g_return_if_fail(!gr || SP_GRADIENT_HAS_STOPS(gr)); + g_return_if_fail(!gr || gr->hasStops()); if (doc != gvs->doc) { /* Disconnect signals */ @@ -252,7 +252,7 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) const GSList *gradients = sp_document_get_resource_list(SP_OBJECT_DOCUMENT(gvs->gr), "gradient"); for (const GSList *curr = gradients; curr; curr = curr->next) { SPGradient* grad = SP_GRADIENT(curr->data); - if (SP_GRADIENT_HAS_STOPS(grad) && (grad->isSwatch() == gvs->swatched)) { + if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) { gl = g_slist_prepend(gl, curr->data); } } @@ -535,7 +535,7 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_ GtkWidget *m = gtk_menu_new(); gtk_widget_show(m); GSList *sl = NULL; - if (gradient->has_stops) { + if ( gradient->hasStops() ) { for ( SPObject *ochild = sp_object_first_child(SP_OBJECT(gradient)) ; ochild != NULL ; ochild = SP_OBJECT_NEXT(ochild) ) { if (SP_IS_STOP(ochild)) { sl = g_slist_append(sl, ochild); @@ -1017,7 +1017,7 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien if (gradient) { gtk_widget_set_sensitive(widget, TRUE); - sp_gradient_ensure_vector(gradient); + gradient->ensureVector(); GtkOptionMenu *mnu = static_cast(g_object_get_data(G_OBJECT(widget), "stopmenu")); SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")); @@ -1140,7 +1140,7 @@ static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GtkObject *o sp_gradient_vector_widget_load_gradient(GTK_WIDGET(object), ngr); } - sp_gradient_ensure_vector(ngr); + ngr->ensureVector(); GtkOptionMenu *mnu = static_cast(g_object_get_data(G_OBJECT(object), "stopmenu")); SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")); @@ -1175,7 +1175,7 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o sp_gradient_vector_widget_load_gradient(GTK_WIDGET(object), ngr); } - sp_gradient_ensure_vector(ngr); + ngr->ensureVector(); /* Set start parameters */ /* We rely on normalized vector, i.e. stops HAVE to exist */ diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index d3092669a..8759854a0 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -538,8 +538,8 @@ void SPPaintSelector::pushAttrsToGradient( SPGradient *gr ) const SPGradientUnits units = SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX; SPGradientSpread spread = SP_GRADIENT_SPREAD_PAD; getGradientProperties( units, spread ); - sp_gradient_set_units(gr, units); - sp_gradient_set_spread(gr, spread); + gr->setUnits(units); + gr->setSpread(spread); SP_OBJECT(gr)->updateRepr(); } diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index a6f5133b7..ce0f8a810 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -116,7 +116,7 @@ void SwatchSelector::_changedCb(SPColorSelector */*csel*/, void *data) // TODO replace with proper - sp_gradient_vector_widget_load_gradient(GTK_WIDGET(swsel->_gsel), ngr); } - sp_gradient_ensure_vector(ngr); + ngr->ensureVector(); SPStop* stop = ngr->getFirstStop(); -- cgit v1.2.3 From 62dc9985efff58d201f5272baebfcbeed8de8c82 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 29 Jun 2010 23:50:45 +0200 Subject: pdf/ps/eps+latex: output tex code to ".pdf_tex" instead of to ".tex" Fixed bugs: - https://launchpad.net/bugs/595312 (bzr r9547) --- src/extension/internal/cairo-ps-out.cpp | 14 ++------------ src/extension/internal/cairo-renderer-pdf-out.cpp | 7 +------ src/extension/internal/latex-text-renderer.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp index 61760e9d9..16adebac3 100644 --- a/src/extension/internal/cairo-ps-out.cpp +++ b/src/extension/internal/cairo-ps-out.cpp @@ -195,12 +195,7 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con // Create LaTeX file (if requested) if (new_textToLaTeX) { - gchar * tex_filename; - //strip filename of ".ps", do not add ".tex" here. - gsize n = g_str_has_suffix(filename, ".ps") ? strlen(filename)-3 : strlen(filename); - tex_filename = g_strndup(filename, n); - ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage, false); - g_free(tex_filename); + ret = latex_render_document_text_to_file(doc, filename, new_exportId, new_areaDrawing, new_areaPage, false); if (!ret) throw Inkscape::Extension::Output::save_failed(); @@ -283,12 +278,7 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co // Create LaTeX file (if requested) if (new_textToLaTeX) { - gchar * tex_filename; - //strip filename of ".eps", do not add ".tex" here. - gsize n = g_str_has_suffix(filename, ".eps") ? strlen(filename)-4 : strlen(filename); - tex_filename = g_strndup(filename, n); - ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage, false); - g_free(tex_filename); + ret = latex_render_document_text_to_file(doc, filename, new_exportId, new_areaDrawing, new_areaPage, false); if (!ret) throw Inkscape::Extension::Output::save_failed(); diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index 808590e04..e8eff20b7 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -213,12 +213,7 @@ CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, // Create LaTeX file (if requested) if (new_textToLaTeX) { - gchar * tex_filename; - //strip filename of ".pdf", do not add ".tex" here. - gsize n = g_str_has_suffix(filename, ".pdf") ? strlen(filename)-4 : strlen(filename); - tex_filename = g_strndup(filename, n); - ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_exportDrawing, new_exportCanvas, true); - g_free(tex_filename); + ret = latex_render_document_text_to_file(doc, filename, new_exportId, new_exportDrawing, new_exportCanvas, true); if (!ret) throw Inkscape::Extension::Output::save_failed(); diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index bebc21f2f..0d98f6b9c 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -51,7 +51,7 @@ namespace Internal { /** * This method is called by the PDF, EPS and PS output extensions. - * @param filename This should be the filename without extension to which the tex code should be written. Output goes to .tex. + * @param filename This should be the filename without '_tex' extension to which the tex code should be written. Output goes to _tex, note the underscore instead of period. */ bool latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, @@ -132,7 +132,7 @@ LaTeXTextRenderer::setTargetFile(gchar const *filename) { _filename = g_path_get_basename(filename); - gchar *filename_ext = g_strdup_printf("%s.tex", filename); + gchar *filename_ext = g_strdup_printf("%s_tex", filename); Inkscape::IO::dump_fopen_call(filename_ext, "K"); FILE *osf = Inkscape::IO::fopen_utf8name(filename_ext, "w+"); if (!osf) { @@ -176,12 +176,12 @@ LaTeXTextRenderer::setTargetFile(gchar const *filename) { static char const preamble[] = "%% To include the image in your LaTeX document, write\n" -"%% \\input{.tex}\n" +"%% \\input{.pdf_tex}\n" "%% instead of\n" "%% \\includegraphics{.pdf}\n" "%% To scale the image, write\n" "%% \\def{\\svgwidth}{}\n" -"%% \\input{.tex}\n" +"%% \\input{.pdf_tex}\n" "%% instead of\n" "%% \\includegraphics[width=]{.pdf}\n" "%%\n" @@ -190,7 +190,7 @@ static char const preamble[] = "%% installed) using\n" "%% \\usepackage{import}\n" "%% in the preamble, and then including the image with\n" -"%% \\import{}{.tex}\n" +"%% \\import{}{.pdf_tex}\n" "%% Alternatively, one can specify\n" "%% \\graphicspath{{/}}\n" "%% \n" -- cgit v1.2.3 From 4bee400f3d7b314c3930b450e6715dfe48a33412 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 1 Jul 2010 23:21:58 +0200 Subject: fix Launchpad bug 593023: crash in constrained snap due to not calling setup() before snapping Fixed bugs: - https://launchpad.net/bugs/593023 (bzr r9550) --- src/gradient-drag.cpp | 3 ++- src/object-snapper.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 227a5f003..c9a982e42 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -809,9 +809,10 @@ gr_knot_moved_midpoint_handler(SPKnot */*knot*/, Geom::Point const &ppointer, gu } else { p = snap_vector_midpoint (p, low_lim, high_lim, 0); if (!(state & GDK_SHIFT_MASK)) { + Inkscape::Snapper::ConstraintLine cl(low_lim, high_lim - low_lim); SPDesktop *desktop = dragger->parent->desktop; SnapManager &m = desktop->namedview->snap_manager; - Inkscape::Snapper::ConstraintLine cl(low_lim, high_lim - low_lim); + m.setup(desktop); m.constrainedSnapReturnByRef(p, Inkscape::SNAPSOURCE_OTHER_HANDLE, cl); } } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index bced0ac44..983a6fede 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -91,6 +91,12 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, return; } + if (_snapmanager->getDesktop() == NULL) { + g_warning("desktop == NULL, so we cannot snap; please inform the developpers of this bug"); + // Apparently the etup() method from the SnapManager class hasn't been called before trying to snap. + } + + if (first_point) { _candidates->clear(); } @@ -99,7 +105,6 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, bbox_to_snap_incl.expandBy(getSnapperTolerance()); // see? for (SPObject* o = sp_object_first_child(parent); o != NULL; o = SP_OBJECT_NEXT(o)) { - g_assert(_snapmanager->getDesktop() != NULL); if (SP_IS_ITEM(o) && !(_snapmanager->getDesktop()->itemIsHidden(SP_ITEM(o)) && !clip_or_mask)) { // Snapping to items in a locked layer is allowed // Don't snap to hidden objects, unless they're a clipped path or a mask -- cgit v1.2.3 From 124ecce5e258ae4922638f30d117e98d09060da8 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Jul 2010 00:40:46 -0700 Subject: Leave swatches when doing a vacuum pass. Fixes bug #594445. Fixed bugs: - https://launchpad.net/bugs/594445 (bzr r9551) --- src/sp-object.cpp | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 420c7b4a6..3b0056b41 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -539,29 +539,31 @@ SPObject::setLabel(gchar const *label) { /** Queues the object for orphan collection */ -void -SPObject::requestOrphanCollection() { +void SPObject::requestOrphanCollection() { g_return_if_fail(document != NULL); // do not remove style or script elements (Bug #276244) - if (SP_IS_STYLE_ELEM(this)) - return; - if (SP_IS_SCRIPT(this)) - return; - - document->queueForOrphanCollection(this); + if (SP_IS_STYLE_ELEM(this)) { + // leave it + } else if (SP_IS_SCRIPT(this)) { + // leave it + } else if (SP_IS_PAINT_SERVER(this) && static_cast(this)->isSwatch() ) { + // leave it + } else { + document->queueForOrphanCollection(this); - /** \todo - * This is a temporary hack added to make fill&stroke rebuild its - * gradient list when the defs are vacuumed. gradient-vector.cpp - * listens to the modified signal on defs, and now we give it that - * signal. Mental says that this should be made automatic by - * merging SPObjectGroup with SPObject; SPObjectGroup would issue - * this signal automatically. Or maybe just derive SPDefs from - * SPObjectGroup? - */ + /** \todo + * This is a temporary hack added to make fill&stroke rebuild its + * gradient list when the defs are vacuumed. gradient-vector.cpp + * listens to the modified signal on defs, and now we give it that + * signal. Mental says that this should be made automatic by + * merging SPObjectGroup with SPObject; SPObjectGroup would issue + * this signal automatically. Or maybe just derive SPDefs from + * SPObjectGroup? + */ - this->requestModified(SP_OBJECT_CHILD_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_CHILD_MODIFIED_FLAG); + } } /** Sends the delete signal to all children of this object recursively */ -- cgit v1.2.3 From 15b2e7f906a311fe2d7e2ff4e4b35c1f00361333 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Jul 2010 01:07:55 -0700 Subject: Do not remove color-profile elements during vacuum defs. Fixes bug #444225. Fixed bugs: - https://launchpad.net/bugs/444225 (bzr r9552) --- src/sp-object.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 3b0056b41..fd17b3c12 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -38,6 +38,7 @@ #include "helper/sp-marshal.h" #include "xml/node-event-vector.h" #include "attributes.h" +#include "color-profile-fns.h" #include "document.h" #include "style.h" #include "sp-object-repr.h" @@ -549,6 +550,8 @@ void SPObject::requestOrphanCollection() { // leave it } else if (SP_IS_PAINT_SERVER(this) && static_cast(this)->isSwatch() ) { // leave it + } else if (IS_COLORPROFILE(this)) { + // leave it } else { document->queueForOrphanCollection(this); -- cgit v1.2.3 From 43519ed46697c28f90abe47d3b480f9bc9372c6e Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Jul 2010 01:18:10 -0700 Subject: Rough pass of Fill-n-Stroke swatch conversion. (bzr r9553) --- src/sp-gradient.cpp | 12 +++++++ src/sp-gradient.h | 2 ++ src/ui/dialog/swatches.cpp | 71 ++++++++++++++++++++++-------------------- src/widgets/fill-style.cpp | 6 +++- src/widgets/paint-selector.cpp | 1 + 5 files changed, 57 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 0c0c94784..9c1ea0da7 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -288,6 +288,18 @@ SPGradientSpread SPGradient::getSpread() const return spread; } +void SPGradient::setSwatch() +{ + if ( !isSwatch() ) { + if ( hasStops() && (getStopCount() == 0) ) { + repr->setAttribute("osb:paint", "solid"); + } else { + repr->setAttribute("osb:paint", "gradient"); + } + requestModified(SP_OBJECT_MODIFIED_FLAG); + } +} + /** * Return stop's color as 32bit value. */ diff --git a/src/sp-gradient.h b/src/sp-gradient.h index 7e6afe052..f1705f1c1 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -142,6 +142,8 @@ public: SPGradientSpread fetchSpread(); SPGradientUnits fetchUnits(); + void setSwatch(); + private: bool invalidateVector(); void rebuildVector(); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 90e9e5f7b..755a10519 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -72,7 +72,8 @@ static std::map docPerPanel; class SwatchesPanelHook : public SwatchesPanel { public: - static void convertGradient( GtkMenuItem * menuitem, gpointer userData ); + static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); + static void addNewGradient( GtkMenuItem *menuitem, gpointer user_data ); }; static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { @@ -139,7 +140,7 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) } } -static void addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) +void SwatchesPanelHook::addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) { if ( bounceTarget ) { SwatchesPanel* swp = bouncePanel; @@ -147,21 +148,22 @@ static void addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) SPDocument *doc = desktop ? desktop->doc() : 0; if (doc) { Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + SPGradient * gr = 0; + { + Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); + Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); + stop->setAttribute("offset", "0"); + stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); + repr->appendChild(stop); + Inkscape::GC::release(stop); - Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); - repr->setAttribute("osb:paint", "solid"); - Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); - stop->setAttribute("offset", "0"); - stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); - repr->appendChild(stop); - Inkscape::GC::release(stop); - - SP_OBJECT_REPR( SP_DOCUMENT_DEFS(doc) )->addChild(repr, NULL); - - SPGradient * gr = static_cast(doc->getObjectByRepr(repr)); + SP_OBJECT_REPR( SP_DOCUMENT_DEFS(doc) )->addChild(repr, NULL); - Inkscape::GC::release(repr); + gr = static_cast(doc->getObjectByRepr(repr)); + Inkscape::GC::release(repr); + } + gr->setSwatch(); editGradientImpl( gr ); } @@ -182,12 +184,9 @@ void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer us for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( targetName == grad->getId() ) { - grad->repr->setAttribute("osb:paint", "solid"); // TODO make conditional - + grad->setSwatch(); sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop")); - - handleGradientsChange(doc); // work-around for signal not being emitted break; } } @@ -253,7 +252,7 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g child = gtk_menu_item_new_with_label(_("Add")); g_signal_connect( G_OBJECT(child), "activate", - G_CALLBACK(addNewGradient), + G_CALLBACK(SwatchesPanelHook::addNewGradient), user_data ); gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); popupExtras.push_back(child); @@ -887,21 +886,25 @@ void SwatchesPanel::handleDefsModified(SPDocument *document) std::map tmpGrads; recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - int cap = std::min(docPalette->_colors.size(), tmpColors.size()); - for (int i = 0; i < cap; i++) { - ColorItem* newColor = tmpColors[i]; - ColorItem* oldColor = docPalette->_colors[i]; - if ( (newColor->def.getType() != oldColor->def.getType()) || - (newColor->def.getR() != oldColor->def.getR()) || - (newColor->def.getG() != oldColor->def.getG()) || - (newColor->def.getB() != oldColor->def.getB()) ) { - oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); - } - if (tmpGrads.find(newColor) != tmpGrads.end()) { - oldColor->setGradient(tmpGrads[newColor]); - } - if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { - oldColor->setPixData(tmpPrevs[newColor], PREVIEW_PIXBUF_WIDTH, VBLOCK); + if ( tmpColors.size() != docPalette->_colors.size() ) { + handleGradientsChange(document); + } else { + int cap = std::min(docPalette->_colors.size(), tmpColors.size()); + for (int i = 0; i < cap; i++) { + ColorItem* newColor = tmpColors[i]; + ColorItem* oldColor = docPalette->_colors[i]; + if ( (newColor->def.getType() != oldColor->def.getType()) || + (newColor->def.getR() != oldColor->def.getR()) || + (newColor->def.getG() != oldColor->def.getG()) || + (newColor->def.getB() != oldColor->def.getB()) ) { + oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); + } + if (tmpGrads.find(newColor) != tmpGrads.end()) { + oldColor->setGradient(tmpGrads[newColor]); + } + if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { + oldColor->setPixData(tmpPrevs[newColor], PREVIEW_PIXBUF_WIDTH, VBLOCK); + } } } } diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 5a7256d83..f1342f3de 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -556,8 +556,12 @@ void FillNStroke::updateFromPaint() } if (!vector) { + SPGradient *gr = sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL); + if ( gr && (psel->mode == SPPaintSelector::MODE_SWATCH) ) { + gr->setSwatch(); + } sp_item_set_gradient(SP_ITEM(i->data), - sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL), + gr, gradient_type, kind == FILL); } else { sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 8759854a0..a569d00bb 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -1102,6 +1102,7 @@ static void sp_paint_selector_set_mode_swatch(SPPaintSelector *psel, SPPaintSele gtk_frame_set_label(GTK_FRAME(psel->frame), _("Swatch fill")); } + #ifdef SP_PS_VERBOSE g_print("Swatch req\n"); #endif -- cgit v1.2.3 From ffd8f7ee3d1b69848b62ad51725751f9a14186d9 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Jul 2010 01:33:56 -0700 Subject: Bump default for "widescreen" to target netbook sizes. (bzr r9554) --- src/ui/uxmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/uxmanager.cpp b/src/ui/uxmanager.cpp index fbe000de9..a3ccb3471 100644 --- a/src/ui/uxmanager.cpp +++ b/src/ui/uxmanager.cpp @@ -131,7 +131,7 @@ UXManagerImpl::UXManagerImpl() : int width = defaultScreen->get_width(); int height = defaultScreen->get_height(); gdouble aspect = static_cast(width) / static_cast(height); - if (aspect > 1.4) { + if (aspect > 1.65) { _widescreen = true; } } -- cgit v1.2.3 From d283452c3d5e9706b9bd1863e3da259884c935b1 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Fri, 2 Jul 2010 19:59:40 +0200 Subject: fix help in latex output (bzr r9555) --- src/extension/internal/latex-text-renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 0d98f6b9c..00448b89e 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -180,7 +180,7 @@ static char const preamble[] = "%% instead of\n" "%% \\includegraphics{.pdf}\n" "%% To scale the image, write\n" -"%% \\def{\\svgwidth}{}\n" +"%% \\def\\svgwidth{}\n" "%% \\input{.pdf_tex}\n" "%% instead of\n" "%% \\includegraphics[width=]{.pdf}\n" -- cgit v1.2.3 From cd7aee702af257919f2220d89fb26af05a8e2599 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 2 Jul 2010 13:54:46 -0700 Subject: Added hidden preference to re-enable floating dialogs on problematic window managers. (bzr r9557) --- src/preferences-skeleton.h | 1 + src/widgets/toolbox.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index c334ae31e..dd925490e 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -343,6 +343,7 @@ static char const preferences_skeleton[] = " \n" " \n" " \n" " \n" diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index c255e087b..b68d8404d 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -992,7 +992,8 @@ static GtkWidget* toolboxNewCommon( GtkWidget* tb, BarId id, GtkPositionType han gtk_widget_set_sensitive(tb, FALSE); GtkWidget *hb = 0; - if ( UXManager::getInstance()->isFloatWindowProblem() ) { + gboolean forceFloatAllowed = Inkscape::Preferences::get()->getBool("/options/workarounds/floatallowed", false); + if ( UXManager::getInstance()->isFloatWindowProblem() && !forceFloatAllowed ) { hb = gtk_event_box_new(); // A simple, neutral container. } else { hb = gtk_handle_box_new(); -- cgit v1.2.3 From d9c3b46f2c4085fa74b3489719534577a032b528 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 02:34:22 -0700 Subject: Create only single-stop gradients when using Fill-n-Stroke to convert solid to a swatch. Preserve CMS colors. (bzr r9560) --- src/desktop-style.cpp | 26 +++++++++++++--- src/gradient-chemistry.cpp | 75 ++++++++++++++++++++-------------------------- src/gradient-chemistry.h | 5 ++-- src/widgets/fill-style.cpp | 18 ++++++----- 4 files changed, 67 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index 26f29d172..e11fa1493 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -436,6 +436,20 @@ stroke_average_width (GSList const *objects) return avgwidth / (g_slist_length ((GSList *) objects) - n_notstroked); } +static bool vectorsClose( std::vector const &lhs, std::vector const &rhs ) +{ + static double epsilon = 1e-6; + bool isClose = false; + if ( lhs.size() == rhs.size() ) { + isClose = true; + for ( size_t i = 0; (i < lhs.size()) && isClose; ++i ) { + isClose = fabs(lhs[i] - rhs[i]) < epsilon; + } + } + return isClose; +} + + /** * Write to style_res the average fill or stroke of list of objects, if applicable. */ @@ -536,11 +550,15 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill iccColor = paint->value.color.icc; iccSeen = true; } else { - if (same_color && (prev[0] != d[0] || prev[1] != d[1] || prev[2] != d[2])) + if (same_color && (prev[0] != d[0] || prev[1] != d[1] || prev[2] != d[2])) { same_color = false; - if ( iccSeen ) { - if(paint->value.color.icc) { - // TODO fix this + iccColor = 0; + } + if ( iccSeen && iccColor ) { + if ( !paint->value.color.icc + || (iccColor->colorProfile != paint->value.color.icc->colorProfile) + || !vectorsClose(iccColor->colors, paint->value.color.icc->colors) ) { + same_color = false; iccColor = 0; } } diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 979b53f1b..4df25aab4 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -1144,15 +1144,29 @@ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *lin } } + +static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gint opacity, gchar const *offset ) +{ + Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); + { + gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%d;", color.c_str(), opacity ); + stop->setAttribute( "style", tmp ); + g_free(tmp); + } + + stop->setAttribute( "offset", offset ); + + parent->appendChild(stop); + Inkscape::GC::release(stop); +} + /* * Get default normalized gradient vector of document, create if there is none */ - -SPGradient * -sp_document_default_gradient_vector(SPDocument *document, guint32 color) +SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor const &color, bool singleStop ) { - SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document); - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document); + SPDefs *defs = static_cast(SP_DOCUMENT_DEFS(document)); + Inkscape::XML::Document *xml_doc = document->rdoc; Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); @@ -1162,41 +1176,17 @@ sp_document_default_gradient_vector(SPDocument *document, guint32 color) // (1) here, search gradients by color and return what is found without duplication // (2) in fill & stroke, show only one copy of each gradient in list - Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); - - gchar b[64]; - sp_svg_write_color(b, sizeof(b), color); - - { - gchar *t = g_strdup_printf("stop-color:%s;stop-opacity:1;", b); - stop->setAttribute("style", t); - g_free(t); + Glib::ustring colorStr = color.toString(); + addStop( repr, colorStr, 1, "0" ); + if ( !singleStop ) { + addStop( repr, colorStr, 0, "1" ); } - stop->setAttribute("offset", "0"); - - repr->appendChild(stop); - Inkscape::GC::release(stop); - - stop = xml_doc->createElement("svg:stop"); - - { - gchar *t = g_strdup_printf("stop-color:%s;stop-opacity:0;", b); - stop->setAttribute("style", t); - g_free(t); - } - - stop->setAttribute("offset", "1"); - - repr->appendChild(stop); - Inkscape::GC::release(stop); - SP_OBJECT_REPR(defs)->addChild(repr, NULL); Inkscape::GC::release(repr); /* fixme: This does not look like nice */ - SPGradient *gr; - gr = (SPGradient *) document->getObjectByRepr(repr); + SPGradient *gr = static_cast(document->getObjectByRepr(repr)); g_assert(gr != NULL); g_assert(SP_IS_GRADIENT(gr)); /* fixme: Maybe add extra sanity check here */ @@ -1209,13 +1199,12 @@ sp_document_default_gradient_vector(SPDocument *document, guint32 color) Return the preferred vector for \a o, made from (in order of preference) its current vector, current fill or stroke color, or from desktop style if \a o is NULL or doesn't have style. */ -SPGradient * -sp_gradient_vector_for_object(SPDocument *const doc, SPDesktop *const desktop, - SPObject *const o, bool const is_fill) +SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *const desktop, + SPObject *const o, bool const is_fill, bool singleStop ) { - guint32 rgba = 0; + SPColor color; if (o == NULL || SP_OBJECT_STYLE(o) == NULL) { - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } else { // take the color of the object SPStyle const &style = *SP_OBJECT_STYLE(o); @@ -1227,17 +1216,17 @@ sp_gradient_vector_for_object(SPDocument *const doc, SPDesktop *const desktop, if (SP_IS_GRADIENT (server)) { return SP_GRADIENT(server)->getVector(true); } else { - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } } else if (paint.isColor()) { - rgba = paint.value.color.toRGBA32( 0xff ); + color = paint.value.color; } else { // if o doesn't use flat color, then take current color of the desktop. - rgba = sp_desktop_get_color(desktop, is_fill); + color = sp_desktop_get_color(desktop, is_fill); } } - return sp_document_default_gradient_vector(doc, rgba); + return sp_document_default_gradient_vector( doc, color, singleStop ); } diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index 3f72fa394..0c8d0afe7 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -42,9 +42,8 @@ SPGradient *sp_item_set_gradient (SPItem *item, SPGradient *gr, SPGradientType t /* * Get default normalized gradient vector of document, create if there is none */ - -SPGradient *sp_document_default_gradient_vector (SPDocument *document, guint32 color = 0); -SPGradient *sp_gradient_vector_for_object (SPDocument *doc, SPDesktop *desktop, SPObject *o, bool is_fill); +SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor const &color, bool singleStop ); +SPGradient *sp_gradient_vector_for_object( SPDocument *doc, SPDesktop *desktop, SPObject *o, bool is_fill, bool singleStop = false ); void sp_object_ensure_fill_gradient_normalized (SPObject *object); void sp_object_ensure_stroke_gradient_normalized (SPObject *object); diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index f1342f3de..19b8448c6 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -523,6 +523,7 @@ void FillNStroke::updateFromPaint() SPGradientType const gradient_type = ( psel->mode != SPPaintSelector::MODE_GRADIENT_RADIAL ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL ); + bool createSwatch = (psel->mode == SPPaintSelector::MODE_SWATCH); SPCSSAttr *css = 0; if (kind == FILL) { @@ -537,15 +538,18 @@ void FillNStroke::updateFromPaint() SPStyle *query = sp_style_new(desktop->doc()); int result = objects_query_fillstroke(const_cast(items), query, kind == FILL); - SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; - guint32 common_rgb = 0; if (result == QUERY_STYLE_MULTIPLE_SAME) { + SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke; + SPColor common; if (!targPaint.isColor()) { - common_rgb = sp_desktop_get_color(desktop, kind == FILL); + common = sp_desktop_get_color(desktop, kind == FILL); } else { - common_rgb = targPaint.value.color.toRGBA32( 0xff ); + common = targPaint.value.color; + } + vector = sp_document_default_gradient_vector( document, common, createSwatch ); + if ( vector && createSwatch ) { + vector->setSwatch(); } - vector = sp_document_default_gradient_vector(document, common_rgb); } sp_style_unref(query); @@ -556,8 +560,8 @@ void FillNStroke::updateFromPaint() } if (!vector) { - SPGradient *gr = sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL); - if ( gr && (psel->mode == SPPaintSelector::MODE_SWATCH) ) { + SPGradient *gr = sp_gradient_vector_for_object( document, desktop, SP_OBJECT(i->data), kind == FILL, createSwatch ); + if ( gr && createSwatch ) { gr->setSwatch(); } sp_item_set_gradient(SP_ITEM(i->data), -- cgit v1.2.3 From 0f742a4711da57918b22c2d193cf97aa60db010d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 15:58:53 -0700 Subject: Suppress gradient handles when editing objects with solid fills. (bzr r9562) --- src/gradient-drag.cpp | 36 +++++++++++++++++++----------------- src/gradient-drag.h | 12 ++++++------ 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index c9a982e42..55348616e 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -1624,41 +1624,43 @@ GrDrag::grabKnot (SPItem *item, gint point_type, gint point_i, bool fill_or_stro Regenerates the draggers list from the current selection; is called when selection is changed or modified, also when a radial dragger needs to update positions of other draggers in the gradient */ -void -GrDrag::updateDraggers () +void GrDrag::updateDraggers () { while (selected) { selected = g_list_remove(selected, selected->data); } // delete old draggers for (GList const* i = this->draggers; i != NULL; i = i->next) { - delete ((GrDragger *) i->data); + delete static_cast(i->data); } - g_list_free (this->draggers); + g_list_free(this->draggers); this->draggers = NULL; - g_return_if_fail (this->selection != NULL); + g_return_if_fail(this->selection != NULL); for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) { - SPItem *item = SP_ITEM(i->data); - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { - addDraggersLinear (SP_LINEARGRADIENT (server), item, true); - } else if (SP_IS_RADIALGRADIENT (server)) { - addDraggersRadial (SP_RADIALGRADIENT (server), item, true); + SPPaintServer *server = style->getFillPaintServer(); + if ( server && server->isSolid() ) { + // Suppress "gradientness" of solid paint + } else if ( SP_IS_LINEARGRADIENT(server) ) { + addDraggersLinear( SP_LINEARGRADIENT(server), item, true ); + } else if ( SP_IS_RADIALGRADIENT(server) ) { + addDraggersRadial( SP_RADIALGRADIENT(server), item, true ); } } if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { - addDraggersLinear (SP_LINEARGRADIENT (server), item, false); - } else if (SP_IS_RADIALGRADIENT (server)) { - addDraggersRadial (SP_RADIALGRADIENT (server), item, false); + SPPaintServer *server = style->getStrokePaintServer(); + if ( server && server->isSolid() ) { + // Suppress "gradientness" of solid paint + } else if ( SP_IS_LINEARGRADIENT(server) ) { + addDraggersLinear( SP_LINEARGRADIENT(server), item, false ); + } else if ( SP_IS_RADIALGRADIENT(server) ) { + addDraggersRadial( SP_RADIALGRADIENT(server), item, false ); } } } diff --git a/src/gradient-drag.h b/src/gradient-drag.h index 460d1396e..3eb625671 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -2,7 +2,7 @@ #define __GRADIENT_DRAG_H__ /* - * On-canvas gradient dragging + * On-canvas gradient dragging * * Authors: * bulia byak @@ -78,7 +78,7 @@ struct GrDragger { void updateKnotShape(); void updateTip(); - + void select(); void deselect(); bool isSelected(); @@ -131,9 +131,9 @@ public: // FIXME: make more of this private! void deleteSelected (bool just_one = false); guint32 getColor(); - - bool keep_selection; - + + bool keep_selection; + GrDragger *getDraggerFor (SPItem *item, gint point_type, gint point_i, bool fill_or_stroke); void grabKnot (GrDragger *dragger, gint x, gint y, guint32 etime); @@ -165,7 +165,7 @@ public: // FIXME: make more of this private! void selected_reverse_vector (); -private: +private: void deselect_all(); void addLine (SPItem *item, Geom::Point p1, Geom::Point p2, guint32 rgba); -- cgit v1.2.3 From e1439ba12c16c3564b6b2801481f14f907b119cb Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 16:02:57 -0700 Subject: Make order of 'auto' swatches match order in document. (bzr r9563) --- src/ui/dialog/swatches.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 755a10519..70e3800a0 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -14,6 +14,7 @@ #include #include +#include #include //for GTK_RESPONSE* types #include @@ -805,6 +806,7 @@ static void recalcSwatchContents(SPDocument* doc, } if ( !newList.empty() ) { + std::reverse(newList.begin(), newList.end()); for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) { SPGradient* grad = *it; -- cgit v1.2.3 From 5e0463d97c2a56fd7008750d8a897d3772bae946 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 20:15:58 -0700 Subject: Suppress gradient direction line for 'solid' gradients. Removed unneeded and outdated macro use. (bzr r9564) --- src/gradient-chemistry.cpp | 23 +++--- src/gradient-context.cpp | 2 - src/gradient-drag.cpp | 33 ++++---- src/selection-chemistry.cpp | 88 ++++++++++---------- src/sp-item.cpp | 171 +++++++++++++++++++-------------------- src/ui/clipboard.cpp | 14 ++-- src/widgets/fill-style.cpp | 20 ++--- src/widgets/gradient-toolbar.cpp | 34 ++++---- 8 files changed, 190 insertions(+), 195 deletions(-) (limited to 'src') diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 4df25aab4..750200841 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -458,24 +458,23 @@ sp_gradient_transform_multiply(SPGradient *gradient, Geom::Matrix postmul, bool g_free(c); } -SPGradient * -sp_item_gradient (SPItem *item, bool fill_or_stroke) +SPGradient *sp_item_gradient(SPItem *item, bool fill_or_stroke) { - SPStyle *style = SP_OBJECT_STYLE (item); - SPGradient *gradient = NULL; + SPStyle *style = item->style; + SPGradient *gradient = 0; if (fill_or_stroke) { if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER(item); - if (SP_IS_GRADIENT (server)) { - gradient = SP_GRADIENT (server); + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + gradient = SP_GRADIENT(server); } } } else { if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER(item); - if (SP_IS_GRADIENT (server)) { - gradient = SP_GRADIENT (server); + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { + gradient = SP_GRADIENT(server); } } } @@ -1212,8 +1211,8 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *con ? style.fill : style.stroke ); if (paint.isPaintserver()) { - SPObject *server = is_fill? SP_OBJECT_STYLE_FILL_SERVER(o) : SP_OBJECT_STYLE_STROKE_SERVER(o); - if (SP_IS_GRADIENT (server)) { + SPObject *server = is_fill? o->style->getFillPaintServer() : o->style->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { return SP_GRADIENT(server)->getVector(true); } else { color = sp_desktop_get_color(desktop, is_fill); diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index 6d6ea8761..bf1566b26 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -1,5 +1,3 @@ -#define __SP_GRADIENT_CONTEXT_C__ - /* * Gradient drawing and editing tool * diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 55348616e..8f0010925 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -1,5 +1,3 @@ -#define __GRADIENT_DRAG_C__ - /* * On-canvas gradient dragging * @@ -503,17 +501,18 @@ GrDraggable::~GrDraggable () } -SPObject * -GrDraggable::getServer () +SPObject *GrDraggable::getServer() { - if (!item) + if (!item) { return NULL; + } SPObject *server = NULL; - if (fill_or_stroke) - server = SP_OBJECT_STYLE_FILL_SERVER (item); - else - server = SP_OBJECT_STYLE_STROKE_SERVER (item); + if (fill_or_stroke) { + server = item->style->getFillPaintServer(); + }else { + server = item->style->getStrokePaintServer(); + } return server; } @@ -1705,10 +1704,12 @@ GrDrag::updateLines () SPStyle *style = SP_OBJECT_STYLE (item); if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( server && server->isSolid() ) { + // Suppress "gradientness" of solid paint + } else if ( SP_IS_LINEARGRADIENT(server) ) { this->addLine (item, sp_item_gradient_get_coords (item, POINT_LG_BEGIN, 0, true), sp_item_gradient_get_coords (item, POINT_LG_END, 0, true), GR_LINE_COLOR_FILL); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if ( SP_IS_RADIALGRADIENT(server) ) { Geom::Point center = sp_item_gradient_get_coords (item, POINT_RG_CENTER, 0, true); this->addLine (item, center, sp_item_gradient_get_coords (item, POINT_RG_R1, 0, true), GR_LINE_COLOR_FILL); this->addLine (item, center, sp_item_gradient_get_coords (item, POINT_RG_R2, 0, true), GR_LINE_COLOR_FILL); @@ -1716,10 +1717,12 @@ GrDrag::updateLines () } if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( server && server->isSolid() ) { + // Suppress "gradientness" of solid paint + } else if ( SP_IS_LINEARGRADIENT(server) ) { this->addLine (item, sp_item_gradient_get_coords (item, POINT_LG_BEGIN, 0, false), sp_item_gradient_get_coords (item, POINT_LG_END, 0, false), GR_LINE_COLOR_STROKE); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if ( SP_IS_RADIALGRADIENT(server) ) { Geom::Point center = sp_item_gradient_get_coords (item, POINT_RG_CENTER, 0, false); this->addLine (item, center, sp_item_gradient_get_coords (item, POINT_RG_R1, 0, false), GR_LINE_COLOR_STROKE); this->addLine (item, center, sp_item_gradient_get_coords (item, POINT_RG_R2, 0, false), GR_LINE_COLOR_STROKE); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index cc153aa71..f1262e9ca 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -285,9 +285,9 @@ void sp_selection_delete_impl(GSList const *items, bool propagate = true, bool p sp_object_ref((SPObject *)i->data, NULL); } for (GSList const *i = items; i != NULL; i = i->next) { - SPItem *item = (SPItem *) i->data; - SP_OBJECT(item)->deleteObject(propagate, propagate_descendants); - sp_object_unref((SPObject *)item, NULL); + SPItem *item = reinterpret_cast(i->data); + item->deleteObject(propagate, propagate_descendants); + sp_object_unref(item, NULL); } } @@ -442,7 +442,7 @@ void sp_edit_clear_all(SPDesktop *dt) GSList *items = sp_item_group_item_list(SP_GROUP(dt->currentLayer())); while (items) { - SP_OBJECT(items->data)->deleteObject(); + reinterpret_cast(items->data)->deleteObject(); items = g_slist_remove(items, items->data); } @@ -453,7 +453,7 @@ void sp_edit_clear_all(SPDesktop *dt) GSList * get_all_items(GSList *list, SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, GSList const *exclude) { - for (SPObject *child = sp_object_first_child(SP_OBJECT(from)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + for (SPObject *child = sp_object_first_child(from) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_ITEM(child) && !desktop->isLayer(SP_ITEM(child)) && (!onlysensitive || !SP_ITEM(child)->isLocked()) && @@ -559,7 +559,7 @@ void sp_edit_invert_in_all_layers(SPDesktop *desktop) } void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc) { - + p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position); // Remember the position and parent of the topmost object. @@ -638,9 +638,9 @@ void sp_selection_group(SPDesktop *desktop) } GSList const *l = (GSList *) selection->reprList(); - + GSList *p = g_slist_copy((GSList *) l); - + selection->clear(); Inkscape::XML::Node *group = xml_doc->createElement("svg:g"); @@ -821,7 +821,7 @@ sp_selection_raise(SPDesktop *desktop) // Iterate over all objects in the selection (starting from top). if (selected) { while (rev) { - SPObject *child = SP_OBJECT(rev->data); + SPObject *child = reinterpret_cast(rev->data); // for each selected object, find the next sibling for (SPObject *newref = child->next; newref; newref = newref->next) { // if the sibling is an item AND overlaps our selection, @@ -918,7 +918,7 @@ sp_selection_lower(SPDesktop *desktop) // Iterate over all objects in the selection (starting from top). if (selected) { while (rev) { - SPObject *child = SP_OBJECT(rev->data); + SPObject *child = reinterpret_cast(rev->data); // for each selected object, find the prev sibling for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) { // if the sibling is an item AND overlaps our selection, @@ -1022,16 +1022,16 @@ SPCSSAttr * take_style_from_item(SPItem *item) { // write the complete cascaded style, context-free - SPCSSAttr *css = sp_css_attr_from_object(SP_OBJECT(item), SP_STYLE_FLAG_ALWAYS); + SPCSSAttr *css = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); if (css == NULL) return NULL; - if ((SP_IS_GROUP(item) && SP_OBJECT(item)->children) || - (SP_IS_TEXT(item) && SP_OBJECT(item)->children && SP_OBJECT(item)->children->next == NULL)) { + if ((SP_IS_GROUP(item) && item->children) || + (SP_IS_TEXT(item) && item->children && item->children->next == NULL)) { // if this is a text with exactly one tspan child, merge the style of that tspan as well // If this is a group, merge the style of its topmost (last) child with style for (SPObject *last_element = item->lastChild(); last_element != NULL; last_element = SP_OBJECT_PREV(last_element)) { - if (SP_OBJECT_STYLE(last_element) != NULL) { + if ( last_element->style ) { SPCSSAttr *temp = sp_css_attr_from_object(last_element, SP_STYLE_FLAG_IFSET); if (temp) { sp_repr_css_merge(css, temp); @@ -1339,7 +1339,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons // we're moving both a clone and its original or any ancestor in clone chain? bool transform_clone_with_original = selection_contains_original(item, selection); // ...both a text-on-path and its path? - bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item(SP_TEXTPATH(sp_object_first_child(SP_OBJECT(item)))) )); + bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item(SP_TEXTPATH(sp_object_first_child(item))) )); // ...both a flowtext and its frame? bool transform_flowtext_with_frame = (SP_IS_FLOWTEXT(item) && selection->includes( SP_FLOWTEXT(item)->get_frame(NULL))); // (only the first frame is checked so far) // ...both an offset and its source? @@ -1374,7 +1374,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons * Same for linked offset if we are also moving its source: do not move it. */ if (transform_textpath_with_path || transform_offset_with_source) { // Restore item->transform field from the repr, in case it was changed by seltrans. - sp_object_read_attr(SP_OBJECT(item), "transform"); + sp_object_read_attr(item, "transform"); } else if (transform_flowtext_with_frame) { // apply the inverse of the region's transform to the so that the flow remains // the same (even though the output itself gets transformed) @@ -1392,7 +1392,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons // transform and its move compensation are both cancelled out. // restore item->transform field from the repr, in case it was changed by seltrans - sp_object_read_attr(SP_OBJECT(item), "transform"); + sp_object_read_attr(item, "transform"); // calculate the matrix we need to apply to the clone to cancel its induced transform from its original Geom::Matrix parent2dt = sp_item_i2d_affine(SP_ITEM(SP_OBJECT_PARENT(item))); @@ -1434,7 +1434,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons // center by the same matrix (only necessary for non-translations) if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) { item->setCenter(old_center * affine); - SP_OBJECT(item)->updateRepr(); + item->updateRepr(); } } } @@ -2096,7 +2096,7 @@ sp_selection_relink(SPDesktop *desktop) continue; SP_OBJECT_REPR(item)->setAttribute("xlink:href", newref); - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); relinked = true; } @@ -2134,10 +2134,10 @@ sp_selection_unlink(SPDesktop *desktop) SPItem *item = (SPItem *) items->data; if (SP_IS_TEXT(item)) { - SPObject *tspan = sp_tref_convert_to_tspan(SP_OBJECT(item)); + SPObject *tspan = sp_tref_convert_to_tspan(item); if (tspan) { - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } // Set unlink to true, and fall into the next if which @@ -2155,7 +2155,7 @@ sp_selection_unlink(SPDesktop *desktop) if (SP_IS_USE(item)) { unlink = sp_use_unlink(SP_USE(item)); } else /*if (SP_IS_TREF(use))*/ { - unlink = SP_ITEM(sp_tref_convert_to_tspan(SP_OBJECT(item))); + unlink = SP_ITEM(sp_tref_convert_to_tspan(item)); } unlinked = true; @@ -2200,7 +2200,7 @@ sp_select_clone_original(SPDesktop *desktop) } else if (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) { original = sp_offset_get_source(SP_OFFSET(item)); } else if (SP_IS_TEXT_TEXTPATH(item)) { - original = sp_textpath_get_path_item(SP_TEXTPATH(sp_object_first_child(SP_OBJECT(item)))); + original = sp_textpath_get_path_item(SP_TEXTPATH(sp_object_first_child(item))); } else if (SP_IS_FLOWTEXT(item)) { original = SP_FLOWTEXT(item)->get_frame(NULL); // first frame only } else { // it's an object that we don't know what to do with @@ -2302,7 +2302,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) if (apply) { // delete objects so that their clones don't get alerted; this object will be restored shortly for (GSList *i = items; i != NULL; i = i->next) { - SPObject *item = SP_OBJECT(i->data); + SPObject *item = reinterpret_cast(i->data); item->deleteObject(false); } } @@ -2341,7 +2341,7 @@ static void sp_selection_to_guides_recursive(SPItem *item, bool deleteitem, bool sp_item_convert_item_to_guides(item); if (deleteitem) { - SP_OBJECT(item)->deleteObject(true); + item->deleteObject(true); } } } @@ -2426,7 +2426,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) if (apply) { // delete objects so that their clones don't get alerted; this object will be restored shortly for (GSList *i = items; i != NULL; i = i->next) { - SPObject *item = SP_OBJECT(i->data); + SPObject *item = reinterpret_cast(i->data); item->deleteObject(false); } } @@ -2503,12 +2503,12 @@ sp_selection_untile(SPDesktop *desktop) SPItem *item = (SPItem *) items->data; - SPStyle *style = SP_OBJECT_STYLE(item); + SPStyle *style = item->style; if (!style || !style->fill.isPaintserver()) continue; - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER(item); + SPPaintServer *server = item->style->getFillPaintServer(); if (!SP_IS_PATTERN(server)) continue; @@ -2520,7 +2520,7 @@ sp_selection_untile(SPDesktop *desktop) Geom::Matrix pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server))); pat_transform *= item->transform; - for (SPObject *child = sp_object_first_child(SP_OBJECT(pattern)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + for (SPObject *child = sp_object_first_child(pattern) ; child != NULL; child = child->next ) { Inkscape::XML::Node *copy = SP_OBJECT_REPR(child)->duplicate(xml_doc); SPItem *i = SP_ITEM(desktop->currentLayer()->appendChildRepr(copy)); @@ -2860,7 +2860,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la GSList *items = g_slist_copy((GSList *) selection->itemList()); items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position); - + // See lp bug #542004 selection->clear(); @@ -2869,7 +2869,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la GSList *apply_to_items = NULL; GSList *items_to_delete = NULL; GSList *items_to_select = NULL; - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool topmost = prefs->getBool("/options/maskobject/topmost", true); bool remove_original = prefs->getBool("/options/maskobject/remove", true); @@ -2878,13 +2878,13 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la if (apply_to_layer) { // all selected items are used for mask, which is applied to a layer apply_to_items = g_slist_prepend(apply_to_items, desktop->currentLayer()); - + for (GSList *i = items; i != NULL; i = i->next) { Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); mask_items = g_slist_prepend(mask_items, dup); - SPObject *item = SP_OBJECT(i->data); - if (remove_original) { + SPObject *item = reinterpret_cast(i->data); + if (remove_original) { items_to_delete = g_slist_prepend(items_to_delete, item); } else { @@ -2898,7 +2898,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la mask_items = g_slist_prepend(mask_items, dup); if (remove_original) { - SPObject *item = SP_OBJECT(i->data); + SPObject *item = reinterpret_cast(i->data); items_to_delete = g_slist_prepend(items_to_delete, item); } @@ -2917,7 +2917,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la mask_items = g_slist_prepend(mask_items, dup); if (remove_original) { - SPObject *item = SP_OBJECT(i->data); + SPObject *item = reinterpret_cast(i->data); items_to_delete = g_slist_prepend(items_to_delete, item); } } @@ -2942,7 +2942,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la reprs_to_group = g_slist_reverse(reprs_to_group); sp_selection_group_impl(reprs_to_group, group, xml_doc, doc); - + reprs_to_group = NULL; // apply clip/mask only to newly created group @@ -3012,14 +3012,14 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la g_slist_free(apply_to_items); for (GSList *i = items_to_delete; NULL != i; i = i->next) { - SPObject *item = SP_OBJECT(i->data); + SPObject *item = reinterpret_cast(i->data); item->deleteObject(false); items_to_select = g_slist_remove(items_to_select, item); } g_slist_free(items_to_delete); - + items_to_select = g_slist_reverse(items_to_select); - + selection->addList(items_to_select); g_slist_free(items_to_select); @@ -3053,11 +3053,11 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { GSList *items = g_slist_copy((GSList *) selection->itemList()); selection->clear(); - + GSList *items_to_ungroup = NULL; GSList *items_to_select = g_slist_copy(items); - items_to_select = g_slist_reverse(items_to_select); - + items_to_select = g_slist_reverse(items_to_select); + // SPObject* refers to a group containing the clipped path or mask itself, // whereas SPItem* refers to the item being clipped or masked @@ -3143,7 +3143,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { } g_slist_free(items_to_ungroup); - + // rebuild selection items_to_select = g_slist_reverse(items_to_select); selection->addList(items_to_select); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 5a2dfb2f0..325009fe5 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -191,16 +191,17 @@ bool SPItem::isVisibleAndUnlocked(unsigned display_key) const { } bool SPItem::isLocked() const { - for (SPObject *o = SP_OBJECT(this); o != NULL; o = SP_OBJECT_PARENT(o)) { - if (SP_IS_ITEM(o) && !(SP_ITEM(o)->sensitive)) + for (SPObject const *o = this; o != NULL; o = o->parent) { + if (SP_IS_ITEM(o) && !(SP_ITEM(o)->sensitive)) { return true; + } } return false; } void SPItem::setLocked(bool locked) { - SP_OBJECT_REPR(this)->setAttribute("sodipodi:insensitive", - ( locked ? "1" : NULL )); + this->repr->setAttribute("sodipodi:insensitive", + ( locked ? "1" : NULL )); updateRepr(); } @@ -250,7 +251,7 @@ void SPItem::resetEvaluated() { requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); } } if ( StatusSet == _evaluated_status ) { - SPObject const *const parent = SP_OBJECT_PARENT(this); + SPObject const *const parent = this->parent; if (SP_IS_SWITCH(parent)) { SP_SWITCH(parent)->resetChildEvaluated(); } @@ -294,7 +295,7 @@ SPItem::setExplicitlyHidden(bool const val) { void SPItem::setCenter(Geom::Point object_centre) { // for getBounds() to work - sp_document_ensure_up_to_date(SP_OBJECT_DOCUMENT(this)); + sp_document_ensure_up_to_date( this->document ); Geom::OptRect bbox = getBounds(sp_item_i2d_affine(this)); if (bbox) { @@ -319,7 +320,7 @@ bool SPItem::isCenterSet() { Geom::Point SPItem::getCenter() const { // for getBounds() to work - sp_document_ensure_up_to_date(SP_OBJECT_DOCUMENT(this)); + sp_document_ensure_up_to_date( this->document ); Geom::OptRect bbox = getBounds(sp_item_i2d_affine(this)); if (bbox) { @@ -342,21 +343,21 @@ void SPItem::raiseToTop() { using Inkscape::Algorithms::find_last_if; SPObject *topmost=find_last_if( - SP_OBJECT_NEXT(this), NULL, &is_item + this->next, NULL, &is_item ); if (topmost) { - Inkscape::XML::Node *repr=SP_OBJECT_REPR(this); - sp_repr_parent(repr)->changeOrder(repr, SP_OBJECT_REPR(topmost)); + Inkscape::XML::Node *repr = this->repr; + sp_repr_parent(repr)->changeOrder( repr, topmost->repr ); } } void SPItem::raiseOne() { SPObject *next_higher=std::find_if( - SP_OBJECT_NEXT(this), NULL, &is_item + this->next, NULL, &is_item ); if (next_higher) { - Inkscape::XML::Node *repr=SP_OBJECT_REPR(this); - Inkscape::XML::Node *ref=SP_OBJECT_REPR(next_higher); + Inkscape::XML::Node *repr = this->repr; + Inkscape::XML::Node *ref = next_higher->repr; sp_repr_parent(repr)->changeOrder(repr, ref); } } @@ -367,15 +368,15 @@ void SPItem::lowerOne() { MutableList next_lower=std::find_if( reverse_list( - SP_OBJECT_PARENT(this)->firstChild(), this + this->parent->firstChild(), this ), MutableList(), &is_item ); if (next_lower) { ++next_lower; - Inkscape::XML::Node *repr=SP_OBJECT_REPR(this); - Inkscape::XML::Node *ref=( next_lower ? SP_OBJECT_REPR(&*next_lower) : NULL ); + Inkscape::XML::Node *repr = this->repr; + Inkscape::XML::Node *ref = ( next_lower ? next_lower->repr : NULL ); sp_repr_parent(repr)->changeOrder(repr, ref); } } @@ -387,15 +388,15 @@ void SPItem::lowerToBottom() { MutableList bottom=find_last_if( reverse_list( - SP_OBJECT_PARENT(this)->firstChild(), this + this->parent->firstChild(), this ), MutableList(), &is_item ); if (bottom) { ++bottom; - Inkscape::XML::Node *repr=SP_OBJECT_REPR(this); - Inkscape::XML::Node *ref=( bottom ? SP_OBJECT_REPR(&*bottom) : NULL ); + Inkscape::XML::Node *repr = this->repr; + Inkscape::XML::Node *ref = ( bottom ? bottom->repr : NULL ); sp_repr_parent(repr)->changeOrder(repr, ref); } } @@ -578,7 +579,7 @@ clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item) nr_arena_item_set_clip(v->arenaitem, ai); nr_arena_item_unref(ai); sp_clippath_set_bbox(SP_CLIPPATH(clip), NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox); - SP_OBJECT(clip)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } } @@ -606,7 +607,7 @@ mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item) nr_arena_item_set_mask(v->arenaitem, ai); nr_arena_item_unref(ai); sp_mask_set_bbox(SP_MASK(mask), NR_ARENA_ITEM_GET_KEY(v->arenaitem), &bbox); - SP_OBJECT(mask)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } } @@ -681,7 +682,7 @@ sp_item_write(SPObject *const object, Inkscape::XML::Document *xml_doc, Inkscape Inkscape::XML::Node *crepr; GSList *l; l = NULL; - for (child = sp_object_first_child(object); child != NULL; child = SP_OBJECT_NEXT(child) ) { + for (child = sp_object_first_child(object); child != NULL; child = child->next ) { if (!SP_IS_TITLE(child) && !SP_IS_DESC(child)) continue; crepr = child->updateRepr(xml_doc, NULL, flags); if (crepr) l = g_slist_prepend (l, crepr); @@ -692,7 +693,7 @@ sp_item_write(SPObject *const object, Inkscape::XML::Document *xml_doc, Inkscape l = g_slist_remove (l, l->data); } } else { - for (child = sp_object_first_child(object) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + for (child = sp_object_first_child(object) ; child != NULL; child = child->next ) { if (!SP_IS_TITLE(child) && !SP_IS_DESC(child)) continue; child->updateRepr(flags); } @@ -788,8 +789,8 @@ sp_item_invoke_bbox_full(SPItem const *item, Geom::OptRect &bbox, Geom::Matrix c // unless this is geometric bbox, extend by filter area and crop the bbox by clip path, if any if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) { - if (SP_OBJECT_STYLE(item) && SP_OBJECT_STYLE(item)->filter.href) { - SPObject *filter = SP_OBJECT_STYLE(item)->getFilter(); + if ( item->style && item->style->filter.href ) { + SPObject *filter = item->style->getFilter(); if (filter && SP_IS_FILTER(filter)) { // default filer area per the SVG spec: double x = -0.1; @@ -912,14 +913,14 @@ unsigned sp_item_pos_in_parent(SPItem *item) g_assert(item != NULL); g_assert(SP_IS_ITEM(item)); - SPObject *parent = SP_OBJECT_PARENT(item); + SPObject *parent = item->parent; g_assert(parent != NULL); g_assert(SP_IS_OBJECT(parent)); - SPObject *object = SP_OBJECT(item); + SPObject *object = item; - unsigned pos=0; - for ( SPObject *iter = sp_object_first_child(parent) ; iter ; iter = SP_OBJECT_NEXT(iter)) { + unsigned pos = 0; + for ( SPObject *iter = sp_object_first_child(parent) ; iter ; iter = iter->next) { if ( iter == object ) { return pos; } @@ -989,8 +990,8 @@ void sp_item_snappoints(SPItem const *item, std::vector clips_and_masks; - clips_and_masks.push_back(SP_OBJECT(item->clip_ref->getObject())); - clips_and_masks.push_back(SP_OBJECT(item->mask_ref->getObject())); + clips_and_masks.push_back(item->clip_ref->getObject()); + clips_and_masks.push_back(item->mask_ref->getObject()); SPDesktop *desktop = inkscape_active_desktop(); for (std::list::const_iterator o = clips_and_masks.begin(); o != clips_and_masks.end(); o++) { @@ -1020,9 +1021,9 @@ sp_item_invoke_print(SPItem *item, SPPrintContext *ctx) if (!item->isHidden()) { if (((SPItemClass *) G_OBJECT_GET_CLASS(item))->print) { if (!item->transform.isIdentity() - || SP_OBJECT_STYLE(item)->opacity.value != SP_SCALE24_MAX) + || item->style->opacity.value != SP_SCALE24_MAX) { - sp_print_bind(ctx, item->transform, SP_SCALE24_TO_FLOAT(SP_OBJECT_STYLE(item)->opacity.value)); + sp_print_bind(ctx, item->transform, SP_SCALE24_TO_FLOAT(item->style->opacity.value)); ((SPItemClass *) G_OBJECT_GET_CLASS(item))->print(item, ctx); sp_print_release(ctx); } else { @@ -1061,8 +1062,8 @@ sp_item_description(SPItem *item) g_free (s); s = snew; } - if (SP_OBJECT_STYLE(item) && SP_OBJECT_STYLE(item)->filter.href && SP_OBJECT_STYLE(item)->filter.href->getObject()) { - const gchar *label = SP_OBJECT_STYLE(item)->filter.href->getObject()->label(); + if ( item->style && item->style->filter.href && item->style->filter.href->getObject() ) { + const gchar *label = item->style->filter.href->getObject()->label(); gchar *snew; if (label) { snew = g_strdup_printf (_("%s; filtered (%s)"), s, _(label)); @@ -1111,7 +1112,7 @@ sp_item_invoke_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags) if (ai != NULL) { item->display = sp_item_view_new_prepend(item->display, item, flags, key, ai); nr_arena_item_set_transform(ai, item->transform); - nr_arena_item_set_opacity(ai, SP_SCALE24_TO_FLOAT(SP_OBJECT_STYLE(item)->opacity.value)); + nr_arena_item_set_opacity(ai, SP_SCALE24_TO_FLOAT(item->style->opacity.value)); nr_arena_item_set_visible(ai, !item->isHidden()); nr_arena_item_set_sensitive(ai, item->sensitive); if (item->clip_ref->getObject()) { @@ -1131,7 +1132,7 @@ sp_item_invoke_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags) NRRect bbox; sp_item_invoke_bbox(item, &bbox, Geom::identity(), TRUE); sp_clippath_set_bbox(SP_CLIPPATH(cp), clip_key, &bbox); - SP_OBJECT(cp)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + cp->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } if (item->mask_ref->getObject()) { SPMask *mask = item->mask_ref->getObject(); @@ -1150,7 +1151,7 @@ sp_item_invoke_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags) NRRect bbox; sp_item_invoke_bbox(item, &bbox, Geom::identity(), TRUE); sp_mask_set_bbox(SP_MASK(mask), mask_key, &bbox); - SP_OBJECT(mask)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } NR_ARENA_ITEM_SET_DATA(ai, item); Geom::OptRect item_bbox; @@ -1204,34 +1205,32 @@ sp_item_invoke_hide(SPItem *item, unsigned key) void sp_item_adjust_pattern (SPItem *item, Geom::Matrix const &postmul, bool set) { - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; - if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); - if (SP_IS_PATTERN (server)) { - SPPattern *pattern = sp_pattern_clone_if_necessary (item, SP_PATTERN (server), "fill"); - sp_pattern_transform_multiply (pattern, postmul, set); + if ( style && style->fill.isPaintserver() ) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_PATTERN(server) ) { + SPPattern *pattern = sp_pattern_clone_if_necessary(item, SP_PATTERN(server), "fill"); + sp_pattern_transform_multiply(pattern, postmul, set); } } - if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); - if (SP_IS_PATTERN (server)) { - SPPattern *pattern = sp_pattern_clone_if_necessary (item, SP_PATTERN (server), "stroke"); - sp_pattern_transform_multiply (pattern, postmul, set); + if ( style && style->stroke.isPaintserver() ) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_PATTERN(server) ) { + SPPattern *pattern = sp_pattern_clone_if_necessary(item, SP_PATTERN(server), "stroke"); + sp_pattern_transform_multiply(pattern, postmul, set); } } - } -void -sp_item_adjust_gradient (SPItem *item, Geom::Matrix const &postmul, bool set) +void sp_item_adjust_gradient( SPItem *item, Geom::Matrix const &postmul, bool set ) { - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; - if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER(item); - if (SP_IS_GRADIENT (server)) { + if ( style && style->fill.isPaintserver() ) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { /** * \note Bbox units for a gradient are generally a bad idea because @@ -1242,40 +1241,37 @@ sp_item_adjust_gradient (SPItem *item, Geom::Matrix const &postmul, bool set) * \todo FIXME: convert back to bbox units after transforming with * the item, so as to preserve the original units. */ - SPGradient *gradient = sp_gradient_convert_to_userspace (SP_GRADIENT (server), item, "fill"); + SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), item, "fill" ); - sp_gradient_transform_multiply (gradient, postmul, set); + sp_gradient_transform_multiply( gradient, postmul, set ); } } - if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER(item); - if (SP_IS_GRADIENT (server)) { - SPGradient *gradient = sp_gradient_convert_to_userspace (SP_GRADIENT (server), item, "stroke"); - sp_gradient_transform_multiply (gradient, postmul, set); + if ( style && style->stroke.isPaintserver() ) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), item, "stroke" ); + sp_gradient_transform_multiply( gradient, postmul, set ); } } } -void -sp_item_adjust_stroke (SPItem *item, gdouble ex) +void sp_item_adjust_stroke( SPItem *item, gdouble ex ) { - SPStyle *style = SP_OBJECT_STYLE (item); - - if (style && !style->stroke.isNone() && !NR_DF_TEST_CLOSE (ex, 1.0, NR_EPSILON)) { + SPStyle *style = item->style; + if ( style && !style->stroke.isNone() && !NR_DF_TEST_CLOSE(ex, 1.0, NR_EPSILON) ) { style->stroke_width.computed *= ex; style->stroke_width.set = TRUE; - if (style->stroke_dash.n_dash != 0) { - int i; - for (i = 0; i < style->stroke_dash.n_dash; i++) { + if ( style->stroke_dash.n_dash != 0 ) { + for (int i = 0; i < style->stroke_dash.n_dash; i++) { style->stroke_dash.dash[i] *= ex; } style->stroke_dash.offset *= ex; } - SP_OBJECT(item)->updateRepr(); + item->updateRepr(); } } @@ -1286,7 +1282,7 @@ Geom::Matrix sp_item_transform_repr (SPItem *item) { Geom::Matrix t_old(Geom::identity()); - gchar const *t_attr = SP_OBJECT_REPR(item)->attribute("transform"); + gchar const *t_attr = item->repr->attribute("transform"); if (t_attr) { Geom::Matrix t; if (sp_svg_transform_read(t_attr, &t)) { @@ -1310,7 +1306,7 @@ sp_item_adjust_stroke_width_recursive(SPItem *item, double expansion) if (item && SP_IS_USE(item)) return; - for (SPObject *o = SP_OBJECT(item)->children; o != NULL; o = o->next) { + for (SPObject *o = item->children; o != NULL; o = o->next) { if (SP_IS_ITEM(o)) sp_item_adjust_stroke_width_recursive(SP_ITEM(o), expansion); } @@ -1326,7 +1322,7 @@ sp_item_adjust_rects_recursive(SPItem *item, Geom::Matrix advertized_transform) sp_rect_compensate_rxry (SP_RECT(item), advertized_transform); } - for (SPObject *o = SP_OBJECT(item)->children; o != NULL; o = o->next) { + for (SPObject *o = item->children; o != NULL; o = o->next) { if (SP_IS_ITEM(o)) sp_item_adjust_rects_recursive(SP_ITEM(o), advertized_transform); } @@ -1348,7 +1344,7 @@ sp_item_adjust_paint_recursive (SPItem *item, Geom::Matrix advertized_transform, // also we do not recurse into clones, because a clone's child is the ghost of its original - // we must not touch it if (!(item && (SP_IS_TEXT(item) || SP_IS_USE(item)))) { - for (SPObject *o = SP_OBJECT(item)->children; o != NULL; o = o->next) { + for (SPObject *o = item->children; o != NULL; o = o->next) { if (SP_IS_ITEM(o)) { // At the level of the transformed item, t_ancestors is identity; // below it, it is the accmmulated chain of transforms from this level to the top level @@ -1452,7 +1448,7 @@ sp_item_write_transform(SPItem *item, Inkscape::XML::Node *repr, Geom::Matrix co !preserve && // user did not chose to preserve all transforms !item->clip_ref->getObject() && // the object does not have a clippath !item->mask_ref->getObject() && // the object does not have a mask - !(!transform.isTranslation() && SP_OBJECT_STYLE(item) && SP_OBJECT_STYLE(item)->getFilter()) + !(!transform.isTranslation() && item->style && item->style->getFilter()) // the object does not have a filter, or the transform is translation (which is supposed to not affect filters) ) { transform_attr = ((SPItemClass *) G_OBJECT_GET_CLASS(item))->set_transform(item, transform); @@ -1463,7 +1459,7 @@ sp_item_write_transform(SPItem *item, Inkscape::XML::Node *repr, Geom::Matrix co // it causes clone SPUse's copy of the original object to brought up to // date with the original. Otherwise, sp_use_bbox returns incorrect // values if called in code handling the transformed signal. - SP_OBJECT(item)->updateRepr(); + item->updateRepr(); // send the relative transform with a _transformed_signal item->_transformed_signal.emit(&advertized_transform, item); @@ -1534,7 +1530,7 @@ i2anc_affine(SPObject const *object, SPObject const *const ancestor) { } else { ret *= SP_ITEM(object)->transform; } - object = SP_OBJECT_PARENT(object); + object = object->parent; } return ret; } @@ -1569,7 +1565,7 @@ Geom::Matrix sp_item_i2d_affine(SPItem const *item) Geom::Matrix const ret( sp_item_i2doc_affine(item) * Geom::Scale(1, -1) - * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); + * Geom::Translate(0, sp_document_height(item->document)) ); return ret; } @@ -1579,10 +1575,10 @@ void sp_item_set_i2d_affine(SPItem *item, Geom::Matrix const &i2dt) g_return_if_fail( SP_IS_ITEM(item) ); Geom::Matrix dt2p; /* desktop to item parent transform */ - if (SP_OBJECT_PARENT(item)) { - dt2p = sp_item_i2d_affine((SPItem *) SP_OBJECT_PARENT(item)).inverse(); + if (item->parent) { + dt2p = sp_item_i2d_affine(static_cast(item->parent)).inverse(); } else { - dt2p = ( Geom::Translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) + dt2p = ( Geom::Translate(0, -sp_document_height(item->document)) * Geom::Scale(1, -1) ); } @@ -1660,16 +1656,17 @@ sp_item_get_arenaitem(SPItem *item, unsigned key) int sp_item_repr_compare_position(SPItem *first, SPItem *second) { - return sp_repr_compare_position(SP_OBJECT_REPR(first), - SP_OBJECT_REPR(second)); + return sp_repr_compare_position(first->repr, + second->repr); } SPItem * sp_item_first_item_child (SPObject *obj) { - for ( SPObject *iter = sp_object_first_child(obj) ; iter ; iter = SP_OBJECT_NEXT(iter)) { - if (SP_IS_ITEM (iter)) + for ( SPObject *iter = sp_object_first_child(obj) ; iter ; iter = iter->next) { + if ( SP_IS_ITEM(iter) ) { return SP_ITEM (iter); + } } return NULL; } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 9ce2ac5ba..0a64e7fa7 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -653,23 +653,23 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection) void ClipboardManagerImpl::_copyUsedDefs(SPItem *item) { // copy fill and stroke styles (patterns and gradients) - SPStyle *style = SP_OBJECT_STYLE(item); + SPStyle *style = item->style; if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER(item); - if (SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server)) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) { _copyGradient(SP_GRADIENT(server)); } - if (SP_IS_PATTERN(server)) { + if ( SP_IS_PATTERN(server) ) { _copyPattern(SP_PATTERN(server)); } } if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER(item); - if (SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server)) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) { _copyGradient(SP_GRADIENT(server)); } - if (SP_IS_PATTERN(server)) { + if ( SP_IS_PATTERN(server) ) { _copyPattern(SP_PATTERN(server)); } } diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index 19b8448c6..a0e343b58 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -556,11 +556,11 @@ void FillNStroke::updateFromPaint() for (GSList const *i = items; i != NULL; i = i->next) { //FIXME: see above if (kind == FILL) { - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + sp_repr_css_change_recursive(reinterpret_cast(i->data)->repr, css, "style"); } if (!vector) { - SPGradient *gr = sp_gradient_vector_for_object( document, desktop, SP_OBJECT(i->data), kind == FILL, createSwatch ); + SPGradient *gr = sp_gradient_vector_for_object( document, desktop, reinterpret_cast(i->data), kind == FILL, createSwatch ); if ( gr && createSwatch ) { gr->setSwatch(); } @@ -578,7 +578,7 @@ void FillNStroke::updateFromPaint() for (GSList const *i = items; i != NULL; i = i->next) { //FIXME: see above if (kind == FILL) { - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + sp_repr_css_change_recursive(reinterpret_cast(i->data)->repr, css, "style"); } SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL); @@ -608,7 +608,7 @@ void FillNStroke::updateFromPaint() */ } else { - Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern); + Inkscape::XML::Node *patrepr = pattern->repr; SPCSSAttr *css = sp_repr_css_attr_new(); gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id")); sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext); @@ -622,17 +622,17 @@ void FillNStroke::updateFromPaint() // objects who already have the same root pattern but through a different href // chain. FIXME: move this to a sp_item_set_pattern for (GSList const *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data); + Inkscape::XML::Node *selrepr = reinterpret_cast(i->data)->repr; if ( (kind == STROKE) && !selrepr) { continue; } - SPObject *selobj = SP_OBJECT(i->data); + SPObject *selobj = reinterpret_cast(i->data); - SPStyle *style = SP_OBJECT_STYLE(selobj); + SPStyle *style = selobj->style; if (style && ((kind == FILL) ? style->fill : style->stroke).isPaintserver()) { - SPObject *server = (kind == FILL) ? - SP_OBJECT_STYLE_FILL_SERVER(selobj) : - SP_OBJECT_STYLE_STROKE_SERVER(selobj); + SPPaintServer *server = (kind == FILL) ? + selobj->style->getFillPaintServer() : + selobj->style->getStrokePaintServer(); if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern) // only if this object's pattern is not rooted in our selected pattern, apply continue; diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index 1d3187985..ce5f5fb8f 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -73,18 +73,17 @@ static void gr_toggle_fillstroke (GtkWidget *button, gpointer data) { } } -void -gr_apply_gradient_to_item (SPItem *item, SPGradient *gr, SPGradientType new_type, guint new_fill, bool do_fill, bool do_stroke) +void gr_apply_gradient_to_item( SPItem *item, SPGradient *gr, SPGradientType new_type, guint new_fill, bool do_fill, bool do_stroke ) { - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; if (do_fill) { if (style && (style->fill.isPaintserver()) && - SP_IS_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (item))) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { + SP_IS_GRADIENT( item->style->getFillPaintServer() )) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_LINEARGRADIENT(server) ) { sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, true); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if ( SP_IS_RADIALGRADIENT(server) ) { sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, true); } } else if (new_fill) { @@ -94,11 +93,11 @@ gr_apply_gradient_to_item (SPItem *item, SPGradient *gr, SPGradientType new_type if (do_stroke) { if (style && (style->stroke.isPaintserver()) && - SP_IS_GRADIENT (SP_OBJECT_STYLE_STROKE_SERVER (item))) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); - if (SP_IS_LINEARGRADIENT (server)) { + SP_IS_GRADIENT( item->style->getStrokePaintServer() )) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_LINEARGRADIENT(server) ) { sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, false); - } else if (SP_IS_RADIALGRADIENT (server)) { + } else if ( SP_IS_RADIALGRADIENT(server) ) { sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, false); } } else if (!new_fill) { @@ -238,7 +237,7 @@ GtkWidget *gr_vector_list(SPDesktop *desktop, bool selection_empty, SPGradient * GtkWidget *hb = gtk_hbox_new (FALSE, 4); GtkWidget *l = gtk_label_new (""); - gchar *label = gr_prepare_label (SP_OBJECT(gradient)); + gchar *label = gr_prepare_label(gradient); gtk_label_set_markup (GTK_LABEL(l), label); g_free (label); gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5); @@ -310,11 +309,11 @@ void gr_read_selection( Inkscape::Selection *selection, // If no selected dragger, read desktop selection for (GSList const* i = selection->itemList(); i; i = i->next) { SPItem *item = SP_ITEM(i->data); - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; if (style && (style->fill.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); - if (SP_IS_GRADIENT(server)) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { SPGradient *gradient = SP_GRADIENT(server)->getVector(); SPGradientSpread spread = SP_GRADIENT(server)->fetchSpread(); @@ -339,14 +338,13 @@ void gr_read_selection( Inkscape::Selection *selection, } } if (style && (style->stroke.isPaintserver())) { - SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); - if (SP_IS_GRADIENT(server)) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { SPGradient *gradient = SP_GRADIENT(server)->getVector(); SPGradientSpread spread = SP_GRADIENT(server)->fetchSpread(); if (gradient && gradient->isSolid()) { gradient = 0; - } if (gradient && (gradient != gr_selected)) { -- cgit v1.2.3 From bdb17f74f1d98a4e544b11befc1006a13eda8ae0 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 3 Jul 2010 20:19:58 -0700 Subject: Removing unused macro. (bzr r9565) --- src/style.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/style.h b/src/style.h index 02ef41bf8..8102ce0ea 100644 --- a/src/style.h +++ b/src/style.h @@ -144,8 +144,6 @@ struct SPILength { #define SP_STYLE_FILL_SERVER(s) (((SPStyle *) (s))->getFillPaintServer()) #define SP_STYLE_STROKE_SERVER(s) (((SPStyle *) (s))->getStrokePaintServer()) -#define SP_OBJECT_STYLE_FILL_SERVER(o) (SP_OBJECT (o)->style->getFillPaintServer()) -#define SP_OBJECT_STYLE_STROKE_SERVER(o) (SP_OBJECT (o)->style->getStrokePaintServer()) class SVGICCColor; -- cgit v1.2.3 From f2bd6839567174ab8e6f589252863284991051d6 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 4 Jul 2010 23:19:23 +0200 Subject: When snapping the object midpoint the snap source wasn't displayed (bzr r9572) --- src/snap-enums.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/snap-enums.h b/src/snap-enums.h index 4e6854054..64be34637 100644 --- a/src/snap-enums.h +++ b/src/snap-enums.h @@ -66,10 +66,10 @@ enum SnapSourceType { SNAPSOURCE_CONVEX_HULL_CORNER, SNAPSOURCE_ELLIPSE_QUADRANT_POINT, SNAPSOURCE_NODE_HANDLE, // eg. nodes in the path editor, handles of stars or rectangles, etc. (tied to a stroke) + SNAPSOURCE_OBJECT_MIDPOINT, //------------------------------------------------------------------- // Other points (e.g. guides, gradient knots) will snap to both bounding boxes and nodes SNAPSOURCE_OTHER_CATEGORY = 1024, // will be used as a flag and must therefore be a power of two - SNAPSOURCE_OBJECT_MIDPOINT, SNAPSOURCE_ROTATION_CENTER, SNAPSOURCE_CENTER, // of ellipse SNAPSOURCE_GUIDE, -- cgit v1.2.3 From 8805a20dd81dc274967db61643735eabb75b5abd Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 4 Jul 2010 20:50:27 -0700 Subject: Prevent conversion of 'solid' gradients. (bzr r9577) --- src/gradient-chemistry.cpp | 124 +++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 750200841..8a199d4a3 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -40,6 +40,7 @@ #include "svg/css-ostringstream.h" #include "preferences.h" +#define noSP_GR_VERBOSE // Terminology: // @@ -52,9 +53,11 @@ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *gr); -SPGradient * -sp_gradient_ensure_vector_normalized(SPGradient *gr) +SPGradient *sp_gradient_ensure_vector_normalized(SPGradient *gr) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_ensure_vector_normalized(%p)", gr); +#endif g_return_val_if_fail(gr != NULL, NULL); g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL); @@ -91,9 +94,12 @@ sp_gradient_ensure_vector_normalized(SPGradient *gr) * Creates new private gradient for the given vector */ -static SPGradient * -sp_gradient_get_private_normalized(SPDocument *document, SPGradient *vector, SPGradientType type) +static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGradient *vector, SPGradientType type) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_get_private_normalized(%p, %p, %d)", document, vector, type); +#endif + g_return_val_if_fail(document != NULL, NULL); g_return_val_if_fail(vector != NULL, NULL); g_return_val_if_fail(SP_IS_GRADIENT(vector), NULL); @@ -131,8 +137,7 @@ sp_gradient_get_private_normalized(SPDocument *document, SPGradient *vector, SPG /** Count how many times gr is used by the styles of o and its descendants */ -guint -count_gradient_hrefs(SPObject *o, SPGradient *gr) +guint count_gradient_hrefs(SPObject *o, SPGradient *gr) { if (!o) return 1; @@ -167,10 +172,12 @@ count_gradient_hrefs(SPObject *o, SPGradient *gr) /** * If gr has other users, create a new private; also check if gr links to vector, relink if not */ -SPGradient * -sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector, - SPGradientType type, SPObject *o) +SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector, + SPGradientType type, SPObject *o) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_fork_private_if_necessary(%p, %p, %d, %p)", gr, vector, type, o); +#endif g_return_val_if_fail(gr != NULL, NULL); g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL); @@ -237,9 +244,11 @@ sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *vector, } } -SPGradient * -sp_gradient_fork_vector_if_necessary (SPGradient *gr) +SPGradient *sp_gradient_fork_vector_if_necessary(SPGradient *gr) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_fork_vector_if_necessary(%p)", gr); +#endif // Some people actually prefer their gradient vectors to be shared... Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (!prefs->getBool("/options/forkgradientvectors/value", true)) @@ -262,9 +271,11 @@ sp_gradient_fork_vector_if_necessary (SPGradient *gr) /** * Obtain the vector from the gradient. A forked vector will be created and linked to this gradient if another gradient uses it. */ -SPGradient * -sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, bool force_vector) +SPGradient *sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, bool force_vector) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_get_forked_vector_if_necessary(%p, %d)", gradient, force_vector); +#endif SPGradient *vector = gradient->getVector(force_vector); vector = sp_gradient_fork_vector_if_necessary (vector); if ( gradient != vector && gradient->ref->getObject() != vector ) { @@ -279,9 +290,11 @@ sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, bool force_vect * instead. No forking or reapplying is done because this is only called for newly created privates. * @return The new gradient. */ -SPGradient * -sp_gradient_reset_to_userspace (SPGradient *gr, SPItem *item) +SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_reset_to_userspace(%p, %p)", gr, item); +#endif Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); // calculate the bbox of the item @@ -331,11 +344,17 @@ sp_gradient_reset_to_userspace (SPGradient *gr, SPItem *item) * Convert an item's gradient to userspace if necessary, also fork it if necessary. * @return The new gradient. */ -SPGradient * -sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *property) +SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *property) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_convert_to_userspace(%p, %p, \"%s\")", gr, item, property); +#endif g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL); + if ( gr && gr->isSolid() ) { + return gr; + } + // First, fork it if it is shared gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(), SP_IS_RADIALGRADIENT(gr) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, SP_OBJECT(item)); @@ -443,9 +462,11 @@ sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar const *prop return gr; } -void -sp_gradient_transform_multiply(SPGradient *gradient, Geom::Matrix postmul, bool set) +void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Matrix postmul, bool set) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_transform_multiply(%p, , %d)", gradient, set); +#endif if (set) { gradient->gradientTransform = postmul; } else { @@ -482,7 +503,7 @@ SPGradient *sp_item_gradient(SPItem *item, bool fill_or_stroke) return gradient; } -SPStop* sp_last_stop(SPGradient *gradient) +SPStop *sp_last_stop(SPGradient *gradient) { for (SPStop *stop = gradient->getFirstStop(); stop != NULL; stop = stop->getNextStop()) { if (stop->getNextStop() == NULL) @@ -491,8 +512,7 @@ SPStop* sp_last_stop(SPGradient *gradient) return NULL; } -SPStop* -sp_get_stop_i(SPGradient *gradient, guint stop_i) +SPStop *sp_get_stop_i(SPGradient *gradient, guint stop_i) { SPStop *stop = gradient->getFirstStop(); @@ -512,20 +532,22 @@ sp_get_stop_i(SPGradient *gradient, guint stop_i) return stop; } -guint32 -average_color (guint32 c1, guint32 c2, gdouble p) +guint32 average_color(guint32 c1, guint32 c2, gdouble p) { guint32 r = (guint32) (SP_RGBA32_R_U (c1) * (1 - p) + SP_RGBA32_R_U (c2) * p); guint32 g = (guint32) (SP_RGBA32_G_U (c1) * (1 - p) + SP_RGBA32_G_U (c2) * p); guint32 b = (guint32) (SP_RGBA32_B_U (c1) * (1 - p) + SP_RGBA32_B_U (c2) * p); guint32 a = (guint32) (SP_RGBA32_A_U (c1) * (1 - p) + SP_RGBA32_A_U (c2) * p); - return SP_RGBA32_U_COMPOSE (r, g, b, a); + return SP_RGBA32_U_COMPOSE(r, g, b, a); } -SPStop * -sp_vector_add_stop (SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset) +SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset) { +#ifdef SP_GR_VERBOSE + g_message("sp_vector_add_stop(%p, %p, %p, %f)", vector, prev_stop, next_stop, offset); +#endif + Inkscape::XML::Node *new_stop_repr = NULL; new_stop_repr = SP_OBJECT_REPR(prev_stop)->duplicate(SP_OBJECT_REPR(vector)->document()); SP_OBJECT_REPR(vector)->addChild(new_stop_repr, SP_OBJECT_REPR(prev_stop)); @@ -547,8 +569,7 @@ sp_vector_add_stop (SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gf return newstop; } -void -sp_item_gradient_edit_stop (SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) +void sp_item_gradient_edit_stop(SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) { SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -588,8 +609,7 @@ sp_item_gradient_edit_stop (SPItem *item, guint point_type, guint point_i, bool } } -guint32 -sp_item_gradient_stop_query_style (SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) +guint32 sp_item_gradient_stop_query_style(SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) { SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -641,9 +661,11 @@ sp_item_gradient_stop_query_style (SPItem *item, guint point_type, guint point_i return 0; } -void -sp_item_gradient_stop_set_style (SPItem *item, guint point_type, guint point_i, bool fill_or_stroke, SPCSSAttr *stop) +void sp_item_gradient_stop_set_style(SPItem *item, guint point_type, guint point_i, bool fill_or_stroke, SPCSSAttr *stop) { +#ifdef SP_GR_VERBOSE + g_message("sp_item_gradient_stop_set_style(%p, %d, %d, %d, %p)", item, point_type, point_i, fill_or_stroke, stop); +#endif SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); if (!gradient || !SP_IS_GRADIENT(gradient)) @@ -698,9 +720,11 @@ sp_item_gradient_stop_set_style (SPItem *item, guint point_type, guint point_i, } } -void -sp_item_gradient_reverse_vector (SPItem *item, bool fill_or_stroke) +void sp_item_gradient_reverse_vector(SPItem *item, bool fill_or_stroke) { +#ifdef SP_GR_VERBOSE + g_message("sp_item_gradient_reverse_vector(%p, %d)", item, fill_or_stroke); +#endif SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); if (!gradient || !SP_IS_GRADIENT(gradient)) return; @@ -756,9 +780,11 @@ sp_item_gradient_reverse_vector (SPItem *item, bool fill_or_stroke) Set the position of point point_type of the gradient applied to item (either fill_or_stroke) to p_w (in desktop coordinates). Write_repr if you want the change to become permanent. */ -void -sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom::Point p_w, bool fill_or_stroke, bool write_repr, bool scale) +void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, Geom::Point p_w, bool fill_or_stroke, bool write_repr, bool scale) { +#ifdef SP_GR_VERBOSE + g_message("sp_item_gradient_set_coords(%p, %d, %d, ...)", item, point_type, point_i ); +#endif SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); if (!gradient || !SP_IS_GRADIENT(gradient)) @@ -953,8 +979,7 @@ sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom } } -SPGradient * -sp_item_gradient_get_vector (SPItem *item, bool fill_or_stroke) +SPGradient *sp_item_gradient_get_vector(SPItem *item, bool fill_or_stroke) { SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -964,8 +989,7 @@ sp_item_gradient_get_vector (SPItem *item, bool fill_or_stroke) return NULL; } -SPGradientSpread -sp_item_gradient_get_spread (SPItem *item, bool fill_or_stroke) +SPGradientSpread sp_item_gradient_get_spread(SPItem *item, bool fill_or_stroke) { SPGradientSpread spread = SP_GRADIENT_SPREAD_PAD; SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -982,9 +1006,11 @@ Returns the position of point point_type of the gradient applied to item (either in desktop coordinates. */ -Geom::Point -sp_item_gradient_get_coords (SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) +Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint point_i, bool fill_or_stroke) { +#ifdef SP_GR_VERBOSE + g_message("sp_item_gradient_get_coords(%p, %d, %d, %d)", item, point_type, point_i, fill_or_stroke); +#endif SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); Geom::Point p (0, 0); @@ -1058,9 +1084,11 @@ sp_item_gradient_get_coords (SPItem *item, guint point_type, guint point_i, bool * gr has to be a normalized vector. */ -SPGradient * -sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType type, bool is_fill) +SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType type, bool is_fill) { +#ifdef SP_GR_VERBOSE + g_message("sp_item_set_gradient(%p, %p, %d, %d)", item, gr, type, is_fill); +#endif g_return_val_if_fail(item != NULL, NULL); g_return_val_if_fail(SP_IS_ITEM(item), NULL); g_return_val_if_fail(gr != NULL, NULL); @@ -1129,6 +1157,9 @@ sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType type, bool is_ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *link) { +#ifdef SP_GR_VERBOSE + g_message("sp_gradient_repr_set_link(%p, %p)", repr, link); +#endif g_return_if_fail(repr != NULL); if (link) { g_return_if_fail(SP_IS_GRADIENT(link)); @@ -1146,6 +1177,9 @@ static void sp_gradient_repr_set_link(Inkscape::XML::Node *repr, SPGradient *lin static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gint opacity, gchar const *offset ) { +#ifdef SP_GR_VERBOSE + g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset); +#endif Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); { gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%d;", color.c_str(), opacity ); -- cgit v1.2.3 From 5f7ed483da0360e83ac618dcab6c20731394dbfe Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 6 Jul 2010 07:13:17 +0200 Subject: =?UTF-8?q?Translations.=20New=20Telugu=20translation=20by=20?= =?UTF-8?q?=E0=B0=B5=E0=B1=80=E0=B0=B5=E0=B1=86=E0=B0=A8=E0=B1=8D=20(Veeve?= =?UTF-8?q?n).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (bzr r9581) --- src/ui/dialog/inkscape-preferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 3c48a7972..866ae01e5 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1116,11 +1116,11 @@ void InkscapePreferences::initPageUI() _("Mongolian (mn)"), _("Nepali (ne)"), _("Norwegian BokmÃ¥l (nb)"), _("Norwegian Nynorsk (nn)"), _("Panjabi (pa)"), _("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"), _("Romanian (ro)"), _("Russian (ru)"), _("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"), - _("Swedish (sv)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")}; + _("Swedish (sv)"),_("Telugu (te_IN)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")}; Glib::ustring langValues[] = {"", "sq", "am", "ar", "hy", "az", "eu", "be", "bg", "bn", "br", "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs", "da", "nl", "dz", "de", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et", "fa", "fi", "fr", "ga", "gl", "he", "hu", "id", "it", "ja", "km", "rw", "ko", "lt", "mk", "mn", "ne", "nb", "nn", "pa", - "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "th", "tr", "uk", "vi" }; + "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te_IN", "th", "tr", "uk", "vi" }; _ui_languages.init( "/ui/language", languages, langValues, G_N_ELEMENTS(languages), languages[0]); _page_ui.add_line( false, _("Language (requires restart):"), _ui_languages, "", -- cgit v1.2.3 From 8f6879f2ede34a0783f72b2276d4318f5b112900 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 6 Jul 2010 01:28:56 -0700 Subject: Removed "Add" and enabled "Delete" for swatch context menu. Updated swatch marker string. (bzr r9582) --- src/sp-gradient.cpp | 32 +++++++++++++++++++++------ src/sp-gradient.h | 2 +- src/ui/dialog/swatches.cpp | 55 +++++++++++++++++++--------------------------- 3 files changed, 48 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 9c1ea0da7..2a3142b04 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -288,15 +288,19 @@ SPGradientSpread SPGradient::getSpread() const return spread; } -void SPGradient::setSwatch() +void SPGradient::setSwatch( bool swatch ) { - if ( !isSwatch() ) { - if ( hasStops() && (getStopCount() == 0) ) { - repr->setAttribute("osb:paint", "solid"); + if ( swatch != isSwatch() ) { + if ( swatch ) { + if ( hasStops() && (getStopCount() == 0) ) { + repr->setAttribute( "osb:paint", "solid" ); + } else { + repr->setAttribute( "osb:paint", "gradient" ); + } } else { - repr->setAttribute("osb:paint", "gradient"); + repr->setAttribute( "osb:paint", 0 ); } - requestModified(SP_OBJECT_MODIFIED_FLAG); + requestModified( SP_OBJECT_MODIFIED_FLAG ); } } @@ -594,12 +598,19 @@ void SPGradientImpl::childAdded(SPObject *object, Inkscape::XML::Node *child, In gr->invalidateVector(); - if (((SPObjectClass *) gradient_parent_class)->child_added) + if (((SPObjectClass *) gradient_parent_class)->child_added) { (* ((SPObjectClass *) gradient_parent_class)->child_added)(object, child, ref); + } SPObject *ochild = sp_object_get_child_by_repr(object, child); if ( ochild && SP_IS_STOP(ochild) ) { gr->has_stops = TRUE; + if ( gr->getStopCount() > 0 ) { + gchar const * attr = gr->repr->attribute("osb:paint"); + if ( attr && !strcmp(attr, "solid") ) { + gr->repr->setAttribute("osb:paint", "gradient"); + } + } } /// \todo Fixme: should we schedule "modified" here? @@ -628,6 +639,13 @@ void SPGradientImpl::removeChild(SPObject *object, Inkscape::XML::Node *child) } } + if ( gr->getStopCount() == 0 ) { + gchar const * attr = gr->repr->attribute("osb:paint"); + if ( attr && !strcmp(attr, "gradient") ) { + gr->repr->setAttribute("osb:paint", "solid"); + } + } + /* Fixme: should we schedule "modified" here? */ object->requestModified(SP_OBJECT_MODIFIED_FLAG); } diff --git a/src/sp-gradient.h b/src/sp-gradient.h index f1705f1c1..b05cb5fb8 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -142,7 +142,7 @@ public: SPGradientSpread fetchSpread(); SPGradientUnits fetchUnits(); - void setSwatch(); + void setSwatch(bool swatch = true); private: bool invalidateVector(); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 70e3800a0..e70cdaccf 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -74,7 +74,7 @@ class SwatchesPanelHook : public SwatchesPanel { public: static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); - static void addNewGradient( GtkMenuItem *menuitem, gpointer user_data ); + static void deleteGradient( GtkMenuItem *menuitem, gpointer userData ); }; static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { @@ -141,53 +141,46 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) } } -void SwatchesPanelHook::addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) +void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) { if ( bounceTarget ) { SwatchesPanel* swp = bouncePanel; SPDesktop* desktop = swp ? swp->getDesktop() : 0; SPDocument *doc = desktop ? desktop->doc() : 0; - if (doc) { - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); - SPGradient * gr = 0; - { - Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); - Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); - stop->setAttribute("offset", "0"); - stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); - repr->appendChild(stop); - Inkscape::GC::release(stop); - - SP_OBJECT_REPR( SP_DOCUMENT_DEFS(doc) )->addChild(repr, NULL); + gint index = GPOINTER_TO_INT(userData); + if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { + Glib::ustring targetName = popupItems[index]; - gr = static_cast(doc->getObjectByRepr(repr)); - Inkscape::GC::release(repr); + const GSList *gradients = sp_document_get_resource_list(doc, "gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + grad->setSwatch(); + sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, + _("Add gradient stop")); + break; + } } - - gr->setSwatch(); - - editGradientImpl( gr ); } } } -void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) +void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ ) { if ( bounceTarget ) { SwatchesPanel* swp = bouncePanel; SPDesktop* desktop = swp ? swp->getDesktop() : 0; SPDocument *doc = desktop ? desktop->doc() : 0; - gint index = GPOINTER_TO_INT(userData); - if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { - Glib::ustring targetName = popupItems[index]; - + if (doc) { + std::string targetName(bounceTarget->def.descr); const GSList *gradients = sp_document_get_resource_list(doc, "gradient"); for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( targetName == grad->getId() ) { - grad->setSwatch(); + //editGradientImpl( grad ); + grad->setSwatch(false); sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, - _("Add gradient stop")); + _("Delete")); break; } } @@ -250,17 +243,13 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); popupExtras.push_back(child); - child = gtk_menu_item_new_with_label(_("Add")); + child = gtk_menu_item_new_with_label(_("Delete")); g_signal_connect( G_OBJECT(child), "activate", - G_CALLBACK(SwatchesPanelHook::addNewGradient), + G_CALLBACK(SwatchesPanelHook::deleteGradient), user_data ); gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); popupExtras.push_back(child); - - child = gtk_menu_item_new_with_label(_("Delete")); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - //popupExtras.push_back(child); gtk_widget_set_sensitive( child, FALSE ); child = gtk_menu_item_new_with_label(_("Edit...")); -- cgit v1.2.3 From 35189a0c69d1607643ea58e725979aa6ec28223c Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 6 Jul 2010 01:31:47 -0700 Subject: Minor cruft cleanup. (bzr r9583) --- src/ui/dialog/swatches.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index e70cdaccf..2f24fe2c4 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -177,7 +177,6 @@ void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*us for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( targetName == grad->getId() ) { - //editGradientImpl( grad ); grad->setSwatch(false); sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT, _("Delete")); -- cgit v1.2.3 From c08d3bc95f873450ce0f31b3c920b1b8fd8412f9 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 6 Jul 2010 02:15:40 -0700 Subject: If 'Edit' on a swatch matches the current selection, invoke Fill-and-Stroke instead of gradient dialog. (bzr r9584) --- src/ui/dialog/swatches.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 2f24fe2c4..29e480e24 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -50,7 +50,7 @@ #include "widgets/eek-preview.h" #include "display/nr-plain-stuff.h" #include "sp-gradient-reference.h" - +#include "dialog-manager.h" namespace Inkscape { namespace UI { @@ -113,11 +113,37 @@ static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) } } -static void editGradientImpl( SPGradient* gr ) +static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) { if ( gr ) { - GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); - gtk_widget_show( dialog ); + bool shown = false; + if ( desktop && desktop->doc() ) { + Inkscape::Selection *selection = sp_desktop_selection( desktop ); + GSList const *items = selection->itemList(); + if (items) { + SPStyle *query = sp_style_new( desktop->doc() ); + int result = objects_query_fillstroke(const_cast(items), query, true); + if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) { + // could be pertinent + if (query->fill.isPaintserver()) { + SPPaintServer* server = query->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* grad = SP_GRADIENT(server); + if ( grad->isSwatch() && grad->getId() == gr->getId()) { + desktop->_dlg_mgr->showDialog("FillAndStroke"); + shown = true; + } + } + } + } + sp_style_unref(query); + } + } + + if (!shown) { + GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); + gtk_widget_show( dialog ); + } } } @@ -133,7 +159,7 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) for (const GSList *item = gradients; item; item = item->next) { SPGradient* grad = SP_GRADIENT(item->data); if ( targetName == grad->getId() ) { - editGradientImpl( grad ); + editGradientImpl( desktop, grad ); break; } } -- cgit v1.2.3 From ac41ce79eb1cc54e2628aa0bdbf12e40a896064a Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Tue, 6 Jul 2010 18:50:10 -0700 Subject: Patch by Johan for LPE Tool prefs page (bzr r9585) --- src/ui/dialog/inkscape-preferences.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 866ae01e5..8f5194eda 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -540,8 +540,9 @@ void InkscapePreferences::initPageTools() this->AddNewObjectsStyle(_page_eraser, "/tools/eraser"); //LPETool - this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL); - this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool"); + // commented out, because the LPETool is not finished yet. + //this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL); + //this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool"); //Text this->AddPage(_page_text, _("Text"), iter_tools, PREFS_PAGE_TOOLS_TEXT); -- cgit v1.2.3 From f20676dc6455b3475ab8729fddf04c2fe64b7c1e Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 6 Jul 2010 22:03:34 -0700 Subject: Tuning fill-n-stroke to support non-solid swatches. (bzr r9586) --- src/widgets/gradient-selector.cpp | 93 ++++++++++++++++++++++----------------- src/widgets/gradient-selector.h | 4 ++ src/widgets/gradient-vector.cpp | 5 +++ src/widgets/paint-selector.cpp | 3 +- src/widgets/swatch-selector.cpp | 6 ++- 5 files changed, 67 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 77defa5c9..5b663c493 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -117,10 +117,10 @@ sp_gradient_selector_class_init (SPGradientSelectorClass *klass) object_class->destroy = sp_gradient_selector_destroy; } -static void -sp_gradient_selector_init (SPGradientSelector *sel) +static void sp_gradient_selector_init(SPGradientSelector *sel) { - GtkWidget *hb, *m, *mi; + sel->safelyInit = true; + new (&sel->nonsolid) std::vector(); sel->mode = SPGradientSelector::MODE_LINEAR; @@ -134,39 +134,44 @@ sp_gradient_selector_init (SPGradientSelector *sel) g_signal_connect (G_OBJECT (sel->vectors), "vector_set", G_CALLBACK (sp_gradient_selector_vector_set), sel); /* Create box for buttons */ - hb = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (sel), hb, FALSE, FALSE, 0); + GtkWidget *hb = gtk_hbox_new( FALSE, 0 ); + sel->nonsolid.push_back(hb); + gtk_box_pack_start( GTK_BOX(sel), hb, FALSE, FALSE, 0 ); GtkTooltips *ttips = gtk_tooltips_new (); sel->add = gtk_button_new_with_label (_("Duplicate")); + sel->nonsolid.push_back(sel->add); gtk_box_pack_start (GTK_BOX (hb), sel->add, TRUE, TRUE, 0); g_signal_connect (G_OBJECT (sel->add), "clicked", G_CALLBACK (sp_gradient_selector_add_vector_clicked), sel); gtk_widget_set_sensitive (sel->add, FALSE); sel->edit = gtk_button_new_with_label (_("Edit...")); + sel->nonsolid.push_back(sel->edit); gtk_box_pack_start (GTK_BOX (hb), sel->edit, TRUE, TRUE, 0); g_signal_connect (G_OBJECT (sel->edit), "clicked", G_CALLBACK (sp_gradient_selector_edit_vector_clicked), sel); gtk_widget_set_sensitive (sel->edit, FALSE); - gtk_widget_show_all (hb); + gtk_widget_show_all(hb); /* Spread selector */ - hb = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hb); - gtk_box_pack_start (GTK_BOX (sel), hb, FALSE, FALSE, 0); - - sel->spread = gtk_option_menu_new (); - gtk_widget_show (sel->spread); - gtk_box_pack_end (GTK_BOX (hb), sel->spread, FALSE, FALSE, 0); - gtk_tooltips_set_tip (ttips, sel->spread, + hb = gtk_hbox_new( FALSE, 0 ); + sel->nonsolid.push_back(hb); + gtk_widget_show(hb); + gtk_box_pack_start( GTK_BOX(sel), hb, FALSE, FALSE, 0 ); + + sel->spread = gtk_option_menu_new(); + sel->nonsolid.push_back(sel->spread); + gtk_widget_show(sel->spread); + gtk_box_pack_end( GTK_BOX(hb), sel->spread, FALSE, FALSE, 0 ); + gtk_tooltips_set_tip( ttips, sel->spread, // TRANSLATORS: for info, see http://www.w3.org/TR/2000/CR-SVG-20000802/pservers.html#LinearGradientSpreadMethodAttribute _("Whether to fill with flat color beyond the ends of the gradient vector " "(spreadMethod=\"pad\"), or repeat the gradient in the same direction " "(spreadMethod=\"repeat\"), or repeat the gradient in alternating opposite " "directions (spreadMethod=\"reflect\")"), NULL); - m = gtk_menu_new (); - mi = gtk_menu_item_new_with_label (_("none")); + GtkWidget *m = gtk_menu_new(); + GtkWidget *mi = gtk_menu_item_new_with_label(_("none")); gtk_menu_append (GTK_MENU (m), mi); g_object_set_data (G_OBJECT (mi), "gradientSpread", GUINT_TO_POINTER (SP_GRADIENT_SPREAD_PAD)); g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (sp_gradient_selector_spread_activate), sel); @@ -180,22 +185,27 @@ sp_gradient_selector_init (SPGradientSelector *sel) gtk_menu_append (GTK_MENU (m), mi); gtk_widget_show_all (m); - gtk_option_menu_set_menu (GTK_OPTION_MENU (sel->spread), m); + gtk_option_menu_set_menu( GTK_OPTION_MENU(sel->spread), m ); - sel->spreadLbl = gtk_label_new (_("Repeat:")); - gtk_widget_show(sel->spreadLbl); - gtk_box_pack_end(GTK_BOX(hb), sel->spreadLbl, FALSE, FALSE, 4); + sel->spreadLbl = gtk_label_new( _("Repeat:") ); + sel->nonsolid.push_back(sel->spreadLbl); + gtk_widget_show( sel->spreadLbl ); + gtk_box_pack_end( GTK_BOX(hb), sel->spreadLbl, FALSE, FALSE, 4 ); } -static void -sp_gradient_selector_destroy (GtkObject *object) +static void sp_gradient_selector_destroy(GtkObject *object) { - SPGradientSelector *sel; + SPGradientSelector *sel = SP_GRADIENT_SELECTOR( object ); - sel = SP_GRADIENT_SELECTOR (object); + if ( sel->safelyInit ) { + sel->safelyInit = false; + using std::vector; + sel->nonsolid.~vector(); + } - if (((GtkObjectClass *) (parent_class))->destroy) + if (((GtkObjectClass *) (parent_class))->destroy) { (* ((GtkObjectClass *) (parent_class))->destroy) (object); + } } GtkWidget * @@ -208,26 +218,15 @@ sp_gradient_selector_new (void) return (GtkWidget *) sel; } -static void removeWidget( GtkWidget *& widget ) -{ - if (widget) { - GtkWidget *parent = gtk_widget_get_parent(widget); - if (parent) { - gtk_container_remove(GTK_CONTAINER(parent), widget); - widget = 0; - } - } -} - void SPGradientSelector::setMode(SelectorMode mode) { if (mode != this->mode) { this->mode = mode; if (mode == MODE_SWATCH) { - removeWidget(add); - removeWidget(edit); - removeWidget(spread); - removeWidget(spreadLbl); + for (std::vector::iterator it = nonsolid.begin(); it != nonsolid.end(); ++it) + { + gtk_widget_hide(*it); + } SPGradientVectorSelector* vs = SP_GRADIENT_VECTOR_SELECTOR(vectors); vs->setSwatched(); @@ -269,6 +268,20 @@ void SPGradientSelector::setVector(SPDocument *doc, SPGradient *vector) sp_gradient_vector_selector_set_gradient(SP_GRADIENT_VECTOR_SELECTOR(vectors), doc, vector); if (vector) { + if ( (mode == MODE_SWATCH) && vector->isSwatch() ) { + if ( vector->isSolid() ) { + for (std::vector::iterator it = nonsolid.begin(); it != nonsolid.end(); ++it) + { + gtk_widget_hide(*it); + } + } else { + for (std::vector::iterator it = nonsolid.begin(); it != nonsolid.end(); ++it) + { + gtk_widget_show_all(*it); + } + } + } + if (edit) { gtk_widget_set_sensitive(edit, TRUE); } diff --git a/src/widgets/gradient-selector.h b/src/widgets/gradient-selector.h index 25f561a6e..860804ec6 100644 --- a/src/widgets/gradient-selector.h +++ b/src/widgets/gradient-selector.h @@ -17,6 +17,7 @@ #include #include +#include #include "sp-gradient.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" @@ -59,6 +60,9 @@ struct SPGradientSelector { GtkWidget *spread; GtkWidget *spreadLbl; + bool safelyInit; + std::vector nonsolid; + void setMode(SelectorMode mode); void setUnits(SPGradientUnits units); void setSpread(SPGradientSpread spread); diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 454c12001..c49d9e06f 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -174,6 +174,10 @@ GtkWidget *sp_gradient_vector_selector_new(SPDocument *doc, SPGradient *gr) void sp_gradient_vector_selector_set_gradient(SPGradientVectorSelector *gvs, SPDocument *doc, SPGradient *gr) { +// g_message("sp_gradient_vector_selector_set_gradient(%p, %p, %p) [%s] %d %d", gvs, doc, gr, +// (gr ? gr->getId():"N/A"), +// (gr ? gr->isSwatch() : -1), +// (gr ? gr->isSolid() : -1)); static gboolean suppress = FALSE; g_return_if_fail(gvs != NULL); @@ -337,6 +341,7 @@ static void sp_gvs_gradient_activate(GtkMenuItem *mi, SPGradientVectorSelector * /* Hmmm - probably we can just re-set it as menuitem data (Lauris) */ //g_print("SPGradientVectorSelector: gradient %s activated\n", SP_OBJECT_ID(gr)); + //g_message("Setting to gradient %p swatch:%d solid:%d", gr, gr->isSwatch(), gr->isSolid()); norm = sp_gradient_ensure_vector_normalized(gr); if (norm != gr) { diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index a569d00bb..cf6a04a3c 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -1082,11 +1082,10 @@ static void sp_paint_selector_set_mode_swatch(SPPaintSelector *psel, SPPaintSele SwatchSelector *swatchsel = 0; if (psel->mode == SPPaintSelector::MODE_SWATCH){ - /* Already have pattern menu */ swatchsel = static_cast(g_object_get_data(G_OBJECT(psel->selector), "swatch-selector")); } else { sp_paint_selector_clear_frame(psel); - /* Create new gradient selector */ + // Create new gradient selector SwatchSelector *swatchsel = new SwatchSelector(); swatchsel->show(); diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index ce0f8a810..88abca358 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -169,10 +169,9 @@ void SwatchSelector::connectchangedHandler( GCallback handler, void *data ) void SwatchSelector::setVector(SPDocument */*doc*/, SPGradient *vector) { //GtkVBox * box = gobj(); - _gsel->setVector((vector) ? SP_OBJECT_DOCUMENT(vector) : 0, vector); - if (vector) { + if ( vector && vector->isSolid() ) { SPStop* stop = vector->getFirstStop(); guint32 const colorVal = sp_stop_get_rgba32(stop); @@ -180,6 +179,9 @@ void SwatchSelector::setVector(SPDocument */*doc*/, SPGradient *vector) SPColor color( SP_RGBA32_R_F(colorVal), SP_RGBA32_G_F(colorVal), SP_RGBA32_B_F(colorVal) ); // set its color, from the stored array _csel->base->setColor( color ); + gtk_widget_show_all( GTK_WIDGET(_csel) ); + } else { + gtk_widget_hide( GTK_WIDGET(_csel) ); } /* -- cgit v1.2.3 From 9562e69ff5bc24fdaed1bbbbf5691054a0b297e2 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Wed, 7 Jul 2010 00:41:42 -0700 Subject: Revert device-color for now. "commit the awesomesauce" (bzr r9587) --- src/color.cpp | 54 ++------------------- src/color.h | 2 - src/desktop-style.cpp | 26 ---------- src/style.cpp | 12 ----- src/svg/Makefile_insert | 1 - src/svg/svg-color.cpp | 105 ---------------------------------------- src/svg/svg-color.h | 3 -- src/svg/svg-device-color.h | 26 ---------- src/widgets/sp-color-scales.cpp | 26 +++------- 9 files changed, 10 insertions(+), 245 deletions(-) delete mode 100644 src/svg/svg-device-color.h (limited to 'src') diff --git a/src/color.cpp b/src/color.cpp index 07c15ff15..ae1bfa05d 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -17,7 +17,6 @@ #include #include "color.h" #include "svg/svg-icc-color.h" -#include "svg/svg-device-color.h" #include "svg/svg-color.h" #include "svg/css-ostringstream.h" @@ -30,8 +29,7 @@ static bool profileMatches( SVGICCColor const* first, SVGICCColor const* second #define PROFILE_EPSILON 0.00000001 SPColor::SPColor() : - icc(0), - device(0) + icc(0) { v.c[0] = 0; v.c[1] = 0; @@ -39,22 +37,19 @@ SPColor::SPColor() : } SPColor::SPColor( SPColor const& other ) : - icc(0), - device(0) + icc(0) { *this = other; } SPColor::SPColor( float r, float g, float b ) : - icc(0), - device(0) + icc(0) { set( r, g, b ); } SPColor::SPColor( guint32 value ) : - icc(0), - device(0) + icc(0) { set( value ); } @@ -62,16 +57,13 @@ SPColor::SPColor( guint32 value ) : SPColor::~SPColor() { delete icc; - delete device; icc = 0; - device = 0; } SPColor& SPColor::operator= (SPColor const& other) { SVGICCColor* tmp_icc = other.icc ? new SVGICCColor(*other.icc) : 0; - SVGDeviceColor* tmp_device = other.device ? new SVGDeviceColor(*other.device) : 0; v.c[0] = other.v.c[0]; v.c[1] = other.v.c[1]; @@ -81,11 +73,6 @@ SPColor& SPColor::operator= (SPColor const& other) } icc = tmp_icc; - if ( device ) { - delete device; - } - device = tmp_device; - return *this; } @@ -100,7 +87,6 @@ bool SPColor::operator == (SPColor const& other) const && (v.c[2] != other.v.c[2]); match &= profileMatches( icc, other.icc ); -//TODO?: match &= devicecolorMatches( device, other.device ); return match; } @@ -219,38 +205,6 @@ std::string SPColor::toString() const css << ')'; } - if ( device && device->type != DEVICE_COLOR_INVALID) { - if ( !css.str().empty() ) { - css << " "; - } - - switch(device->type){ - case DEVICE_GRAY: - css << "device-gray("; - break; - case DEVICE_RGB: - css << "device-rgb("; - break; - case DEVICE_CMYK: - css << "device-cmyk("; - break; - case DEVICE_NCHANNEL: - css << "device-nchannel("; - break; - case DEVICE_COLOR_INVALID: - //should not be reached - break; - } - - for (vector::const_iterator i(device->colors.begin()), - iEnd(device->colors.end()); - i != iEnd; ++i) { - if (i!=device->colors.begin()) css << ", "; - css << *i; - } - css << ')'; - } - return css.str(); } diff --git a/src/color.h b/src/color.h index 7fd351360..bebeaec60 100644 --- a/src/color.h +++ b/src/color.h @@ -34,7 +34,6 @@ #define SP_RGBA32_F_COMPOSE(r,g,b,a) SP_RGBA32_U_COMPOSE (SP_COLOR_F_TO_U (r), SP_COLOR_F_TO_U (g), SP_COLOR_F_TO_U (b), SP_COLOR_F_TO_U (a)) struct SVGICCColor; -struct SVGDeviceColor; /** * An RGB color with optional icc-color part @@ -60,7 +59,6 @@ struct SPColor { std::string toString() const; SVGICCColor* icc; - SVGDeviceColor* device; union { float c[3]; } v; diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index e11fa1493..5866b14fb 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -44,7 +44,6 @@ #include "desktop-style.h" #include "svg/svg-icc-color.h" -#include "svg/svg-device-color.h" #include "box3d-side.h" /** @@ -466,7 +465,6 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill paint_res->set = TRUE; SVGICCColor* iccColor = 0; - SVGDeviceColor* devColor = 0; bool iccSeen = false; gfloat c[4]; @@ -570,22 +568,6 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill c[2] += d[2]; c[3] += SP_SCALE24_TO_FLOAT (isfill? style->fill_opacity.value : style->stroke_opacity.value); - // average device color - unsigned int it; - if (i==objects /*if this is the first object in the GList*/ - && paint->value.color.device){ - devColor = new SVGDeviceColor(*paint->value.color.device); - for (it=0; it < paint->value.color.device->colors.size(); it++){ - devColor->colors[it] = 0; - } - } - - if (devColor && paint->value.color.device && paint->value.color.device->type == devColor->type){ - for (it=0; it < paint->value.color.device->colors.size(); it++){ - devColor->colors[it] += paint->value.color.device->colors[it]; - } - } - num ++; } @@ -625,14 +607,6 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill paint_res->value.color.icc = tmp; } - // divide and store the device-color - if (devColor){ - for (unsigned int it=0; it < devColor->colors.size(); it++){ - devColor->colors[it] /= num; - } - paint_res->value.color.device = devColor; - } - if (num > 1) { if (same_color) return QUERY_STYLE_MULTIPLE_SAME; diff --git a/src/style.cpp b/src/style.cpp index 2b5804671..ffc1fb0ae 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -28,7 +28,6 @@ #include "svg/svg.h" #include "svg/svg-color.h" #include "svg/svg-icc-color.h" -#include "svg/svg-device-color.h" #include "display/canvas-bpath.h" #include "attributes.h" @@ -3259,17 +3258,6 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume } paint->value.color.icc = tmp; } - if (strneq(str, "device-gray(", 12) || - strneq(str, "device-rgb(", 11) || - strneq(str, "device-cmyk(", 12) || - strneq(str, "device-nchannel(", 16)) { - SVGDeviceColor* tmp = new SVGDeviceColor(); - if ( ! sp_svg_read_device_color( str, &str, tmp ) ) { - delete tmp; - tmp = 0; - } - paint->value.color.device = tmp; - } } } } diff --git a/src/svg/Makefile_insert b/src/svg/Makefile_insert index c27b2291c..265210a45 100644 --- a/src/svg/Makefile_insert +++ b/src/svg/Makefile_insert @@ -14,7 +14,6 @@ ink_common_sources += \ svg/svg-affine.cpp \ svg/svg-color.cpp \ svg/svg-color.h \ - svg/svg-device-color.h \ svg/svg-icc-color.h \ svg/svg-length.cpp \ svg/svg-length.h \ diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp index 7d43b68ee..04f387798 100644 --- a/src/svg/svg-color.cpp +++ b/src/svg/svg-color.cpp @@ -35,7 +35,6 @@ #include "preferences.h" #include "svg-color.h" #include "svg-icc-color.h" -#include "svg-device-color.h" #if ENABLE_LCMS #include @@ -606,110 +605,6 @@ bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest ) return sp_svg_read_icc_color(str, NULL, dest); } -bool sp_svg_read_device_color( gchar const *str, gchar const **end_ptr, SVGDeviceColor* dest) -{ - bool good = true; - unsigned int max_colors; - - if ( end_ptr ) { - *end_ptr = str; - } - if ( dest ) { - dest->colors.clear(); - } - - if ( !str ) { - // invalid input - good = false; - } else { - while ( g_ascii_isspace(*str) ) { - str++; - } - - dest->type = DEVICE_COLOR_INVALID; - if (strneq( str, "device-gray(", 12 )){ - dest->type = DEVICE_GRAY; - max_colors=1; - str += 12; - } - - if (strneq( str, "device-rgb(", 11 )){ - dest->type = DEVICE_RGB; - max_colors=3; - str += 11; - } - - if (strneq( str, "device-cmyk(", 12 )){ - dest->type = DEVICE_CMYK; - max_colors=4; - str += 12; - } - - if (strneq( str, "device-nchannel(", 16 )){ - dest->type = DEVICE_NCHANNEL; - max_colors=0; - str += 16; - } - - if ( dest->type != DEVICE_COLOR_INVALID ) { - while ( g_ascii_isspace(*str) ) { - str++; - } - - while ( *str && *str != ')' ) { - if ( g_ascii_isdigit(*str) || *str == '.' || *str == '-' || *str == '+') { - gchar* endPtr = 0; - gdouble dbl = g_ascii_strtod( str, &endPtr ); - if ( !errno ) { - if ( dest ) { - dest->colors.push_back( dbl ); - } - str = endPtr; - } else { - good = false; - break; - } - - while ( g_ascii_isspace(*str) || *str == ',' ) { - str++; - } - } else { - break; - } - } - } - - // We need to have ended on a closing parenthesis - if ( good ) { - while ( g_ascii_isspace(*str) ) { - str++; - } - good &= (*str == ')'); - } - } - - if ( dest->colors.size() == 0) good=false; - if ( dest->type != DEVICE_NCHANNEL && (dest->colors.size() != max_colors)) good=false; - - if ( good ) { - if ( end_ptr ) { - *end_ptr = str; - } - } else { - if ( dest ) { - dest->type = DEVICE_COLOR_INVALID; - dest->colors.clear(); - } - } - - return good; -} - - -bool sp_svg_read_device_color( gchar const *str, SVGDeviceColor* dest) -{ - return sp_svg_read_device_color(str, NULL, dest); -} /* Local Variables: diff --git a/src/svg/svg-color.h b/src/svg/svg-color.h index f4e534652..a3868c149 100644 --- a/src/svg/svg-color.h +++ b/src/svg/svg-color.h @@ -4,7 +4,6 @@ #include class SVGICCColor; -class SVGDeviceColor; guint32 sp_svg_read_color(gchar const *str, unsigned int dfl); guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 def); @@ -12,8 +11,6 @@ void sp_svg_write_color(char *buf, unsigned int buflen, unsigned int rgba32); bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor* dest ); bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest ); -bool sp_svg_read_device_color( gchar const *str, gchar const **end_ptr, SVGDeviceColor* dest ); -bool sp_svg_read_device_color( gchar const *str, SVGDeviceColor* dest ); void icc_color_to_sRGB(SVGICCColor* dest, guchar* r, guchar* g, guchar* b); #endif /* !SVG_SVG_COLOR_H_SEEN */ diff --git a/src/svg/svg-device-color.h b/src/svg/svg-device-color.h deleted file mode 100644 index 305133ed3..000000000 --- a/src/svg/svg-device-color.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SVG_DEVICE_COLOR_H_SEEN -#define SVG_DEVICE_COLOR_H_SEEN - -#include -#include - -typedef enum {DEVICE_COLOR_INVALID, DEVICE_GRAY, DEVICE_RGB, DEVICE_CMYK, DEVICE_NCHANNEL} SVGDeviceColorType; - -struct SVGDeviceColor { - SVGDeviceColorType type; - std::vector colors; -}; - - -#endif /* !SVG_DEVICE_COLOR_H_SEEN */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/widgets/sp-color-scales.cpp b/src/widgets/sp-color-scales.cpp index e41b81e5c..d20cf65ef 100644 --- a/src/widgets/sp-color-scales.cpp +++ b/src/widgets/sp-color-scales.cpp @@ -11,7 +11,6 @@ #include "../dialogs/dialog-events.h" #include "sp-color-scales.h" #include "svg/svg-icc-color.h" -#include "svg/svg-device-color.h" #define CSC_CHANNEL_R (1 << 0) #define CSC_CHANNEL_G (1 << 1) @@ -232,12 +231,6 @@ void ColorScales::_recalcColor( gboolean changing ) case SP_COLOR_SCALES_MODE_CMYK: { _getCmykaFloatv( c ); - color.device = new SVGDeviceColor(); - color.device->type=DEVICE_CMYK; - color.device->colors.clear(); - for (int i=0;i<4;i++){ - color.device->colors.push_back(c[i]); - } float rgb[3]; sp_color_cmyk_to_rgb_floatv( rgb, c[0], c[1], c[2], c[3] ); @@ -483,19 +476,12 @@ void ColorScales::setMode(SPColorScalesMode mode) gtk_widget_show (_b[4]); _updating = TRUE; - if (_color.device && _color.device->type == DEVICE_CMYK){ - setScaled( _a[0], _color.device->colors[0] ); - setScaled( _a[1], _color.device->colors[1] ); - setScaled( _a[2], _color.device->colors[2] ); - setScaled( _a[3], _color.device->colors[3] ); - } else { - //If we still dont have a device-color, convert from rbga - sp_color_rgb_to_cmyk_floatv (c, rgba[0], rgba[1], rgba[2]); - setScaled( _a[0], c[0] ); - setScaled( _a[1], c[1] ); - setScaled( _a[2], c[2] ); - setScaled( _a[3], c[3] ); - } + sp_color_rgb_to_cmyk_floatv (c, rgba[0], rgba[1], rgba[2]); + setScaled( _a[0], c[0] ); + setScaled( _a[1], c[1] ); + setScaled( _a[2], c[2] ); + setScaled( _a[3], c[3] ); + setScaled( _a[4], rgba[3] ); _updating = FALSE; _updateSliders( CSC_CHANNELS_ALL ); -- cgit v1.2.3 From 6a1c87bf0c06c67532e63a5fb2271210f4c16650 Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Wed, 7 Jul 2010 16:33:52 -0700 Subject: Disabling Print Colors dialog due to lack of resolution from mailing list thread and no response by author (bzr r9593) --- src/desktop.cpp | 4 ++-- src/desktop.h | 6 +++--- src/menus-skeleton.h | 5 +++-- src/ui/dialog/dialog-manager.cpp | 6 +++--- src/ui/dialog/print-colors-preview-dialog.cpp | 3 ++- src/verbs.cpp | 10 +++++----- src/verbs.h | 2 +- 7 files changed, 19 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index 52f172577..a93fb6a4a 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -462,9 +462,9 @@ void SPDesktop::displayModeToggle() { _setDisplayMode(Inkscape::RENDERMODE_OUTLINE); break; case Inkscape::RENDERMODE_OUTLINE: - _setDisplayMode(Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW); + _setDisplayMode(Inkscape::RENDERMODE_NORMAL); break; - case Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW: +// case Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW: default: _setDisplayMode(Inkscape::RENDERMODE_NORMAL); } diff --git a/src/desktop.h b/src/desktop.h index 00f6cfdd5..af2473baf 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -203,9 +203,9 @@ struct SPDesktop : public Inkscape::UI::View::View void setDisplayModeOutline() { _setDisplayMode(Inkscape::RENDERMODE_OUTLINE); } - void setDisplayModePrintColorsPreview() { - _setDisplayMode(Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW); - } +// void setDisplayModePrintColorsPreview() { +// _setDisplayMode(Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW); +// } void displayModeToggle(); Inkscape::RenderMode _display_mode; Inkscape::RenderMode getMode() const { return _display_mode; } diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 4e4c45b8c..9c0ca1767 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -108,8 +108,9 @@ static char const menus_skeleton[] = " \n" " \n" " \n" -" \n" -" \n" +// Better location in menu needs to be found +//" \n" +//" \n" " \n" " \n" " \n" diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 6d3bc817e..aab9d89d7 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -41,7 +41,7 @@ #include "ui/dialog/icon-preview.h" #include "ui/dialog/floating-behavior.h" #include "ui/dialog/dock-behavior.h" -#include "ui/dialog/print-colors-preview-dialog.h" +//#include "ui/dialog/print-colors-preview-dialog.h" #include "preferences.h" #ifdef ENABLE_SVG_FONTS @@ -104,7 +104,7 @@ DialogManager::DialogManager() { registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); - registerFactory("PrintColorsPreviewDialog", &create); +// registerFactory("PrintColorsPreviewDialog", &create); registerFactory("Script", &create); #ifdef ENABLE_SVG_FONTS registerFactory("SvgFontsDialog", &create); @@ -132,7 +132,7 @@ DialogManager::DialogManager() { registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); - registerFactory("PrintColorsPreviewDialog", &create); +// registerFactory("PrintColorsPreviewDialog", &create); registerFactory("Script", &create); #ifdef ENABLE_SVG_FONTS registerFactory("SvgFontsDialog", &create); diff --git a/src/ui/dialog/print-colors-preview-dialog.cpp b/src/ui/dialog/print-colors-preview-dialog.cpp index f4d83c271..1f999f692 100644 --- a/src/ui/dialog/print-colors-preview-dialog.cpp +++ b/src/ui/dialog/print-colors-preview-dialog.cpp @@ -7,7 +7,7 @@ * Copyright (C) 2009 Authors * Released under GNU GPLv2 (or later). Read the file 'COPYING' for more information. */ - +/* #include "desktop.h" #include "print-colors-preview-dialog.h" #include "preferences.h" @@ -98,3 +98,4 @@ PrintColorsPreviewDialog::~PrintColorsPreviewDialog(){} } // namespace Dialog } // namespace UI } // namespace Inkscape +*/ diff --git a/src/verbs.cpp b/src/verbs.cpp index 24c17aad8..c2af399c5 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1682,9 +1682,9 @@ ZoomVerb::perform(SPAction *action, void *data, void */*pdata*/) case SP_VERB_VIEW_MODE_OUTLINE: dt->setDisplayModeOutline(); break; - case SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW: - dt->setDisplayModePrintColorsPreview(); - break; +// case SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW: +// dt->setDisplayModePrintColorsPreview(); +// break; case SP_VERB_VIEW_MODE_TOGGLE: dt->displayModeToggle(); break; @@ -2569,8 +2569,8 @@ Verb *Verb::_base_verbs[] = { N_("Switch to normal display without filters"), NULL), new ZoomVerb(SP_VERB_VIEW_MODE_OUTLINE, "ViewModeOutline", N_("_Outline"), N_("Switch to outline (wireframe) display mode"), NULL), - new ZoomVerb(SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW, "ViewModePrintColorsPreview", N_("_Print Colors Preview"), - N_("Switch to print colors preview mode"), NULL), +// new ZoomVerb(SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW, "ViewModePrintColorsPreview", N_("_Print Colors Preview"), +// N_("Switch to print colors preview mode"), NULL), new ZoomVerb(SP_VERB_VIEW_MODE_TOGGLE, "ViewModeToggle", N_("_Toggle"), N_("Toggle between normal and outline display modes"), NULL), diff --git a/src/verbs.h b/src/verbs.h index 36bb9f9d9..7c04ba3f6 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -214,7 +214,7 @@ enum { SP_VERB_VIEW_MODE_NORMAL, SP_VERB_VIEW_MODE_NO_FILTERS, SP_VERB_VIEW_MODE_OUTLINE, - SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW, +// SP_VERB_VIEW_MODE_PRINT_COLORS_PREVIEW, SP_VERB_VIEW_MODE_TOGGLE, SP_VERB_VIEW_CMS_TOGGLE, SP_VERB_VIEW_ICON_PREVIEW, -- cgit v1.2.3 From 50f9aa34d9c9563df9002d8a70ae37a747c8f422 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 8 Jul 2010 22:02:03 -0700 Subject: Cleanup of gradient swatch property and collection policy. (bzr r9602) --- src/attributes.cpp | 1 + src/attributes.h | 1 + src/gradient-chemistry.cpp | 12 ++++--- src/sp-gradient.cpp | 78 +++++++++++++++++++++++++++++++++------------- src/sp-paint-server.cpp | 20 ++++-------- src/sp-paint-server.h | 13 ++++++-- 6 files changed, 82 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/attributes.cpp b/src/attributes.cpp index 3cfe04fab..c44a7da4e 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -280,6 +280,7 @@ static SPStyleProp const props[] = { {SP_ATTR_GRADIENTUNITS, "gradientUnits"}, {SP_ATTR_GRADIENTTRANSFORM, "gradientTransform"}, {SP_ATTR_SPREADMETHOD, "spreadMethod"}, + {SP_ATTR_OSB_SWATCH, "osb:paint"}, /* SPRadialGradient */ {SP_ATTR_FX, "fx"}, {SP_ATTR_FY, "fy"}, diff --git a/src/attributes.h b/src/attributes.h index c21087e36..aadb4d165 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -281,6 +281,7 @@ enum SPAttributeEnum { SP_ATTR_GRADIENTUNITS, SP_ATTR_GRADIENTTRANSFORM, SP_ATTR_SPREADMETHOD, + SP_ATTR_OSB_SWATCH, /* SPRadialGradient */ SP_ATTR_FX, SP_ATTR_FY, diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 8a199d4a3..974a13b5f 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -1203,11 +1203,13 @@ SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor c Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient"); - repr->setAttribute("inkscape:collect", "always"); - // set here, but removed when it's edited in the gradient editor - // to further reduce clutter, we could - // (1) here, search gradients by color and return what is found without duplication - // (2) in fill & stroke, show only one copy of each gradient in list + if ( !singleStop ) { + repr->setAttribute("inkscape:collect", "always"); + // set here, but removed when it's edited in the gradient editor + // to further reduce clutter, we could + // (1) here, search gradients by color and return what is found without duplication + // (2) in fill & stroke, show only one copy of each gradient in list + } Glib::ustring colorStr = color.toString(); addStop( repr, colorStr, 1, "0" ); diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 2a3142b04..665040616 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -291,15 +291,10 @@ SPGradientSpread SPGradient::getSpread() const void SPGradient::setSwatch( bool swatch ) { if ( swatch != isSwatch() ) { - if ( swatch ) { - if ( hasStops() && (getStopCount() == 0) ) { - repr->setAttribute( "osb:paint", "solid" ); - } else { - repr->setAttribute( "osb:paint", "gradient" ); - } - } else { - repr->setAttribute( "osb:paint", 0 ); - } + this->swatch = swatch; // to make isSolid() work, this happens first + gchar const* paintVal = swatch ? (isSolid() ? "solid" : "gradient") : 0; + sp_object_setAttribute( this, "osb:paint", paintVal, 0 ); + requestModified( SP_OBJECT_MODIFIED_FLAG ); } } @@ -438,11 +433,16 @@ void SPGradientImpl::build(SPObject *object, SPDocument *document, Inkscape::XML { SPGradient *gradient = SP_GRADIENT(object); - if (((SPObjectClass *) gradient_parent_class)->build) + // Work-around in case a swatch had been marked for immediate collection: + if ( repr->attribute("osb:paint") && repr->attribute("inkscape:collect") ) { + repr->setAttribute("inkscape:collect", 0); + } + + if (((SPObjectClass *) gradient_parent_class)->build) { (* ((SPObjectClass *) gradient_parent_class)->build)(object, document, repr); + } - SPObject *ochild; - for ( ochild = sp_object_first_child(object) ; ochild ; ochild = SP_OBJECT_NEXT(ochild) ) { + for ( SPObject *ochild = sp_object_first_child(object); ochild; ochild = ochild->next ) { if (SP_IS_STOP(ochild)) { gradient->has_stops = TRUE; break; @@ -453,6 +453,7 @@ void SPGradientImpl::build(SPObject *object, SPDocument *document, Inkscape::XML sp_object_read_attr(object, "gradientTransform"); sp_object_read_attr(object, "spreadMethod"); sp_object_read_attr(object, "xlink:href"); + sp_object_read_attr(object, "osb:paint"); /* Register ourselves */ sp_document_add_resource(document, "gradient", object); @@ -553,9 +554,31 @@ void SPGradientImpl::setGradientAttr(SPObject *object, unsigned key, gchar const gr->ref->detach(); } break; + case SP_ATTR_OSB_SWATCH: + { + bool newVal = (value != 0); + bool modified = false; + if (newVal != gr->swatch) { + gr->swatch = newVal; + modified = true; + } + if (newVal) { + // Might need to flip solid/gradient + Glib::ustring paintVal = ( gr->hasStops() && (gr->getStopCount() == 0) ) ? "solid" : "gradient"; + if ( paintVal != value ) { + sp_object_setAttribute( gr, "osb:paint", paintVal.c_str(), 0 ); + modified = true; + } + } + if (modified) { + object->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + } + break; default: - if (((SPObjectClass *) gradient_parent_class)->set) + if (((SPObjectClass *) gradient_parent_class)->set) { ((SPObjectClass *) gradient_parent_class)->set(object, key, value); + } break; } } @@ -607,8 +630,8 @@ void SPGradientImpl::childAdded(SPObject *object, Inkscape::XML::Node *child, In gr->has_stops = TRUE; if ( gr->getStopCount() > 0 ) { gchar const * attr = gr->repr->attribute("osb:paint"); - if ( attr && !strcmp(attr, "solid") ) { - gr->repr->setAttribute("osb:paint", "gradient"); + if ( attr && strcmp(attr, "gradient") ) { + sp_object_setAttribute( gr, "osb:paint", "gradient", 0 ); } } } @@ -640,9 +663,10 @@ void SPGradientImpl::removeChild(SPObject *object, Inkscape::XML::Node *child) } if ( gr->getStopCount() == 0 ) { + g_message("Check on remove"); gchar const * attr = gr->repr->attribute("osb:paint"); - if ( attr && !strcmp(attr, "gradient") ) { - gr->repr->setAttribute("osb:paint", "solid"); + if ( attr && strcmp(attr, "solid") ) { + sp_object_setAttribute( gr, "osb:paint", "solid", 0 ); } } @@ -714,15 +738,17 @@ Inkscape::XML::Node *SPGradientImpl::write(SPObject *object, Inkscape::XML::Docu { SPGradient *gr = SP_GRADIENT(object); - if (((SPObjectClass *) gradient_parent_class)->write) + if (((SPObjectClass *) gradient_parent_class)->write) { (* ((SPObjectClass *) gradient_parent_class)->write)(object, xml_doc, repr, flags); + } if (flags & SP_OBJECT_WRITE_BUILD) { GSList *l = NULL; for (SPObject *child = sp_object_first_child(object); child; child = SP_OBJECT_NEXT(child)) { - Inkscape::XML::Node *crepr; - crepr = child->updateRepr(xml_doc, NULL, flags); - if (crepr) l = g_slist_prepend(l, crepr); + Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); + if (crepr) { + l = g_slist_prepend(l, crepr); + } } while (l) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); @@ -771,6 +797,16 @@ Inkscape::XML::Node *SPGradientImpl::write(SPObject *object, Inkscape::XML::Docu } } + if ( (flags & SP_OBJECT_WRITE_EXT) && gr->isSwatch() ) { + if ( gr->isSolid() ) { + repr->setAttribute( "osb:paint", "solid" ); + } else { + repr->setAttribute( "osb:paint", "gradient" ); + } + } else { + repr->setAttribute( "osb:paint", 0 ); + } + return repr; } diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp index 5858f9a0e..4b5366a46 100644 --- a/src/sp-paint-server.cpp +++ b/src/sp-paint-server.cpp @@ -21,7 +21,6 @@ #include "xml/node.h" static void sp_paint_server_class_init(SPPaintServerClass *psc); -static void sp_paint_server_init(SPPaintServer *ps); static void sp_paint_server_release(SPObject *object); @@ -30,7 +29,7 @@ static void sp_painter_stale_fill(SPPainter *painter, NRPixBlock *pb); static SPObjectClass *parent_class; static GSList *stale_painters = NULL; -GType sp_paint_server_get_type (void) +GType SPPaintServer::getType(void) { static GType type = 0; if (!type) { @@ -43,7 +42,7 @@ GType sp_paint_server_get_type (void) NULL, /* class_data */ sizeof(SPPaintServer), 16, /* n_preallocs */ - (GInstanceInitFunc) sp_paint_server_init, + (GInstanceInitFunc) SPPaintServer::init, NULL, /* value_table */ }; type = g_type_register_static(SP_TYPE_OBJECT, "SPPaintServer", &info, (GTypeFlags) 0); @@ -58,9 +57,10 @@ static void sp_paint_server_class_init(SPPaintServerClass *psc) parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT); } -static void sp_paint_server_init(SPPaintServer *ps) +void SPPaintServer::init(SPPaintServer *ps) { ps->painters = NULL; + ps->swatch = false; } static void sp_paint_server_release(SPObject *object) @@ -157,24 +157,16 @@ static void sp_painter_stale_fill(SPPainter */*painter*/, NRPixBlock *pb) bool SPPaintServer::isSwatch() const { - bool swatch = false; - if (SP_IS_GRADIENT(this)) { - SPGradient *grad = SP_GRADIENT(this); - swatch = grad->hasStops() && repr->attribute("osb:paint"); - } return swatch; } bool SPPaintServer::isSolid() const { bool solid = false; - if (SP_IS_GRADIENT(this)) { + if (swatch && SP_IS_GRADIENT(this)) { SPGradient *grad = SP_GRADIENT(this); if ( grad->hasStops() && (grad->getStopCount() == 0) ) { - gchar const * attr = repr->attribute("osb:paint"); - if (attr && !strcmp(attr, "solid")) { - solid = true; - } + solid = true; } } return solid; diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h index a76daf4d1..dc7bcc9c5 100644 --- a/src/sp-paint-server.h +++ b/src/sp-paint-server.h @@ -21,7 +21,7 @@ class SPPainter; -#define SP_TYPE_PAINT_SERVER (sp_paint_server_get_type ()) +#define SP_TYPE_PAINT_SERVER (SPPaintServer::getType()) #define SP_PAINT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_PAINT_SERVER, SPPaintServer)) #define SP_PAINT_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_PAINT_SERVER, SPPaintServerClass)) #define SP_IS_PAINT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_PAINT_SERVER)) @@ -47,8 +47,17 @@ struct SPPaintServer : public SPObject { /** List of paints */ SPPainter *painters; +protected: + bool swatch; +public: + + static GType getType(void); + bool isSwatch() const; bool isSolid() const; + +private: + static void init(SPPaintServer *ps); }; struct SPPaintServerClass { @@ -59,8 +68,6 @@ struct SPPaintServerClass { void (* painter_free) (SPPaintServer *ps, SPPainter *painter); }; -GType sp_paint_server_get_type (void); - SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); SPPainter *sp_painter_free (SPPainter *painter); -- cgit v1.2.3 From a03928688ee7805ad8bf79e384769d983dbc451d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 10 Jul 2010 10:36:42 +0200 Subject: CSS length attributes must have units. (bzr r9605) --- src/widgets/toolbox.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index b68d8404d..bdf1e6ff2 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -6861,7 +6861,7 @@ static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl // Set css word-spacing SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream osfs; - osfs << adj->value; + osfs << adj->value << "px"; // For now always use px sp_repr_css_set_property (css, "word-spacing", osfs.str().c_str()); // Apply word-spacing to selected objects. @@ -6900,7 +6900,7 @@ static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tb // Set css letter-spacing SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream osfs; - osfs << adj->value; + osfs << adj->value << "px"; // For now always use px sp_repr_css_set_property (css, "letter-spacing", osfs.str().c_str()); // Apply letter-spacing to selected objects. -- cgit v1.2.3 From b33eae6f31e0016b7bb1d654cffce215277d3e39 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 11 Jul 2010 01:25:08 -0700 Subject: Stop setting of stops from getting url() reference colors. (bzr r9606) --- src/gradient-drag.cpp | 128 +++++++++++++++++++++++++++++++------------------- src/gradient-drag.h | 2 + src/sp-gradient.cpp | 1 + 3 files changed, 82 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 8f0010925..25309dd61 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -176,41 +176,74 @@ gr_drag_style_query (SPStyle *style, int property, gpointer data) } } -bool -gr_drag_style_set (const SPCSSAttr *css, gpointer data) +bool GrDrag::styleSet( const SPCSSAttr *css ) { - GrDrag *drag = (GrDrag *) data; - - if (!drag->selected) + if (!selected) { return false; + } - SPCSSAttr *stop = sp_repr_css_attr_new (); + SPCSSAttr *stop = sp_repr_css_attr_new(); // See if the css contains interesting properties, and if so, translate them into the format // acceptable for gradient stops // any of color properties, in order of increasing priority: - if (css->attribute("flood-color")) + if (css->attribute("flood-color")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("flood-color")); + } - if (css->attribute("lighting-color")) + if (css->attribute("lighting-color")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("lighting-color")); + } - if (css->attribute("color")) + if (css->attribute("color")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("color")); + } - if (css->attribute("stroke") && strcmp(css->attribute("stroke"), "none")) + if (css->attribute("stroke") && strcmp(css->attribute("stroke"), "none")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("stroke")); + } - if (css->attribute("fill") && strcmp(css->attribute("fill"), "none")) + if (css->attribute("fill") && strcmp(css->attribute("fill"), "none")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("fill")); + } - if (css->attribute("stop-color")) + if (css->attribute("stop-color")) { sp_repr_css_set_property (stop, "stop-color", css->attribute("stop-color")); + } + + // Make sure the style is allowed for gradient stops. + if ( !sp_repr_css_property_is_unset( stop, "stop-color") ) { + Glib::ustring tmp = sp_repr_css_property( stop, "stop-color", "" ); + Glib::ustring::size_type pos = tmp.find("url(#"); + if ( pos != Glib::ustring::npos ) { + Glib::ustring targetName = tmp.substr(pos + 5, tmp.length() - 6); + const GSList *gradients = sp_document_get_resource_list(desktop->doc(), "gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + SPGradient *vect = grad->getVector(); + SPStop *firstStop = (vect) ? vect->getFirstStop() : grad->getFirstStop(); + if (firstStop) { + Glib::ustring stopColorStr; + if (firstStop->currentColor) { + stopColorStr = sp_object_get_style_property(firstStop, "color", NULL); + } else { + stopColorStr = firstStop->specified_color.toString(); + } + if ( !stopColorStr.empty() ) { + sp_repr_css_set_property( stop, "stop-color", stopColorStr.c_str() ); + } + } + break; + } + } + } + } if (css->attribute("stop-opacity")) { // direct setting of stop-opacity has priority - sp_repr_css_set_property (stop, "stop-opacity", css->attribute("stop-opacity")); + sp_repr_css_set_property(stop, "stop-opacity", css->attribute("stop-opacity")); } else { // multiply all opacity properties: gdouble accumulated = 1.0; accumulated *= sp_svg_read_percentage(css->attribute("flood-opacity"), 1.0); @@ -220,11 +253,12 @@ gr_drag_style_set (const SPCSSAttr *css, gpointer data) Inkscape::CSSOStringStream os; os << accumulated; - sp_repr_css_set_property (stop, "stop-opacity", os.str().c_str()); + sp_repr_css_set_property(stop, "stop-opacity", os.str().c_str()); if ((css->attribute("fill") && !css->attribute("stroke") && !strcmp(css->attribute("fill"), "none")) || - (css->attribute("stroke") && !css->attribute("fill") && !strcmp(css->attribute("stroke"), "none"))) - sp_repr_css_set_property (stop, "stop-opacity", "0"); // if a single fill/stroke property is set to none, don't change color, set opacity to 0 + (css->attribute("stroke") && !css->attribute("fill") && !strcmp(css->attribute("stroke"), "none"))) { + sp_repr_css_set_property(stop, "stop-opacity", "0"); // if a single fill/stroke property is set to none, don't change color, set opacity to 0 + } } if (!stop->attributeList()) { // nothing for us here, pass it on @@ -232,13 +266,13 @@ gr_drag_style_set (const SPCSSAttr *css, gpointer data) return false; } - for (GList const* sel = drag->selected; sel != NULL; sel = sel->next) { // for all selected draggers - GrDragger* dragger = (GrDragger*) sel->data; + for (GList const* sel = selected; sel != NULL; sel = sel->next) { // for all selected draggers + GrDragger* dragger = reinterpret_cast(sel->data); for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger - GrDraggable *draggable = (GrDraggable *) i->data; + GrDraggable *draggable = reinterpret_cast(i->data); - drag->local_change = true; - sp_item_gradient_stop_set_style (draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke, stop); + local_change = true; + sp_item_gradient_stop_set_style(draggable->item, draggable->point_type, draggable->point_i, draggable->fill_or_stroke, stop); } } @@ -402,51 +436,47 @@ GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) } -GrDrag::GrDrag(SPDesktop *desktop) { - - this->desktop = desktop; - - this->selection = sp_desktop_selection(desktop); - - this->draggers = NULL; - this->lines = NULL; - this->selected = NULL; - - this->hor_levels.clear(); - this->vert_levels.clear(); - - this->local_change = false; - - this->sel_changed_connection = this->selection->connectChanged( - sigc::bind ( +GrDrag::GrDrag(SPDesktop *desktop) : + selected(0), + keep_selection(false), + local_change(false), + desktop(desktop), + hor_levels(), + vert_levels(), + draggers(0), + lines(0), + selection(sp_desktop_selection(desktop)), + sel_changed_connection(), + sel_modified_connection(), + style_set_connection(), + style_query_connection() +{ + sel_changed_connection = selection->connectChanged( + sigc::bind( sigc::ptr_fun(&gr_drag_sel_changed), (gpointer)this ) ); - this->sel_modified_connection = this->selection->connectModified( + sel_modified_connection = selection->connectModified( sigc::bind( sigc::ptr_fun(&gr_drag_sel_modified), (gpointer)this ) ); - this->style_set_connection = this->desktop->connectSetStyle( - sigc::bind( - sigc::ptr_fun(&gr_drag_style_set), - (gpointer)this ) - ); + style_set_connection = desktop->connectSetStyle( sigc::mem_fun(*this, &GrDrag::styleSet) ); - this->style_query_connection = this->desktop->connectQueryStyle( + style_query_connection = desktop->connectQueryStyle( sigc::bind( sigc::ptr_fun(&gr_drag_style_query), (gpointer)this ) ); - this->updateDraggers (); - this->updateLines (); - this->updateLevels (); + updateDraggers(); + updateLines(); + updateLevels(); if (desktop->gr_item) { - this->setSelected (getDraggerFor (desktop->gr_item, desktop->gr_point_type, desktop->gr_point_i, desktop->gr_fill_or_stroke)); + setSelected(getDraggerFor(desktop->gr_item, desktop->gr_point_type, desktop->gr_point_i, desktop->gr_fill_or_stroke)); } } diff --git a/src/gradient-drag.h b/src/gradient-drag.h index 3eb625671..22c0dbfb6 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -175,6 +175,8 @@ private: void addDraggersRadial (SPRadialGradient *rg, SPItem *item, bool fill_or_stroke); void addDraggersLinear (SPLinearGradient *lg, SPItem *item, bool fill_or_stroke); + bool styleSet( const SPCSSAttr *css ); + Inkscape::Selection *selection; sigc::connection sel_changed_connection; sigc::connection sel_modified_connection; diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 665040616..34912d1da 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -172,6 +172,7 @@ sp_stop_set(SPObject *object, unsigned key, gchar const *value) if (streq(p, "currentColor")) { stop->currentColor = true; } else { + // TODO need to properly read full color, including icc guint32 const color = sp_svg_read_color(p, 0); stop->specified_color.set( color ); } -- cgit v1.2.3 From 35300c9822f9f84c8a011913235fd4e5dc2c5ac8 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 12 Jul 2010 07:51:13 +0200 Subject: - Snap while rotating an object using the selector tool - Rename the ConstraintLine class to SnapConstraint - Move some duplicated code to 2geom (bzr r9607) --- src/2geom/circle.cpp | 17 ++++ src/2geom/circle.h | 10 ++- src/context-fns.cpp | 6 +- src/display/canvas-axonomgrid.cpp | 3 +- src/display/canvas-axonomgrid.h | 2 +- src/display/canvas-grid.cpp | 3 +- src/display/canvas-grid.h | 2 +- src/display/snap-indicator.cpp | 1 - src/draw-context.cpp | 2 +- src/gradient-drag.cpp | 4 +- src/guide-snapper.cpp | 3 +- src/guide-snapper.h | 2 +- src/knot-holder-entity.cpp | 4 +- src/knot-holder-entity.h | 2 +- src/line-snapper.cpp | 61 +++++++++----- src/line-snapper.h | 4 +- src/live_effects/lpe-circle_3pts.cpp | 22 +---- src/live_effects/lpe-circle_with_radius.cpp | 20 +---- src/object-edit.cpp | 20 ++--- src/object-snapper.cpp | 65 +++++++++------ src/object-snapper.h | 6 +- src/pen-context.cpp | 2 +- src/seltrans.cpp | 43 ++++++---- src/snap.cpp | 119 ++++++++++++++++++++-------- src/snap.h | 27 ++++--- src/snapper.h | 63 +++++++++++---- src/ui/tool/node.cpp | 12 +-- 27 files changed, 327 insertions(+), 198 deletions(-) (limited to 'src') diff --git a/src/2geom/circle.cpp b/src/2geom/circle.cpp index c3cea0ae7..00b91de12 100644 --- a/src/2geom/circle.cpp +++ b/src/2geom/circle.cpp @@ -97,6 +97,23 @@ Circle::arc(Point const& initial, Point const& inner, Point const& final, return e.arc(initial, inner, final, _svg_compliant); } +void +Circle::getPath(std::vector &path_out) { + Path pb; + + D2 B; + Linear bo = Linear(0, 2 * M_PI); + + B[0] = cos(bo,4); + B[1] = sin(bo,4); + + B = B * m_ray + m_centre; + + pb.append(SBasisCurve(B)); + + path_out.push_back(pb); +} + } // end namespace Geom diff --git a/src/2geom/circle.h b/src/2geom/circle.h index 27d4fcc3f..c346b8c8f 100644 --- a/src/2geom/circle.h +++ b/src/2geom/circle.h @@ -38,7 +38,7 @@ #include <2geom/point.h> #include <2geom/exception.h> - +#include <2geom/path.h> namespace Geom { @@ -56,6 +56,11 @@ class Circle { } + Circle(Point center, double r) + : m_centre(center), m_ray(r) + { + } + Circle(double A, double B, double C, double D) { set(A, B, C, D); @@ -86,6 +91,9 @@ class Circle arc(Point const& initial, Point const& inner, Point const& final, bool _svg_compliant = true); + void + getPath(std::vector &path_out); + Point center() const { return m_centre; diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 0ff7bd120..b22cd488d 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -132,11 +132,11 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item /* Try to snap p[0] (the opposite corner) along the constraint vector */ s[0] = m.constrainedSnap(Inkscape::SnapCandidatePoint(p[0], Inkscape::SNAPSOURCE_NODE_HANDLE), - Inkscape::Snapper::ConstraintLine(p[0] - p[1])); + Inkscape::Snapper::SnapConstraint(p[0] - p[1])); /* Try to snap p[1] (the dragged corner) along the constraint vector */ s[1] = m.constrainedSnap(Inkscape::SnapCandidatePoint(p[1], Inkscape::SNAPSOURCE_NODE_HANDLE), - Inkscape::Snapper::ConstraintLine(p[1] - p[0])); + Inkscape::Snapper::SnapConstraint(p[1] - p[0])); /* Choose the best snap and update points accordingly */ if (s[0].getSnapDistance() < s[1].getSnapDistance()) { @@ -157,7 +157,7 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item /* Our origin is the opposite corner. Snap the drag point along the constraint vector */ p[0] = center; snappoint = m.constrainedSnap(Inkscape::SnapCandidatePoint(p[1], Inkscape::SNAPSOURCE_NODE_HANDLE), - Inkscape::Snapper::ConstraintLine(p[1] - p[0])); + Inkscape::Snapper::SnapConstraint(p[1] - p[0])); if (snappoint.getSnapped()) { p[1] = snappoint.getPoint(); } diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 37469fa73..d17689b06 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -794,9 +794,10 @@ void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Poin sc.grid_lines.push_back(dummy); } -void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const +void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); + dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 58185e2e6..4a9820792 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -79,7 +79,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index a79a6b610..fe1e92824 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -1030,9 +1030,10 @@ void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point co sc.grid_lines.push_back(dummy); } -void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const +void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); + dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index a11d77d1d..0aedb02a0 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -167,7 +167,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; CanvasXYGrid *grid; }; diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index fe5bd0371..0409e64b1 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -51,7 +51,6 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap g_assert(_desktop != NULL); if (!p.getSnapped()) { - g_warning("No snapping took place, so no snap target will be displayed"); return; // If we haven't snapped, then it is of no use to draw a snapindicator } diff --git a/src/draw-context.cpp b/src/draw-context.cpp index 3049f3a6a..a531b88d1 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -511,7 +511,7 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p, /* Snap it along best vector */ SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager; m.setup(SP_EVENT_CONTEXT_DESKTOP(ec)); - m.constrainedSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE, Inkscape::Snapper::ConstraintLine(best)); + m.constrainedSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE, Inkscape::Snapper::SnapConstraint(best)); } } } diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 25309dd61..1492e9008 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -688,7 +688,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp snap_vector = get_snap_vector (p, dr_snap, M_PI/snaps, 0); } if (snap_vector) { - Inkscape::Snapper::ConstraintLine cl(dr_snap, p + *snap_vector - dr_snap); + Inkscape::Snapper::SnapConstraint cl(dr_snap, p + *snap_vector - dr_snap); Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapCandidatePoint(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE), cl); if (s.getSnapped()) { s.setTransformation(s.getPoint() - p); @@ -838,7 +838,7 @@ gr_knot_moved_midpoint_handler(SPKnot */*knot*/, Geom::Point const &ppointer, gu } else { p = snap_vector_midpoint (p, low_lim, high_lim, 0); if (!(state & GDK_SHIFT_MASK)) { - Inkscape::Snapper::ConstraintLine cl(low_lim, high_lim - low_lim); + Inkscape::Snapper::SnapConstraint cl(low_lim, high_lim - low_lim); SPDesktop *desktop = dragger->parent->desktop; SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index 4f70521e0..aad4502ca 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -81,9 +81,10 @@ void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom } -void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const +void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); + dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/guide-snapper.h b/src/guide-snapper.h index 5de1b56a4..4e5e5d1d1 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -36,7 +36,7 @@ private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; }; } diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 2d0d5eb02..be61125c4 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -101,7 +101,7 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p) } Geom::Point -KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::ConstraintLine const &constraint) +KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint) { Geom::Matrix const i2d (sp_item_i2d_affine(item)); Geom::Point s = p * i2d; @@ -123,7 +123,7 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: } else { // constrainedSnap() will first project the point p onto the constraint line and then try to snap along that line. // This way the constraint is already enforced, no need to worry about that later on - Inkscape::Snapper::ConstraintLine transformed_constraint = Inkscape::Snapper::ConstraintLine(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d); + Inkscape::Snapper::SnapConstraint transformed_constraint = Inkscape::Snapper::SnapConstraint(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d); m.constrainedSnapReturnByRef(s, Inkscape::SNAPSOURCE_NODE_HANDLE, transformed_constraint); } diff --git a/src/knot-holder-entity.h b/src/knot-holder-entity.h index c8fd29ddf..aba93798a 100644 --- a/src/knot-holder-entity.h +++ b/src/knot-holder-entity.h @@ -58,7 +58,7 @@ public: //private: Geom::Point snap_knot_position(Geom::Point const &p); - Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::ConstraintLine const &constraint); + Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint); SPKnot *knot; SPItem *item; diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index fc40643c8..5ceece66b 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -63,7 +63,7 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &/*bbox_to_snap*/, - ConstraintLine const &c, + SnapConstraint const &c, std::vector const */*it*/) const { @@ -75,20 +75,46 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, const LineList lines = _getSnapLines(p.getPoint()); for (LineList::const_iterator i = lines.begin(); i != lines.end(); i++) { - if (Geom::L2(c.getDirection()) > 0) { // Can't do a constrained snap without a constraint - // constraint line - Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p.getPoint(); - Geom::Line line1(point_on_line, point_on_line + c.getDirection()); - - // grid/guide line - Geom::Point const p1 = i->second; // point at guide/grid line - Geom::Point const p2 = p1 + Geom::rot90(i->first); // 2nd point at guide/grid line - Geom::Line line2(p1, p2); + Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p.getPoint(); + Geom::Line gridguide_line(i->second, i->second + Geom::rot90(i->first)); + if (c.isCircular()) { + // Find the intersections between the line and the circular constraint + // First, project the origin of the circle onto the line + Geom::Point const origin = c.getPoint(); + Geom::Point const p_proj = Geom::projection(origin, gridguide_line); + Geom::Point v_orig = c.getDirection(); // vector from the origin to the original (untransformed) point + Geom::Point v_proj = p_proj - origin; + Geom::Coord dist = Geom::L2(v_proj); // distance from circle origin to constraint line + Geom::Coord radius = c.getRadius(); + Geom::Coord radians = NR_HUGE; + if (dist == radius) { + // Only one point of intersection; + // Calculate the rotation in radians... + radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); + _addSnappedPoint(sc, p_proj, Geom::L2(p.getPoint() - p_proj), p.getSourceType(), p.getSourceNum(), true, radians); + } else if (dist < radius) { + // Two points of intersection, symmetrical with respect to the projected point + // Calculate half the length of the linesegment between the two points of intersection + Geom::Coord l = sqrt(radius*radius - dist*dist); + Geom::Coord d = Geom::L2(gridguide_line.versor()); // length of versor, needed to normalize the versor + if (d > 0) { + Geom::Point v = l*gridguide_line.versor()/d; + v_proj = p_proj + v - origin; + radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); + _addSnappedPoint(sc, p_proj + v, Geom::L2(p.getPoint() - (p_proj + v)), p.getSourceType(), p.getSourceNum(), true, radians); + v_proj = p_proj - v - origin; + radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); + _addSnappedPoint(sc, p_proj - v, Geom::L2(p.getPoint() - (p_proj - v)), p.getSourceType(), p.getSourceNum(), true, radians); + } + } + } else { + // Find the intersections between the line and the linear constraint + Geom::Line constraint_line(point_on_line, point_on_line + c.getDirection()); Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default try { - inters = Geom::intersection(line1, line2); + inters = Geom::intersection(constraint_line, gridguide_line); } catch (Geom::InfiniteSolutions e) { @@ -97,23 +123,14 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, } if (inters) { - Geom::Point t = line1.pointAt((*inters).ta); + Geom::Point t = constraint_line.pointAt((*inters).ta); const Geom::Coord dist = Geom::L2(t - p.getPoint()); if (dist < getSnapperTolerance()) { // When doing a constrained snap, we're already at an intersection. // This snappoint is therefore fully constrained, so there's no need // to look for additional intersections; just return the snapped point // and forget about the line - _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum(), true); - // For any line that's within range, we will also look at it's "point on line" p1. For guides - // this point coincides with its origin; for grids this is of no use, but we cannot - // discern between grids and guides here - Geom::Coord const dist_p1 = Geom::L2(p1 - p.getPoint()); - if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum(), true); - // Only relevant for guides; grids don't have an origin per line - // Therefore _addSnappedLinesOrigin() will only be implemented for guides - } + _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum(), true, 1); } } } diff --git a/src/line-snapper.h b/src/line-snapper.h index 1aa3526cc..403c8cbba 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -34,7 +34,7 @@ public: void constrainedSnap(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, - ConstraintLine const &c, + SnapConstraint const &c, std::vector const *it) const; protected: @@ -54,7 +54,7 @@ private: // Will only be implemented for guide lines, because grid lines don't have an origin virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; - virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const = 0; + virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const = 0; }; } diff --git a/src/live_effects/lpe-circle_3pts.cpp b/src/live_effects/lpe-circle_3pts.cpp index d600ef046..951a3b7c8 100644 --- a/src/live_effects/lpe-circle_3pts.cpp +++ b/src/live_effects/lpe-circle_3pts.cpp @@ -17,6 +17,7 @@ // You might need to include other 2geom files. You can add them here: #include <2geom/path.h> +#include <2geom/circle.h> namespace Inkscape { namespace LivePathEffect { @@ -30,24 +31,6 @@ LPECircle3Pts::~LPECircle3Pts() { } -static void _circle(Geom::Point center, double radius, std::vector &path_out) { - using namespace Geom; - - Geom::Path pb; - - D2 B; - Linear bo = Linear(0, 2 * M_PI); - - B[0] = cos(bo,4); - B[1] = sin(bo,4); - - B = B * radius + center; - - pb.append(SBasisCurve(B)); - - path_out.push_back(pb); -} - static void _circle3(Geom::Point const &A, Geom::Point const &B, Geom::Point const &C, std::vector &path_out) { using namespace Geom; @@ -64,7 +47,8 @@ static void _circle3(Geom::Point const &A, Geom::Point const &B, Geom::Point con Point M = D + v * lambda; double radius = L2(M - A); - _circle(M, radius, path_out); + Geom::Circle c(M, radius); + c.getPath(path_out); } std::vector diff --git a/src/live_effects/lpe-circle_with_radius.cpp b/src/live_effects/lpe-circle_with_radius.cpp index 574a9c004..71611e18b 100644 --- a/src/live_effects/lpe-circle_with_radius.cpp +++ b/src/live_effects/lpe-circle_with_radius.cpp @@ -18,6 +18,7 @@ #include <2geom/sbasis.h> #include <2geom/bezier-to-sbasis.h> #include <2geom/d2.h> +#include <2geom/circle.h> using namespace Geom; @@ -38,22 +39,6 @@ LPECircleWithRadius::~LPECircleWithRadius() } -void _circle(Geom::Point center, double radius, std::vector &path_out) { - Geom::Path pb; - - D2 B; - Linear bo = Linear(0, 2 * M_PI); - - B[0] = cos(bo,4); - B[1] = sin(bo,4); - - B = B * radius + center; - - pb.append(SBasisCurve(B)); - - path_out.push_back(pb); -} - std::vector LPECircleWithRadius::doEffect_path (std::vector const & path_in) { @@ -64,7 +49,8 @@ LPECircleWithRadius::doEffect_path (std::vector const & path_in) double radius = Geom::L2(pt - center); - _circle(center, radius, path_out); + Geom::Circle c(center, radius); + c.getPath(path_out); return path_out; } diff --git a/src/object-edit.cpp b/src/object-edit.cpp index 1d81aa7f5..83b01013c 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -141,7 +141,7 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained - Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(-1, 0))); + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(-1, 0))); if (state & GDK_CONTROL_MASK) { gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0; @@ -191,7 +191,7 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained - Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1))); + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1))); if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry, // resulting in a perfect circle (and not an ellipse) @@ -280,13 +280,13 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or // snap to horizontal or diagonal if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->height.computed = MAX(h_orig + minx / ratio, 0); } else { // closer to the horizontal, change only width, height is h_orig - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->height.computed = MAX(h_orig, 0); @@ -297,13 +297,13 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or // snap to vertical or diagonal if (miny != 0 && fabs(minx/miny) > 0.5 * ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->width.computed = MAX(w_orig + miny * ratio, 0); } else { // closer to the vertical, change only height, width is w_orig - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->width.computed = MAX(w_orig, 0); @@ -370,14 +370,14 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin // snap to horizontal or diagonal if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y); rect->height.computed = MAX(h_orig - minx / ratio, 0); } else { // closer to the horizontal, change only width, height is h_orig - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->y.computed = MIN(origin[Geom::Y], opposite_y); @@ -389,14 +389,14 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin // snap to vertical or diagonal if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-ratio, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x); rect->width.computed = MAX(w_orig - miny * ratio, 0); } else { // closer to the vertical, change only height, width is w_orig - s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1))); + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1))); minx = s[Geom::X] - origin[Geom::X]; miny = s[Geom::Y] - origin[Geom::Y]; rect->x.computed = MIN(origin[Geom::X], opposite_x); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 983a6fede..f96335c4a 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -16,6 +16,7 @@ #include <2geom/point.h> #include <2geom/rect.h> #include <2geom/line.h> +#include <2geom/circle.h> #include "document.h" #include "sp-namedview.h" #include "sp-image.h" @@ -522,7 +523,7 @@ bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::ve void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, - ConstraintLine const &c) const + SnapConstraint const &c) const { _collectPaths(p, p.getSourceNum() == 0); @@ -537,36 +538,54 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, direction_vector = Geom::unit_vector(direction_vector); } - // The intersection point of the constraint line with any path, - // must lie within two points on the constraintline: p_min_on_cl and p_max_on_cl - // The distance between those points is twice the snapping tolerance + // The intersection point of the constraint line with any path, must lie within two points on the + // SnapConstraint: p_min_on_cl and p_max_on_cl. The distance between those points is twice the snapping tolerance Geom::Point const p_proj_on_cl = p.getPoint(); // projection has already been taken care of in constrainedSnap in the snapmanager; Geom::Point const p_min_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl - getSnapperTolerance() * direction_vector); Geom::Point const p_max_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl + getSnapperTolerance() * direction_vector); + Geom::Coord tolerance = getSnapperTolerance(); - Geom::Path cl; - std::vector clv; - cl.start(p_min_on_cl); - cl.appendNew(p_max_on_cl); - clv.push_back(cl); + // PS: Because the paths we're about to snap to are all expressed relative to document coordinate system, we will have + // to convert the snapper coordinates from the desktop coordinates to document coordinates + + std::vector constraint_path; + if (c.isCircular()) { + Geom::Circle constraint_circle(_snapmanager->getDesktop()->dt2doc(c.getPoint()), c.getRadius()); + constraint_circle.getPath(constraint_path); + } else { + Geom::Path constraint_line; + constraint_line.start(p_min_on_cl); + constraint_line.appendNew(p_max_on_cl); + constraint_path.push_back(constraint_line); + } for (std::vector::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) { if (k->path_vector) { - Geom::CrossingSet cs = Geom::crossings(clv, *(k->path_vector)); - if (cs.size() > 0) { - // We need only the first element of cs, because cl is only a single straight linesegment - // This first element contains a vector filled with crossings of cl with k->first - for (std::vector::const_iterator m = cs[0].begin(); m != cs[0].end(); m++) { - if ((*m).ta >= 0 && (*m).ta <= 1 ) { - // Reconstruct the point of intersection - Geom::Point p_inters = p_min_on_cl + ((*m).ta) * (p_max_on_cl - p_min_on_cl); - // When it's within snapping range, then return it - // (within snapping range == between p_min_on_cl and p_max_on_cl == 0 < ta < 1) - Geom::Coord dist = Geom::L2(_snapmanager->getDesktop()->dt2doc(p_proj_on_cl) - p_inters); - SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox); + Geom::CrossingSet cs = Geom::crossings(constraint_path, *(k->path_vector)); + unsigned int index = 0; + for (Geom::CrossingSet::const_iterator i = cs.begin(); i != cs.end(); i++) { + if (index >= constraint_path.size()) { + break; + } + for (Geom::Crossings::const_iterator m = (*i).begin(); m != (*i).end(); m++) { + //std::cout << "ta = " << (*m).ta << " | tb = " << (*m).tb << std::endl; + // Reconstruct the point of intersection + Geom::Point p_inters = constraint_path[index].pointAt((*m).ta); + // .. and convert it to desktop coordinates + p_inters = _snapmanager->getDesktop()->doc2dt(p_inters); + Geom::Coord dist = Geom::L2(p_proj_on_cl - p_inters); + SnappedPoint s = SnappedPoint(p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);; + if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it + if (c.isCircular()) { + Geom::Point v_orig = c.getDirection(); // vector from the origin to the original (untransformed) point + Geom::Point v_inters = p_inters - c.getPoint(); + Geom::Coord radians = atan2(Geom::dot(Geom::rot90(v_orig), v_inters), Geom::dot(v_orig, v_inters)); + s.setTransformation(Geom::Point(radians, radians)); + } sc.points.push_back(s); } } + index++; } } } @@ -622,7 +641,7 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, - ConstraintLine const &c, + SnapConstraint const &c, std::vector const *it) const { if (_snap_enabled == false || _snapmanager->snapprefs.getSnapFrom(p.getSourceType()) == false) { @@ -677,7 +696,7 @@ void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc, void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, Geom::Point const &p, Geom::Point const &guide_normal, - ConstraintLine const &/*c*/) const + SnapConstraint const &/*c*/) const { /* Get a list of all the SPItems that we will try to snap to */ std::vector cand; diff --git a/src/object-snapper.h b/src/object-snapper.h index caf643f73..454a18545 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -46,7 +46,7 @@ public: void guideConstrainedSnap(SnappedConstraints &sc, Geom::Point const &p, Geom::Point const &guide_normal, - ConstraintLine const &c) const; + SnapConstraint const &c) const; bool ThisSnapperMightSnap() const; bool GuidesMightSnap() const; @@ -63,7 +63,7 @@ public: void constrainedSnap(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, - ConstraintLine const &c, + SnapConstraint const &c, std::vector const *it) const; private: @@ -98,7 +98,7 @@ private: void _snapPathsConstrained(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, // in desktop coordinates - ConstraintLine const &c) const; + SnapConstraint const &c) const; bool isUnselectedNode(Geom::Point const &point, std::vector const *unselected_nodes) const; diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 5b9f6808a..4a21d7bcb 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -1470,7 +1470,7 @@ void pen_set_to_nearest_horiz_vert(const SPPenContext *const pc, Geom::Point &pt } } else { // Create a horizontal or vertical constraint line - Inkscape::Snapper::ConstraintLine cl(origin, next_dir ? Geom::Point(0, 1) : Geom::Point(1, 0)); + Inkscape::Snapper::SnapConstraint cl(origin, next_dir ? Geom::Point(0, 1) : Geom::Point(1, 0)); // Snap along the constraint line; if we didn't snap then still the constraint will be applied SnapManager &m = pc->desktop->namedview->snap_manager; diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 05f47d4ab..9c83dd63e 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -1209,7 +1209,7 @@ gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::P SnapManager &m = _desktop->namedview->snap_manager; m.setup(_desktop, false, _items_const); - Inkscape::Snapper::ConstraintLine const constraint(component_vectors[dim_b]); + Inkscape::Snapper::SnapConstraint const constraint(component_vectors[dim_b]); // When skewing, we cannot snap the corners of the bounding box, see the comment in "constrainedSnapSkew" for details Geom::Point const s(skew[dim_a], scale[dim_a]); Inkscape::SnappedPoint sn = m.constrainedSnapSkew(_snap_points, _point, constraint, s, _origin, Geom::Dim2(dim_b)); @@ -1276,7 +1276,10 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) if (fabs(h2) < 1e-15) return FALSE; Geom::Point q2 = d2 / h2; // normalized new vector to handle - double radians; + Geom::Rotate r1(q1); + Geom::Rotate r2(q2); + + double radians = atan2(Geom::dot(Geom::rot90(d1), d2), Geom::dot(d1, d2));; if (state & GDK_CONTROL_MASK) { // Snap to defined angle increments double cos_t = Geom::dot(q1, q2); @@ -1285,15 +1288,25 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) if (snaps) { radians = ( M_PI / snaps ) * floor( radians * snaps / M_PI + .5 ); } - q1 = Geom::Point(1, 0); - q2 = Geom::Point(cos(radians), sin(radians)); + r1 = Geom::Rotate(0); //q1 = Geom::Point(1, 0); + r2 = Geom::Rotate(radians); //q2 = Geom::Point(cos(radians), sin(radians)); } else { - radians = atan2(Geom::dot(Geom::rot90(d1), d2), - Geom::dot(d1, d2)); + SnapManager &m = _desktop->namedview->snap_manager; + m.setup(_desktop, false, _items_const); + // When rotating, we cannot snap the corners of the bounding box, see the comment in "constrainedSnapRotate" for details + Inkscape::SnappedPoint sn = m.constrainedSnapRotate(_snap_points, _point, radians, _origin); + + if (sn.getSnapped()) { + _desktop->snapindicator->set_new_snaptarget(sn); + // We snapped something, so change the rotation to reflect it + radians = sn.getTransformation()[0]; + r1 = Geom::Rotate(0); + r2 = Geom::Rotate(radians); + } else { + _desktop->snapindicator->remove_snaptarget(); + } } - Geom::Rotate const r1(q1); - Geom::Rotate const r2(q2); // Calculate the relative affine _relative_affine = r2 * r1.inverse(); @@ -1460,14 +1473,14 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) // the constraint-line once. The constraint lines are parallel, but might not be colinear. // Therefore we will have to set the point through which the constraint-line runs // individually for each point to be snapped; this will be handled however by _snapTransformed() - s.push_back(m.constrainedSnapTranslation(_bbox_points_for_translating, + s.push_back(m.constrainedSnapTranslate(_bbox_points_for_translating, _point, - Inkscape::Snapper::ConstraintLine(component_vectors[dim]), + Inkscape::Snapper::SnapConstraint(component_vectors[dim]), dxy)); - s.push_back(m.constrainedSnapTranslation(_snap_points, + s.push_back(m.constrainedSnapTranslate(_snap_points, _point, - Inkscape::Snapper::ConstraintLine(component_vectors[dim]), + Inkscape::Snapper::SnapConstraint(component_vectors[dim]), dxy)); } else { // !control @@ -1477,8 +1490,8 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) g_get_current_time(&starttime); */ /* Snap to things with no constraint */ - s.push_back(m.freeSnapTranslation(_bbox_points_for_translating, _point, dxy)); - s.push_back(m.freeSnapTranslation(_snap_points, _point, dxy)); + s.push_back(m.freeSnapTranslate(_bbox_points_for_translating, _point, dxy)); + s.push_back(m.freeSnapTranslate(_snap_points, _point, dxy)); /*g_get_current_time(&endtime); double elapsed = ((((double)endtime.tv_sec - starttime.tv_sec) * G_USEC_PER_SEC + (endtime.tv_usec - starttime.tv_usec))) / 1000.0; @@ -1504,7 +1517,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) if (control) { // If we didn't snap, then we should still constrain horizontally or vertically // (When we did snap, then this constraint has already been enforced by - // calling constrainedSnapTranslation() above) + // calling constrainedSnapTranslate() above) if (fabs(dxy[Geom::X]) > fabs(dxy[Geom::Y])) { dxy[Geom::Y] = 0; } else { diff --git a/src/snap.cpp b/src/snap.cpp index c47f93ff1..265b7c19a 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -335,7 +335,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t, Geom::Point c void SnapManager::constrainedSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap) const { Inkscape::SnappedPoint const s = constrainedSnap(Inkscape::SnapCandidatePoint(p, source_type, 0), constraint, bbox_to_snap); @@ -359,13 +359,19 @@ void SnapManager::constrainedSnapReturnByRef(Geom::Point &p, */ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint const &p, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap) const { // First project the mouse pointer onto the constraint Geom::Point pp = constraint.projection(p.getPoint()); - Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, Geom::L2(pp - p.getPoint()), 0, false, true, false); + Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, NR_HUGE, 0, false, true, false); + if (constraint.isCircular()) { + Geom::Point v_orig = constraint.getDirection(); // vector from the origin to the original (untransformed) point + Geom::Point v_proj = pp - constraint.getPoint(); // vector from the origin to the projected point + Geom::Coord angle = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); + no_snap.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating + } if (!someSnapperMightSnap()) { // Always return point on constraint @@ -464,7 +470,7 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) // Snap to nodes or paths SnappedConstraints sc; - Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); + Inkscape::Snapper::SnapConstraint cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { object.constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL); } @@ -509,7 +515,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( std::vector const &points, Geom::Point const &pointer, bool constrained, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Transformation transformation_type, Geom::Point const &transformation, Geom::Point const &origin, @@ -559,8 +565,17 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point g_assert(best_snapped_point.getAtIntersection() == false); - std::vector::iterator j = transformed_points.begin(); + // Warnings for the devs + if (constrained && transformation_type == SCALE && !uniform) { + g_warning("Non-uniform constrained scaling is not supported!"); + } + + if (!constrained && transformation_type == ROTATE) { + // We do not yet allow for simultaneous rotation and scaling + g_warning("Unconstrained rotation is not supported!"); + } + std::vector::iterator j = transformed_points.begin(); // std::cout << std::endl; bool first_free_snap = true; @@ -568,27 +583,28 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /* Snap it */ Inkscape::SnappedPoint snapped_point; - Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint; - Geom::Point const b = ((*i).getPoint() - origin); // vector to original point + Inkscape::Snapper::SnapConstraint dedicated_constraint = constraint; + Geom::Point const b = ((*i).getPoint() - origin); // vector to original point (not the transformed point! required for rotations!) if (constrained) { - if ((transformation_type == SCALE || transformation_type == STRETCH) && uniform) { + if (((transformation_type == SCALE || transformation_type == STRETCH) && uniform)) { // When uniformly scaling, each point will have its own unique constraint line, // running from the scaling origin to the original untransformed point. We will // calculate that line here - dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, b); + dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b); + } else if (transformation_type == ROTATE) { + // Geom::L2(b) is the radius of the circular constraint + dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b, Geom::L2(b)); } else if (transformation_type == STRETCH) { // when non-uniform stretching { - dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i).getPoint(), component_vectors[dim]); - } else if (transformation_type == TRANSLATION) { + dedicated_constraint = Inkscape::Snapper::SnapConstraint((*i).getPoint(), component_vectors[dim]); + } else if (transformation_type == TRANSLATE) { // When doing a constrained translation, all points will move in the same direction, i.e. // either horizontally or vertically. The lines along which they move are therefore all - // parallel, but might not be colinear. Therefore we will have to set the point through - // which the constraint-line runs here, for each point individually. - dedicated_constraint.setPoint((*i).getPoint()); + // parallel, but might not be colinear. Therefore we will have to specify the point through + // which the constraint-line runs here, for each point individually. (we could also have done this + // earlier on, e.g. in seltrans.cpp but we're being lazy there and don't want to add an iteration loop) + dedicated_constraint = Inkscape::Snapper::SnapConstraint((*i).getPoint(), constraint.getDirection()); } // else: leave the original constraint, e.g. for skewing - if (transformation_type == SCALE && !uniform) { - g_warning("Non-uniform constrained scaling is not supported!"); - } snapped_point = constrainedSnap(*j, dedicated_constraint, bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; @@ -597,7 +613,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // When scaling, a point aligned either horizontally or vertically with the origin can only // move in that specific direction; therefore it should only snap in that direction, otherwise // we will get snapped points with an invalid transformation - dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); + dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, component_vectors[c1]); snapped_point = constrainedSnap(*j, dedicated_constraint, bbox); } else { // If we have a collection of SnapCandidatePoints, with mixed constrained snapping and free snapping @@ -627,7 +643,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( //Geom::Point const b = (*i - origin); // vector to original point switch (transformation_type) { - case TRANSLATION: + case TRANSLATE: result = snapped_point.getPoint() - (*i).getPoint(); /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of @@ -693,6 +709,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); snapped_point.setSecondSnapDistance(NR_HUGE); break; + case ROTATE: + result = snapped_point.getTransformation(); + // Store the metric for this transformation as a virtual distance (we're storing an angle) + snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); + snapped_point.setSecondSnapDistance(NR_HUGE); + break; default: g_assert_not_reached(); } @@ -738,22 +760,21 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::freeSnapTranslation(std::vector const &p, +Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, Geom::Point const &tr) const { if (p.size() == 1) { - Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + return _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); } /** * \brief Apply a translation to a set of points and try to snap along a constraint * - * \param point_type Category of points to which the source point belongs: node or bounding box. * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). * \param constraint The direction or line along which snapping must occur. @@ -761,24 +782,23 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(std::vector const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector const &p, Geom::Point const &pointer, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::Point const &tr) const { if (p.size() == 1) { - Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + return _snapTransformed(p, pointer, true, constraint, TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); } /** * \brief Apply a scaling to a set of points and try to snap freely in 2 degrees-of-freedom * - * \param point_type Category of points to which the source point belongs: node or bounding box. * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). * \param s Proposed scaling; the final scaling can only be calculated after snapping has occurred @@ -803,7 +823,6 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector const &p, Geom::Point const &pointer, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::Point const &s, Geom::Point const &o, Geom::Dim2 d) const @@ -892,6 +909,36 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector const &p, + Geom::Point const &pointer, + Geom::Coord const &angle, + Geom::Point const &o) const +{ + // Snapping the nodes of the bounding box of a selection that is being transformed, will only work if + // the transformation of the bounding box is equal to the transformation of the individual nodes. This is + // NOT the case for example when rotating or skewing. The bounding box itself cannot possibly rotate or skew, + // so it's corners have a different transformation. The snappers cannot handle this, therefore snapping + // of bounding boxes is not allowed here. + + if (p.size() == 1) { + Geom::Point pt = _transformPoint(p.at(0), ROTATE, Geom::Point(angle, angle), o, Geom::X, false); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + } + + return _snapTransformed(p, pointer, true, Geom::Point(0,0), ROTATE, Geom::Point(angle, angle), o, Geom::X, false); + +} + /** * \brief Given a set of possible snap targets, find the best target (which is not necessarily * also the nearest target), and show the snap indicator if requested @@ -1116,7 +1163,7 @@ Geom::Point SnapManager::_transformPoint(Inkscape::SnapCandidatePoint const &p, /* Work out the transformed version of this point */ Geom::Point transformed; switch (transformation_type) { - case TRANSLATION: + case TRANSLATE: transformed = p.getPoint() + transformation; break; case SCALE: @@ -1141,6 +1188,10 @@ Geom::Point SnapManager::_transformPoint(Inkscape::SnapCandidatePoint const &p, // Apply that scale factor here transformed[1-dim] = (p.getPoint() - origin)[1 - dim] * transformation[1] + origin[1 - dim]; break; + case ROTATE: + // for rotations: transformation[0] stores the angle in radians + transformed = (p.getPoint() - origin) * Geom::Rotate(transformation[0]) + origin; + break; default: g_assert_not_reached(); } diff --git a/src/snap.h b/src/snap.h index 8a5688bea..26e599cc6 100644 --- a/src/snap.h +++ b/src/snap.h @@ -67,10 +67,11 @@ class SnapManager { public: enum Transformation { - TRANSLATION, + TRANSLATE, SCALE, STRETCH, - SKEW + SKEW, + ROTATE }; SnapManager(SPNamedView const *v); @@ -113,23 +114,23 @@ public: // point, by overwriting p, if snapping has occurred; otherwise p is untouched void constrainedSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapCandidatePoint const &p, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const; void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const; - Inkscape::SnappedPoint freeSnapTranslation(std::vector const &p, + Inkscape::SnappedPoint freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, Geom::Point const &tr) const; - Inkscape::SnappedPoint constrainedSnapTranslation(std::vector const &p, + Inkscape::SnappedPoint constrainedSnapTranslate(std::vector const &p, Geom::Point const &pointer, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::Point const &tr) const; Inkscape::SnappedPoint freeSnapScale(std::vector const &p, @@ -151,11 +152,16 @@ public: Inkscape::SnappedPoint constrainedSnapSkew(std::vector const &p, Geom::Point const &pointer, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor Geom::Point const &o, Geom::Dim2 d) const; + Inkscape::SnappedPoint constrainedSnapRotate(std::vector const &p, + Geom::Point const &pointer, + Geom::Coord const &angle, + Geom::Point const &o) const; + Inkscape::GuideSnapper guide; ///< guide snapper Inkscape::ObjectSnapper object; ///< snapper to other objects Inkscape::SnapPreferences snapprefs; @@ -181,14 +187,11 @@ private: SPDesktop const *_desktop; bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to std::vector *_unselected_nodes; ///< Nodes of the path that is currently being edited and which have not been selected and which will therefore be stationary. Only these nodes will be considered for snapping to. Of each unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored - //TODO: Make _unselected_nodes type safe; in the line above int is used for Inkscape::SnapTargetType, but if I remember - //correctly then in other cases the int is being used for Inkscape::SnapSourceType, or for both. How to make - //this type safe? Inkscape::SnappedPoint _snapTransformed(std::vector const &points, Geom::Point const &pointer, bool constrained, - Inkscape::Snapper::ConstraintLine const &constraint, + Inkscape::Snapper::SnapConstraint const &constraint, Transformation transformation_type, Geom::Point const &transformation, Geom::Point const &origin, diff --git a/src/snapper.h b/src/snapper.h index b5bb17de9..d8214db80 100644 --- a/src/snapper.h +++ b/src/snapper.h @@ -15,6 +15,7 @@ #include #include #include +#include // for g_assert #include "snapped-point.h" #include "snapped-line.h" @@ -63,18 +64,29 @@ public: std::vector const */*it*/, std::vector */*unselected_nodes*/) const {}; - class ConstraintLine + // Class for storing the constraint for constrained snapping; can be + // - a line (infinite line with origin, running through _point pointing in _direction) + // - a direction (infinite line without origin, i.e. only a direction vector, stored in _direction) + // - a circle (_point denotes the center, _radius doesn't need an explanation, _direction contains + // the vector from the origin to the original untransformed point); + class SnapConstraint { + private: + enum SnapConstraintType {LINE, DIRECTION, CIRCLE}; + public: - ConstraintLine(Geom::Point const &d) : _has_point(false), _direction(d) {} - ConstraintLine(Geom::Point const &p, Geom::Point const &d) : _has_point(true), _point(p), _direction(d) {} - ConstraintLine(Geom::Line const &l) : _has_point(true), _point(l.origin()), _direction(l.versor()) {} + // Constructs a direction constraint, e.g. horizontal or vertical but without a specified point + SnapConstraint(Geom::Point const &d) : _direction(d), _type(DIRECTION) {} + // Constructs a linear constraint + SnapConstraint(Geom::Point const &p, Geom::Point const &d) : _point(p), _direction(d), _type(LINE) {} + SnapConstraint(Geom::Line const &l) : _point(l.origin()), _direction(l.versor()), _type(LINE) {} + // Constructs a circular constraint + SnapConstraint(Geom::Point const &p, Geom::Point const &d, Geom::Coord const &r) : _point(p), _direction(d), _radius(r), _type(CIRCLE) {} - bool hasPoint() const { - return _has_point; - } + bool hasPoint() const {return _type != DIRECTION;} Geom::Point getPoint() const { + g_assert(_type != DIRECTION); return _point; } @@ -82,28 +94,45 @@ public: return _direction; } - void setPoint(Geom::Point const &p) { - _point = p; - _has_point = true; + Geom::Coord getRadius() const { + g_assert(_type == CIRCLE); + return _radius; } - Geom::Point projection(Geom::Point const &p) const { // returns the projection of p on this constraintline - Geom::Point const p1_on_cl = _has_point ? _point : p; - Geom::Point const p2_on_cl = p1_on_cl + _direction; - return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl)); + bool isCircular() const { return _type == CIRCLE; } + bool isLinear() const { return _type == LINE; } + bool isDirection() const { return _type == DIRECTION; } + + Geom::Point projection(Geom::Point const &p) const { // returns the projection of p on this constraint + if (_type == CIRCLE) { + // project on to a circular constraint + Geom::Point v_orig = p - _point; + Geom::Coord l = Geom::L2(v_orig); + if (l > 0) { + return _point + _radius * v_orig/l; // Length of _direction is equal to the radius + } else { + // point to be projected is exactly at the center of the circle, so any point on the circle is a projection + return _point + Geom::Point(_radius, 0); + } + } else { + // project on to a linear constraint + Geom::Point const p1_on_cl = (_type == LINE) ? _point : p; + Geom::Point const p2_on_cl = p1_on_cl + _direction; + return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl)); + } } private: - - bool _has_point; Geom::Point _point; Geom::Point _direction; + Geom::Coord _radius; + SnapConstraintType _type; }; virtual void constrainedSnap(SnappedConstraints &/*sc*/, Inkscape::SnapCandidatePoint const &/*p*/, Geom::OptRect const &/*bbox_to_snap*/, - ConstraintLine const &/*c*/, + SnapConstraint const &/*c*/, std::vector const */*it*/) const {}; protected: diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 9c9c58ff1..886ddd1be 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -266,7 +266,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) Node *node_away = (this == &_parent->_front ? _parent->_prev() : _parent->_next()); if (_parent->type() == NODE_SMOOTH && Node::_is_line_segment(_parent, node_away)) { - Inkscape::Snapper::ConstraintLine cl(_parent->position(), + Inkscape::Snapper::SnapConstraint cl(_parent->position(), _parent->position() - node_away->position()); Inkscape::SnappedPoint p; p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl); @@ -974,7 +974,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) // with Ctrl+Alt, constrain to handle lines // project the new position onto a handle line that is closer boost::optional front_point, back_point; - boost::optional line_front, line_back; + boost::optional line_front, line_back; if (_front.isDegenerate()) { if (_is_line_segment(this, _next())) front_point = _next()->position() - origin; @@ -988,9 +988,9 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) back_point = _back.relativePos(); } if (front_point) - line_front = Inkscape::Snapper::ConstraintLine(origin, *front_point); + line_front = Inkscape::Snapper::SnapConstraint(origin, *front_point); if (back_point) - line_back = Inkscape::Snapper::ConstraintLine(origin, *back_point); + line_back = Inkscape::Snapper::SnapConstraint(origin, *back_point); // TODO: combine the snap and non-snap branches by modifying snap.h / snap.cpp if (snap) { @@ -1029,8 +1029,8 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) // with Ctrl, constrain to axes // TODO combine the two branches if (snap) { - Inkscape::Snapper::ConstraintLine line_x(origin, Geom::Point(1, 0)); - Inkscape::Snapper::ConstraintLine line_y(origin, Geom::Point(0, 1)); + Inkscape::Snapper::SnapConstraint line_x(origin, Geom::Point(1, 0)); + Inkscape::Snapper::SnapConstraint line_y(origin, Geom::Point(0, 1)); fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_x); bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_y); } -- cgit v1.2.3 From a26a126bb753ce5f863343822ab64c022d867f6d Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 14 Jul 2010 00:32:30 +0200 Subject: i18n. Fix for bug #601522 (embedding prompt dialog's caption is not translated). (bzr r9614) --- src/extension/internal/gdkpixbuf-input.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index a1295406c..df7f3481c 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -2,6 +2,7 @@ # include #endif #include +#include #include "document-private.h" #include #include "extension/input.h" @@ -143,10 +144,10 @@ GdkpixbufInput::init(void) if (strcmp(extensions[i], "svg.gz") == 0) { continue; } - + gchar *caption = g_strdup_printf(_("%s GDK pixbuf Input"), name); gchar *xmlString = g_strdup_printf( "\n" - "" N_("%s GDK pixbuf Input") "\n" + "%s\n" "org.inkscape.input.gdkpixbuf.%s\n" "\n" "<_option value='embed'>" N_("embed") "\n" @@ -160,7 +161,7 @@ GdkpixbufInput::init(void) "%s\n" "\n" "", - name, + caption, extensions[i], extensions[i], mimetypes[j], @@ -171,6 +172,7 @@ GdkpixbufInput::init(void) Inkscape::Extension::build_from_mem(xmlString, new GdkpixbufInput()); g_free(xmlString); + g_free(caption); }} g_free(name); -- cgit v1.2.3 From b7d87206fa0e36ef860dfbf64249a3454a87ecd8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 17 Jul 2010 00:29:25 +0200 Subject: Fix build failure when DBus is not enabled (bzr r9618) --- src/extension/dbus/Makefile_insert | 20 ++++++++++++++++++++ src/file.cpp | 9 ++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/dbus/Makefile_insert b/src/extension/dbus/Makefile_insert index ce733364c..a5eb3fdf4 100644 --- a/src/extension/dbus/Makefile_insert +++ b/src/extension/dbus/Makefile_insert @@ -1,5 +1,7 @@ ## Makefile.am fragment sourced by src/Makefile.am. +if WITH_DBUS + ############################# # Sources for DBus interface ############################# @@ -88,3 +90,21 @@ libinkdbus_la_LIBADD = \ pkgconfig_DATA = extension/dbus/wrapper/inkdbus.pc pkgconfigdir = $(libdir)/pkgconfig +else # WITH_DBUS + +EXTRA_DIST += \ + extension/dbus/dbus-init.cpp \ + extension/dbus/dbus-init.h \ + extension/dbus/application-interface.cpp \ + extension/dbus/application-interface.h \ + extension/dbus/document-interface.cpp \ + extension/dbus/document-interface.h \ + extension/dbus/wrapper/inkscape-dbus-wrapper.h \ + extension/dbus/wrapper/inkscape-dbus-wrapper.c \ + extension/dbus/wrapper/inkdbus.pc \ + extension/dbus/org.inkscape.service.in \ + extension/dbus/application-interface.xml \ + extension/dbus/document-interface.xml + +endif + diff --git a/src/file.cpp b/src/file.cpp index 1186a1f07..50fcd3642 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -42,7 +42,6 @@ #include "extension/input.h" #include "extension/output.h" #include "extension/system.h" -#include "extension/dbus/dbus-init.h" #include "file.h" #include "helper/png-write.h" #include "id-clash.h" @@ -69,6 +68,10 @@ # include #endif +#ifdef WITH_DBUS +#include "extension/dbus/dbus-init.h" +#endif + //#ifdef WITH_INKBOARD //#include "jabber_whiteboard/session-manager.h" //#endif @@ -136,7 +139,11 @@ sp_file_new(const Glib::ustring &templ) sp_namedview_window_from_document(dt); sp_namedview_update_layers_from_document(dt); } + +#ifdef WITH_DBUS Inkscape::Extension::Dbus::dbus_init_desktop_interface(dt); +#endif + return dt; } -- cgit v1.2.3 From 846961debf7ef8d98f081509c4aa4ca5b880e25d Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 17 Jul 2010 22:13:52 +0200 Subject: Simplify code related to snapping while rotating (bzr r9619) --- src/display/canvas-axonomgrid.cpp | 3 +-- src/display/canvas-axonomgrid.h | 2 +- src/display/canvas-grid.cpp | 3 +-- src/display/canvas-grid.h | 2 +- src/guide-snapper.cpp | 3 +-- src/guide-snapper.h | 2 +- src/line-snapper.cpp | 19 +++++-------------- src/line-snapper.h | 2 +- src/object-snapper.cpp | 6 ------ src/snap.cpp | 14 +++++--------- 10 files changed, 17 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index d17689b06..37469fa73 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -794,10 +794,9 @@ void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Poin sc.grid_lines.push_back(dummy); } -void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const +void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); - dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 4a9820792..58185e2e6 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -79,7 +79,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index fe1e92824..a79a6b610 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -1030,10 +1030,9 @@ void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point co sc.grid_lines.push_back(dummy); } -void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const +void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); - dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 0aedb02a0..a11d77d1d 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -167,7 +167,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; CanvasXYGrid *grid; }; diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index aad4502ca..4f70521e0 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -81,10 +81,9 @@ void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom } -void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const +void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); - dummy.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating sc.points.push_back(dummy); } diff --git a/src/guide-snapper.h b/src/guide-snapper.h index 4e5e5d1d1..5de1b56a4 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -36,7 +36,7 @@ private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; }; } diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index 5ceece66b..19e6c0fe6 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -83,16 +83,11 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // First, project the origin of the circle onto the line Geom::Point const origin = c.getPoint(); Geom::Point const p_proj = Geom::projection(origin, gridguide_line); - Geom::Point v_orig = c.getDirection(); // vector from the origin to the original (untransformed) point - Geom::Point v_proj = p_proj - origin; - Geom::Coord dist = Geom::L2(v_proj); // distance from circle origin to constraint line + Geom::Coord dist = Geom::L2(p_proj - origin); // distance from circle origin to constraint line Geom::Coord radius = c.getRadius(); - Geom::Coord radians = NR_HUGE; if (dist == radius) { // Only one point of intersection; - // Calculate the rotation in radians... - radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); - _addSnappedPoint(sc, p_proj, Geom::L2(p.getPoint() - p_proj), p.getSourceType(), p.getSourceNum(), true, radians); + _addSnappedPoint(sc, p_proj, Geom::L2(p.getPoint() - p_proj), p.getSourceType(), p.getSourceNum(), true); } else if (dist < radius) { // Two points of intersection, symmetrical with respect to the projected point // Calculate half the length of the linesegment between the two points of intersection @@ -100,12 +95,8 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, Geom::Coord d = Geom::L2(gridguide_line.versor()); // length of versor, needed to normalize the versor if (d > 0) { Geom::Point v = l*gridguide_line.versor()/d; - v_proj = p_proj + v - origin; - radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); - _addSnappedPoint(sc, p_proj + v, Geom::L2(p.getPoint() - (p_proj + v)), p.getSourceType(), p.getSourceNum(), true, radians); - v_proj = p_proj - v - origin; - radians = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); - _addSnappedPoint(sc, p_proj - v, Geom::L2(p.getPoint() - (p_proj - v)), p.getSourceType(), p.getSourceNum(), true, radians); + _addSnappedPoint(sc, p_proj + v, Geom::L2(p.getPoint() - (p_proj + v)), p.getSourceType(), p.getSourceNum(), true); + _addSnappedPoint(sc, p_proj - v, Geom::L2(p.getPoint() - (p_proj - v)), p.getSourceType(), p.getSourceNum(), true); } } } else { @@ -130,7 +121,7 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // This snappoint is therefore fully constrained, so there's no need // to look for additional intersections; just return the snapped point // and forget about the line - _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum(), true, 1); + _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum(), true); } } } diff --git a/src/line-snapper.h b/src/line-snapper.h index 403c8cbba..4f3d17998 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -54,7 +54,7 @@ private: // Will only be implemented for guide lines, because grid lines don't have an origin virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; - virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap, Geom::Coord angle) const = 0; + virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const = 0; }; } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index f96335c4a..22d5f35aa 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -576,12 +576,6 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, Geom::Coord dist = Geom::L2(p_proj_on_cl - p_inters); SnappedPoint s = SnappedPoint(p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);; if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it - if (c.isCircular()) { - Geom::Point v_orig = c.getDirection(); // vector from the origin to the original (untransformed) point - Geom::Point v_inters = p_inters - c.getPoint(); - Geom::Coord radians = atan2(Geom::dot(Geom::rot90(v_orig), v_inters), Geom::dot(v_orig, v_inters)); - s.setTransformation(Geom::Point(radians, radians)); - } sc.points.push_back(s); } } diff --git a/src/snap.cpp b/src/snap.cpp index 265b7c19a..1127ccba1 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -366,12 +366,6 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint Geom::Point pp = constraint.projection(p.getPoint()); Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, NR_HUGE, 0, false, true, false); - if (constraint.isCircular()) { - Geom::Point v_orig = constraint.getDirection(); // vector from the origin to the original (untransformed) point - Geom::Point v_proj = pp - constraint.getPoint(); // vector from the origin to the projected point - Geom::Coord angle = atan2(Geom::dot(Geom::rot90(v_orig), v_proj), Geom::dot(v_orig, v_proj)); - no_snap.setTransformation(Geom::Point(angle, angle)); // Store the rotation (in radians), needed in case of snapping while rotating - } if (!someSnapperMightSnap()) { // Always return point on constraint @@ -639,7 +633,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /* We snapped. Find the transformation that describes where the snapped point has ** ended up, and also the metric for this transformation. */ - Geom::Point const a = (snapped_point.getPoint() - origin); // vector to snapped point + Geom::Point const a = snapped_point.getPoint() - origin; // vector to snapped point //Geom::Point const b = (*i - origin); // vector to original point switch (transformation_type) { @@ -703,14 +697,16 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSecondSnapDistance(NR_HUGE); break; case SKEW: - result[0] = (snapped_point.getPoint()[dim] - ((*i).getPoint())[dim]) / (((*i).getPoint())[1 - dim] - origin[1 - dim]); // skew factor + result[0] = (snapped_point.getPoint()[dim] - ((*i).getPoint())[dim]) / b[1 - dim]; // skew factor result[1] = transformation[1]; // scale factor // Store the metric for this transformation as a virtual distance snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); snapped_point.setSecondSnapDistance(NR_HUGE); break; case ROTATE: - result = snapped_point.getTransformation(); + // a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b + result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a)); + result[1] = result[1]; // how else should we store an angle in a point ;-) // Store the metric for this transformation as a virtual distance (we're storing an angle) snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); snapped_point.setSecondSnapDistance(NR_HUGE); -- cgit v1.2.3 From 481d61d14a18ea012527b6b93590bff6ad75ba33 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 17 Jul 2010 17:24:31 -0700 Subject: Correct behavior of gradient stops to extract color from swatch when color is drag-n-drop'ed or selected. (bzr r9620) --- src/extension/internal/javafx-out.cpp | 4 +- src/gradient-drag.cpp | 77 ++++++++++++++++++++++------------- src/gradient-drag.h | 2 + src/sp-gradient.cpp | 47 ++++----------------- src/sp-gradient.h | 1 + src/sp-stop.cpp | 30 +++++++++++++- src/sp-stop.h | 5 +++ src/style.cpp | 67 ++++++++++++++++-------------- src/style.h | 7 ++++ src/widgets/gradient-vector.cpp | 37 +++++------------ 10 files changed, 151 insertions(+), 126 deletions(-) (limited to 'src') diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index a4d348940..c635f7b2d 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -386,7 +386,7 @@ bool JavaFXOutput::doStyle(SPStyle *style) /** * Fill */ - SPIPaint fill = style->fill; + SPIPaint const &fill = style->fill; if (fill.isColor()) { // see color.h for how to parse SPColor @@ -423,7 +423,7 @@ bool JavaFXOutput::doStyle(SPStyle *style) */ if (style->stroke_opacity.value > 0) { - SPIPaint stroke = style->stroke; + SPIPaint const &stroke = style->stroke; out(" stroke: %s\n", rgba(stroke.value.color, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)).c_str()); double strokewidth = style->stroke_width.value; diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 1492e9008..e7536a86a 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -176,6 +176,43 @@ gr_drag_style_query (SPStyle *style, int property, gpointer data) } } +Glib::ustring GrDrag::makeStopSafeColor( gchar const *str, bool &isNull ) +{ + Glib::ustring colorStr; + if ( str ) { + isNull = false; + colorStr = str; + Glib::ustring::size_type pos = colorStr.find("url(#"); + if ( pos != Glib::ustring::npos ) { + Glib::ustring targetName = colorStr.substr(pos + 5, colorStr.length() - 6); + const GSList *gradients = sp_document_get_resource_list(desktop->doc(), "gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + SPGradient *vect = grad->getVector(); + SPStop *firstStop = (vect) ? vect->getFirstStop() : grad->getFirstStop(); + if (firstStop) { + Glib::ustring stopColorStr; + if (firstStop->currentColor) { + stopColorStr = sp_object_get_style_property(firstStop, "color", NULL); + } else { + stopColorStr = firstStop->specified_color.toString(); + } + if ( !stopColorStr.empty() ) { + colorStr = stopColorStr; + } + } + break; + } + } + } + } else { + isNull = true; + } + + return colorStr; +} + bool GrDrag::styleSet( const SPCSSAttr *css ) { if (!selected) { @@ -214,30 +251,10 @@ bool GrDrag::styleSet( const SPCSSAttr *css ) // Make sure the style is allowed for gradient stops. if ( !sp_repr_css_property_is_unset( stop, "stop-color") ) { - Glib::ustring tmp = sp_repr_css_property( stop, "stop-color", "" ); - Glib::ustring::size_type pos = tmp.find("url(#"); - if ( pos != Glib::ustring::npos ) { - Glib::ustring targetName = tmp.substr(pos + 5, tmp.length() - 6); - const GSList *gradients = sp_document_get_resource_list(desktop->doc(), "gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - SPGradient *vect = grad->getVector(); - SPStop *firstStop = (vect) ? vect->getFirstStop() : grad->getFirstStop(); - if (firstStop) { - Glib::ustring stopColorStr; - if (firstStop->currentColor) { - stopColorStr = sp_object_get_style_property(firstStop, "color", NULL); - } else { - stopColorStr = firstStop->specified_color.toString(); - } - if ( !stopColorStr.empty() ) { - sp_repr_css_set_property( stop, "stop-color", stopColorStr.c_str() ); - } - } - break; - } - } + bool stopIsNull = false; + Glib::ustring tmp = makeStopSafeColor( sp_repr_css_property( stop, "stop-color", "" ), stopIsNull ); + if ( !stopIsNull && !tmp.empty() ) { + sp_repr_css_set_property( stop, "stop-color", tmp.c_str() ); } } @@ -393,14 +410,18 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance) bool GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) { + // Note: not sure if a null pointer can come in for the style, but handle that just in case + bool stopIsNull = false; + Glib::ustring toUse = makeStopSafeColor( c, stopIsNull ); + // first, see if we can drop onto one of the existing draggers for (GList *i = draggers; i != NULL; i = i->next) { // for all draggables of dragger GrDragger *d = (GrDragger *) i->data; if (Geom::L2(p - d->point)*desktop->current_zoom() < 5) { SPCSSAttr *stop = sp_repr_css_attr_new (); - sp_repr_css_set_property (stop, "stop-color", c); - sp_repr_css_set_property (stop, "stop-opacity", "1"); + sp_repr_css_set_property( stop, "stop-color", stopIsNull ? 0 : toUse.c_str() ); + sp_repr_css_set_property( stop, "stop-opacity", "1" ); for (GSList *j = d->draggables; j != NULL; j = j->next) { // for all draggables of dragger GrDraggable *draggable = (GrDraggable *) j->data; local_change = true; @@ -423,8 +444,8 @@ GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) SPStop *stop = addStopNearPoint (line->item, p, 5/desktop->current_zoom()); if (stop) { SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, "stop-color", c); - sp_repr_css_set_property (css, "stop-opacity", "1"); + sp_repr_css_set_property( css, "stop-color", stopIsNull ? 0 : toUse.c_str() ); + sp_repr_css_set_property( css, "stop-opacity", "1" ); sp_repr_css_change (SP_OBJECT_REPR (stop), css, "style"); return true; } diff --git a/src/gradient-drag.h b/src/gradient-drag.h index 22c0dbfb6..8cbe9f305 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -177,6 +177,8 @@ private: bool styleSet( const SPCSSAttr *css ); + Glib::ustring makeStopSafeColor( gchar const *str, bool &isNull ); + Inkscape::Selection *selection; sigc::connection sel_changed_connection; sigc::connection sel_modified_connection; diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 34912d1da..68efd0832 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -45,6 +45,7 @@ #include "streq.h" #include "uri.h" #include "xml/repr.h" +#include "style.h" #define SP_MACROS_SILENT #include "macros.h" @@ -172,9 +173,7 @@ sp_stop_set(SPObject *object, unsigned key, gchar const *value) if (streq(p, "currentColor")) { stop->currentColor = true; } else { - // TODO need to properly read full color, including icc - guint32 const color = sp_svg_read_color(p, 0); - stop->specified_color.set( color ); + stop->specified_color = SPStop::readStopColor( p ); } } { @@ -192,8 +191,7 @@ sp_stop_set(SPObject *object, unsigned key, gchar const *value) stop->currentColor = true; } else { stop->currentColor = false; - guint32 const color = sp_svg_read_color(p, 0); - stop->specified_color.set( color ); + stop->specified_color = SPStop::readStopColor( p ); } } object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); @@ -233,11 +231,12 @@ sp_stop_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML: repr = xml_doc->createElement("svg:stop"); } - guint32 specifiedcolor = stop->specified_color.toRGBA32( 255 ); + Glib::ustring colorStr = stop->specified_color.toString(); gfloat opacity = stop->opacity; - if (((SPObjectClass *) stop_parent_class)->write) + if (((SPObjectClass *) stop_parent_class)->write) { (* ((SPObjectClass *) stop_parent_class)->write)(object, xml_doc, repr, flags); + } // Since we do a hackish style setting here (because SPStyle does not support stop-color and // stop-opacity), we must do it AFTER calling the parent write method; otherwise @@ -248,9 +247,7 @@ sp_stop_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML: if (stop->currentColor) { os << "currentColor"; } else { - gchar c[64]; - sp_svg_write_color(c, sizeof(c), specifiedcolor); - os << c; + os << colorStr; } os << ";stop-opacity:" << opacity; repr->setAttribute("style", os.str().c_str()); @@ -324,29 +321,6 @@ sp_stop_get_rgba32(SPStop const *const stop) } } -/** - * Return stop's color as SPColor. - */ -static SPColor -sp_stop_get_color(SPStop const *const stop) -{ - if (stop->currentColor) { - char const *str = sp_object_get_style_property(stop, "color", NULL); - guint32 const dfl = 0; - /* Default value: arbitrarily black. (SVG1.1 and CSS2 both say that the initial - * value depends on user agent, and don't give any further restrictions that I can - * see.) */ - guint32 color = dfl; - if (str) { - color = sp_svg_read_color(str, dfl); - } - SPColor ret( color ); - return ret; - } else { - return stop->specified_color; - } -} - /* * Gradient */ @@ -664,7 +638,6 @@ void SPGradientImpl::removeChild(SPObject *object, Inkscape::XML::Node *child) } if ( gr->getStopCount() == 0 ) { - g_message("Check on remove"); gchar const * attr = gr->repr->attribute("osb:paint"); if ( attr && strcmp(attr, "solid") ) { sp_object_setAttribute( gr, "osb:paint", "solid", 0 ); @@ -1000,9 +973,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) sp_repr_set_css_double(child, "offset", gr->vector.stops[i].offset); /* strictly speaking, offset an SVG rather than a CSS one, but exponents make no * sense for offset proportions. */ - gchar c[64]; - sp_svg_write_color(c, sizeof(c), gr->vector.stops[i].color.toRGBA32( 0x00 )); - os << "stop-color:" << c << ";stop-opacity:" << gr->vector.stops[i].opacity; + os << "stop-color:" << gr->vector.stops[i].color.toString() << ";stop-opacity:" << gr->vector.stops[i].opacity; child->setAttribute("style", os.str().c_str()); /* Order will be reversed here */ cl = g_slist_prepend(cl, child); @@ -1099,7 +1070,7 @@ void SPGradient::rebuildVector() // down to 100%." gstop.offset = CLAMP(gstop.offset, 0, 1); - gstop.color = sp_stop_get_color(stop); + gstop.color = stop->getEffectiveColor(); gstop.opacity = stop->opacity; vector.stops.push_back(gstop); diff --git a/src/sp-gradient.h b/src/sp-gradient.h index b05cb5fb8..97ea78fca 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -18,6 +18,7 @@ */ #include +#include #include "libnr/nr-matrix.h" #include "sp-paint-server.h" #include "sp-gradient-spread.h" diff --git a/src/sp-stop.cpp b/src/sp-stop.cpp index 740cfef78..71f937927 100644 --- a/src/sp-stop.cpp +++ b/src/sp-stop.cpp @@ -15,7 +15,7 @@ #include "sp-stop.h" - +#include "style.h" // A stop might have some non-stop siblings SPStop* SPStop::getNextStop() @@ -52,6 +52,34 @@ SPStop* SPStop::getPrevStop() return result; } +SPColor SPStop::readStopColor( Glib::ustring const &styleStr, guint32 dfl ) +{ + SPColor color(dfl); + SPStyle* style = sp_style_new(0); + SPIPaint paint; + paint.read( styleStr.c_str(), *style ); + if ( paint.isColor() ) { + color = paint.value.color; + } + sp_style_unref(style); + return color; +} + +SPColor SPStop::getEffectiveColor() const +{ + SPColor ret; + if (currentColor) { + char const *str = sp_object_get_style_property(this, "color", NULL); + /* Default value: arbitrarily black. (SVG1.1 and CSS2 both say that the initial + * value depends on user agent, and don't give any further restrictions that I can + * see.) */ + ret = readStopColor( str, 0 ); + } else { + ret = specified_color; + } + return ret; +} + /* diff --git a/src/sp-stop.h b/src/sp-stop.h index bf6893db1..2cf8ad690 100644 --- a/src/sp-stop.h +++ b/src/sp-stop.h @@ -9,6 +9,7 @@ */ #include +#include #include "sp-object.h" #include "color.h" @@ -43,8 +44,12 @@ struct SPStop : public SPObject { gfloat opacity; + static SPColor readStopColor( Glib::ustring const &styleStr, guint32 dfl = 0 ); + SPStop* getNextStop(); SPStop* getPrevStop(); + + SPColor getEffectiveColor() const; }; /// The SPStop vtable. diff --git a/src/style.cpp b/src/style.cpp index ffc1fb0ae..a4094621f 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -1,5 +1,3 @@ -#define __SP_STYLE_C__ - /** @file * @brief SVG stylesheets implementation. */ @@ -85,7 +83,6 @@ static void sp_style_read_ilength(SPILength *val, gchar const *str); static void sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str); static void sp_style_read_itextdecoration(SPITextDecoration *val, gchar const *str); static void sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document); -static void sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document); static void sp_style_read_ifontsize(SPIFontSize *val, gchar const *str); static void sp_style_read_ibaselineshift(SPIBaselineShift *val, gchar const *str); static void sp_style_read_ifilter(gchar const *str, SPStyle *style, SPDocument *document); @@ -488,11 +485,11 @@ sp_style_new_from_object(SPObject *object) g_return_val_if_fail(object != NULL, NULL); g_return_val_if_fail(SP_IS_OBJECT(object), NULL); - SPStyle *style = sp_style_new(SP_OBJECT_DOCUMENT(object)); + SPStyle *style = sp_style_new( object->document ); style->object = object; style->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_style_object_release), style)); - if (object && SP_OBJECT_IS_CLONED(object)) { + if (object && object->cloned) { style->cloned = true; } @@ -574,7 +571,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) sp_style_clear(style); - if (object && SP_OBJECT_IS_CLONED(object)) { + if (object && object->cloned) { style->cloned = true; } @@ -662,7 +659,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) if (!style->fill.set) { val = repr->attribute("fill"); if (val) { - sp_style_read_ipaint(&style->fill, val, style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL); + style->fill.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL ); } } /* fill-opacity */ @@ -678,7 +675,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) if (!style->stroke.set) { val = repr->attribute("stroke"); if (val) { - sp_style_read_ipaint(&style->stroke, val, style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL); + style->stroke.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL ); } } SPS_READ_PLENGTH_IF_UNSET(&style->stroke_width, repr, "stroke-width"); @@ -1083,7 +1080,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) } case SP_PROP_FILL: if (!style->fill.set) { - sp_style_read_ipaint(&style->fill, val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL); + style->fill.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL ); } break; case SP_PROP_FILL_OPACITY: @@ -1150,7 +1147,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) case SP_PROP_STROKE: if (!style->stroke.set) { - sp_style_read_ipaint(&style->stroke, val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL); + style->stroke.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL ); } break; case SP_PROP_STROKE_WIDTH: @@ -3200,18 +3197,17 @@ sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume * * \pre paint == \&style.fill || paint == \&style.stroke. */ -static void -sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document) +void SPIPaint::read( gchar const *str, SPStyle &style, SPDocument *document ) { while (g_ascii_isspace(*str)) { ++str; } - paint->clear(); + clear(); if (streq(str, "inherit")) { - paint->set = TRUE; - paint->inherit = TRUE; + set = TRUE; + inherit = TRUE; } else { if ( strneq(str, "url", 3) ) { gchar *uri = extract_uri( str, &str ); @@ -3219,33 +3215,33 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume ++str; } // TODO check on and comment the comparrison "paint != &style->color". - if ( uri && *uri && (paint != &style->color) ) { - paint->set = TRUE; + if ( uri && *uri && (this != &style.color) ) { + set = TRUE; // it may be that this style's SPIPaint has not yet created its URIReference; // now that we have a document, we can create it here - if (!paint->value.href && document) { - paint->value.href = new SPPaintServerReference(document); - paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((paint == &style->fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), style)); + if (!value.href && document) { + value.href = new SPPaintServerReference(document); + value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((this == &style.fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), &style)); } // TODO check what this does in light of move away from union - sp_style_set_ipaint_to_uri_string (style, paint, uri); + sp_style_set_ipaint_to_uri_string (&style, this, uri); } g_free( uri ); } - if (streq(str, "currentColor") && paint != &style->color) { - paint->set = TRUE; - paint->currentcolor = TRUE; - } else if (streq(str, "none") && paint != &style->color) { - paint->set = TRUE; - paint->noneSet = TRUE; + if (streq(str, "currentColor") && (this != &style.color)) { + set = TRUE; + currentcolor = TRUE; + } else if (streq(str, "none") && (this != &style.color)) { + set = TRUE; + noneSet = TRUE; } else { guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff); if (rgb0 != 0xff) { - paint->setColor( rgb0 ); - paint->set = TRUE; + setColor( rgb0 ); + set = TRUE; while (g_ascii_isspace(*str)) { ++str; @@ -3256,7 +3252,7 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume delete tmp; tmp = 0; } - paint->value.color.icc = tmp; + value.color.icc = tmp; } } } @@ -4025,6 +4021,17 @@ sp_style_write_ifilter(gchar *p, gint const len, gchar const *key, return 0; } +SPIPaint::SPIPaint() : + set(0), + inherit(0), + currentcolor(0), + colorSet(0), + noneSet(0), + value() +{ + value.color.set( 0 ); + value.href = 0; +} void SPIPaint::clear() { diff --git a/src/style.h b/src/style.h index 8102ce0ea..b38df2532 100644 --- a/src/style.h +++ b/src/style.h @@ -159,6 +159,7 @@ struct SPIPaint { SPColor color; } value; + SPIPaint(); bool isSet() const { return true; /* set || colorSet*/} bool isSameType( SPIPaint const & other ) const {return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);} @@ -174,6 +175,12 @@ struct SPIPaint { void setColor( float r, float g, float b ) {value.color.set( r, g, b ); colorSet = true;} void setColor( guint32 val ) {value.color.set( val ); colorSet = true;} void setColor( SPColor const& color ) {value.color = color; colorSet = true;} + + void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0); + +private: + SPIPaint(SPIPaint const&); + SPIPaint &operator=(SPIPaint const &); }; /// Filter type internal to SPStyle diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index c49d9e06f..7f0256665 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -479,11 +479,8 @@ static void verify_grad(SPGradient *gradient) xml_doc = SP_OBJECT_REPR(gradient)->document(); if (i < 1) { - gchar c[64]; - sp_svg_write_color(c, sizeof(c), 0x00000000); - Inkscape::CSSOStringStream os; - os << "stop-color:" << c << ";stop-opacity:" << 1.0 << ";"; + os << "stop-color: #000000;stop-opacity:" << 1.0 << ";"; Inkscape::XML::Node *child; @@ -555,11 +552,9 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_ } else { for (; sl != NULL; sl = sl->next){ - SPStop *stop; - GtkWidget *i; if (SP_IS_STOP(sl->data)){ - stop = SP_STOP(sl->data); - i = gtk_menu_item_new(); + SPStop *stop = SP_STOP(sl->data); + GtkWidget *i = gtk_menu_item_new(); gtk_widget_show(i); g_object_set_data(G_OBJECT(i), "stop", stop); GtkWidget *hb = gtk_hbox_new(FALSE, 4); @@ -605,11 +600,8 @@ static void sp_grad_edit_select(GtkOptionMenu *mnu, GtkWidget *tbl) blocked = TRUE; SPColorSelector *csel = (SPColorSelector*)g_object_get_data(G_OBJECT(tbl), "cselector"); - guint32 const c = sp_stop_get_rgba32(stop); - csel->base->setAlpha(SP_RGBA32_A_F(c)); - SPColor color( SP_RGBA32_R_F(c), SP_RGBA32_G_F(c), SP_RGBA32_B_F(c) ); // set its color, from the stored array - csel->base->setColor( color ); + csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity ); GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offspn")); GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offslide")); @@ -1026,15 +1018,11 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien GtkOptionMenu *mnu = static_cast(g_object_get_data(G_OBJECT(widget), "stopmenu")); SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")); - guint32 const c = sp_stop_get_rgba32(stop); - /// get the color selector + // get the color selector SPColorSelector *csel = SP_COLOR_SELECTOR(g_object_get_data(G_OBJECT(widget), "cselector")); - // set alpha - csel->base->setAlpha(SP_RGBA32_A_F(c)); - SPColor color( SP_RGBA32_R_F(c), SP_RGBA32_G_F(c), SP_RGBA32_B_F(c) ); - // set color - csel->base->setColor( color ); + + csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity ); /* Fill preview */ GtkWidget *w = static_cast(g_object_get_data(G_OBJECT(widget), "preview")); @@ -1159,10 +1147,6 @@ static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GtkObject *o static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *object) { - SPColor color; - float alpha; - guint32 rgb; - if (blocked) { return; } @@ -1190,14 +1174,13 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")); csel = static_cast(g_object_get_data(G_OBJECT(object), "cselector")); + SPColor color; + float alpha = 0; csel->base->getColorAlpha( color, alpha ); - rgb = color.toRGBA32( 0x00 ); sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", stop->offset); Inkscape::CSSOStringStream os; - gchar c[64]; - sp_svg_write_color(c, sizeof(c), rgb); - os << "stop-color:" << c << ";stop-opacity:" << static_cast(alpha) <<";"; + os << "stop-color:" << color.toString() << ";stop-opacity:" << static_cast(alpha) <<";"; SP_OBJECT_REPR(stop)->setAttribute("style", os.str().c_str()); // g_snprintf(c, 256, "stop-color:#%06x;stop-opacity:%g;", rgb >> 8, static_cast(alpha)); //SP_OBJECT_REPR(stop)->setAttribute("style", c); -- cgit v1.2.3 From d495877a1362d8af3246462fd48c1f1585c7addc Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 17 Jul 2010 23:32:23 -0700 Subject: Correct the default for the save-as location to match the UI. Fixes bug #561375 (pending branch) (bzr r9623) --- src/extension/system.cpp | 2 +- src/preferences-skeleton.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/system.cpp b/src/extension/system.cpp index 6ffa7f57f..5412a5cc0 100644 --- a/src/extension/system.cpp +++ b/src/extension/system.cpp @@ -589,7 +589,7 @@ get_file_save_path (SPDocument *doc, FileSaveMethod method) { switch (method) { case FILE_SAVE_METHOD_SAVE_AS: { - bool use_current_dir = prefs->getBool("/dialogs/save_as/use_current_dir"); + bool use_current_dir = prefs->getBool("/dialogs/save_as/use_current_dir", true); if (doc->uri && use_current_dir) { path = Glib::path_get_dirname(doc->uri); } else { diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index dd925490e..c73cae17f 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -193,7 +193,7 @@ static char const preferences_skeleton[] = " \n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" -- cgit v1.2.3 From 85f7f284bd34c9696705c781c6e4b3251ff058ba Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 18 Jul 2010 02:17:58 -0700 Subject: Turn off color profile debug messages. (bzr r9624) --- src/color-profile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/color-profile.cpp b/src/color-profile.cpp index 43709793c..a8238556c 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -2,7 +2,7 @@ # include "config.h" #endif -#define DEBUG_LCMS +#define noDEBUG_LCMS #include #include -- cgit v1.2.3 From 03e65527a5994b916056f263e96d9bc19acff878 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 18 Jul 2010 12:12:38 +0200 Subject: - do not use shift to disable snapping while holding shift to rotate a guide - snap guides to paths too - always show the same snap indicator (bzr r9625) --- src/desktop-events.cpp | 14 ++++++-------- src/display/snap-indicator.cpp | 30 +++++++++--------------------- src/object-snapper.cpp | 8 +++----- src/object-snapper.h | 2 +- src/snap.cpp | 3 +-- 5 files changed, 20 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp index 810f501d7..bb22b0faa 100644 --- a/src/desktop-events.cpp +++ b/src/desktop-events.cpp @@ -296,10 +296,9 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) if (!(event->motion.state & GDK_SHIFT_MASK)) { m.guideConstrainedSnap(motion_dt, *guide); } - } else if (!(event->motion.state & GDK_SHIFT_MASK)) { - if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) { - m.guideFreeSnap(motion_dt, guide->normal_to_line, drag_type); - } + } else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) { + // cannot use shift here to disable snapping, because we already use it for rotating the guide + m.guideFreeSnap(motion_dt, guide->normal_to_line, drag_type); } switch (drag_type) { @@ -361,10 +360,9 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) if (!(event->button.state & GDK_SHIFT_MASK)) { m.guideConstrainedSnap(event_dt, *guide); } - } else if (!(event->button.state & GDK_SHIFT_MASK)) { - if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) { - m.guideFreeSnap(event_dt, guide->normal_to_line, drag_type); - } + } else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) { + // cannot use shift here to disable snapping, because we already use it for rotating the guide + m.guideFreeSnap(event_dt, guide->normal_to_line, drag_type); } if (sp_canvas_world_pt_inside_window(item->canvas, event_w)) { diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 0409e64b1..776c56c15 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -228,27 +228,15 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap // Display the snap indicator (i.e. the cross) SPCanvasItem * canvasitem = NULL; - if (p.getTarget() == SNAPTARGET_NODE_SMOOTH || p.getTarget() == SNAPTARGET_NODE_CUSP) { - canvasitem = sp_canvas_item_new(sp_desktop_tempgroup (_desktop), - SP_TYPE_CTRL, - "anchor", GTK_ANCHOR_CENTER, - "size", 10.0, - "stroked", TRUE, - "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_DIAMOND, - NULL ); - } else { - canvasitem = sp_canvas_item_new(sp_desktop_tempgroup (_desktop), - SP_TYPE_CTRL, - "anchor", GTK_ANCHOR_CENTER, - "size", 10.0, - "stroked", TRUE, - "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); - } + canvasitem = sp_canvas_item_new(sp_desktop_tempgroup (_desktop), + SP_TYPE_CTRL, + "anchor", GTK_ANCHOR_CENTER, + "size", 10.0, + "stroked", TRUE, + "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); const int timeout_val = 1200; // TODO add preference for snap indicator timeout? diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 22d5f35aa..57d5b0fc5 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -281,18 +281,16 @@ void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, } } -void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &sc, +void Inkscape::ObjectSnapper::_snapTranslatingGuide(SnappedConstraints &sc, Geom::Point const &p, Geom::Point const &guide_normal) const { // Iterate through all nodes, find out which one is the closest to this guide, and snap to it! _collectNodes(SNAPSOURCE_GUIDE, true); - // Although we won't snap to paths here (which would give us under constrained snaps) we can still snap to intersections of paths. if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { _collectPaths(Inkscape::SnapCandidatePoint(p, SNAPSOURCE_GUIDE), true); _snapPaths(sc, Inkscape::SnapCandidatePoint(p, SNAPSOURCE_GUIDE), NULL, NULL); - // The paths themselves should be discarded in findBestSnap(), as we should only snap to their intersections } SnappedPoint s; @@ -682,7 +680,7 @@ void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc, } _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); - _snapTranslatingGuideToNodes(sc, p, guide_normal); + _snapTranslatingGuide(sc, p, guide_normal); } @@ -706,7 +704,7 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, } _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); - _snapTranslatingGuideToNodes(sc, p, guide_normal); + _snapTranslatingGuide(sc, p, guide_normal); } diff --git a/src/object-snapper.h b/src/object-snapper.h index 454a18545..b0084c2d7 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -84,7 +84,7 @@ private: Inkscape::SnapCandidatePoint const &p, std::vector *unselected_nodes) const; // in desktop coordinates - void _snapTranslatingGuideToNodes(SnappedConstraints &sc, + void _snapTranslatingGuide(SnappedConstraints &sc, Geom::Point const &p, Geom::Point const &guide_normal) const; diff --git a/src/snap.cpp b/src/snap.cpp index 1127ccba1..ccaf3dee3 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -430,8 +430,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, (*i)->freeSnap(sc, candidate, Geom::OptRect(), NULL, NULL); } - // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) - Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false, true); + Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false, false); s.getPoint(p); } -- cgit v1.2.3 From 3792c590a31a9155ccb69279ca591de17fa2e3db Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 19 Jul 2010 09:14:43 +0200 Subject: Fix snapping to midpoints of closing segments (bzr r9627) --- src/object-snapper.cpp | 12 +++++-- src/sp-shape.cpp | 86 +++++++++++++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 57d5b0fc5..7d593dfc4 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -13,6 +13,7 @@ #include "svg/svg.h" #include <2geom/path-intersection.h> +#include <2geom/pathvector.h> #include <2geom/point.h> #include <2geom/rect.h> #include <2geom/line.h> @@ -386,9 +387,14 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & if (!very_lenghty_prose && !very_complex_path) { SPCurve *curve = curve_for_item(root_item); if (curve) { - // We will get our own copy of the path, which must be freed at some point - Geom::PathVector *borderpathv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); - _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(borderpathv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. + // We will get our own copy of the pathvector, which must be freed at some point + + // Geom::PathVector *pv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); + + Geom::PathVector *pv = new Geom::PathVector(curve->get_pathvector()); + (*pv) *= sp_item_i2d_affine(root_item) * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt(); // (_edit_transform * _i2d_transform); + + _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(pv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. curve->unref(); } } diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 3064341b6..0038908bf 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -1208,51 +1208,57 @@ static void sp_shape_snappoints(SPItem const *item, std::vectorgetSnapToItemNode()) { - p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + // Add the first point of the path + p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - while (curve_it2 != path_it->end_closed()) + while (curve_it1 != path_it->end_default()) { - /* Test whether to add the node between curve_it1 and curve_it2. - * Loop to end_closed (so always including closing segment); the last node to be added - * is the node between the closing segment and the segment before that, regardless - * of the path being closed or not. If the path is closed, the final point was already added by - * adding the initial point. */ - - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); - - bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); - bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); - - if (c1 || c2) { - Inkscape::SnapSourceType sst; - Inkscape::SnapTargetType stt; - switch (nodetype) { - case Geom::NODE_CUSP: - sst = Inkscape::SNAPSOURCE_NODE_CUSP; - stt = Inkscape::SNAPTARGET_NODE_CUSP; - break; - case Geom::NODE_SMOOTH: - case Geom::NODE_SYMM: - sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; - stt = Inkscape::SNAPTARGET_NODE_SMOOTH; - break; - default: - sst = Inkscape::SNAPSOURCE_UNDEFINED; - stt = Inkscape::SNAPTARGET_UNDEFINED; - break; - } - p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); - } - - // Consider midpoints of line segments for snapping - if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) - if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { - p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); - } - } + // For each path: consider midpoints of line segments for snapping + if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) + if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { + p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + } + + if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop + if (snapprefs->getSnapToItemNode() && !path_it->closed()) { + // Add the last point of the path, but only for open paths + // (for closed paths the first and last point will coincide) + p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + } + } else { + /* Test whether to add the node between curve_it1 and curve_it2. + * Loop to end_default (so only iterating through the stroked part); */ + + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); + + bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); + bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); + + if (c1 || c2) { + Inkscape::SnapSourceType sst; + Inkscape::SnapTargetType stt; + switch (nodetype) { + case Geom::NODE_CUSP: + sst = Inkscape::SNAPSOURCE_NODE_CUSP; + stt = Inkscape::SNAPTARGET_NODE_CUSP; + break; + case Geom::NODE_SMOOTH: + case Geom::NODE_SYMM: + sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; + stt = Inkscape::SNAPTARGET_NODE_SMOOTH; + break; + default: + sst = Inkscape::SNAPSOURCE_UNDEFINED; + stt = Inkscape::SNAPTARGET_UNDEFINED; + break; + } + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); + } + } ++curve_it1; ++curve_it2; -- cgit v1.2.3 From dcd8bdc37504934d8aa62a0d69373cf31c7a1c65 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 20 Jul 2010 00:02:19 +0200 Subject: fix build broken by 9620 (bzr r9630) --- src/style.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/style.h b/src/style.h index b38df2532..d437a50f0 100644 --- a/src/style.h +++ b/src/style.h @@ -178,9 +178,9 @@ struct SPIPaint { void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0); -private: - SPIPaint(SPIPaint const&); - SPIPaint &operator=(SPIPaint const &); +//private: +// SPIPaint(SPIPaint const&); +// SPIPaint &operator=(SPIPaint const &); }; /// Filter type internal to SPStyle -- cgit v1.2.3 From f6745b23938b91b6bd5fa5f4b2cdc48ae819bead Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 20 Jul 2010 01:05:20 -0700 Subject: Restore code safety for all but Win32. (bzr r9632) --- src/style.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/style.h b/src/style.h index d437a50f0..f937fe33b 100644 --- a/src/style.h +++ b/src/style.h @@ -178,9 +178,12 @@ struct SPIPaint { void read( gchar const *str, SPStyle &tyle, SPDocument *document = 0); -//private: -// SPIPaint(SPIPaint const&); -// SPIPaint &operator=(SPIPaint const &); + // Win32 is a temp work-around until the emf extension is fixed: +#ifndef WIN32 +private: + SPIPaint(SPIPaint const&); + SPIPaint &operator=(SPIPaint const &); +#endif // WIN32 }; /// Filter type internal to SPStyle -- cgit v1.2.3 From 1bdbb699669ead878488dbda5452305ecfe19a5d Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Tue, 20 Jul 2010 21:18:58 +0200 Subject: - Remove some old code which snapped the rotation center to the bbox, and which discarded all of the snapping settings - Improve the logic behind the snapping buttons, i.e. what snaps to what for each of the buttons (bzr r9634) --- src/object-snapper.cpp | 77 ++++++++++++++++++++++++++------------------------ src/object-snapper.h | 1 - src/seltrans.cpp | 19 ------------- src/snap.cpp | 5 ++-- 4 files changed, 42 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 7d593dfc4..4c5ad800c 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -86,10 +86,7 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, bool const clip_or_mask, Geom::Matrix const additional_affine) const // transformation of the item being clipped / masked { - bool const c1 = (snap_dim == TRANSL_SNAP_XY) && ThisSnapperMightSnap(); - bool const c2 = (snap_dim != TRANSL_SNAP_XY) && GuidesMightSnap(); - - if (!(c1 || c2)) { + if (!((snap_dim == TRANSL_SNAP_XY) && ThisSnapperMightSnap())) { return; } @@ -98,7 +95,6 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, // Apparently the etup() method from the SnapManager class hasn't been called before trying to snap. } - if (first_point) { _candidates->clear(); } @@ -338,7 +334,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & } // Consider the page border for snapping - if (_snapmanager->snapprefs.getSnapToPageBorder()) { + if (_snapmanager->snapprefs.getSnapToPageBorder() && _snapmanager->snapprefs.getSnapModeBBoxOrNodes()) { Geom::PathVector *border_path = _getBorderPathv(); if (border_path != NULL) { _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(border_path, SNAPTARGET_PAGE_BORDER, Geom::OptRect())); @@ -363,7 +359,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & //Build a list of all paths considered for snapping to //Add the item's path to snap to - if (_snapmanager->snapprefs.getSnapToItemPath()) { + if (_snapmanager->snapprefs.getSnapToItemPath() && _snapmanager->snapprefs.getSnapModeNode()) { if (p_is_other || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node)) { // Snapping to the path of characters is very cool, but for a large // chunk of text this will take ages! So limit snapping to text paths @@ -402,7 +398,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & } //Add the item's bounding box to snap to - if (_snapmanager->snapprefs.getSnapToBBoxPath()) { + if (_snapmanager->snapprefs.getSnapToBBoxPath() && _snapmanager->snapprefs.getSnapModeBBox()) { if (p_is_other || !(_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) { // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox // of the item AND the bbox of the clipping path at the same time @@ -606,15 +602,28 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); } - if (_snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes() - || _snapmanager->snapprefs.getSnapToBBoxNode() || _snapmanager->snapprefs.getSnapToPageBorder() - || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() - || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() - || _snapmanager->snapprefs.getIncludeItemCenter()) { + + bool snap_nodes = _snapmanager->snapprefs.getSnapModeNode() && ( + _snapmanager->snapprefs.getSnapToItemNode() || + _snapmanager->snapprefs.getSnapSmoothNodes() || + _snapmanager->snapprefs.getSnapLineMidpoints() || + _snapmanager->snapprefs.getSnapObjectMidpoints() + ) || _snapmanager->snapprefs.getSnapModeBBox() && ( + _snapmanager->snapprefs.getSnapToBBoxNode() || + _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || + _snapmanager->snapprefs.getSnapBBoxMidpoints() + ) || _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( + _snapmanager->snapprefs.getIncludeItemCenter() || + _snapmanager->snapprefs.getSnapToPageBorder() + ); + + if (snap_nodes) { _snapNodes(sc, p, unselected_nodes); } - if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { + if (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getSnapToItemPath() || + _snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxPath() || + _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->snapprefs.getSnapToPageBorder()) { unsigned n = (unselected_nodes == NULL) ? 0 : unselected_nodes->size(); if (n > 0) { /* While editing a path in the node tool, findCandidates must ignore that path because @@ -719,29 +728,23 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, */ bool Inkscape::ObjectSnapper::ThisSnapperMightSnap() const { - bool snap_to_something = _snapmanager->snapprefs.getSnapToItemPath() - || _snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes() - || _snapmanager->snapprefs.getSnapToBBoxPath() - || _snapmanager->snapprefs.getSnapToBBoxNode() - || _snapmanager->snapprefs.getSnapToPageBorder() - || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() - || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() - || _snapmanager->snapprefs.getIncludeItemCenter(); - - return (_snap_enabled && _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && snap_to_something); -} - -bool Inkscape::ObjectSnapper::GuidesMightSnap() const // almost the same as ThisSnapperMightSnap above, but only looking at points (and not paths) -{ - bool snap_to_something = _snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes() - || _snapmanager->snapprefs.getSnapToPageBorder() - || (_snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxNode()) - || (_snapmanager->snapprefs.getSnapModeBBox() && (_snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints())) - || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints())) - || (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getIncludeItemCenter()) - || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapToItemPath() && _snapmanager->snapprefs.getSnapIntersectionCS())); - - return (_snap_enabled && _snapmanager->snapprefs.getSnapModeGuide() && snap_to_something); + bool snap_to_something = (_snapmanager->snapprefs.getSnapModeNode() && ( + _snapmanager->snapprefs.getSnapToItemPath() || + _snapmanager->snapprefs.getSnapToItemNode() || + _snapmanager->snapprefs.getSnapSmoothNodes() || + _snapmanager->snapprefs.getSnapLineMidpoints() || + _snapmanager->snapprefs.getSnapObjectMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBox() && ( + _snapmanager->snapprefs.getSnapToBBoxPath() || + _snapmanager->snapprefs.getSnapToBBoxNode() || + _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || + _snapmanager->snapprefs.getSnapBBoxMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( + _snapmanager->snapprefs.getSnapToPageBorder() || + _snapmanager->snapprefs.getIncludeItemCenter() + )); + + return (_snap_enabled && snap_to_something); } void Inkscape::ObjectSnapper::_clear_paths() const diff --git a/src/object-snapper.h b/src/object-snapper.h index b0084c2d7..f3b54ed08 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -49,7 +49,6 @@ public: SnapConstraint const &c) const; bool ThisSnapperMightSnap() const; - bool GuidesMightSnap() const; Geom::Coord getSnapperTolerance() const; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 9c83dd63e..b9bf4c6ce 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -1339,25 +1339,6 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) } } - if ( !(state & GDK_SHIFT_MASK) && _bbox ) { - // screen pixels to snap center to bbox -#define SNAP_DIST 5 - // FIXME: take from prefs - double snap_dist = SNAP_DIST / _desktop->current_zoom(); - - for (int i = 0; i < 2; i++) { - if (fabs(pt[i] - _bbox->min()[i]) < snap_dist) { - pt[i] = _bbox->min()[i]; - } - if (fabs(pt[i] - _bbox->midpoint()[i]) < snap_dist) { - pt[i] = _bbox->midpoint()[i]; - } - if (fabs(pt[i] - _bbox->max()[i]) < snap_dist) { - pt[i] = _bbox->max()[i]; - } - } - } - // status text GString *xs = SP_PX_TO_METRIC_STRING(pt[Geom::X], _desktop->namedview->getDefaultMetric()); GString *ys = SP_PX_TO_METRIC_STRING(pt[Geom::Y], _desktop->namedview->getDefaultMetric()); diff --git a/src/snap.cpp b/src/snap.cpp index ccaf3dee3..ccbd449bd 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -174,7 +174,6 @@ void SnapManager::freeSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Geom::OptRect const &bbox_to_snap) const { - //TODO: SnapCandidatePoint and point_type are somewhat redundant; can't we get rid of the point_type parameter? Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); s.getPoint(p); } @@ -408,7 +407,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, return; } - if (!(object.GuidesMightSnap() || snapprefs.getSnapToGuides())) { + if (!(object.ThisSnapperMightSnap() || snapprefs.getSnapToGuides())) { return; } @@ -419,7 +418,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, // Snap to nodes SnappedConstraints sc; - if (object.GuidesMightSnap()) { + if (object.ThisSnapperMightSnap()) { object.guideFreeSnap(sc, p, guide_normal); } -- cgit v1.2.3 From fc337f39ebcfa544acbd2be2fdc6943d7d584d78 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 21 Jul 2010 02:17:34 +0200 Subject: When snapping to handle lines (Ctrl+Alt node drag), snap to perpendiculars of those lines as well (bzr r9636) --- src/ui/tool/node.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 886ddd1be..69c09602e 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -969,12 +969,27 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) if (held_control(*event)) { Geom::Point origin = _last_drag_origin(); - Inkscape::SnappedPoint fp, bp; + Inkscape::SnappedPoint fp, bp, fpp, bpp; if (held_alt(*event)) { // with Ctrl+Alt, constrain to handle lines - // project the new position onto a handle line that is closer - boost::optional front_point, back_point; - boost::optional line_front, line_back; + // project the new position onto a handle line that is closer; + // also snap to perpendiculars of handle lines + + // TODO: this code is repetitive to the point of sillyness. Find a way + // to express this concisely by modifying the semantics of snapping calls. + // During a non-snap invocation, we should call constrainedSnap() + // anyway, but it should just return the closest point matching the constraint + // rather than snapping to an object. There should be comparison + // operators defined for snap results, to simplify determining the best one, + // or the snapping calls should take a reference to a snapping result and + // replace it with the current result if it's better. + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int snaps = prefs->getIntLimited("/options/rotationsnapsperpi/value", 12, 1, 1000); + double min_angle = M_PI / snaps; + + boost::optional front_point, back_point, fperp_point, bperp_point; + boost::optional line_front, line_back, line_fperp, line_bperp; if (_front.isDegenerate()) { if (_is_line_segment(this, _next())) front_point = _next()->position() - origin; @@ -987,10 +1002,28 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) } else { back_point = _back.relativePos(); } - if (front_point) + if (front_point) { line_front = Inkscape::Snapper::SnapConstraint(origin, *front_point); - if (back_point) + fperp_point = Geom::rot90(*front_point); + } + if (back_point) { line_back = Inkscape::Snapper::SnapConstraint(origin, *back_point); + bperp_point = Geom::rot90(*back_point); + } + // perpendiculars only snap when they are further than snap increment away + // from the second handle constraint + if (fperp_point && (!back_point || + (fabs(Geom::angle_between(*fperp_point, *back_point)) > min_angle && + fabs(Geom::angle_between(*fperp_point, *back_point)) < M_PI - min_angle))) + { + line_fperp = Inkscape::Snapper::SnapConstraint(origin, *fperp_point); + } + if (bperp_point && (!front_point || + (fabs(Geom::angle_between(*bperp_point, *front_point)) > min_angle && + fabs(Geom::angle_between(*bperp_point, *front_point)) < M_PI - min_angle))) + { + line_bperp = Inkscape::Snapper::SnapConstraint(origin, *bperp_point); + } // TODO: combine the snap and non-snap branches by modifying snap.h / snap.cpp if (snap) { @@ -1002,11 +1035,25 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), *line_back); } + if (line_fperp) { + fpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, + _snapSourceType()), *line_fperp); + } + if (line_bperp) { + bpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, + _snapSourceType()), *line_bperp); + } } - if (fp.getSnapped() || bp.getSnapped()) { + if (fp.getSnapped() || bp.getSnapped() || fpp.getSnapped() || bpp.getSnapped()) { if (fp.isOtherSnapBetter(bp, false)) { fp = bp; } + if (fp.isOtherSnapBetter(fpp, false)) { + fp = fpp; + } + if (fp.isOtherSnapBetter(bpp, false)) { + fp = bpp; + } fp.getPoint(new_pos); _desktop->snapindicator->set_new_snaptarget(fp); } else { @@ -1019,6 +1066,16 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) pos = pos2; } + if (line_fperp) { + Geom::Point pos2 = line_fperp->projection(new_pos); + if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) + pos = pos2; + } + if (line_bperp) { + Geom::Point pos2 = line_bperp->projection(new_pos); + if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) + pos = pos2; + } if (pos) { new_pos = *pos; } else { -- cgit v1.2.3 From 1dc0534ee0f4e03687ae455cb838fd804fc30209 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 21 Jul 2010 15:30:04 +0200 Subject: Make OpenMP actually work on systems that use Autoconf. (bzr r9637) --- src/display/nr-filter-gaussian.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index 9509eaef7..a45e838da 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -590,7 +590,8 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) double const deviation_y_org = _deviation_y * trans.expansionY(); int const PC = NR_PIXBLOCK_BPP(in); #if HAVE_OPENMP - int const NTHREADS = std::max(1,std::min(8, Inkscape::Preferences::get()->getInt("/options/threading/numthreads", omp_get_num_procs()))); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int const NTHREADS = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256); #else int const NTHREADS = 1; #endif // HAVE_OPENMP -- cgit v1.2.3 From b7e8ffa3ab5fd61971c571c4fff599b57d2aafe0 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Wed, 21 Jul 2010 21:26:08 +0200 Subject: 1) Fix snapping of guides to nodes/paths; 2) replace a g_assert with a return statement (bzr r9638) --- src/object-snapper.cpp | 101 ++++++++++++++++++++----------------------------- src/object-snapper.h | 7 ---- src/sp-item.cpp | 11 +++++- 3 files changed, 50 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 4c5ad800c..ef5dcc7d0 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -75,18 +75,16 @@ bool Inkscape::ObjectSnapper::getSnapperAlwaysSnap() const * \param parent Pointer to the document's root, or to a clipped path or mask object * \param it List of items to ignore * \param bbox_to_snap Bounding box hulling the whole bunch of points, all from the same selection and having the same transformation - * \param DimensionToSnap Snap in X, Y, or both directions. */ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, std::vector const *it, bool const &first_point, Geom::Rect const &bbox_to_snap, - DimensionToSnap const snap_dim, bool const clip_or_mask, Geom::Matrix const additional_affine) const // transformation of the item being clipped / masked { - if (!((snap_dim == TRANSL_SNAP_XY) && ThisSnapperMightSnap())) { + if (!ThisSnapperMightSnap()) { return; } @@ -125,17 +123,17 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, // we should also consider that path or mask for snapping to obj = SP_OBJECT(item->clip_ref->getObject()); if (obj) { - _findCandidates(obj, it, false, bbox_to_snap, snap_dim, true, sp_item_i2doc_affine(item)); + _findCandidates(obj, it, false, bbox_to_snap, true, sp_item_i2doc_affine(item)); } obj = SP_OBJECT(item->mask_ref->getObject()); if (obj) { - _findCandidates(obj, it, false, bbox_to_snap, snap_dim, true, sp_item_i2doc_affine(item)); + _findCandidates(obj, it, false, bbox_to_snap, true, sp_item_i2doc_affine(item)); } } } if (SP_IS_GROUP(o)) { - _findCandidates(o, it, false, bbox_to_snap, snap_dim, clip_or_mask, additional_affine); + _findCandidates(o, it, false, bbox_to_snap, clip_or_mask, additional_affine); } else { Geom::OptRect bbox_of_item = Geom::Rect(); if (clip_or_mask) { @@ -295,6 +293,7 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuide(SnappedConstraints &sc, Geom::Coord tol = getSnapperTolerance(); for (std::vector::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { + // Project each node (*k) on the guide line (running through point p) Geom::Point p_proj = Geom::projection((*k).getPoint(), Geom::Line(p, p + Geom::rot90(guide_normal))); Geom::Coord dist = Geom::L2((*k).getPoint() - p_proj); // distance from node to the guide @@ -385,10 +384,10 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & if (curve) { // We will get our own copy of the pathvector, which must be freed at some point - // Geom::PathVector *pv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); + // Geom::PathVector *pv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); - Geom::PathVector *pv = new Geom::PathVector(curve->get_pathvector()); - (*pv) *= sp_item_i2d_affine(root_item) * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt(); // (_edit_transform * _i2d_transform); + Geom::PathVector *pv = new Geom::PathVector(curve->get_pathvector()); + (*pv) *= sp_item_i2d_affine(root_item) * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt(); // (_edit_transform * _i2d_transform); _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(pv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. curve->unref(); @@ -599,31 +598,31 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, /* Get a list of all the SPItems that we will try to snap to */ if (p.getSourceNum() == 0) { Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p.getPoint(), p.getPoint()); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, false, Geom::identity()); } - bool snap_nodes = _snapmanager->snapprefs.getSnapModeNode() && ( - _snapmanager->snapprefs.getSnapToItemNode() || - _snapmanager->snapprefs.getSnapSmoothNodes() || - _snapmanager->snapprefs.getSnapLineMidpoints() || - _snapmanager->snapprefs.getSnapObjectMidpoints() - ) || _snapmanager->snapprefs.getSnapModeBBox() && ( - _snapmanager->snapprefs.getSnapToBBoxNode() || - _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || - _snapmanager->snapprefs.getSnapBBoxMidpoints() - ) || _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( - _snapmanager->snapprefs.getIncludeItemCenter() || - _snapmanager->snapprefs.getSnapToPageBorder() - ); + bool snap_nodes = (_snapmanager->snapprefs.getSnapModeNode() && ( + _snapmanager->snapprefs.getSnapToItemNode() || + _snapmanager->snapprefs.getSnapSmoothNodes() || + _snapmanager->snapprefs.getSnapLineMidpoints() || + _snapmanager->snapprefs.getSnapObjectMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBox() && ( + _snapmanager->snapprefs.getSnapToBBoxNode() || + _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || + _snapmanager->snapprefs.getSnapBBoxMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( + _snapmanager->snapprefs.getIncludeItemCenter() || + _snapmanager->snapprefs.getSnapToPageBorder() + )); if (snap_nodes) { _snapNodes(sc, p, unselected_nodes); } if (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getSnapToItemPath() || - _snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxPath() || - _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->snapprefs.getSnapToPageBorder()) { + _snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxPath() || + _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->snapprefs.getSnapToPageBorder()) { unsigned n = (unselected_nodes == NULL) ? 0 : unselected_nodes->size(); if (n > 0) { /* While editing a path in the node tool, findCandidates must ignore that path because @@ -658,7 +657,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, /* Get a list of all the SPItems that we will try to snap to */ if (p.getSourceNum() == 0) { Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p.getPoint(), p.getPoint()); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, false, Geom::identity()); } // A constrained snap, is a snap in only one degree of freedom (specified by the constraint line). @@ -685,16 +684,7 @@ void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc, std::vector cand; std::vector const it; //just an empty list - DimensionToSnap snap_dim; - if (guide_normal == to_2geom(component_vectors[Geom::Y])) { - snap_dim = GUIDE_TRANSL_SNAP_Y; - } else if (guide_normal == to_2geom(component_vectors[Geom::X])) { - snap_dim = GUIDE_TRANSL_SNAP_X; - } else { - snap_dim = ANGLED_GUIDE_TRANSL_SNAP; - } - - _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), false, Geom::identity()); _snapTranslatingGuide(sc, p, guide_normal); } @@ -709,16 +699,7 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, std::vector cand; std::vector const it; //just an empty list - DimensionToSnap snap_dim; - if (guide_normal == to_2geom(component_vectors[Geom::Y])) { - snap_dim = GUIDE_TRANSL_SNAP_Y; - } else if (guide_normal == to_2geom(component_vectors[Geom::X])) { - snap_dim = GUIDE_TRANSL_SNAP_X; - } else { - snap_dim = ANGLED_GUIDE_TRANSL_SNAP; - } - - _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), false, Geom::identity()); _snapTranslatingGuide(sc, p, guide_normal); } @@ -729,20 +710,20 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, bool Inkscape::ObjectSnapper::ThisSnapperMightSnap() const { bool snap_to_something = (_snapmanager->snapprefs.getSnapModeNode() && ( - _snapmanager->snapprefs.getSnapToItemPath() || - _snapmanager->snapprefs.getSnapToItemNode() || - _snapmanager->snapprefs.getSnapSmoothNodes() || - _snapmanager->snapprefs.getSnapLineMidpoints() || - _snapmanager->snapprefs.getSnapObjectMidpoints() - )) || (_snapmanager->snapprefs.getSnapModeBBox() && ( - _snapmanager->snapprefs.getSnapToBBoxPath() || - _snapmanager->snapprefs.getSnapToBBoxNode() || - _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || - _snapmanager->snapprefs.getSnapBBoxMidpoints() - )) || (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( - _snapmanager->snapprefs.getSnapToPageBorder() || - _snapmanager->snapprefs.getIncludeItemCenter() - )); + _snapmanager->snapprefs.getSnapToItemPath() || + _snapmanager->snapprefs.getSnapToItemNode() || + _snapmanager->snapprefs.getSnapSmoothNodes() || + _snapmanager->snapprefs.getSnapLineMidpoints() || + _snapmanager->snapprefs.getSnapObjectMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBox() && ( + _snapmanager->snapprefs.getSnapToBBoxPath() || + _snapmanager->snapprefs.getSnapToBBoxNode() || + _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || + _snapmanager->snapprefs.getSnapBBoxMidpoints() + )) || (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && ( + _snapmanager->snapprefs.getSnapToPageBorder() || + _snapmanager->snapprefs.getIncludeItemCenter() + )); return (_snap_enabled && snap_to_something); } diff --git a/src/object-snapper.h b/src/object-snapper.h index f3b54ed08..99c8a077e 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -33,12 +33,6 @@ public: ObjectSnapper(SnapManager *sm, Geom::Coord const d); ~ObjectSnapper(); - enum DimensionToSnap { - GUIDE_TRANSL_SNAP_X, // For snapping a vertical guide (normal in the X-direction) to objects, - GUIDE_TRANSL_SNAP_Y, // For snapping a horizontal guide (normal in the Y-direction) to objects - ANGLED_GUIDE_TRANSL_SNAP, // For snapping an angled guide, while translating it accross the desktop - TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides - void guideFreeSnap(SnappedConstraints &sc, Geom::Point const &p, Geom::Point const &guide_normal) const; @@ -75,7 +69,6 @@ private: std::vector const *it, bool const &first_point, Geom::Rect const &bbox_to_snap, - DimensionToSnap snap_dim, bool const _clip_or_mask, Geom::Matrix const additional_affine) const; diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 325009fe5..d213ce2d7 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -973,8 +973,15 @@ static void sp_item_private_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { - g_assert (item != NULL); - g_assert (SP_IS_ITEM(item)); + if (item == NULL) { + g_warning("sp_item_snappoints: cannot snap because no item is being provided"); + return; + } + + if (!SP_IS_ITEM(item)) { + g_warning("sp_item_snappoints: cannot snap because this is not a SP_ITEM"); + return; + } // Get the snappoints of the item SPItemClass const &item_class = *(SPItemClass const *) G_OBJECT_GET_CLASS(item); -- cgit v1.2.3 From 8855ed84189c7724817ccb09cdb5da239ba3fd48 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 22 Jul 2010 02:09:48 +0200 Subject: Fix sculpting of nodes with non-degenerate handles. (bzr r9639) --- src/ui/tool/control-point-selection.cpp | 48 +++++++++++++++++++++++++++++++-- src/ui/tool/control-point-selection.h | 7 ++--- 2 files changed, 50 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index f880d2ddf..615587eeb 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -273,8 +273,11 @@ void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point) _grabbed_point = point; _farthest_point = point; double maxdist = 0; + Geom::Matrix m; + m.setIdentity(); for (iterator i = _points.begin(); i != _points.end(); ++i) { _original_positions.insert(std::make_pair(*i, (*i)->position())); + _last_trans.insert(std::make_pair(*i, m)); double dist = Geom::distance(*_grabbed_point, **i); if (dist > maxdist) { maxdist = dist; @@ -288,12 +291,52 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion * Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point]; double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]); if (held_alt(*event) && fdist > 0) { - // sculpting + // Sculpting for (iterator i = _points.begin(); i != _points.end(); ++i) { SelectableControlPoint *cur = (*i); + Geom::Matrix trans; + trans.setIdentity(); double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]); double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist); - cur->move(_original_positions[cur] + abs_delta * deltafrac); + if (dist != 0.0) { + // The sculpting transformation is not affine, but it can be + // locally approximated by one. Here we compute the local + // affine approximation of the sculpting transformation near + // the currently transformed point. We then transform the point + // by this approximation. This gives us sensible behavior for node handles. + // NOTE: probably it would be better to transform the node handles, + // but ControlPointSelection is supposed to work for any + // SelectableControlPoints, not only Nodes. We could create a specialized + // NodeSelection class that inherits from this one and move sculpting there. + Geom::Point origdx(Geom::EPSILON, 0); + Geom::Point origdy(0, Geom::EPSILON); + Geom::Point origp = _original_positions[cur]; + Geom::Point origpx = _original_positions[cur] + origdx; + Geom::Point origpy = _original_positions[cur] + origdy; + double distdx = Geom::distance(origpx, _original_positions[_grabbed_point]); + double distdy = Geom::distance(origpy, _original_positions[_grabbed_point]); + double deltafracdx = 0.5 + 0.5 * cos(M_PI * distdx/fdist); + double deltafracdy = 0.5 + 0.5 * cos(M_PI * distdy/fdist); + Geom::Point newp = origp + abs_delta * deltafrac; + Geom::Point newpx = origpx + abs_delta * deltafracdx; + Geom::Point newpy = origpy + abs_delta * deltafracdy; + Geom::Point newdx = (newpx - newp) / Geom::EPSILON; + Geom::Point newdy = (newpy - newp) / Geom::EPSILON; + + Geom::Matrix itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0); + if (itrans.isSingular()) + itrans.setIdentity(); + + trans *= Geom::Translate(-cur->position()); + trans *= _last_trans[cur].inverse(); + trans *= itrans; + trans *= Geom::Translate(_original_positions[cur] + abs_delta * deltafrac); + _last_trans[cur] = itrans; + } else { + trans *= Geom::Translate(-cur->position() + _original_positions[cur] + abs_delta * deltafrac); + } + cur->transform(trans); + //cur->move(_original_positions[cur] + abs_delta * deltafrac); } } else { Geom::Point delta = new_pos - _grabbed_point->position(); @@ -309,6 +352,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion * void ControlPointSelection::_pointUngrabbed() { _original_positions.clear(); + _last_trans.clear(); _dragging = false; _grabbed_point = _farthest_point = NULL; _updateBounds(); diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 514ecb2e3..8023c3e28 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -1,5 +1,5 @@ /** @file - * Node selection - stores a set of nodes and applies transformations + * Control point selection - stores a set of control points and applies transformations * to them */ /* Authors: @@ -9,8 +9,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifndef SEEN_UI_TOOL_NODE_SELECTION_H -#define SEEN_UI_TOOL_NODE_SELECTION_H +#ifndef SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H +#define SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H #include #include @@ -132,6 +132,7 @@ private: set_type _points; set_type _all_points; INK_UNORDERED_MAP _original_positions; + INK_UNORDERED_MAP _last_trans; boost::optional _rot_radius; boost::optional _mouseover_rot_radius; Geom::OptRect _bounds; -- cgit v1.2.3 From a96bb3e891e103864fe501a92bad96a9ad04351e Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 24 Jul 2010 14:37:50 +0200 Subject: Avoid self-snapping when dragging a rotation center, and draw the rotation center at the snapped position (bzr r9641) --- src/object-snapper.cpp | 12 +++++-- src/selection.cpp | 2 ++ src/seltrans.cpp | 19 +++++++++-- src/snap.cpp | 3 ++ src/snap.h | 9 +++++ src/sp-shape.cpp | 90 +++++++++++++++++++++++++------------------------- 6 files changed, 85 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index ef5dcc7d0..c1ed08f12 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -228,11 +228,17 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapSourceType const &t, _snapmanager->snapprefs.setSnapIntersectionCS(false); } + bool old_pref2 = _snapmanager->snapprefs.getIncludeItemCenter(); + if ((*i).item == _snapmanager->getRotationCenterSource()) { + // don't snap to this item's rotation center + _snapmanager->snapprefs.setIncludeItemCenter(false); + } + sp_item_snappoints(root_item, *_points_to_snap_to, &_snapmanager->snapprefs); - if (_snapmanager->snapprefs.getSnapToItemPath()) { - _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); - } + // restore the original snap preferences + _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); + _snapmanager->snapprefs.setIncludeItemCenter(old_pref2); } //Collect the bounding box's corners so we can snap to them diff --git a/src/selection.cpp b/src/selection.cpp index 96c66e0c5..3f333e4e2 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -406,6 +406,8 @@ Geom::OptRect Selection::boundsInDocument(SPItem::BBoxType type) const { } /** Extract the position of the center from the first selected object */ +// If we have a selection of multiple items, then the center of the first item +// will be returned; this is also the case in SelTrans::centerRequest() boost::optional Selection::center() const { GSList *items = (GSList *) const_cast(this)->itemList(); Geom::Point center; diff --git a/src/seltrans.cpp b/src/seltrans.cpp index b9bf4c6ce..764c222a8 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -883,7 +883,11 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position, if (handle.request(this, handle, *position, state)) { sp_knot_set_position(knot, *position, state); SP_CTRL(_grip)->moveto(*position); - SP_CTRL(_norm)->moveto(_origin); + if (&handle == &handle_center) { + SP_CTRL(_norm)->moveto(*position); + } else { + SP_CTRL(_norm)->moveto(_origin); + } } return TRUE; @@ -1329,7 +1333,18 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) { SnapManager &m = _desktop->namedview->snap_manager; m.setup(_desktop); - m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_OTHER_HANDLE); + + // Center is being dragged for the first item in the selection only + // Find out which item is first ... + GSList *items = (GSList *) const_cast(_selection)->itemList(); + SPItem *first = NULL; + if (items) { + first = reinterpret_cast(g_slist_last(items)->data); // from the first item in selection + } + // ... and store that item because later on we need to make sure that + // this transformation center won't snap to itself + m.setRotationCenterSource(first); + m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER); if (state & GDK_CONTROL_MASK) { if ( fabs(_point[Geom::X] - pt[Geom::X]) > fabs(_point[Geom::Y] - pt[Geom::Y]) ) { diff --git a/src/snap.cpp b/src/snap.cpp index ccbd449bd..fc8837c43 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -1079,6 +1079,7 @@ void SnapManager::setup(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; } /** @@ -1109,6 +1110,7 @@ void SnapManager::setup(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; } /// Setup, taking the list of items to ignore from the desktop's selection. @@ -1121,6 +1123,7 @@ void SnapManager::setupIgnoreSelection(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; _items_to_ignore.clear(); Inkscape::Selection *sel = _desktop->selection; diff --git a/src/snap.h b/src/snap.h index 26e599cc6..f740f3c62 100644 --- a/src/snap.h +++ b/src/snap.h @@ -92,11 +92,19 @@ public: std::vector &items_to_ignore, std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); + void setupIgnoreSelection(SPDesktop const *desktop, bool snapindicator = true, std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); + // If we're dragging a rotation center, then setRotationCenterSource() stores the parent item + // of this rotation center; this reference is used to make sure that we do not snap a rotation + // center to itself + // NOTE: Must be called after calling setup(), not before! + void setRotationCenterSource(SPItem *item) {_rotation_center_source_item = item;} + SPItem* getRotationCenterSource() {return _rotation_center_source_item;} + // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a // point if snapping has occurred (by overwriting p); otherwise p is untouched void freeSnapReturnByRef(Geom::Point &p, @@ -183,6 +191,7 @@ protected: private: std::vector _items_to_ignore; ///< Items that should not be snapped to, for example the items that are currently being dragged. Set using the setup() method + SPItem *_rotation_center_source_item; // to avoid snapping a rotation center to itself SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged SPDesktop const *_desktop; bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 0038908bf..b64ad45e0 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -1208,57 +1208,57 @@ static void sp_shape_snappoints(SPItem const *item, std::vectorgetSnapToItemNode()) { - // Add the first point of the path - p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + // Add the first point of the path + p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve while (curve_it1 != path_it->end_default()) { - // For each path: consider midpoints of line segments for snapping - if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) - if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { - p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); - } - } - - if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop - if (snapprefs->getSnapToItemNode() && !path_it->closed()) { - // Add the last point of the path, but only for open paths - // (for closed paths the first and last point will coincide) - p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); - } - } else { - /* Test whether to add the node between curve_it1 and curve_it2. - * Loop to end_default (so only iterating through the stroked part); */ - - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); - - bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); - bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); - - if (c1 || c2) { - Inkscape::SnapSourceType sst; - Inkscape::SnapTargetType stt; - switch (nodetype) { - case Geom::NODE_CUSP: - sst = Inkscape::SNAPSOURCE_NODE_CUSP; - stt = Inkscape::SNAPTARGET_NODE_CUSP; - break; - case Geom::NODE_SMOOTH: - case Geom::NODE_SYMM: - sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; - stt = Inkscape::SNAPTARGET_NODE_SMOOTH; - break; - default: - sst = Inkscape::SNAPSOURCE_UNDEFINED; - stt = Inkscape::SNAPTARGET_UNDEFINED; - break; - } - p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); - } - } + // For each path: consider midpoints of line segments for snapping + if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) + if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { + p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + } + + if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop + if (snapprefs->getSnapToItemNode() && !path_it->closed()) { + // Add the last point of the path, but only for open paths + // (for closed paths the first and last point will coincide) + p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + } + } else { + /* Test whether to add the node between curve_it1 and curve_it2. + * Loop to end_default (so only iterating through the stroked part); */ + + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); + + bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); + bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); + + if (c1 || c2) { + Inkscape::SnapSourceType sst; + Inkscape::SnapTargetType stt; + switch (nodetype) { + case Geom::NODE_CUSP: + sst = Inkscape::SNAPSOURCE_NODE_CUSP; + stt = Inkscape::SNAPTARGET_NODE_CUSP; + break; + case Geom::NODE_SMOOTH: + case Geom::NODE_SYMM: + sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; + stt = Inkscape::SNAPTARGET_NODE_SMOOTH; + break; + default: + sst = Inkscape::SNAPSOURCE_UNDEFINED; + stt = Inkscape::SNAPTARGET_UNDEFINED; + break; + } + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); + } + } ++curve_it1; ++curve_it2; -- cgit v1.2.3 From 470e0b234c1076a3373f8b5759da517ceba586ef Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 24 Jul 2010 18:11:16 -0700 Subject: Adding preference to suppress packing of previews. (bzr r9643) --- src/preferences-skeleton.h | 4 +++- src/ui/dialog/icon-preview.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index c73cae17f..283960b80 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -391,7 +391,9 @@ static char const preferences_skeleton[] = " \n" "\n" " \n" +" id=\"iconpreview\"\n" +" pack=\"1\"\n" +" selectionOnly=\"0\">\n" " \n" " getBool("/iconpreview/pack", true); + std::vector pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default"); std::vector rawSizes; @@ -182,7 +184,7 @@ IconPreviewPanel::IconPreviewPanel() : align->add(*buttons[i]); int pad = 12; - if ((avail == 0) && (previous == 0)) { + if ( !pack || ( (avail == 0) && (previous == 0) ) ) { verts->pack_end(*align, Gtk::PACK_SHRINK); previous = sizes[i]; avail = sizes[i]; -- cgit v1.2.3 From 891cc7951b541d02863ca3c6a858334abeb6132e Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 24 Jul 2010 21:54:39 -0700 Subject: Added preference to keep last selected item shown. (bzr r9644) --- src/preferences-skeleton.h | 1 + src/ui/dialog/icon-preview.cpp | 46 +++++++++++++++++++++++++----------------- src/ui/dialog/icon-preview.h | 1 + 3 files changed, 30 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 283960b80..e117e85a5 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -393,6 +393,7 @@ static char const preferences_skeleton[] = " \n" " \n" diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 7be667383..d3a28d96f 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -86,6 +86,7 @@ IconPreviewPanel::IconPreviewPanel() : document(0), timer(0), pending(false), + targetId(), hot(1), selectionButton(0), desktopChangeConn(), @@ -302,28 +303,33 @@ void IconPreviewPanel::refreshPreview() // Do not refresh too quickly queueRefresh(); } else if ( desktop ) { + bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", false); if ( selectionButton && selectionButton->get_active() ) { - Inkscape::Selection * sel = sp_desktop_selection(desktop); - if ( sel ) { - //g_message("found a selection to play with"); - - GSList const *items = sel->itemList(); - SPObject *target = 0; - while ( items && !target ) { - SPItem* item = SP_ITEM( items->data ); - SPObject * obj = SP_OBJECT(item); - gchar const *id = obj->getId(); - if ( id ) { - target = obj; + SPObject *target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0; + if ( !target ) { + targetId.clear(); + Inkscape::Selection * sel = sp_desktop_selection(desktop); + if ( sel ) { + //g_message("found a selection to play with"); + + GSList const *items = sel->itemList(); + while ( items && !target ) { + SPItem* item = SP_ITEM( items->data ); + SPObject * obj = SP_OBJECT(item); + gchar const *id = obj->getId(); + if ( id ) { + targetId = id; + target = obj; + } + + items = g_slist_next(items); } - - items = g_slist_next(items); - } - if ( target ) { - renderPreview(target); } } + if ( target ) { + renderPreview(target); + } } else { SPObject *target = desktop->currentRoot(); if ( target ) { @@ -362,7 +368,11 @@ void IconPreviewPanel::queueRefresh() void IconPreviewPanel::modeToggled() { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active())); + bool selectionOnly = (selectionButton && selectionButton->get_active()); + prefs->setBool("/iconpreview/selectionOnly", selectionOnly); + if ( !selectionOnly ) { + targetId.clear(); + } refreshPreview(); } diff --git a/src/ui/dialog/icon-preview.h b/src/ui/dialog/icon-preview.h index 9de882569..0842c3c5e 100644 --- a/src/ui/dialog/icon-preview.h +++ b/src/ui/dialog/icon-preview.h @@ -68,6 +68,7 @@ private: Gtk::VBox iconBox; Gtk::HPaned splitter; + Glib::ustring targetId; int hot; int numEntries; int* sizes; -- cgit v1.2.3 From 7afe2c3b4f0162d27eda1ef244922cec513b0dff Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 24 Jul 2010 21:58:14 -0700 Subject: Added preference to suppress icon preview frames. (bzr r9645) --- src/preferences-skeleton.h | 1 + src/ui/dialog/icon-preview.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index e117e85a5..d7b93f13f 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -394,6 +394,7 @@ static char const preferences_skeleton[] = " id=\"iconpreview\"\n" " pack=\"1\"\n" " selectionHold=\"0\"\n" +" showFrames=\"1\"\n" " selectionOnly=\"0\">\n" " \n" diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index d3a28d96f..2fb684a38 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -171,10 +171,14 @@ IconPreviewPanel::IconPreviewPanel() : Glib::ustring label(*labels[i]); buttons[i] = new Gtk::ToggleToolButton(label); buttons[i]->set_active( i == hot ); - Gtk::Frame *frame = new Gtk::Frame(); - frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN); - frame->add(*images[i]); - buttons[i]->set_icon_widget(*Gtk::manage(frame)); + if ( prefs->getBool("/iconpreview/showFrames", true) ) { + Gtk::Frame *frame = new Gtk::Frame(); + frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN); + frame->add(*images[i]); + buttons[i]->set_icon_widget(*Gtk::manage(frame)); + } else { + buttons[i]->set_icon_widget(*images[i]); + } tips.set_tip((*buttons[i]), label); -- cgit v1.2.3 From 9cc1a98a31b9b4a28257c9dedb05c9ad64a8bc43 Mon Sep 17 00:00:00 2001 From: Leo Albert Jackson Date: Sun, 25 Jul 2010 01:40:03 -0400 Subject: Pixmap fix apply (bzr r9646) --- src/pixmaps/cursor-node-d.xpm | 32 ++++++++++++++++---------------- src/pixmaps/cursor-node-m.xpm | 34 +++++++++++++++++----------------- src/pixmaps/cursor-select-d.xpm | 36 ++++++++++++++++++------------------ src/pixmaps/cursor-select-m.xpm | 40 ++++++++++++++++++++-------------------- 4 files changed, 71 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/pixmaps/cursor-node-d.xpm b/src/pixmaps/cursor-node-d.xpm index cdc792a3a..264da58c3 100644 --- a/src/pixmaps/cursor-node-d.xpm +++ b/src/pixmaps/cursor-node-d.xpm @@ -2,7 +2,7 @@ static char const *cursor_node_d_xpm[] = { "32 32 3 1", " g None", -". g #FFFFFF", +". g #ffffff", "+ g #000000", " . ", ".+. ", @@ -18,21 +18,21 @@ static char const *cursor_node_d_xpm[] = { " .++++++. ", " .+++++. ", " .+++.. ", -" .+. ++ ++ ", -" . +..+..+ ", -" ++..+..++ ", -" +.+..+..+.+ ", -" +.+..+..+.+ ", -" +.+..+..+.+ ", -" +.........+ ", -" +.........+ ", -" +........+ ", -" +........+ ", -" +......+ ", -" +......+ ", -" +.....+ ", -" +.....+ ", -" +++++++ ", +" .+. ++ ", +" . +++..+++ ", +" +..+..+..+ ", +" ++..+..+..++ ", +" +.+..+..+..+.+ ", +" +.+..+..+..+.+ ", +" +............+ ", +" +............+ ", +" +...........+ ", +" +..........+ ", +" +.........+ ", +" +........+ ", +" +.......+ ", +" +.......+ ", +" +++++++++ ", " ", " ", " "}; diff --git a/src/pixmaps/cursor-node-m.xpm b/src/pixmaps/cursor-node-m.xpm index 272eeb884..08574bfb0 100644 --- a/src/pixmaps/cursor-node-m.xpm +++ b/src/pixmaps/cursor-node-m.xpm @@ -15,24 +15,24 @@ static char const *cursor_node_m_xpm[] = { " .++++. ", " .+++++. ", " .+++++. ", -" .++++++. ++++ ", +" .++++++. +++ ", " .+++++. +.+..+ ", -" .+++.. +..+..++ ", -" .+. +..+..+.+ ", -" . + +..+..+..+ ", -" +.++..+..+..+ ", -" +..+..+..+..+ ", -" +..+..+..+..+ ", -" +..+..+..+..+ ", -" +...........+ ", -" +..........+ ", -" +.........+ ", -" +........+ ", -" +.......+ ", -" +......+ ", -" +.....+ ", -" +.....+ ", -" +++++++ ", +" .+++.. +..+..++++ ", +" .+. +..+..+..+ ", +" . +..+..+..++ ", +" +++..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +.............+ ", +" +............+ ", +" +...........+ ", +" +..........+ ", +" +.........+ ", +" +........+ ", +" +.......+ ", +" +.......+ ", +" +++++++++ ", " ", " ", " "}; diff --git a/src/pixmaps/cursor-select-d.xpm b/src/pixmaps/cursor-select-d.xpm index 53b8c0cdf..13acc0aad 100644 --- a/src/pixmaps/cursor-select-d.xpm +++ b/src/pixmaps/cursor-select-d.xpm @@ -2,7 +2,7 @@ static char const *cursor_select_d_xpm[] = { "32 32 3 1", " g None", -". g #FFFFFF", +". g #ffffff", "+ g #000000", "+ ", "++ ", @@ -17,22 +17,22 @@ static char const *cursor_select_d_xpm[] = { "+.........+ ", "+..........+ ", "+......++++ ", -"+...+..+ ", +"+...+++. ", "+..+ +..+ ", -"+.+ +..+ ", -"++ +..+ ++ ++ ", -" +..+ +..+..+ ", -" +..+ ++..+..++ ", -" +..+ +.+..+..+.+ ", -" ++ +..+..+..+..+ ", -" +..+..+..+..+ ", -" +...........+ ", -" +...........+ ", -" +.........+ ", -" +........+ ", -" +......+ ", -" +......+ ", -" +.....+ ", -" +.....+ ", -" +++++++ ", +"+.+ +..+ ++ ", +".. +..+ +++..+ ", +" +..+ +..+..+++ ", +" +..+ +++..+..+..+ ", +" +..+ +..+..+..+..++ ", +" +++ +..+..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +.............+ ", +" +.............+ ", +" +............+ ", +" +..........+ ", +" +.........+ ", +" +.........+ ", +" +.........+ ", +" +.........+ ", +" +++++++++++ ", " "}; diff --git a/src/pixmaps/cursor-select-m.xpm b/src/pixmaps/cursor-select-m.xpm index beea4739a..48be49f77 100644 --- a/src/pixmaps/cursor-select-m.xpm +++ b/src/pixmaps/cursor-select-m.xpm @@ -2,7 +2,7 @@ static char const *cursor_select_m_xpm[] = { "32 32 3 1", " g None", -". g #FFFFFF", +". g #ffffff", "+ g #000000", "+ ", "++ ", @@ -17,22 +17,22 @@ static char const *cursor_select_m_xpm[] = { "+.........+ ", "+..........+ ", "+......++++ ", -"+...+..+ ++ ++ ", -"+..+ +..+ +..+..+ ", -"+.+ +..+ +..+..+ ", -"++ +..+ +..+..++ ", -" +..+ +..+..+.+ ", -" +..+ ++ +..+..+..+ ", -" +..+ +.++..+..+..+ ", -" ++ +..+..+..+..+ ", -" +..+..+..+..+ ", -" +..+..+..+..+ ", -" +...........+ ", -" +..........+ ", -" +.........+ ", -" +........+ ", -" +.......+ ", -" +......+ ", -" +.....+ ", -" +.....+ ", -" +++++++ "}; +"+...+..+ ++++ ", +"+..++..+ ++++..+ ", +"+.+ +..+ +..+..+++ ", +"++ +..+ +..+..+..+ ", +" +..+ +..+..+..++ ", +" +..+ +++..+..+..+.+ ", +" +..+ +..+..+..+..+.+ ", +" +++ +..+..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +..+..+..+..+.+ ", +" +.............+ ", +" +.............+ ", +" +...........+ ", +" +..........+ ", +" +........+ ", +" +........+ ", +" +........+ ", +" +........+ ", +" ++++++++++ "}; -- cgit v1.2.3 From f473fad8dfd7875de0f416817a6f77b89a8433d9 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 25 Jul 2010 00:37:14 -0700 Subject: Make icon preview seleciton stikcy by default. (bzr r9647) --- src/preferences-skeleton.h | 2 +- src/ui/dialog/icon-preview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index d7b93f13f..cabb13d47 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -393,7 +393,7 @@ static char const preferences_skeleton[] = " \n" " getBool("/iconpreview/selectionHold", false); + bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", true); if ( selectionButton && selectionButton->get_active() ) { SPObject *target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0; -- cgit v1.2.3 From b3725365a24e922e5bda09d7489c2ed17d94108f Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 25 Jul 2010 22:29:45 +0200 Subject: 1) Snap to transformation center even if it's outside of the bounding box of the parent item 2) In some cases the snap source indicator wasn't shown (bzr r9648) --- src/display/snap-indicator.cpp | 16 ++++++++-------- src/object-snapper.cpp | 11 ++++++----- src/snap-enums.h | 2 +- src/snap.cpp | 5 ++++- 4 files changed, 19 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 776c56c15..c3198cd37 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -229,14 +229,14 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap // Display the snap indicator (i.e. the cross) SPCanvasItem * canvasitem = NULL; canvasitem = sp_canvas_item_new(sp_desktop_tempgroup (_desktop), - SP_TYPE_CTRL, - "anchor", GTK_ANCHOR_CENTER, - "size", 10.0, - "stroked", TRUE, - "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); + SP_TYPE_CTRL, + "anchor", GTK_ANCHOR_CENTER, + "size", 10.0, + "stroked", TRUE, + "stroke_color", pre_snap ? 0x7f7f7fff : 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); const int timeout_val = 1200; // TODO add preference for snap indicator timeout? diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index c1ed08f12..d84ee9c4f 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -6,7 +6,7 @@ * Carl Hetherington * Diederik van Lierop * - * Copyright (C) 2005 - 2008 Authors + * Copyright (C) 2005 - 2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -148,7 +148,8 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, } if (bbox_of_item) { // See if the item is within range - if (bbox_to_snap_incl.intersects(*bbox_of_item)) { + if (bbox_to_snap_incl.intersects(*bbox_of_item) + || (_snapmanager->snapprefs.getIncludeItemCenter() && bbox_to_snap_incl.contains(item->getCenter()))) { // rotation center might be outside of the bounding box // This item is within snapping range, so record it as a candidate _candidates->push_back(SnapCandidateItem(item, clip_or_mask, additional_affine)); // For debugging: print the id of the candidate to the console @@ -626,9 +627,9 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, _snapNodes(sc, p, unselected_nodes); } - if (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getSnapToItemPath() || - _snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxPath() || - _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->snapprefs.getSnapToPageBorder()) { + if ((_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getSnapToItemPath()) || + (_snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxPath()) || + (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->snapprefs.getSnapToPageBorder())) { unsigned n = (unselected_nodes == NULL) ? 0 : unselected_nodes->size(); if (n > 0) { /* While editing a path in the node tool, findCandidates must ignore that path because diff --git a/src/snap-enums.h b/src/snap-enums.h index 64be34637..aa5db9328 100644 --- a/src/snap-enums.h +++ b/src/snap-enums.h @@ -66,7 +66,7 @@ enum SnapSourceType { SNAPSOURCE_CONVEX_HULL_CORNER, SNAPSOURCE_ELLIPSE_QUADRANT_POINT, SNAPSOURCE_NODE_HANDLE, // eg. nodes in the path editor, handles of stars or rectangles, etc. (tied to a stroke) - SNAPSOURCE_OBJECT_MIDPOINT, + SNAPSOURCE_OBJECT_MIDPOINT, // midpoint of rectangles, polygon, etc. //------------------------------------------------------------------- // Other points (e.g. guides, gradient knots) will snap to both bounding boxes and nodes SNAPSOURCE_OTHER_CATEGORY = 1024, // will be used as a flag and must therefore be a power of two diff --git a/src/snap.cpp b/src/snap.cpp index fc8837c43..bac37737f 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -763,6 +763,8 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vectorgetBool("/options/snapclosestonly/value")) { bool p_is_a_node = p.getSourceType() & Inkscape::SNAPSOURCE_NODE_CATEGORY; bool p_is_a_bbox = p.getSourceType() & Inkscape::SNAPSOURCE_BBOX_CATEGORY; + bool p_is_other = p.getSourceType() & Inkscape::SNAPSOURCE_OTHER_CATEGORY; - if (snapprefs.getSnapEnabledGlobally() && ((p_is_a_node && snapprefs.getSnapModeNode()) || (p_is_a_bbox && snapprefs.getSnapModeBBox()))) { + if (snapprefs.getSnapEnabledGlobally() && (p_is_other || (p_is_a_node && snapprefs.getSnapModeNode()) || (p_is_a_bbox && snapprefs.getSnapModeBBox()))) { _desktop->snapindicator->set_new_snapsource(p); } else { _desktop->snapindicator->remove_snapsource(); -- cgit v1.2.3 From fec969196e3840b9bc0de1c7374209609ccb2678 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 25 Jul 2010 16:55:49 -0700 Subject: Added debug info. Throttle down icon preview rendering based on observed duration. (bzr r9650) --- src/ui/dialog/icon-preview.cpp | 74 +++++++++++++++++++++++++++++++++++------- src/ui/dialog/icon-preview.h | 2 ++ 2 files changed, 65 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 0eddfa285..c8f5d2c2e 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -41,6 +41,8 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, const gchar *name, unsigned int psize ); } +#define noICON_VERBOSE 1 + namespace Inkscape { namespace UI { namespace Dialog { @@ -85,7 +87,9 @@ IconPreviewPanel::IconPreviewPanel() : desktop(0), document(0), timer(0), + renderTimer(0), pending(false), + minDelay(0.1), targetId(), hot(1), selectionButton(0), @@ -249,6 +253,11 @@ IconPreviewPanel::~IconPreviewPanel() delete timer; timer = 0; } + if ( renderTimer ) { + renderTimer->stop(); + delete renderTimer; + renderTimer = 0; + } selChangedConn.disconnect(); docModConn.disconnect(); @@ -262,6 +271,22 @@ IconPreviewPanel::~IconPreviewPanel() //######################################################################### +#if ICON_VERBOSE +static Glib::ustring getTimestr() +{ + Glib::ustring str; + GTimeVal now = {0, 0}; + g_get_current_time(&now); + glong secs = now.tv_sec % 60; + glong mins = (now.tv_sec / 60) % 60; + gchar *ptr = g_strdup_printf(":%02ld:%02ld.%06ld", mins, secs, now.tv_usec); + str = ptr; + g_free(ptr); + ptr = 0; + return str; +} +#endif // ICON_VERBOSE + void IconPreviewPanel::setDesktop( SPDesktop* desktop ) { Panel::setDesktop(desktop); @@ -303,14 +328,21 @@ void IconPreviewPanel::refreshPreview() if (!timer) { timer = new Glib::Timer(); } - if (timer->elapsed() < 0.1) { + if (timer->elapsed() < minDelay) { +#if ICON_VERBOSE + g_message( "%s Deferring refresh as too soon. calling queueRefresh()", getTimestr().c_str() ); +#endif //ICON_VERBOSE // Do not refresh too quickly queueRefresh(); } else if ( desktop ) { +#if ICON_VERBOSE + g_message( "%s Refreshing preview.", getTimestr().c_str() ); +#endif // ICON_VERBOSE bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", true); + SPObject *target = 0; if ( selectionButton && selectionButton->get_active() ) { - SPObject *target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0; + target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0; if ( !target ) { targetId.clear(); Inkscape::Selection * sel = sp_desktop_selection(desktop); @@ -331,15 +363,15 @@ void IconPreviewPanel::refreshPreview() } } } - if ( target ) { - renderPreview(target); - } } else { - SPObject *target = desktop->currentRoot(); - if ( target ) { - renderPreview(target); - } + target = desktop->currentRoot(); } + if ( target ) { + renderPreview(target); + } +#if ICON_VERBOSE + g_message( "%s resetting timer", getTimestr().c_str() ); +#endif // ICON_VERBOSE timer->reset(); } } @@ -350,9 +382,15 @@ bool IconPreviewPanel::refreshCB() if (!timer) { timer = new Glib::Timer(); } - if ( timer->elapsed() > 0.1 ) { + if ( timer->elapsed() > minDelay ) { +#if ICON_VERBOSE + g_message( "%s refreshCB() timer has progressed", getTimestr().c_str() ); +#endif // ICON_VERBOSE callAgain = false; refreshPreview(); +#if ICON_VERBOSE + g_message( "%s refreshCB() setting pending false", getTimestr().c_str() ); +#endif // ICON_VERBOSE pending = false; } return callAgain; @@ -362,6 +400,9 @@ void IconPreviewPanel::queueRefresh() { if (!pending) { pending = true; +#if ICON_VERBOSE + g_message( "%s queueRefresh() Setting pending true", getTimestr().c_str() ); +#endif // ICON_VERBOSE if (!timer) { timer = new Glib::Timer(); } @@ -385,8 +426,14 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) { SPDocument * doc = SP_OBJECT_DOCUMENT(obj); gchar const * id = obj->getId(); + if ( !renderTimer ) { + renderTimer = new Glib::Timer(); + } + renderTimer->reset(); -// g_message(" setting up to render '%s' as the icon", id ); +#if ICON_VERBOSE + g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id ); +#endif // ICON_VERBOSE NRArenaItem *root = NULL; @@ -415,6 +462,11 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey); nr_object_unref((NRObject *) arena); + renderTimer->stop(); + minDelay = std::max( 0.1, renderTimer->elapsed() * 3.0 ); +#if ICON_VERBOSE + g_message(" render took %f seconds.", renderTimer->elapsed()); +#endif // ICON_VERBOSE } void IconPreviewPanel::updateMagnify() diff --git a/src/ui/dialog/icon-preview.h b/src/ui/dialog/icon-preview.h index 0842c3c5e..f8957086a 100644 --- a/src/ui/dialog/icon-preview.h +++ b/src/ui/dialog/icon-preview.h @@ -61,7 +61,9 @@ private: SPDesktop *desktop; SPDocument *document; Glib::Timer *timer; + Glib::Timer *renderTimer; bool pending; + gdouble minDelay; Gtk::Tooltips tips; -- cgit v1.2.3 From c5a6fcc6b89ec6afe90d1dd2289182580145f9cf Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 25 Jul 2010 17:34:37 -0700 Subject: Added preference to suppress auto-refresh of icon previews. (bzr r9651) --- src/preferences-skeleton.h | 1 + src/ui/dialog/icon-preview.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index cabb13d47..32f4b7c35 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -392,6 +392,7 @@ static char const preferences_skeleton[] = "\n" " desktop = Panel::getDesktop(); if ( this->desktop ) { docReplacedConn = this->desktop->connectDocumentReplaced(sigc::hide<0>(sigc::mem_fun(this, &IconPreviewPanel::setDocument))); - if (this->desktop->selection) { + if ( this->desktop->selection && Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) { selChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh))); } } @@ -316,7 +316,9 @@ void IconPreviewPanel::setDocument( SPDocument *document ) this->document = document; if (this->document) { - docModConn = this->document->connectModified(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh))); + if ( Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) { + docModConn = this->document->connectModified(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh))); + } queueRefresh(); } } -- cgit v1.2.3 From 073f9069a756df6736c077257a6678a56c38176d Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 26 Jul 2010 22:45:01 +0200 Subject: While rotating, don't try snapping points coincident with the rotation center (bzr r9652) --- src/snap.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/snap.cpp b/src/snap.cpp index bac37737f..810e2dd8b 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -585,8 +585,18 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // calculate that line here dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b); } else if (transformation_type == ROTATE) { - // Geom::L2(b) is the radius of the circular constraint - dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b, Geom::L2(b)); + Geom::Coord r = Geom::L2(b); // the radius of the circular constraint + if (r < 1e-9) { // points too close to the rotation center will not move. Don't try to snap these + // as they will always yield a perfect snap result if they're already snapped beforehand (e.g. + // when the transformation center has been snapped to a grid intersection in the selector tool) + continue; // skip this SnapCandidate and continue with the next one + // PS1: Apparently we don't have to do this for skewing, but why? + // PS2: We cannot easily filter these points upstream, e.g. in the grab() method (seltrans.cpp) + // because the rotation center will change when pressing shift, and grab() won't be recalled. + // Filtering could be done in handleRequest() (again in seltrans.cpp), by iterating through + // the snap candidates. But hey, we're iterating here anyway. + } + dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b, r); } else if (transformation_type == STRETCH) { // when non-uniform stretching { dedicated_constraint = Inkscape::Snapper::SnapConstraint((*i).getPoint(), component_vectors[dim]); } else if (transformation_type == TRANSLATE) { @@ -702,9 +712,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSecondSnapDistance(NR_HUGE); break; case ROTATE: - // a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b - result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a)); - result[1] = result[1]; // how else should we store an angle in a point ;-) + // a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b + result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a)); + result[1] = result[1]; // how else should we store an angle in a point ;-) // Store the metric for this transformation as a virtual distance (we're storing an angle) snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); snapped_point.setSecondSnapDistance(NR_HUGE); -- cgit v1.2.3 From 8a48268e3fd41be6b708d0a6b5a0c9cdf7ecc226 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 00:17:25 +0200 Subject: fix crash bug 607557 Fixed bugs: - https://launchpad.net/bugs/607557 (bzr r9653) --- src/ui/dialog/livepatheffect-editor.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 62ed4e639..fb24d8e72 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -299,6 +299,10 @@ LivePathEffectEditor::effect_list_reload(SPLPEItem *lpeitem) PathEffectList::iterator it; for( it = effectlist.begin() ; it!=effectlist.end(); it++ ) { + if ( !(*it)->lpeobject ) { + continue; + } + if ((*it)->lpeobject->get_lpe()) { Gtk::TreeModel::Row row = *(effectlist_store->append()); row[columns.col_name] = (*it)->lpeobject->get_lpe()->getName(); -- cgit v1.2.3 From d8ebf97dc2d2916a3fa76c194e6399198c5253dc Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 00:26:16 +0200 Subject: add powerstroke initial shot (bzr r9654) --- src/live_effects/CMakeLists.txt | 1 + src/live_effects/Makefile_insert | 2 + src/live_effects/effect-enum.h | 1 + src/live_effects/effect.cpp | 6 ++ src/live_effects/lpe-powerstroke.cpp | 156 +++++++++++++++++++++++++++++++++++ src/live_effects/lpe-powerstroke.h | 67 +++++++++++++++ 6 files changed, 233 insertions(+) create mode 100644 src/live_effects/lpe-powerstroke.cpp create mode 100644 src/live_effects/lpe-powerstroke.h (limited to 'src') diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index adf172247..70e8cbaf8 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -21,6 +21,7 @@ lpeobject-reference.cpp lpe-patternalongpath.cpp lpe-perp_bisector.cpp lpe-perspective_path.cpp +lpe-powerstroke.cpp lpe-skeleton.cpp lpe-sketch.cpp lpe-spiro.cpp diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index 1cc2e1b69..aacabc2db 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -67,6 +67,8 @@ ink_common_sources += \ live_effects/lpe-parallel.h \ live_effects/lpe-copy_rotate.cpp \ live_effects/lpe-copy_rotate.h \ + live_effects/lpe-powerstroke.cpp \ + live_effects/lpe-powerstroke.h \ live_effects/lpe-offset.cpp \ live_effects/lpe-offset.h \ live_effects/lpe-ruler.cpp \ diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 6f1004ae5..535cc2564 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -48,6 +48,7 @@ enum EffectType { DYNASTROKE, RECURSIVE_SKELETON, EXTRUDE, + POWERSTROKE, INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 6266fade0..9dbd27b50 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -75,6 +75,7 @@ #include "live_effects/lpe-line_segment.h" #include "live_effects/lpe-recursiveskeleton.h" #include "live_effects/lpe-extrude.h" +#include "live_effects/lpe-powerstroke.h" namespace Inkscape { @@ -100,6 +101,7 @@ const Util::EnumData LPETypeData[] = { {PATH_LENGTH, N_("Path length"), "path_length"}, {PERP_BISECTOR, N_("Perpendicular bisector"), "perp_bisector"}, {PERSPECTIVE_PATH, N_("Perspective path"), "perspective_path"}, + {POWERSTROKE, N_("Power stroke"), "powerstroke"}, {COPY_ROTATE, N_("Rotate copies"), "copy_rotate"}, {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, @@ -120,6 +122,7 @@ const Util::EnumData LPETypeData[] = { {ROUGH_HATCHES, N_("Hatches (rough)"), "rough_hatches"}, {SKETCH, N_("Sketch"), "sketch"}, {RULER, N_("Ruler"), "ruler"}, +/* 0.49 */ }; const Util::EnumDataConverter LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); @@ -237,6 +240,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case EXTRUDE: neweffect = static_cast ( new LPEExtrude(lpeobj) ); break; + case POWERSTROKE: + neweffect = static_cast ( new LPEPowerStroke(lpeobj) ); + break; default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); neweffect = NULL; diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp new file mode 100644 index 000000000..c3de621ee --- /dev/null +++ b/src/live_effects/lpe-powerstroke.cpp @@ -0,0 +1,156 @@ +#define INKSCAPE_LPE_POWERSTROKE_CPP +/** \file + * @brief PowerStroke LPE implementation. Creates curves with modifiable stroke width. + */ +/* Authors: + * Johan Engelen + * + * Copyright (C) 2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/lpe-powerstroke.h" + +#include "sp-shape.h" +#include "display/curve.h" + +#include <2geom/path.h> +#include <2geom/piecewise.h> +#include <2geom/sbasis-geometric.h> +#include <2geom/svg-elliptical-arc.h> +#include <2geom/transforms.h> + +namespace Inkscape { +namespace LivePathEffect { + +LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + offset_1(_("Start Offset"), _("Handle to control the distance of the offset from the curve"), "offset_1", &wr, this), + offset_2(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_2", &wr, this), + offset_3(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_3", &wr, this) +// offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this) +{ + show_orig_path = true; + + registerParameter( dynamic_cast(&offset_1) ); + registerParameter( dynamic_cast(&offset_2) ); + registerParameter( dynamic_cast(&offset_3) ); +// registerParameter( dynamic_cast(&offset_points) ); + + /* register all your knotholder handles here: */ + //registerKnotHolderHandle(new PowerStroke::KnotHolderEntityAttachMyHandle(), _("help message")); +} + +LPEPowerStroke::~LPEPowerStroke() +{ + +} + + +void +LPEPowerStroke::doOnApply(SPLPEItem *lpeitem) +{ + offset_1.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->first_point())); + offset_2.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point())); + offset_3.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point())); +} + +static void append_half_circle(Geom::Piecewise > &pwd2, + Geom::Point const center, Geom::Point const &dir) { + using namespace Geom; + + double r = L2(dir); + SVGEllipticalArc cap(center + dir, r, r, angle_between(Point(1,0), dir), false, false, center - dir); + Piecewise > cap_pwd2(cap.toSBasis()); + pwd2.continuousConcat(cap_pwd2); +} + +Geom::Piecewise > +LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & pwd2_in) +{ + using namespace Geom; + + double t1 = nearest_point(offset_1, pwd2_in); + double offset1 = L2(pwd2_in.valueAt(t1) - offset_1); + + double t2 = nearest_point(offset_2, pwd2_in); + double offset2 = L2(pwd2_in.valueAt(t2) - offset_2); + + double t3 = nearest_point(offset_3, pwd2_in); + double offset3 = L2(pwd2_in.valueAt(t3) - offset_3); + + /* + unsigned number_of_points = offset_points.data.size(); + double* t = new double[number_of_points]; + Point* offset = new double[number_of_points]; + for (unsigned i = 0; i < number_of_points; ++i) { + t[i] = nearest_point(offset_points.data[i], pwd2_in); + Point A = pwd2_in.valueAt(t[i]); + offset[i] = L2(A - offset_points.data[i]); + } + */ + + // create stroke path where points (x,y) = (t, offset) + Path strokepath; + strokepath.start( Point(pwd2_in.domain().min(),0) ); + strokepath.appendNew( Point(t1, offset1) ); + strokepath.appendNew( Point(t2, offset2) ); + strokepath.appendNew( Point(t3, offset3) ); + strokepath.appendNew( Point(pwd2_in.domain().max(), 0) ); + strokepath.appendNew( Point(t3, -offset3) ); + strokepath.appendNew( Point(t2, -offset2) ); + strokepath.appendNew( Point(t1, -offset1) ); + strokepath.close(); + + D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); + Piecewise x = Piecewise(patternd2[0]); + Piecewise y = Piecewise(patternd2[1]); + + Piecewise > der = unitVector(derivative(pwd2_in)); + Piecewise > n = rot90(der); + +// output = pwd2_in + n * offset; +// append_half_circle(output, pwd2_in.lastValue(), n.lastValue() * offset); +// output.continuousConcat(reverse(pwd2_in - n * offset)); +// append_half_circle(output, pwd2_in.firstValue(), -n.firstValue() * offset); + + Piecewise > output = compose(pwd2_in,x) + y*compose(n,x); + return output; +} + + +/* ######################## + * Define the classes for your knotholder handles here + */ + +/* +namespace PowerStroke { + +class KnotHolderEntityMyHandle : public LPEKnotHolderEntity +{ +public: + // the set() and get() methods must be implemented, click() is optional + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get(); + //virtual void knot_click(guint state); +}; + +} // namespace PowerStroke +*/ + +/* ######################## */ + +} //namespace LivePathEffect +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h new file mode 100644 index 000000000..9c6e3effe --- /dev/null +++ b/src/live_effects/lpe-powerstroke.h @@ -0,0 +1,67 @@ +/** @file + * @brief PowerStroke LPE effect, see lpe-powerstroke.cpp. + */ +/* Authors: + * Johan Engelen + * + * Copyright (C) 2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_LPE_POWERSTROKE_H +#define INKSCAPE_LPE_POWERSTROKE_H + +#include "live_effects/effect.h" +#include "live_effects/parameter/point.h" +#include "live_effects/parameter/array.h" + +namespace Inkscape { +namespace LivePathEffect { + +// each knotholder handle for your LPE requires a separate class derived from KnotHolderEntity; +// define it in lpe-powerstroke.cpp and register it in the effect's constructor +/** +namespace PowerStroke { + // we need a separate namespace to avoid clashes with other LPEs + class KnotHolderEntityMyHandle; +} +**/ + +class LPEPowerStroke : public Effect { +public: + LPEPowerStroke(LivePathEffectObject *lpeobject); + virtual ~LPEPowerStroke(); + + virtual Geom::Piecewise > doEffect_pwd2 (Geom::Piecewise > const & pwd2_in); + + virtual void doOnApply(SPLPEItem *lpeitem); + + /* the knotholder entity classes (if any) must be declared friends */ + //friend class PowerStroke::KnotHolderEntityMyHandle; + +private: + PointParam offset_1; + PointParam offset_2; + PointParam offset_3; +// ArrayParam offset_points; + + LPEPowerStroke(const LPEPowerStroke&); + LPEPowerStroke& operator=(const LPEPowerStroke&); +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 4075a755483a1e5ac8681a41b5875c1231e9e294 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 27 Jul 2010 01:37:52 +0200 Subject: Fix initial combo box values in filter effects dialog (bzr r9655) --- src/ui/dialog/filter-effects-dialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 1672c4b69..b2b9fe089 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -176,7 +176,7 @@ public: if (tip_text) { _tt.set_tip(*this, tip_text); } - combo = new ComboBoxEnum(default_value, c, a); + combo = new ComboBoxEnum(default_value, c, a, false); add(*combo); show_all(); } -- cgit v1.2.3 From 22cce088046ec5cfeff1ca9c7afe4aa8998ebe46 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 01:43:02 +0200 Subject: more powerstroke build infrastructure (bzr r9656) --- src/live_effects/lpe-powerstroke.cpp | 29 +++-------------------------- src/live_effects/lpe-powerstroke.h | 16 ++-------------- src/live_effects/parameter/CMakeLists.txt | 1 + src/live_effects/parameter/Makefile_insert | 2 ++ src/live_effects/parameter/array.cpp | 16 ++++++++++++++++ 5 files changed, 24 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index c3de621ee..b349f9aa6 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -28,18 +28,15 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_1(_("Start Offset"), _("Handle to control the distance of the offset from the curve"), "offset_1", &wr, this), offset_2(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_2", &wr, this), - offset_3(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_3", &wr, this) -// offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this) + offset_3(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_3", &wr, this), + offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this) { show_orig_path = true; registerParameter( dynamic_cast(&offset_1) ); registerParameter( dynamic_cast(&offset_2) ); registerParameter( dynamic_cast(&offset_3) ); -// registerParameter( dynamic_cast(&offset_points) ); - - /* register all your knotholder handles here: */ - //registerKnotHolderHandle(new PowerStroke::KnotHolderEntityAttachMyHandle(), _("help message")); + registerParameter( dynamic_cast(&offset_points) ); } LPEPowerStroke::~LPEPowerStroke() @@ -119,26 +116,6 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & return output; } - -/* ######################## - * Define the classes for your knotholder handles here - */ - -/* -namespace PowerStroke { - -class KnotHolderEntityMyHandle : public LPEKnotHolderEntity -{ -public: - // the set() and get() methods must be implemented, click() is optional - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get(); - //virtual void knot_click(guint state); -}; - -} // namespace PowerStroke -*/ - /* ######################## */ } //namespace LivePathEffect diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 9c6e3effe..811c63259 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -14,20 +14,11 @@ #include "live_effects/effect.h" #include "live_effects/parameter/point.h" -#include "live_effects/parameter/array.h" +#include "live_effects/parameter/powerstrokepointarray.h" namespace Inkscape { namespace LivePathEffect { -// each knotholder handle for your LPE requires a separate class derived from KnotHolderEntity; -// define it in lpe-powerstroke.cpp and register it in the effect's constructor -/** -namespace PowerStroke { - // we need a separate namespace to avoid clashes with other LPEs - class KnotHolderEntityMyHandle; -} -**/ - class LPEPowerStroke : public Effect { public: LPEPowerStroke(LivePathEffectObject *lpeobject); @@ -37,14 +28,11 @@ public: virtual void doOnApply(SPLPEItem *lpeitem); - /* the knotholder entity classes (if any) must be declared friends */ - //friend class PowerStroke::KnotHolderEntityMyHandle; - private: PointParam offset_1; PointParam offset_2; PointParam offset_3; -// ArrayParam offset_points; + PowerStrokePointArrayParam offset_points; LPEPowerStroke(const LPEPowerStroke&); LPEPowerStroke& operator=(const LPEPowerStroke&); diff --git a/src/live_effects/parameter/CMakeLists.txt b/src/live_effects/parameter/CMakeLists.txt index 2fa0d5bc6..8657b2bec 100644 --- a/src/live_effects/parameter/CMakeLists.txt +++ b/src/live_effects/parameter/CMakeLists.txt @@ -5,6 +5,7 @@ parameter.cpp path.cpp path-reference.cpp point.cpp +powerstrokepointarray.cpp random.cpp text.cpp unit.cpp diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert index 74b166e8b..99cd88d62 100644 --- a/src/live_effects/parameter/Makefile_insert +++ b/src/live_effects/parameter/Makefile_insert @@ -16,6 +16,8 @@ ink_common_sources += \ live_effects/parameter/path-reference.h \ live_effects/parameter/path.cpp \ live_effects/parameter/path.h \ + live_effects/parameter/powerstrokepointarray.cpp \ + live_effects/parameter/powerstrokepointarray.h \ live_effects/parameter/text.cpp \ live_effects/parameter/text.h \ live_effects/parameter/unit.cpp \ diff --git a/src/live_effects/parameter/array.cpp b/src/live_effects/parameter/array.cpp index c576bedd5..d1c30edf7 100644 --- a/src/live_effects/parameter/array.cpp +++ b/src/live_effects/parameter/array.cpp @@ -12,6 +12,7 @@ #include "svg/stringstream.h" #include <2geom/coord.h> +#include <2geom/point.h> namespace Inkscape { @@ -35,6 +36,21 @@ ArrayParam::readsvg(const gchar * str) return newx; } +template <> +Geom::Point +ArrayParam::readsvg(const gchar * str) +{ + gchar ** strarray = g_strsplit(str, ",", 2); + double newx, newy; + unsigned int success = sp_svg_number_read_d(strarray[0], &newx); + success += sp_svg_number_read_d(strarray[1], &newy); + g_strfreev (strarray); + if (success == 2) { + return Geom::Point(newx, newy); + } + return Geom::Point(Geom::infinity(),Geom::infinity()); +} + } /* namespace LivePathEffect */ } /* namespace Inkscape */ -- cgit v1.2.3 From 9149b1f7d003d80cdba338e7685c04be130c8595 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 27 Jul 2010 03:03:02 +0200 Subject: More sensible ranges for feSpecularLighting and feDiffuseLighting parameters (bzr r9657) --- src/ui/dialog/filter-effects-dialog.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index b2b9fe089..9cfb9c0b5 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -2177,13 +2177,14 @@ void FilterEffectsDialog::init_settings_widgets() _settings->type(NR_FILTER_COMPONENTTRANSFER); _settings->add_notimplemented(); + /* //TRANSLATORS: for info on "Slope" and "Intercept", see http://id.mind.net/~zona/mmts/functionInstitute/linearFunctions/lsif.html - /*_settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter); - _ct_slope = _settings->add_spinslider(SP_ATTR_SLOPE, _("Slope"), -100, 100, 1, 0.01, 1); - _ct_intercept = _settings->add_spinslider(SP_ATTR_INTERCEPT, _("Intercept"), -100, 100, 1, 0.01, 1); - _ct_amplitude = _settings->add_spinslider(SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 100, 1, 0.01, 1); - _ct_exponent = _settings->add_spinslider(SP_ATTR_EXPONENT, _("Exponent"), 0, 100, 1, 0.01, 1); - _ct_offset = _settings->add_spinslider(SP_ATTR_OFFSET, _("Offset"), -100, 100, 1, 0.01, 1);*/ + _settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter); + _ct_slope = _settings->add_spinslider(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2); + _ct_intercept = _settings->add_spinslider(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2); + _ct_amplitude = _settings->add_spinslider(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2); + _ct_exponent = _settings->add_spinslider(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2); + _ct_offset = _settings->add_spinslider(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/ _settings->type(NR_FILTER_COMPOSITE); _settings->add_combo(COMPOSITE_OVER, SP_ATTR_OPERATOR, _("Operator:"), CompositeOperatorConverter); @@ -2205,8 +2206,8 @@ void FilterEffectsDialog::init_settings_widgets() _settings->type(NR_FILTER_DIFFUSELIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Diffuse Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -1000, 1000, 1, 0.01, 1, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 100, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); @@ -2238,9 +2239,9 @@ void FilterEffectsDialog::init_settings_widgets() _settings->type(NR_FILTER_SPECULARLIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Specular Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -1000, 1000, 1, 0.01, 1, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 100, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); - _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 128, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); + _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); -- cgit v1.2.3 From 1e4fe6a386934bad8318455e060eb732fc909775 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 19:55:31 +0200 Subject: commit missing files (bzr r9658) --- .../parameter/powerstrokepointarray.cpp | 154 +++++++++++++++++++++ src/live_effects/parameter/powerstrokepointarray.h | 59 ++++++++ 2 files changed, 213 insertions(+) create mode 100644 src/live_effects/parameter/powerstrokepointarray.cpp create mode 100644 src/live_effects/parameter/powerstrokepointarray.h (limited to 'src') diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp new file mode 100644 index 000000000..923266a94 --- /dev/null +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -0,0 +1,154 @@ +#define INKSCAPE_LIVEPATHEFFECT_POWERSTROKE_POINT_ARRAY_CPP + +/* + * Copyright (C) Johan Engelen 2007 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/powerstrokepointarray.h" + +#include "live_effects/effect.h" +#include "svg/svg.h" +#include "svg/stringstream.h" +#include +#include "ui/widget/point.h" +#include "widgets/icon.h" +#include "ui/widget/registered-widget.h" +#include "inkscape.h" +#include "verbs.h" +#include "knotholder.h" + +// needed for on-canvas editting: +#include "desktop.h" + +namespace Inkscape { + +namespace LivePathEffect { + +PowerStrokePointArrayParam::PowerStrokePointArrayParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, const gchar *htip) + : ArrayParam(label, tip, key, wr, effect, 0) +{ + knot_shape = SP_KNOT_SHAPE_DIAMOND; + knot_mode = SP_KNOT_MODE_XOR; + knot_color = 0xffffff00; + handle_tip = g_strdup(htip); +} + +PowerStrokePointArrayParam::~PowerStrokePointArrayParam() +{ + if (handle_tip) + g_free(handle_tip); +} + +Gtk::Widget * +PowerStrokePointArrayParam::param_newWidget(Gtk::Tooltips * /*tooltips*/) +{ + return NULL; +/* + Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage( + new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label, + param_tooltip, + param_key, + *param_wr, + param_effect->getRepr(), + param_effect->getSPDoc() ) ); + // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP) + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Geom::Matrix transf = desktop->doc2dt(); + pointwdg->setTransform(transf); + pointwdg->setValue( *this ); + pointwdg->clearProgrammatically(); + pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter")); + + Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() ); + static_cast(hbox)->pack_start(*pointwdg, true, true); + static_cast(hbox)->show_all_children(); + + return dynamic_cast (hbox); +*/ +} + + +void +PowerStrokePointArrayParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) +{ +// param_set_and_write_new_value( (*this) * postmul ); +} + + +void +PowerStrokePointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color) +{ + knot_shape = shape; + knot_mode = mode; + knot_color = color; +} + +class PowerStrokePointArrayParamKnotHolderEntity : public LPEKnotHolderEntity { +public: + PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index); + virtual ~PowerStrokePointArrayParamKnotHolderEntity() {} + + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); + virtual Geom::Point knot_get(); + virtual void knot_click(guint state); + +private: + PowerStrokePointArrayParam *_pparam; + unsigned int _index; +}; + +PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index) + : _pparam(p), + _index(index) +{ +} + +void +PowerStrokePointArrayParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) +{ +// Geom::Point const s = snap_knot_position(p); +// pparam->param_setValue(s); +// sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); +} + +Geom::Point +PowerStrokePointArrayParamKnotHolderEntity::knot_get() +{ + Geom::Point canvas_point; + return canvas_point; +} + +void +PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint /*state*/) +{ + g_print ("This is the %d handle associated to parameter '%s'\n", _index, _pparam->param_key.c_str()); +} + +void +PowerStrokePointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) +{ + //PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this); + // TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself??? + //e->create(desktop, item, knotholder, handleTip(), knot_shape, knot_mode, knot_color); + //knotholder->add(e); + +} + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h new file mode 100644 index 000000000..0a33c0369 --- /dev/null +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -0,0 +1,59 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_POWERSTROKE_POINT_ARRAY_H +#define INKSCAPE_LIVEPATHEFFECT_POWERSTROKE_POINT_ARRAY_H + +/* + * Inkscape::LivePathEffectParameters + * +* Copyright (C) Johan Engelen 2007 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include +#include <2geom/point.h> + +#include + +#include "live_effects/parameter/array.h" + +#include "knot-holder-entity.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class PowerStrokePointArrayParam : public ArrayParam { +public: + PowerStrokePointArrayParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + const gchar *handle_tip = NULL); // tip for automatically associated on-canvas handle + virtual ~PowerStrokePointArrayParam(); + + virtual Gtk::Widget * param_newWidget(Gtk::Tooltips * tooltips); + + virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/); + + void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + + virtual bool providesKnotHolderEntities() { return true; } + virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + +private: + PowerStrokePointArrayParam(const PowerStrokePointArrayParam&); + PowerStrokePointArrayParam& operator=(const PowerStrokePointArrayParam&); + + SPKnotShapeType knot_shape; + SPKnotModeType knot_mode; + guint32 knot_color; + gchar *handle_tip; +}; + + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif -- cgit v1.2.3 From afd21a94139c8e747ef048bc64ceea0fc8d3d572 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 21:56:51 +0200 Subject: powerstroke: arbitrary number of control points. (bzr r9659) --- src/live_effects/lpe-powerstroke.cpp | 52 ++++++++-------------- src/live_effects/lpe-powerstroke.h | 3 -- src/live_effects/parameter/array.h | 9 ++-- .../parameter/powerstrokepointarray.cpp | 21 ++++----- src/live_effects/parameter/powerstrokepointarray.h | 4 ++ 5 files changed, 39 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index b349f9aa6..da2b9d6a9 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -26,16 +26,10 @@ namespace LivePathEffect { LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), - offset_1(_("Start Offset"), _("Handle to control the distance of the offset from the curve"), "offset_1", &wr, this), - offset_2(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_2", &wr, this), - offset_3(_("End Offset"), _("Handle to control the distance of the offset from the curve"), "offset_3", &wr, this), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this) { show_orig_path = true; - registerParameter( dynamic_cast(&offset_1) ); - registerParameter( dynamic_cast(&offset_2) ); - registerParameter( dynamic_cast(&offset_3) ); registerParameter( dynamic_cast(&offset_points) ); } @@ -48,9 +42,12 @@ LPEPowerStroke::~LPEPowerStroke() void LPEPowerStroke::doOnApply(SPLPEItem *lpeitem) { - offset_1.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->first_point())); - offset_2.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point())); - offset_3.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->curve->last_point())); + std::vector points; + points.push_back( *(SP_SHAPE(lpeitem)->curve->first_point()) ); + Geom::Path const *path = SP_SHAPE(lpeitem)->curve->first_path(); + points.push_back( path->pointAt(path->size()/2) ); + points.push_back( *(SP_SHAPE(lpeitem)->curve->last_point()) ); + offset_points.param_set_and_write_new_value(points); } static void append_half_circle(Geom::Piecewise > &pwd2, @@ -68,38 +65,27 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & { using namespace Geom; - double t1 = nearest_point(offset_1, pwd2_in); - double offset1 = L2(pwd2_in.valueAt(t1) - offset_1); + std::vector ts(offset_points.data().size()); - double t2 = nearest_point(offset_2, pwd2_in); - double offset2 = L2(pwd2_in.valueAt(t2) - offset_2); - - double t3 = nearest_point(offset_3, pwd2_in); - double offset3 = L2(pwd2_in.valueAt(t3) - offset_3); - - /* - unsigned number_of_points = offset_points.data.size(); - double* t = new double[number_of_points]; - Point* offset = new double[number_of_points]; - for (unsigned i = 0; i < number_of_points; ++i) { - t[i] = nearest_point(offset_points.data[i], pwd2_in); - Point A = pwd2_in.valueAt(t[i]); - offset[i] = L2(A - offset_points.data[i]); + for (unsigned int i; i < ts.size(); ++i) { + double t = nearest_point(offset_points.data().at(i), pwd2_in); + double offset = L2(pwd2_in.valueAt(t) - offset_points.data().at(i)); + ts.at(i) = Geom::Point(t, offset); } - */ // create stroke path where points (x,y) = (t, offset) Path strokepath; strokepath.start( Point(pwd2_in.domain().min(),0) ); - strokepath.appendNew( Point(t1, offset1) ); - strokepath.appendNew( Point(t2, offset2) ); - strokepath.appendNew( Point(t3, offset3) ); + for (unsigned int i = 0 ; i < ts.size(); ++i) { + strokepath.appendNew(ts.at(i)); + } strokepath.appendNew( Point(pwd2_in.domain().max(), 0) ); - strokepath.appendNew( Point(t3, -offset3) ); - strokepath.appendNew( Point(t2, -offset2) ); - strokepath.appendNew( Point(t1, -offset1) ); + for (unsigned int i = 0; i < ts.size(); ++i) { + Geom::Point temp = ts.at(ts.size() - 1 - i); + strokepath.appendNew( Geom::Point(temp[X], - temp[Y]) ); + } strokepath.close(); - + D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); Piecewise x = Piecewise(patternd2[0]); Piecewise y = Piecewise(patternd2[1]); diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 811c63259..66b2ab89f 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -29,9 +29,6 @@ public: virtual void doOnApply(SPLPEItem *lpeitem); private: - PointParam offset_1; - PointParam offset_2; - PointParam offset_3; PowerStrokePointArrayParam offset_points; LPEPowerStroke(const LPEPowerStroke&); diff --git a/src/live_effects/parameter/array.h b/src/live_effects/parameter/array.h index e5f230111..89c344594 100644 --- a/src/live_effects/parameter/array.h +++ b/src/live_effects/parameter/array.h @@ -85,10 +85,7 @@ public: g_free(str); } -private: - ArrayParam(const ArrayParam&); - ArrayParam& operator=(const ArrayParam&); - +protected: std::vector _vector; size_t _default_size; @@ -103,6 +100,10 @@ private: } StorageType readsvg(const gchar * str); + +private: + ArrayParam(const ArrayParam&); + ArrayParam& operator=(const ArrayParam&); }; diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 923266a94..49ef05319 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -33,7 +33,7 @@ PowerStrokePointArrayParam::PowerStrokePointArrayParam( const Glib::ustring& lab { knot_shape = SP_KNOT_SHAPE_DIAMOND; knot_mode = SP_KNOT_MODE_XOR; - knot_color = 0xffffff00; + knot_color = 0xff00ff00; handle_tip = g_strdup(htip); } @@ -110,15 +110,16 @@ PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolder void PowerStrokePointArrayParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) { -// Geom::Point const s = snap_knot_position(p); -// pparam->param_setValue(s); -// sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); + Geom::Point const s = snap_knot_position(p); + _pparam->_vector.at(_index) = s; +// _pparam->param_set_and_write_new_value(_pparam->_vector); + sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); } Geom::Point PowerStrokePointArrayParamKnotHolderEntity::knot_get() { - Geom::Point canvas_point; + Geom::Point canvas_point = _pparam->_vector.at(_index); return canvas_point; } @@ -131,11 +132,11 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint /*state*/) void PowerStrokePointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) { - //PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this); - // TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself??? - //e->create(desktop, item, knotholder, handleTip(), knot_shape, knot_mode, knot_color); - //knotholder->add(e); - + for (unsigned int i = 0; i < _vector.size(); ++i) { + PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this, i); + e->create(desktop, item, knotholder, handle_tip, knot_shape, knot_mode, knot_color); + knotholder->add(e); + } } } /* namespace LivePathEffect */ diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index 0a33c0369..66eb3c987 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -22,6 +22,8 @@ namespace Inkscape { namespace LivePathEffect { +class PowerStrokePointArrayParamKnotHolderEntity; + class PowerStrokePointArrayParam : public ArrayParam { public: PowerStrokePointArrayParam( const Glib::ustring& label, @@ -41,6 +43,8 @@ public: virtual bool providesKnotHolderEntities() { return true; } virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + friend class PowerStrokePointArrayParamKnotHolderEntity; + private: PowerStrokePointArrayParam(const PowerStrokePointArrayParam&); PowerStrokePointArrayParam& operator=(const PowerStrokePointArrayParam&); -- cgit v1.2.3 From 813ae6f7f9543c0b16f785907890e6cc1a43f990 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 27 Jul 2010 22:30:10 +0200 Subject: powerstroke: sort point option (bzr r9660) --- src/live_effects/lpe-powerstroke.cpp | 14 +++++++++++++- src/live_effects/lpe-powerstroke.h | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index da2b9d6a9..cb45e0518 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -26,11 +26,13 @@ namespace LivePathEffect { LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), - offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this) + offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), + sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve."), "sort_points", &wr, this, true) { show_orig_path = true; registerParameter( dynamic_cast(&offset_points) ); + registerParameter( dynamic_cast(&sort_points) ); } LPEPowerStroke::~LPEPowerStroke() @@ -60,11 +62,18 @@ static void append_half_circle(Geom::Piecewise > &pwd2, pwd2.continuousConcat(cap_pwd2); } +static bool compare_offsets (Geom::Point first, Geom::Point second) +{ + return first[Geom::X] <= second[Geom::X]; +} + + Geom::Piecewise > LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & pwd2_in) { using namespace Geom; + // perhaps use std::list instead of std::vector? std::vector ts(offset_points.data().size()); for (unsigned int i; i < ts.size(); ++i) { @@ -72,6 +81,9 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & double offset = L2(pwd2_in.valueAt(t) - offset_points.data().at(i)); ts.at(i) = Geom::Point(t, offset); } + if (sort_points) { + sort(ts.begin(), ts.end(), compare_offsets); + } // create stroke path where points (x,y) = (t, offset) Path strokepath; diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h index 66b2ab89f..6c208fda4 100644 --- a/src/live_effects/lpe-powerstroke.h +++ b/src/live_effects/lpe-powerstroke.h @@ -13,7 +13,7 @@ #define INKSCAPE_LPE_POWERSTROKE_H #include "live_effects/effect.h" -#include "live_effects/parameter/point.h" +#include "live_effects/parameter/bool.h" #include "live_effects/parameter/powerstrokepointarray.h" namespace Inkscape { @@ -30,6 +30,7 @@ public: private: PowerStrokePointArrayParam offset_points; + BoolParam sort_points; LPEPowerStroke(const LPEPowerStroke&); LPEPowerStroke& operator=(const LPEPowerStroke&); -- cgit v1.2.3 From 68616889b6eaf53f4e019f1566b7edf56e8ec521 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 28 Jul 2010 00:29:47 +0200 Subject: Duplicate the undo key passed to sp_document_maybe_done, instead of simply assigning it. Allows the function to be used with dynamically created keys and fixes undo stack spam when adjusting filter parameter values (LP #579932). Fixed bugs: - https://launchpad.net/bugs/579932 (bzr r9661) --- src/document-undo.cpp | 4 +++- src/document.cpp | 5 ++++- src/document.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/document-undo.cpp b/src/document-undo.cpp index ae1c82e71..62259fa19 100644 --- a/src/document-undo.cpp +++ b/src/document-undo.cpp @@ -198,7 +198,9 @@ sp_document_maybe_done (SPDocument *doc, const gchar *key, const unsigned int ev doc->priv->undoStackObservers.notifyUndoCommitEvent(event); } - doc->actionkey = key; + if (doc->actionkey) + g_free(doc->actionkey); + doc->actionkey = key ? g_strdup(key) : NULL; doc->virgin = FALSE; doc->setModifiedSinceSave(); diff --git a/src/document.cpp b/src/document.cpp index eff6d6e81..eebc50a98 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -211,7 +211,10 @@ SPDocument::~SPDocument() { inkscape_unref(); keepalive = FALSE; } - + if (actionkey) { + g_free(actionkey); + actionkey = NULL; + } //delete this->_whiteboard_session_manager; } diff --git a/src/document.h b/src/document.h index e70582006..bcc072f70 100644 --- a/src/document.h +++ b/src/document.h @@ -96,7 +96,7 @@ struct SPDocument : public Inkscape::GC::Managed<>, SPDocumentPrivate *priv; /// Last action key - const gchar *actionkey; + gchar *actionkey; /// Handler ID guint modified_id; -- cgit v1.2.3 From b866548d43ef89eefbbec860e0935f8f2505277f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 27 Jul 2010 18:57:53 -0700 Subject: Safer fix for bug #579932 that won't leak memory. (bzr r9662) --- src/document-undo.cpp | 24 ++++++++++++++---------- src/document.cpp | 8 ++------ src/document.h | 3 ++- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/document-undo.cpp b/src/document-undo.cpp index 62259fa19..e63fe8a52 100644 --- a/src/document-undo.cpp +++ b/src/document-undo.cpp @@ -125,11 +125,10 @@ sp_document_done (SPDocument *doc, const unsigned int event_type, Glib::ustring sp_document_maybe_done (doc, NULL, event_type, event_description); } -void -sp_document_reset_key (Inkscape::Application */*inkscape*/, SPDesktop */*desktop*/, GtkObject *base) +void sp_document_reset_key( Inkscape::Application * /*inkscape*/, SPDesktop * /*desktop*/, GtkObject *base ) { - SPDocument *doc = (SPDocument *) base; - doc->actionkey = NULL; + SPDocument *doc = reinterpret_cast(base); + doc->actionkey.clear(); } namespace { @@ -171,6 +170,9 @@ sp_document_maybe_done (SPDocument *doc, const gchar *key, const unsigned int ev g_assert (doc != NULL); g_assert (doc->priv != NULL); g_assert (doc->priv->sensitive); + if ( key && !*key ) { + g_warning("Blank undo key specified."); + } Inkscape::Debug::EventTracker tracker(doc, key, event_type); @@ -188,7 +190,7 @@ sp_document_maybe_done (SPDocument *doc, const gchar *key, const unsigned int ev return; } - if (key && doc->actionkey && !strcmp (key, doc->actionkey) && doc->priv->undo) { + if (key && !doc->actionkey.empty() && (doc->actionkey == key) && doc->priv->undo) { ((Inkscape::Event *)doc->priv->undo->data)->event = sp_repr_coalesce_log (((Inkscape::Event *)doc->priv->undo->data)->event, log); } else { @@ -198,9 +200,11 @@ sp_document_maybe_done (SPDocument *doc, const gchar *key, const unsigned int ev doc->priv->undoStackObservers.notifyUndoCommitEvent(event); } - if (doc->actionkey) - g_free(doc->actionkey); - doc->actionkey = key ? g_strdup(key) : NULL; + if ( key ) { + doc->actionkey = key; + } else { + doc->actionkey.clear(); + } doc->virgin = FALSE; doc->setModifiedSinceSave(); @@ -259,7 +263,7 @@ sp_document_undo (SPDocument *doc) doc->priv->sensitive = FALSE; doc->priv->seeking = true; - doc->actionkey = NULL; + doc->actionkey.clear(); finish_incomplete_transaction(*doc); @@ -305,7 +309,7 @@ sp_document_redo (SPDocument *doc) doc->priv->sensitive = FALSE; doc->priv->seeking = true; - doc->actionkey = NULL; + doc->actionkey.clear(); finish_incomplete_transaction(*doc); diff --git a/src/document.cpp b/src/document.cpp index eebc50a98..3c9f7e5ed 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -92,7 +92,7 @@ SPDocument::SPDocument() : base(0), name(0), priv(0), // reset in ctor - actionkey(0), + actionkey(), modified_id(0), rerouting_handler_id(0), profileManager(0), // deferred until after other initialization @@ -211,10 +211,6 @@ SPDocument::~SPDocument() { inkscape_unref(); keepalive = FALSE; } - if (actionkey) { - g_free(actionkey); - actionkey = NULL; - } //delete this->_whiteboard_session_manager; } @@ -291,7 +287,7 @@ void SPDocument::collectOrphans() { void SPDocument::reset_key (void */*dummy*/) { - actionkey = NULL; + actionkey.clear(); } SPDocument * diff --git a/src/document.h b/src/document.h index bcc072f70..5810b5358 100644 --- a/src/document.h +++ b/src/document.h @@ -96,7 +96,8 @@ struct SPDocument : public Inkscape::GC::Managed<>, SPDocumentPrivate *priv; /// Last action key - gchar *actionkey; + Glib::ustring actionkey; + /// Handler ID guint modified_id; -- cgit v1.2.3 From bf84950712fccc32dc0030edb9d2a04b6ec9a68d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 28 Jul 2010 11:12:57 +0200 Subject: Fix rendering of "plain" SVG text. (bzr r9665) --- src/libnrtype/Layout-TNG-Compute.cpp | 41 ++++++++++++++++++++++++++---------- src/sp-text.cpp | 2 +- 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 192596ecf..77e21ef56 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -445,22 +445,32 @@ class Layout::Calculator // we may also have y move orders to deal with here (dx, dy and rotate are done per span) - // Comment added: 1 June 2010: - // The first line in a normal object is placed by the read-in "y" value. The rest are - // determined by Inkscape. This is to allow insertation of new lines in the middle - // of a object. New "y" values are then stored in each that represents - // a new line. The line spacing should depend only on font-size and line-height (and not - // on any y-kerning). Line spacing is already handled by the calling routine. Note that - // this may render improperly any SVG with s created/edited by other programs. + // Comment updated: 23 July 2010: + // We must handle two cases: + // + // 1. Inkscape SVG where the first line is placed by the read-in "y" value and the + // rest are determined by 'font-size' and 'line-height' (and not by any + // y-kerning). s in this case are marked by sodipodi:role="line". This + // allows new lines to be inserted in the middle of a object. On output, + // new "y" values are calculated for each that represents a new line. Line + // spacing is already handled by the calling routine. + // + // 2. Plain SVG where each or is placed by its own "x" and "y" values. + // Note that in this case Inkscape treats each object with any included + // s as a single line of text. This can be confusing in the code below. + if (!it_chunk->broken_spans.empty() // Not empty paragraph && it_chunk->broken_spans.front().start.char_byte == 0 ) { // Beginning of unbroken span - // If empty or new line + // If empty or new line (sodipode:role="line") if( _flow._characters.empty() || _flow._characters.back().chunk(&_flow).in_line != _flow._lines.size() - 1) { + // This is the Inkscape SVG case. + // // If "y" attribute is set, use it (initial "y" attributes in - // other than the first have already been stripped). + // other than the first have already been stripped for + // marked with role="line", see sp-text.cpp: SPText::_buildLayoutInput). if( it_chunk->broken_spans.front().start.iter_span->y._set ) { // Use set "y" attribute @@ -475,9 +485,17 @@ class Layout::Calculator } // Reset relative y_offset ("dy" attribute is relative but should be reset at - // the beginning of each .) + // the beginning of each line since each line will have a new "y" written out.) _y_offset = 0.0; + } else { + + // This is the plain SVG case + // + // "x" and "y" are used to place text, simulating lines as necessary + if( it_chunk->broken_spans.front().start.iter_span->y._set ) { + _y_offset = it_chunk->broken_spans.front().start.iter_span->y.computed - new_line.baseline_y; + } } } _flow._chunks.push_back(new_chunk); @@ -1243,8 +1261,9 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition span_pos; for( ; ; ) { std::vector scan_runs; - scan_runs = _scanline_maker->makeScanline(*line_height); + scan_runs = _scanline_maker->makeScanline(*line_height); // Only one line with "InfiniteScanlineMaker while (scan_runs.empty()) { + // Only used by ShapeScanlineMaker if (!_goToNextWrapShape()) return false; // no more shapes to wrap in to scan_runs = _scanline_maker->makeScanline(*line_height); } diff --git a/src/sp-text.cpp b/src/sp-text.cpp index bae625f58..36f67aa88 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -528,7 +528,7 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio } else if (SP_IS_TSPAN(root)) { SPTSpan *tspan = SP_TSPAN(root); - // x, y attributes are stripped from some tspans as we do our own line layout + // x, y attributes are stripped from some tspans marked with role="line" as we do our own line layout. // This should be checked carefully, as it can undo line layout in imported SVG files. bool use_xy = !in_textpath && (tspan->role == SP_TSPAN_ROLE_UNSPECIFIED || !tspan->attributes.singleXYCoordinates()); tspan->attributes.mergeInto(&optional_attrs, parent_optional_attrs, parent_attrs_offset, use_xy, true); -- cgit v1.2.3 From a5a5859cfebd3c5652f6163a3826f49765573d3e Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 28 Jul 2010 23:41:55 +0200 Subject: powerstroke: ctrl+click inserts new stroke knot. BUGGY. reselect object after adding stroke knot (bzr r9666) --- src/live_effects/parameter/powerstrokepointarray.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 49ef05319..99c327207 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -124,9 +124,17 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() } void -PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint /*state*/) +PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state) { g_print ("This is the %d handle associated to parameter '%s'\n", _index, _pparam->param_key.c_str()); + + if (state & GDK_CONTROL_MASK) { + std::vector & vec = _pparam->_vector; + vec.insert(vec.begin() + _index, 1, vec.at(_index)); + _pparam->param_set_and_write_new_value(vec); + g_print ("Added handle %d associated to parameter '%s'\n", _index, _pparam->param_key.c_str()); + /// @todo this BUGS ! the knot stuff should be reloaded when adding a new node! + } } void -- cgit v1.2.3 From b507fe5badb979cfc29be7236e08e39b4373a8b8 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 28 Jul 2010 23:54:22 +0200 Subject: powerstroke: fix terrible bug, clean up code, add interpolator framework (bzr r9667) --- src/live_effects/lpe-powerstroke.cpp | 78 ++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index cb45e0518..447b85664 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -18,9 +18,48 @@ #include <2geom/path.h> #include <2geom/piecewise.h> #include <2geom/sbasis-geometric.h> -#include <2geom/svg-elliptical-arc.h> #include <2geom/transforms.h> + +/// @TODO Move this to 2geom +namespace Geom { +namespace Interpolate { + +class Interpolator { +public: + Interpolator() {}; + virtual ~Interpolator() {}; + +// virtual Piecewise > interpolateToPwD2Sb(std::vector points) = 0; + virtual Path interpolateToPath(std::vector points) = 0; + +private: + Interpolator(const Interpolator&); + Interpolator& operator=(const Interpolator&); +}; + +class Linear : public Interpolator { +public: + Linear() {}; + virtual ~Linear() {}; + + virtual Path interpolateToPath(std::vector points) { + Path strokepath; + strokepath.start( points.at(0) ); + for (unsigned int i = 1 ; i < points.size(); ++i) { + strokepath.appendNew(points.at(i)); + } + return strokepath; + }; + +private: + Linear(const Linear&); + Linear& operator=(const Linear&); +}; + +} //namespace Interpolate +} //namespace Geom + namespace Inkscape { namespace LivePathEffect { @@ -52,19 +91,9 @@ LPEPowerStroke::doOnApply(SPLPEItem *lpeitem) offset_points.param_set_and_write_new_value(points); } -static void append_half_circle(Geom::Piecewise > &pwd2, - Geom::Point const center, Geom::Point const &dir) { - using namespace Geom; - - double r = L2(dir); - SVGEllipticalArc cap(center + dir, r, r, angle_between(Point(1,0), dir), false, false, center - dir); - Piecewise > cap_pwd2(cap.toSBasis()); - pwd2.continuousConcat(cap_pwd2); -} - static bool compare_offsets (Geom::Point first, Geom::Point second) { - return first[Geom::X] <= second[Geom::X]; + return first[Geom::X] < second[Geom::X]; } @@ -74,28 +103,25 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & using namespace Geom; // perhaps use std::list instead of std::vector? - std::vector ts(offset_points.data().size()); - - for (unsigned int i; i < ts.size(); ++i) { + std::vector ts(offset_points.data().size() + 2); + // first and last point coincide with input path (for now at least) + ts.front() = Point(pwd2_in.domain().min(),0); + ts.back() = Point(pwd2_in.domain().max(),0); + for (unsigned int i = 0; i < offset_points.data().size(); ++i) { double t = nearest_point(offset_points.data().at(i), pwd2_in); double offset = L2(pwd2_in.valueAt(t) - offset_points.data().at(i)); - ts.at(i) = Geom::Point(t, offset); + ts.at(i+1) = Geom::Point(t, offset); } + if (sort_points) { sort(ts.begin(), ts.end(), compare_offsets); } // create stroke path where points (x,y) = (t, offset) - Path strokepath; - strokepath.start( Point(pwd2_in.domain().min(),0) ); - for (unsigned int i = 0 ; i < ts.size(); ++i) { - strokepath.appendNew(ts.at(i)); - } - strokepath.appendNew( Point(pwd2_in.domain().max(), 0) ); - for (unsigned int i = 0; i < ts.size(); ++i) { - Geom::Point temp = ts.at(ts.size() - 1 - i); - strokepath.appendNew( Geom::Point(temp[X], - temp[Y]) ); - } + Geom::Interpolate::Linear interpolator; + Path strokepath = interpolator.interpolateToPath(ts); + Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1); + strokepath.append(mirroredpath, Geom::Path::STITCH_DISCONTINUOUS); strokepath.close(); D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); -- cgit v1.2.3 From 7db5211b131348ff4929579301725eac217c99bc Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Thu, 29 Jul 2010 00:13:19 +0200 Subject: powerstroke: code only, added bad interpolator (bzr r9668) --- src/live_effects/lpe-powerstroke.cpp | 49 +++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 447b85664..af5739b32 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -19,6 +19,7 @@ #include <2geom/piecewise.h> #include <2geom/sbasis-geometric.h> #include <2geom/transforms.h> +#include <2geom/bezier-utils.h> /// @TODO Move this to 2geom @@ -44,12 +45,12 @@ public: virtual ~Linear() {}; virtual Path interpolateToPath(std::vector points) { - Path strokepath; - strokepath.start( points.at(0) ); + Path path; + path.start( points.at(0) ); for (unsigned int i = 1 ; i < points.size(); ++i) { - strokepath.appendNew(points.at(i)); + path.appendNew(points.at(i)); } - return strokepath; + return path; }; private: @@ -57,6 +58,46 @@ private: Linear& operator=(const Linear&); }; +// this class is terrible +class CubicBezierFit : public Interpolator { +public: + CubicBezierFit() {}; + virtual ~CubicBezierFit() {}; + + virtual Path interpolateToPath(std::vector points) { + unsigned int n_points = points.size(); + // worst case gives us 2 segment per point + int max_segs = 8*n_points; + Geom::Point * b = g_new(Geom::Point, max_segs); + Geom::Point * points_array = g_new(Geom::Point, 4*n_points); + for (unsigned i = 0; i < n_points; ++i) { + points_array[i] = points.at(i); + } + + double tolerance_sq = 0; // this value is just a random guess + + int const n_segs = Geom::bezier_fit_cubic_r(b, points_array, n_points, + tolerance_sq, max_segs); + + Geom::Path fit; + if ( n_segs > 0) + { + fit.start(b[0]); + for (int c = 0; c < n_segs; c++) { + fit.appendNew(b[4*c+1], b[4*c+2], b[4*c+3]); + } + } + g_free(b); + g_free(points_array); + return fit; + }; + +private: + CubicBezierFit(const CubicBezierFit&); + CubicBezierFit& operator=(const CubicBezierFit&); +}; + + } //namespace Interpolate } //namespace Geom -- cgit v1.2.3 From eb7cb50faa8dd87fd507d3d496767b735401d0d5 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Thu, 29 Jul 2010 00:22:18 +0200 Subject: powerstroke: add visually 'nice' interpolator, good enough for now (bzr r9669) --- src/live_effects/lpe-powerstroke.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index af5739b32..addddd06f 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -97,6 +97,28 @@ private: CubicBezierFit& operator=(const CubicBezierFit&); }; +/// @todo invent name for this class +class CubicBezierJohan : public Interpolator { +public: + CubicBezierJohan() {}; + virtual ~CubicBezierJohan() {}; + + virtual Path interpolateToPath(std::vector points) { + Path fit; + fit.start(points.at(0)); + for (unsigned int i = 1; i < points.size(); ++i) { + Point p0 = points.at(i-1); + Point p1 = points.at(i); + Point dx = Point(p1[X] - p0[X], 0); + fit.appendNew(p0+0.2*dx, p1-0.2*dx, p1); + } + return fit; + }; + +private: + CubicBezierJohan(const CubicBezierJohan&); + CubicBezierJohan& operator=(const CubicBezierJohan&); +}; } //namespace Interpolate } //namespace Geom @@ -159,7 +181,7 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & } // create stroke path where points (x,y) = (t, offset) - Geom::Interpolate::Linear interpolator; + Geom::Interpolate::CubicBezierJohan interpolator; Path strokepath = interpolator.interpolateToPath(ts); Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1); strokepath.append(mirroredpath, Geom::Path::STITCH_DISCONTINUOUS); -- cgit v1.2.3 From c7abf5840c23b3abfde9a9c3207cad4eee6b0dfc Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 30 Jul 2010 08:39:08 +0200 Subject: i18n. Fix for Bug #611025 (Setup for widescreen work does not show translated). (bzr r9670) --- src/interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index b33443d1b..6dc29288f 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -904,7 +904,7 @@ void addTaskMenuItems(GtkMenu *menu, Inkscape::UI::View::View *view) gchar const* data[] = { _("Default"), _("Default interface setup"), _("Custom"), _("Set the custom task"), - _("Wide"), _("Setup for widescreen work."), + _("Wide"), _("Setup for widescreen work"), 0, 0 }; -- cgit v1.2.3 From 59f56e0c14005e4c386a162a5ce66398b710a82f Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 31 Jul 2010 00:52:27 +0200 Subject: powerstroke: redefine meaning of offset point parameter values. now knots move with path (bzr r9672) --- src/live_effects/lpe-powerstroke.cpp | 19 ++++++++------- .../parameter/powerstrokepointarray.cpp | 28 +++++++++++++++------- src/live_effects/parameter/powerstrokepointarray.h | 8 +++++++ 3 files changed, 38 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index addddd06f..68cdac115 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -133,6 +133,8 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : { show_orig_path = true; + /// @todo offset_points are initialized with empty path, is that bug-save? + registerParameter( dynamic_cast(&offset_points) ); registerParameter( dynamic_cast(&sort_points) ); } @@ -147,10 +149,10 @@ void LPEPowerStroke::doOnApply(SPLPEItem *lpeitem) { std::vector points; - points.push_back( *(SP_SHAPE(lpeitem)->curve->first_point()) ); - Geom::Path const *path = SP_SHAPE(lpeitem)->curve->first_path(); - points.push_back( path->pointAt(path->size()/2) ); - points.push_back( *(SP_SHAPE(lpeitem)->curve->last_point()) ); + Geom::Path::size_type size = SP_SHAPE(lpeitem)->curve->get_pathvector().front().size_open(); + points.push_back( Geom::Point(0,0) ); + points.push_back( Geom::Point(0.5*size,0) ); + points.push_back( Geom::Point(size,0) ); offset_points.param_set_and_write_new_value(points); } @@ -165,15 +167,15 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & { using namespace Geom; + offset_points.set_pwd2(pwd2_in); + // perhaps use std::list instead of std::vector? std::vector ts(offset_points.data().size() + 2); // first and last point coincide with input path (for now at least) ts.front() = Point(pwd2_in.domain().min(),0); ts.back() = Point(pwd2_in.domain().max(),0); for (unsigned int i = 0; i < offset_points.data().size(); ++i) { - double t = nearest_point(offset_points.data().at(i), pwd2_in); - double offset = L2(pwd2_in.valueAt(t) - offset_points.data().at(i)); - ts.at(i+1) = Geom::Point(t, offset); + ts.at(i+1) = offset_points.data().at(i); } if (sort_points) { @@ -192,7 +194,8 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & Piecewise y = Piecewise(patternd2[1]); Piecewise > der = unitVector(derivative(pwd2_in)); - Piecewise > n = rot90(der); + Piecewise > n = rot90(der); + offset_points.set_pwd2_normal(n); // output = pwd2_in + n * offset; // append_half_circle(output, pwd2_in.lastValue(), n.lastValue() * offset); diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index 99c327207..c20980193 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -11,13 +11,11 @@ #include "live_effects/effect.h" #include "svg/svg.h" #include "svg/stringstream.h" -#include -#include "ui/widget/point.h" -#include "widgets/icon.h" -#include "ui/widget/registered-widget.h" -#include "inkscape.h" -#include "verbs.h" #include "knotholder.h" +#include "sp-lpe-item.h" + +#include <2geom/piecewise.h> +#include <2geom/sbasis-geometric.h> // needed for on-canvas editting: #include "desktop.h" @@ -110,16 +108,28 @@ PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolder void PowerStrokePointArrayParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint /*state*/) { +/// @todo how about item transforms??? + using namespace Geom; + Piecewise > const & pwd2 = _pparam->get_pwd2(); + Piecewise > const & n = _pparam->get_pwd2_normal(); + Geom::Point const s = snap_knot_position(p); - _pparam->_vector.at(_index) = s; -// _pparam->param_set_and_write_new_value(_pparam->_vector); + double t = nearest_point(s, pwd2); + double offset = dot(s - pwd2.valueAt(t), n.valueAt(t)); + _pparam->_vector.at(_index) = Geom::Point(t, offset); sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); } Geom::Point PowerStrokePointArrayParamKnotHolderEntity::knot_get() { - Geom::Point canvas_point = _pparam->_vector.at(_index); + using namespace Geom; + Piecewise > const & pwd2 = _pparam->get_pwd2(); + Piecewise > const & n = _pparam->get_pwd2_normal(); + + Point offset_point = _pparam->_vector.at(_index); + + Point canvas_point = pwd2.valueAt(offset_point[X]) + offset_point[Y] * n.valueAt(offset_point[X]); return canvas_point; } diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index 66eb3c987..06d406dfe 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -43,6 +43,11 @@ public: virtual bool providesKnotHolderEntities() { return true; } virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + void set_pwd2(Geom::Piecewise > const & pwd2_in) { last_pwd2 = pwd2_in; } + Geom::Piecewise > const & get_pwd2() { return last_pwd2; } + void set_pwd2_normal(Geom::Piecewise > const & pwd2_in) { last_pwd2_normal = pwd2_in; } + Geom::Piecewise > const & get_pwd2_normal() { return last_pwd2_normal; } + friend class PowerStrokePointArrayParamKnotHolderEntity; private: @@ -53,6 +58,9 @@ private: SPKnotModeType knot_mode; guint32 knot_color; gchar *handle_tip; + + Geom::Piecewise > last_pwd2; + Geom::Piecewise > last_pwd2_normal; }; -- cgit v1.2.3 From 7dba444cb945b48feb3001d4cb1e19650ff01ba1 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 31 Jul 2010 02:01:03 +0200 Subject: powerstroke: add code that handles closed paths (bzr r9673) --- src/live_effects/lpe-powerstroke.cpp | 93 +++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 68cdac115..6109ea498 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -169,40 +169,79 @@ LPEPowerStroke::doEffect_pwd2 (Geom::Piecewise > const & offset_points.set_pwd2(pwd2_in); - // perhaps use std::list instead of std::vector? - std::vector ts(offset_points.data().size() + 2); - // first and last point coincide with input path (for now at least) - ts.front() = Point(pwd2_in.domain().min(),0); - ts.back() = Point(pwd2_in.domain().max(),0); - for (unsigned int i = 0; i < offset_points.data().size(); ++i) { - ts.at(i+1) = offset_points.data().at(i); - } + Piecewise > der = unitVector(derivative(pwd2_in)); + Piecewise > n = rot90(der); + offset_points.set_pwd2_normal(n); - if (sort_points) { - sort(ts.begin(), ts.end(), compare_offsets); + // see if we should treat the path as being closed. + bool closed_path = false; + if ( are_near(pwd2_in.firstValue(), pwd2_in.lastValue()) ) { + closed_path = true; } - // create stroke path where points (x,y) = (t, offset) - Geom::Interpolate::CubicBezierJohan interpolator; - Path strokepath = interpolator.interpolateToPath(ts); - Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1); - strokepath.append(mirroredpath, Geom::Path::STITCH_DISCONTINUOUS); - strokepath.close(); + Piecewise > output; + if (!closed_path) { + // perhaps use std::list instead of std::vector? + std::vector ts(offset_points.data().size() + 2); + // first and last point coincide with input path (for now at least) + ts.front() = Point(pwd2_in.domain().min(),0); + ts.back() = Point(pwd2_in.domain().max(),0); + for (unsigned int i = 0; i < offset_points.data().size(); ++i) { + ts.at(i+1) = offset_points.data().at(i); + } - D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); - Piecewise x = Piecewise(patternd2[0]); - Piecewise y = Piecewise(patternd2[1]); + if (sort_points) { + sort(ts.begin(), ts.end(), compare_offsets); + } - Piecewise > der = unitVector(derivative(pwd2_in)); - Piecewise > n = rot90(der); - offset_points.set_pwd2_normal(n); + // create stroke path where points (x,y) := (t, offset) + Geom::Interpolate::CubicBezierJohan interpolator; + Path strokepath = interpolator.interpolateToPath(ts); + Path mirroredpath = strokepath.reverse() * Geom::Scale(1,-1); + + strokepath.append(mirroredpath, Geom::Path::STITCH_DISCONTINUOUS); + strokepath.close(); + + D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); + Piecewise x = Piecewise(patternd2[0]); + Piecewise y = Piecewise(patternd2[1]); + + output = compose(pwd2_in,x) + y*compose(n,x); + } else { + // path is closed -// output = pwd2_in + n * offset; -// append_half_circle(output, pwd2_in.lastValue(), n.lastValue() * offset); -// output.continuousConcat(reverse(pwd2_in - n * offset)); -// append_half_circle(output, pwd2_in.firstValue(), -n.firstValue() * offset); + // perhaps use std::list instead of std::vector? + std::vector ts = offset_points.data(); + if (sort_points) { + sort(ts.begin(), ts.end(), compare_offsets); + } + // add extra points for interpolation between first and last point + Point first_point = ts.front(); + Point last_point = ts.back(); + ts.insert(ts.begin(), last_point - Point(pwd2_in.domain().extent() ,0)); + ts.push_back( first_point + Point(pwd2_in.domain().extent() ,0) ); + // create stroke path where points (x,y) := (t, offset) + Geom::Interpolate::CubicBezierJohan interpolator; + Path strokepath = interpolator.interpolateToPath(ts); + + // output 2 separate paths + D2 > patternd2 = make_cuts_independent(strokepath.toPwSb()); + Piecewise x = Piecewise(patternd2[0]); + Piecewise y = Piecewise(patternd2[1]); + // find time values for which x lies outside path domain + // and only take portion of x and y that lies within those time values + std::vector< double > rtsmin = roots (x - pwd2_in.domain().min()); + std::vector< double > rtsmax = roots (x - pwd2_in.domain().max()); + if ( !rtsmin.empty() && !rtsmax.empty() ) { + x = portion(x, rtsmin.at(0), rtsmax.at(0)); + y = portion(y, rtsmin.at(0), rtsmax.at(0)); + } + output = compose(pwd2_in,x) + y*compose(n,x); + x = reverse(x); + y = reverse(y); + output.concat(compose(pwd2_in,x) - y*compose(n,x)); + } - Piecewise > output = compose(pwd2_in,x) + y*compose(n,x); return output; } -- cgit v1.2.3 From ca9b8c554f24722ec29ea29df38cb0254c7987b3 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 3 Aug 2010 21:44:44 +0200 Subject: New feature: to exchange position of two objects (bug #171944) Fixed bugs: - https://launchpad.net/bugs/171944 (bzr r9681) --- src/ui/dialog/align-and-distribute.cpp | 165 +++++++++++++++++++++++++++++---- src/ui/dialog/align-and-distribute.h | 15 ++- src/ui/icon-names.h | 6 ++ 3 files changed, 167 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index a75a8d68d..048c46a20 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -518,8 +518,8 @@ public: guint row, guint column, AlignAndDistribute &dialog) : - Action(id, tiptext, row, column + 4, - dialog.graphLayout_table(), dialog.tooltips(), dialog) + Action(id, tiptext, row, column, + dialog.rearrange_table(), dialog.tooltips(), dialog) {} private : @@ -542,6 +542,101 @@ private : } }; +class ActionExchangePositions : public Action { +public: + enum SortOrder { + None, + ZOrder, + Clockwise + }; + + ActionExchangePositions(Glib::ustring const &id, + Glib::ustring const &tiptext, + guint row, + guint column, + AlignAndDistribute &dialog, SortOrder order = None) : + Action(id, tiptext, row, column, + dialog.rearrange_table(), dialog.tooltips(), dialog), + sortOrder(order) + {}; + + +private : + const SortOrder sortOrder; + static boost::optional center; + + static bool sort_compare(const SPItem * a,const SPItem * b) { + if (a == NULL) return false; + if (b == NULL) return true; + if (center) { + Geom::Point point_a = a->getCenter() - (*center); + Geom::Point point_b = b->getCenter() - (*center); + // First criteria: Sort according to the angle to the center point + double angle_a = atan2(double(point_a[Geom::Y]), double(point_a[Geom::X])); + double angle_b = atan2(double(point_b[Geom::Y]), double(point_b[Geom::X])); + if (angle_a != angle_b) return (angle_a < angle_b); + // Second criteria: Sort according to the distance the center point + Geom::Coord length_a = point_a.length(); + Geom::Coord length_b = point_b.length(); + if (length_a != length_b) return (length_a > length_b); + } + // Last criteria: Sort according to the z-coordinate + return (a->isSiblingOf(b)); + } + + virtual void on_button_click() + { + SPDesktop *desktop = _dialog.getDesktop(); + if (!desktop) return; + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + if (!selection) return; + + using Inkscape::Util::GSListConstIterator; + std::list selected; + selected.insert >(selected.end(), selection->itemList(), NULL); + if (selected.empty()) return; + + //Check 2 or more selected objects + if (selected.size() < 2) return; + + // see comment in ActionAlign above + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); + prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); + + // sort the list + if (sortOrder != None) { + if (sortOrder == Clockwise) { + center = selection->center(); + } else { // sorting by ZOrder is outomatically done by not setting the center + center.reset(); + } + selected.sort(ActionExchangePositions::sort_compare); + } + std::list::iterator it(selected.begin()); + Geom::Point p1 = (*it)->getCenter(); + for (++it ;it != selected.end(); ++it) + { + Geom::Point p2 = (*it)->getCenter(); + Geom::Point delta = p1 - p2; + sp_item_move_rel((*it),Geom::Translate(delta[Geom::X],delta[Geom::Y] )); + p1 = p2; + } + Geom::Point p2 = selected.front()->getCenter(); + Geom::Point delta = p1 - p2; + sp_item_move_rel(selected.front(),Geom::Translate(delta[Geom::X],delta[Geom::Y] )); + + // restore compensation setting + prefs->setInt("/options/clonecompensation/value", saved_compensation); + + sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, + _("Exchange Positions")); + } +}; +// instantiae the private static member +boost::optional ActionExchangePositions::center; + class ActionUnclump : public Action { public : ActionUnclump(const Glib::ustring &id, @@ -550,7 +645,7 @@ public : guint column, AlignAndDistribute &dialog): Action(id, tiptext, row, column, - dialog.distribute_table(), dialog.tooltips(), dialog) + dialog.rearrange_table(), dialog.tooltips(), dialog) {} private : @@ -581,7 +676,7 @@ public : guint column, AlignAndDistribute &dialog): Action(id, tiptext, row, column, - dialog.distribute_table(), dialog.tooltips(), dialog) + dialog.rearrange_table(), dialog.tooltips(), dialog) {} private : @@ -792,13 +887,13 @@ AlignAndDistribute::AlignAndDistribute() randomize_bbox(), _alignFrame(_("Align")), _distributeFrame(_("Distribute")), + _rearrangeFrame(_("Rearrange")), _removeOverlapFrame(_("Remove overlaps")), - _graphLayoutFrame(_("Connector network layout")), _nodesFrame(_("Nodes")), _alignTable(2, 6, true), - _distributeTable(3, 6, true), + _distributeTable(2, 6, true), + _rearrangeTable(1, 5, false), _removeOverlapTable(1, 5, false), - _graphLayoutTable(1, 5, false), _nodesTable(1, 4, true), _anchorLabel(_("Relative to: ")), _selgrpLabel(_("Treat selection as group: ")) @@ -882,22 +977,33 @@ AlignAndDistribute::AlignAndDistribute() _("Distribute baselines of texts vertically"), 1, 5, this->distribute_table(), Geom::Y, true); + // Rearrange + //Graph Layout + addGraphLayoutButton(INKSCAPE_ICON_DISTRIBUTE_GRAPH, + _("Nicely arrange selected connector network"), + 0, 0); + addExchangePositionsButton(INKSCAPE_ICON_EXCHANGE_POSITIONS, + _("Exchange positions of selected objects - selection order"), + 0, 1); + addExchangePositionsByZOrderButton(INKSCAPE_ICON_EXCHANGE_POSITIONS_ZORDER, + _("Exchange positions of selected objects - stacking order"), + 0, 2); + addExchangePositionsClockwiseButton(INKSCAPE_ICON_EXCHANGE_POSITIONS_CLOCKWISE, + _("Exchange positions of selected objects - clockwise rotate"), + 0, 3); + //Randomize & Unclump addRandomizeButton(INKSCAPE_ICON_DISTRIBUTE_RANDOMIZE, _("Randomize centers in both dimensions"), - 2, 2); + 0, 4); addUnclumpButton(INKSCAPE_ICON_DISTRIBUTE_UNCLUMP, _("Unclump objects: try to equalize edge-to-edge distances"), - 2, 4); + 0, 5); //Remove overlaps addRemoveOverlapsButton(INKSCAPE_ICON_DISTRIBUTE_REMOVE_OVERLAPS, _("Move objects as little as possible so that their bounding boxes do not overlap"), 0, 0); - //Graph Layout - addGraphLayoutButton(INKSCAPE_ICON_DISTRIBUTE_GRAPH, - _("Nicely arrange selected connector network"), - 0, 0); //Node Mode buttons // NOTE: "align nodes vertically" means "move nodes vertically until they align on a common @@ -943,8 +1049,8 @@ AlignAndDistribute::AlignAndDistribute() _alignFrame.add(_alignBox); _distributeFrame.add(_distributeTable); + _rearrangeFrame.add(_rearrangeTable); _removeOverlapFrame.add(_removeOverlapTable); - _graphLayoutFrame.add(_graphLayoutTable); _nodesFrame.add(_nodesTable); Gtk::Box *contents = _getContents(); @@ -954,8 +1060,8 @@ AlignAndDistribute::AlignAndDistribute() contents->pack_start(_alignFrame, true, true); contents->pack_start(_distributeFrame, true, true); + contents->pack_start(_rearrangeFrame, true, true); contents->pack_start(_removeOverlapFrame, true, true); - contents->pack_start(_graphLayoutFrame, true, true); contents->pack_start(_nodesFrame, true, true); //Connect to the global tool change signal @@ -1010,8 +1116,8 @@ void AlignAndDistribute::setMode(bool nodeEdit) ((_alignFrame).*(mSel))(); ((_distributeFrame).*(mSel))(); + ((_rearrangeFrame).*(mSel))(); ((_removeOverlapFrame).*(mSel))(); - ((_graphLayoutFrame).*(mSel))(); ((_nodesFrame).*(mNode))(); } @@ -1063,6 +1169,33 @@ void AlignAndDistribute::addGraphLayoutButton(const Glib::ustring &id, const Gli ); } +void AlignAndDistribute::addExchangePositionsButton(const Glib::ustring &id, const Glib::ustring tiptext, + guint row, guint col) +{ + _actionList.push_back( + new ActionExchangePositions( + id, tiptext, row, col, *this) + ); +} + +void AlignAndDistribute::addExchangePositionsByZOrderButton(const Glib::ustring &id, const Glib::ustring tiptext, + guint row, guint col) +{ + _actionList.push_back( + new ActionExchangePositions( + id, tiptext, row, col, *this, ActionExchangePositions::ZOrder) + ); +} + +void AlignAndDistribute::addExchangePositionsClockwiseButton(const Glib::ustring &id, const Glib::ustring tiptext, + guint row, guint col) +{ + _actionList.push_back( + new ActionExchangePositions( + id, tiptext, row, col, *this, ActionExchangePositions::Clockwise) + ); +} + void AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col) { diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index 297b3d2a1..f55998385 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -55,8 +55,8 @@ public: Gtk::Table &align_table(){return _alignTable;} Gtk::Table &distribute_table(){return _distributeTable;} + Gtk::Table &rearrange_table(){return _rearrangeTable;} Gtk::Table &removeOverlap_table(){return _removeOverlapTable;} - Gtk::Table &graphLayout_table(){return _graphLayoutTable;} Gtk::Table &nodes_table(){return _nodesTable;} Gtk::Tooltips &tooltips(){return _tooltips;} @@ -82,6 +82,15 @@ protected: void addGraphLayoutButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col); + void addExchangePositionsButton(const Glib::ustring &id, + const Glib::ustring tiptext, + guint row, guint col); + void addExchangePositionsByZOrderButton(const Glib::ustring &id, + const Glib::ustring tiptext, + guint row, guint col); + void addExchangePositionsClockwiseButton(const Glib::ustring &id, + const Glib::ustring tiptext, + guint row, guint col); void addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col); void addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext, @@ -90,8 +99,8 @@ protected: guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute); std::list _actionList; - Gtk::Frame _alignFrame, _distributeFrame, _removeOverlapFrame, _graphLayoutFrame, _nodesFrame; - Gtk::Table _alignTable, _distributeTable, _removeOverlapTable, _graphLayoutTable, _nodesTable; + Gtk::Frame _alignFrame, _distributeFrame, _rearrangeFrame, _removeOverlapFrame, _nodesFrame; + Gtk::Table _alignTable, _distributeTable, _rearrangeTable, _removeOverlapTable, _nodesTable; Gtk::HBox _anchorBox; Gtk::HBox _selgrpBox; Gtk::VBox _alignBox; diff --git a/src/ui/icon-names.h b/src/ui/icon-names.h index d36d4a41a..92fd86a48 100644 --- a/src/ui/icon-names.h +++ b/src/ui/icon-names.h @@ -206,6 +206,12 @@ "edit-select-original" #define INKSCAPE_ICON_EDIT_UNDO_HISTORY \ "edit-undo-history" +#define INKSCAPE_ICON_EXCHANGE_POSITIONS \ + "exchange-positions" +#define INKSCAPE_ICON_EXCHANGE_POSITIONS_ZORDER \ + "exchange-positions-zorder" +#define INKSCAPE_ICON_EXCHANGE_POSITIONS_CLOCKWISE \ + "exchange-positions-clockwise" #define INKSCAPE_ICON_FILL_RULE_EVEN_ODD \ "fill-rule-even-odd" #define INKSCAPE_ICON_FILL_RULE_NONZERO \ -- cgit v1.2.3 From db0d4942a39db535558093ccdce6d01bfda4ec33 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Wed, 4 Aug 2010 08:31:30 +0200 Subject: Small fix to emf filter that makes it build using TDM's mingw 4.5.0 (bzr r9682) --- src/extension/internal/emf-win32-inout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 9d25f3a7f..0e283b909 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -733,7 +733,7 @@ assert_empty_path(PEMF_CALLBACK_DATA d, const char * /*fun*/) static int CALLBACK -myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR, int /*nObj*/, LPARAM lpData) +myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const *lpEMFR, int /*nObj*/, LPARAM lpData) { PEMF_CALLBACK_DATA d; SVGOStringStream tmp_outsvg; -- cgit v1.2.3 From 97893dd02e0f080b39cebcf2df9f532978e7ca06 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Wed, 4 Aug 2010 08:59:03 +0200 Subject: Fix for subtle bug in parsing export area, found by Vaughn Spurlin using Coverity (bzr r9683) --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 9f7bc9ad3..78b66d847 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1345,7 +1345,7 @@ sp_do_export_png(SPDocument *doc) if (sp_export_area) { /* Try to parse area (given in SVG pixels) */ gdouble x0,y0,x1,y1; - if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &y1) == 4) { + if (sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &y1) != 4) { g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area); return; } -- cgit v1.2.3 From 46d8863ef81a9614385298c6ccd2664402aafef0 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Wed, 4 Aug 2010 11:25:00 +0200 Subject: Added reinterpret_cast to work around a difference of opinion between gcc versions. (bzr r9684) --- src/extension/internal/emf-win32-inout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 0e283b909..98b5f0114 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -2353,7 +2353,8 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) d.pDesc[lstrlen(d.pDesc)] = '#'; } - EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL); + // This ugly reinterpret_cast is to prevent old versions of gcc from whining about a mismatch in the const-ness of the arguments + EnumEnhMetaFile(NULL, hemf, reinterpret_cast(myEnhMetaFileProc), (LPVOID) &d, NULL); DeleteEnhMetaFile(hemf); } else { -- cgit v1.2.3 From 501fa25940bc7f0f6f67a69284996974efdb9734 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Wed, 4 Aug 2010 14:51:48 +0200 Subject: Fix to background handling that avoids both duplication and aliasing as much as possible. (bzr r9685) --- src/display/nr-arena-item.cpp | 37 +++++-------- src/display/nr-arena-item.h | 2 +- src/display/nr-filter-slot.cpp | 119 +++++++++++++++++------------------------ src/display/nr-filter-slot.h | 18 ++++--- 4 files changed, 75 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index b80df7273..3b8dceb93 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -323,8 +323,11 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area item->state); #ifdef NR_ARENA_ITEM_VERBOSE - printf ("Invoke render %p: %d %d - %d %d\n", item, area->x0, area->y0, - area->x1, area->y1); + g_message ("Invoke render %p on %p: %d %d - %d %d, %d %d - %d %d", item, pb, + area->x0, area->y0, + area->x1, area->y1, + item->drawbox.x0, item->drawbox.y0, + item->drawbox.x1, item->drawbox.y1); #endif /* If we are invisible, just return successfully */ @@ -415,8 +418,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area /* Determine, whether we need temporary buffer */ if (item->clip || item->mask || ((item->opacity != 255) && !item->render_opacity) - || (item->filter && filter) || item->background_new - || (item->parent && item->parent->background_pb)) { + || (item->filter && filter) || item->background_new) { /* Setup and render item buffer */ NRPixBlock ipb; @@ -432,8 +434,7 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area /* If background access is used, save the pixblock address. * This address is set to NULL at the end of this block */ - if (item->background_new || - (item->parent && item->parent->background_pb)) { + if (item->background_new) { item->background_pb = &ipb; } @@ -859,29 +860,15 @@ nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox) /** Returns a background image for use with filter effects. */ NRPixBlock * -nr_arena_item_get_background (NRArenaItem const *item, int depth) +nr_arena_item_get_background (NRArenaItem const *item) { - NRPixBlock *pb; - if (!item->background_pb) - return NULL; if (item->background_new) { - pb = new NRPixBlock (); - nr_pixblock_setup_fast (pb, item->background_pb->mode, - item->background_pb->area.x0, - item->background_pb->area.y0, - item->background_pb->area.x1, - item->background_pb->area.y1, true); - if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) // allocation failed - return NULL; + return item->background_pb; } else if (item->parent) { - pb = nr_arena_item_get_background (item->parent, depth + 1); - } else + return nr_arena_item_get_background (item->parent); + } else { return NULL; - - if (depth > 0) - nr_blit_pixblock_pixblock (pb, item->background_pb); - - return pb; + } } /* Helpers */ diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h index 2faa7d2d0..e92fb1313 100644 --- a/src/display/nr-arena-item.h +++ b/src/display/nr-arena-item.h @@ -181,7 +181,7 @@ void nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask); void nr_arena_item_set_order (NRArenaItem *item, int order); void nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect &bbox); -NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item, int depth = 0); +NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item); /* Helpers */ diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index 7df9ab979..354b31b4d 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -70,26 +70,22 @@ FilterSlot::FilterSlot(int slots, NRArenaItem const *item) blurquality(BLUR_QUALITY_BEST), _arena_item(item) { - _slot_count = ((slots > 0) ? slots : 2); - _slot = new NRPixBlock*[_slot_count]; - _slot_number = new int[_slot_count]; - - for (int i = 0 ; i < _slot_count ; i++) { - _slot[i] = NULL; - _slot_number[i] = NR_FILTER_SLOT_NOT_SET; - } + _slots.reserve((slots > 0) ? slots : 2); } FilterSlot::~FilterSlot() { - for (int i = 0 ; i < _slot_count ; i++) { - if (_slot[i]) { - nr_pixblock_release(_slot[i]); - delete _slot[i]; + for (unsigned int i = 0 ; i < _slots.size() ; i++) { + if (_slots[i].owned) { + nr_pixblock_release(_slots[i].pb); + delete _slots[i].pb; } } - delete[] _slot; - delete[] _slot_number; +} + +FilterSlot::slot_entry_t::~slot_entry_t() +{ + // It's a bad idea to destruct pixblocks here, as this will also be called upon resizing _slots } NRPixBlock *FilterSlot::get(int slot_nr) @@ -99,7 +95,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) /* If we didn't have the specified image, but we could create it * from the other information we have, let's do that */ - if (_slot[index] == NULL + if (_slots[index].pb == NULL && (slot_nr == NR_FILTER_SOURCEALPHA || slot_nr == NR_FILTER_BACKGROUNDIMAGE || slot_nr == NR_FILTER_BACKGROUNDALPHA @@ -112,7 +108,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) pb = nr_arena_item_get_background(_arena_item); if (pb) { pb->empty = false; - this->set(NR_FILTER_BACKGROUNDIMAGE, pb); + this->set(NR_FILTER_BACKGROUNDIMAGE, pb, false); } else { NRPixBlock *source = this->get(NR_FILTER_SOURCEGRAPHIC); pb = new NRPixBlock(); @@ -145,12 +141,12 @@ NRPixBlock *FilterSlot::get(int slot_nr) } } - if (_slot[index]) { - _slot[index]->empty = false; + if (_slots[index].pb) { + _slots[index].pb->empty = false; } - assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr); - return _slot[index]; + assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr); + return _slots[index].pb; } void FilterSlot::get_final(int slot_nr, NRPixBlock *result) { @@ -175,7 +171,7 @@ void FilterSlot::get_final(int slot_nr, NRPixBlock *result) { } } -void FilterSlot::set(int slot_nr, NRPixBlock *pb) +void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership) { /* Unnamed slot is for saving filter primitive results, when parameter * 'result' is not set. Only the filter immediately after this one @@ -189,7 +185,7 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb) assert(index >= 0); // Unnamed slot is only for Inkscape::Filters::FilterSlot internal use. assert(slot_nr != NR_FILTER_UNNAMED_SLOT); - assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr); + assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr); if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) { Geom::Matrix trans = units.get_matrix_display2pb(); @@ -225,6 +221,10 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb) * is not too high, but can get thousands of pixels wide. * Rotate this 45 degrees -> _huge_ image */ g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (transform)"); + if (takeOwnership) { + nr_pixblock_release(pb); + delete pb; + } return; } if (filterquality == FILTER_QUALITY_BEST) { @@ -232,8 +232,11 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb) } else { NR::transform_nearest(trans_pb, pb, trans); } - nr_pixblock_release(pb); - delete pb; + if (takeOwnership) { + nr_pixblock_release(pb); + delete pb; + } + takeOwnership = true; pb = trans_pb; } else if (fabs(trans[0] - 1) > 1e-6 || fabs(trans[3] - 1) > 1e-6) { NRPixBlock *trans_pb = new NRPixBlock; @@ -255,31 +258,34 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb) min_x, min_y, max_x, max_y, true); if (trans_pb->size != NR_PIXBLOCK_SIZE_TINY && trans_pb->data.px == NULL) { g_warning("Memory allocation failed in Inkscape::Filters::FilterSlot::set (scaling)"); + if (takeOwnership) { + nr_pixblock_release(pb); + delete pb; + } return; } NR::scale_bicubic(trans_pb, pb, trans); - nr_pixblock_release(pb); - delete pb; + if (takeOwnership) { + nr_pixblock_release(pb); + delete pb; + } + takeOwnership = true; pb = trans_pb; } } - if(_slot[index]) { - nr_pixblock_release(_slot[index]); - delete _slot[index]; + if(_slots[index].owned) { + nr_pixblock_release(_slots[index].pb); + delete _slots[index].pb; } - _slot[index] = pb; + _slots[index].pb = pb; + _slots[index].owned = takeOwnership; _last_out = index; } int FilterSlot::get_slot_count() { - int seek = _slot_count; - do { - seek--; - } while (!_slot[seek] && _slot_number[seek] == NR_FILTER_SLOT_NOT_SET); - - return seek + 1; + return _slots.size(); } NRArenaItem const* FilterSlot::get_arenaitem() @@ -299,47 +305,22 @@ int FilterSlot::_get_index(int slot_nr) slot_nr == NR_FILTER_STROKEPAINT || slot_nr == NR_FILTER_UNNAMED_SLOT); - int index = -1; if (slot_nr == NR_FILTER_SLOT_NOT_SET) { return _last_out; } + /* Search, if the slot already exists */ - for (int i = 0 ; i < _slot_count ; i++) { - if (_slot_number[i] == slot_nr) { - index = i; - break; + for (int i = 0 ; i < (int)_slots.size() ; i++) { + if (_slots[i].number == slot_nr) { + return i; } } /* If the slot doesn't already exist, create it */ - if (index == -1) { - int seek = _slot_count; - do { - seek--; - } while ((seek >= 0) && (_slot_number[seek] == NR_FILTER_SLOT_NOT_SET)); - /* If there is no space for more slots, create more space */ - if (seek == _slot_count - 1) { - NRPixBlock **new_slot = new NRPixBlock*[_slot_count * 2]; - int *new_number = new int[_slot_count * 2]; - for (int i = 0 ; i < _slot_count ; i++) { - new_slot[i] = _slot[i]; - new_number[i] = _slot_number[i]; - } - for (int i = _slot_count ; i < _slot_count * 2 ; i++) { - new_slot[i] = NULL; - new_number[i] = NR_FILTER_SLOT_NOT_SET; - } - delete[] _slot; - delete[] _slot_number; - _slot = new_slot; - _slot_number = new_number; - _slot_count *= 2; - } - /* Now that there is space, create the slot */ - _slot_number[seek + 1] = slot_nr; - index = seek + 1; - } - return index; + slot_entry_t entry; + entry.number = slot_nr; + _slots.push_back(entry); + return (int)_slots.size()-1; } void FilterSlot::set_units(FilterUnits const &units) { diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h index 8d7a82d2d..a12d75a26 100644 --- a/src/display/nr-filter-slot.h +++ b/src/display/nr-filter-slot.h @@ -17,6 +17,7 @@ #include "libnr/nr-pixblock.h" #include "display/nr-filter-types.h" #include "display/nr-filter-units.h" +#include struct NRArenaItem; @@ -59,11 +60,11 @@ public: * If there was a pixblock already assigned with this slot, * that pixblock is destroyed. * Pixblocks passed to this function should be considered - * managed by this FilterSlot object. + * managed by this FilterSlot object if takeOwnership==true. * Pixblocks passed to this function should be reserved with - * c++ -style new-operator. + * c++ -style new-operator (if managed by FilterSlot). */ - void set(int slot, NRPixBlock *pb); + void set(int slot, NRPixBlock *pb, bool takeOwnership=true); /** Returns the number of slots in use. */ int get_slot_count(); @@ -84,9 +85,14 @@ public: int get_blurquality(void); private: - NRPixBlock **_slot; - int *_slot_number; - int _slot_count; + struct slot_entry_t { + NRPixBlock* pb; + int number; + bool owned; + slot_entry_t() : pb(0), number(NR_FILTER_SLOT_NOT_SET), owned(false) {} + ~slot_entry_t(); + }; + std::vector _slots; int _last_out; -- cgit v1.2.3 From aa39e018948d363286e87f6c038f14bb7b9ea178 Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Wed, 4 Aug 2010 17:39:04 +0200 Subject: A modification of pixops_mix that allows for input images that extend beyond the output image (bzr r9686) --- src/display/nr-filter-pixops.h | 126 +++++++++++++---------------------------- 1 file changed, 39 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/display/nr-filter-pixops.h b/src/display/nr-filter-pixops.h index b2db7067a..22b1a55cd 100644 --- a/src/display/nr-filter-pixops.h +++ b/src/display/nr-filter-pixops.h @@ -2,6 +2,7 @@ #define __NR_FILTER_PIXOPS_H__ #include "libnr/nr-pixblock.h" +#include /* * Per-pixel image manipulation functions. @@ -41,96 +42,47 @@ void pixops_mix(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) { unsigned char *out_data = NR_PIXBLOCK_PX(&out); unsigned char zero_rgba[4] = {0, 0, 0, 0}; - if (in1.area.y0 < in2.area.y0) { - // in1 begins before in2 on y-axis - for (int y = in1.area.y0 ; y < in2.area.y0 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in1.area.y0) * in1.rs; - for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } - } else if (in1.area.y0 > in2.area.y0) { - // in2 begins before in1 on y-axis - for (int y = in2.area.y0 ; y < in1.area.y0 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in2.area.y0) * in2.rs; - for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in_line + 4 * (x - in2.area.x0)); - } - } - } - - for (int y = std::max(in1.area.y0, in2.area.y0) ; - y < std::min(in1.area.y1, in2.area.y1) ; ++y) { - int out_line = (y - out.area.y0) * out.rs; - int in1_line = (y - in1.area.y0) * in1.rs; - int in2_line = (y - in2.area.y0) * in2.rs; + // Possible scenarios (omitting cases where an interval is empty and those which are the same by interchanging 1 and 2): + // 01020, 01320, 01310 (no overlap, partial overlap, full overlap) + int out_y0 = out.area.y0; + int out_y1 = std::max(out.area.y1,out_y0); // Enforce sanity + int in1_y0 = std::min(std::max(in1.area.y0,out_y0),out_y1); + int in2_y0 = std::min(std::max(in2.area.y0,out_y0),out_y1); + int in1_y1 = std::min(std::max(in1.area.y1,in1_y0),out_y1); + int in2_y1 = std::min(std::max(in2.area.y1,in2_y0),out_y1); + int min_in_y0 = std::min(in1_y0,in2_y0); + int max_in_y0 = std::max(in1_y0,in2_y0); + int min_in_y1 = std::min(in1_y1,in2_y1); + int max_in_y1 = std::max(in1_y1,in2_y1); + int const yBound[6] = {out_y0, min_in_y0, std::min(max_in_y0,min_in_y1), std::max(max_in_y0,min_in_y1), max_in_y1, out_y1}; + bool const in1_zero_y[5] = {true, in1_y0>yBound[1], in1_y0>yBound[2] || in1_y1<=yBound[2], in1_y1<=yBound[3], true}; + bool const in2_zero_y[5] = {true, in2_y0>yBound[1], in2_y0>yBound[2] || in2_y1<=yBound[2], in2_y1<=yBound[3], true}; - if (in1.area.x0 < in2.area.x0) { - // in1 begins before in2 on x-axis - for (int x = in1.area.x0 ; x < in2.area.x0 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } else if (in1.area.x0 > in2.area.x0) { - // in2 begins before in1 on x-axis - for (int x = in2.area.x0 ; x < in1.area.x0 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - } + int out_x0 = out.area.x0; + int out_x1 = std::max(out.area.x1,out_x0); + int in1_x0 = std::min(std::max(in1.area.x0,out_x0),out_x1); + int in2_x0 = std::min(std::max(in2.area.x0,out_x0),out_x1); + int in1_x1 = std::min(std::max(in1.area.x1,in1_x0),out_x1); + int in2_x1 = std::min(std::max(in2.area.x1,in2_x0),out_x1); + int min_in_x0 = std::min(in1_x0,in2_x0); + int max_in_x0 = std::max(in1_x0,in2_x0); + int min_in_x1 = std::min(in1_x1,in2_x1); + int max_in_x1 = std::max(in1_x1,in2_x1); + int const xBound[6] = {out_x0, min_in_x0, std::min(max_in_x0,min_in_x1), std::max(max_in_x0,min_in_x1), max_in_x1, out_x1}; + bool const in1_zero_x[5] = {true, in1_x0>xBound[1], in1_x0>xBound[2] || in1_x1<=xBound[2], in1_x1<=xBound[3], true}; + bool const in2_zero_x[5] = {true, in2_x0>xBound[1], in2_x0>xBound[2] || in2_x1<=xBound[2], in2_x1<=xBound[3], true}; - for (int x = std::max(in1.area.x0, in2.area.x0) ; - x < std::min(in1.area.x1, in2.area.x1) ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - - if (in1.area.x1 > in2.area.x1) { - // in1 ends after in2 on x-axis - for (int x = in2.area.x1 ; x < in1.area.x1 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in1_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } else if (in1.area.x1 < in2.area.x1) { - // in2 ends after in1 on x-axis - for (int x = in1.area.x1 ; x < in2.area.x1 ; ++x) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in2_line + 4 * (x - in2.area.x0)); - } - } - } - - if (in1.area.y1 > in2.area.y1) { - // in1 ends after in2 on y-axis - for (int y = in2.area.y1 ; y < in1.area.y1 ; y++) { - int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in1.area.y0) * in1.rs; - for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - in1_data + in_line + 4 * (x - in1.area.x0), - zero_rgba); - } - } - } else if (in1.area.y1 < in2.area.y1) { - // in2 ends after in1 on y-axis - for (int y = in1.area.y1 ; y < in2.area.y1 ; y++) { + for (int yr = 0 ; yr < 5 ; yr++) { + for(int y = yBound[yr] ; y < yBound[yr+1] ; y++) { int out_line = (y - out.area.y0) * out.rs; - int in_line = (y - in2.area.y0) * in2.rs; - for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) { - blend(out_data + out_line + 4 * (x - out.area.x0), - zero_rgba, - in2_data + in_line + 4 * (x - in2.area.x0)); + int in1_line = (y - in1.area.y0) * in1.rs; + int in2_line = (y - in2.area.y0) * in2.rs; + for (int xr = 0 ; xr < 5 ; xr++) { + for(int x = xBound[xr] ; x < xBound[xr+1] ; x++) { + blend(out_data + out_line + 4 * (x - out.area.x0), + (in1_zero_x[xr]||in1_zero_y[yr]) ? zero_rgba : (in1_data + in1_line + 4 * (x - in1.area.x0)), + (in2_zero_x[xr]||in2_zero_y[yr]) ? zero_rgba : (in2_data + in2_line + 4 * (x - in2.area.x0))); + } } } } -- cgit v1.2.3 From b718a4a04f78125813e2a728b1b0b23e31676649 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 6 Aug 2010 01:16:47 -0700 Subject: Corects delete/delete[] issue. Fixes bug #613723. Fixed bugs: - https://launchpad.net/bugs/613723 (bzr r9691) --- src/trace/quantize.cpp | 58 +++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/trace/quantize.cpp b/src/trace/quantize.cpp index 8acfe0c34..2db1bbf34 100644 --- a/src/trace/quantize.cpp +++ b/src/trace/quantize.cpp @@ -545,44 +545,48 @@ IndexedMap *rgbMapQuantize(RgbMap *rgbmap, int ncolor) assert(rgbmap); assert(ncolor > 0); + IndexedMap *newmap = 0; + pool pool; - Ocnode *tree; + Ocnode *tree = 0; try { - tree = octreeBuild(&pool, rgbmap, ncolor); + tree = octreeBuild(&pool, rgbmap, ncolor); } - catch (std::bad_alloc& ex) { - return NULL; //should do smthg else? + catch (std::bad_alloc &ex) { + //should do smthg else? } - RGB *rgbpal = new RGB[ncolor]; - int indexes = 0; - octreeIndex(tree, rgbpal, &indexes); - - octreeDelete(&pool, tree); + if ( tree ) { + RGB *rgbpal = new RGB[ncolor]; + int indexes = 0; + octreeIndex(tree, rgbpal, &indexes); - // stacking with increasing contrasts - qsort((void *)rgbpal, indexes, sizeof(RGB), compRGB); + octreeDelete(&pool, tree); - // make the new map - IndexedMap *newmap = IndexedMapCreate(rgbmap->width, rgbmap->height); - if (!newmap) { delete rgbpal; return NULL; } + // stacking with increasing contrasts + qsort((void *)rgbpal, indexes, sizeof(RGB), compRGB); - // fill in the color lookup table - for (int i = 0; i < indexes; i++) newmap->clut[i] = rgbpal[i]; - newmap->nrColors = indexes; - - // fill in new map pixels - for (int y = 0; y < rgbmap->height; y++) - { - for (int x = 0; x < rgbmap->width; x++) - { - RGB rgb = rgbmap->getPixel(rgbmap, x, y); - int index = findRGB(rgbpal, ncolor, rgb); - newmap->setPixel(newmap, x, y, index); + // make the new map + newmap = IndexedMapCreate(rgbmap->width, rgbmap->height); + if (newmap) { + // fill in the color lookup table + for (int i = 0; i < indexes; i++) { + newmap->clut[i] = rgbpal[i]; + } + newmap->nrColors = indexes; + + // fill in new map pixels + for (int y = 0; y < rgbmap->height; y++) { + for (int x = 0; x < rgbmap->width; x++) { + RGB rgb = rgbmap->getPixel(rgbmap, x, y); + int index = findRGB(rgbpal, ncolor, rgb); + newmap->setPixel(newmap, x, y, index); + } } } + delete[] rgbpal; + } - delete rgbpal; return newmap; } -- cgit v1.2.3 From a83da58db0ad8e9a0b559a9fd5a55f40e247f38e Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 7 Aug 2010 10:15:18 +0200 Subject: Add a constrained snap method that takes multiple constraints. This reduces the code repetitiveness in the node tool (bzr r9692) --- src/snap.cpp | 62 +++++++++++++++++++++++++++ src/snap.h | 4 ++ src/snapped-point.h | 4 +- src/ui/tool/node.cpp | 117 +++++++-------------------------------------------- 4 files changed, 85 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/snap.cpp b/src/snap.cpp index 810e2dd8b..bcacb81e2 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -389,6 +389,68 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint return no_snap; } +/* See the documentation for constrainedSnap() directly above for more details. + * The difference is that multipleConstrainedSnaps() will take a list of constraints instead of a single one, + * and will try to snap the SnapCandidatePoint to all of the provided constraints and see which one fits best + * \param p Source point to be snapped + * \param constraints List of directions or lines along which snapping must occur + * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation + */ + + +Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandidatePoint const &p, + std::vector const &constraints, + Geom::OptRect const &bbox_to_snap) const +{ + + Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(p.getPoint(), p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, NR_HUGE, 0, false, true, false); + if (constraints.size() == 0) { + return no_snap; + } + + SnappedConstraints sc; + SnapperList const snappers = getSnappers(); + std::vector projections; + bool snapping_is_futile = !someSnapperMightSnap(); + + // Iterate over the constraints + for (std::vector::const_iterator c = constraints.begin(); c != constraints.end(); c++) { + // Project the mouse pointer onto the constraint; In case we don't snap then we will + // return the projection onto the constraint, such that the constraint is always enforced + Geom::Point pp = (*c).projection(p.getPoint()); + projections.push_back(pp); + // Try to snap to the constraint + if (!snapping_is_futile) { + for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { + (*i)->constrainedSnap(sc, p, bbox_to_snap, *c, &_items_to_ignore); + } + } + } + + Inkscape::SnappedPoint result = findBestSnap(p, sc, true); + + if (result.getSnapped()) { + // only change the snap indicator if we really snapped to something + if (_snapindicator) { + _desktop->snapindicator->set_new_snaptarget(result); + } + return result; + } + + // So we didn't snap, but we still need to return a point on one of the constraints + // Find out which of the constraints yielded the closest projection of point p + no_snap.setPoint(projections.front()); + for (std::vector::iterator pp = projections.begin(); pp != projections.end(); pp++) { + if (pp != projections.begin()) { + if (Geom::L2(*pp - p.getPoint()) < Geom::L2(no_snap.getPoint() - p.getPoint())) { + no_snap.setPoint(*pp); + } + } + } + + return no_snap; +} + /** * \brief Try to snap a point of a guide to another guide or to a node * diff --git a/src/snap.h b/src/snap.h index f740f3c62..c85c51963 100644 --- a/src/snap.h +++ b/src/snap.h @@ -129,6 +129,10 @@ public: Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Inkscape::SnappedPoint multipleConstrainedSnaps(Inkscape::SnapCandidatePoint const &p, + std::vector const &constraints, + Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const; void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const; diff --git a/src/snapped-point.h b/src/snapped-point.h index 05e954e1e..4b4882ee4 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -54,7 +54,9 @@ public: * has occurred; A check should be implemented in the calling code * to check for snapping. Use this method only when really needed, e.g. * when the calling code is trying to snap multiple points and must - * determine itself which point is most appropriate + * determine itself which point is most appropriate, or when doing a + * constrainedSnap that also enforces projection onto the constraint (in + * which case you need the new point anyway, even if we didn't snap) */ Geom::Point getPoint() const {return _point;} void setPoint(Geom::Point const &p) {_point = p;} diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 69c09602e..a8582ccc5 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -270,9 +270,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) _parent->position() - node_away->position()); Inkscape::SnappedPoint p; p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl); - if (p.getSnapped()) { - p.getPoint(new_pos); - } + new_pos = p.getPoint(); } else { sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE); } @@ -945,7 +943,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) // For a note on how snapping is implemented in Inkscape, see snap.h. SnapManager &sm = _desktop->namedview->snap_manager; bool snap = sm.someSnapperMightSnap(); - std::vector unselected; + Inkscape::SnappedPoint sp; if (snap) { /* setup * TODO We are doing this every time a snap happens. It should once be done only once @@ -955,6 +953,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) * TODO Snapping to unselected segments of selected paths doesn't work yet. */ // Build the list of unselected nodes. + std::vector unselected; typedef ControlPointSelection::Set Set; Set &nodes = _selection.allPoints(); for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) { @@ -964,32 +963,22 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) unselected.push_back(p); } } - sm.setupIgnoreSelection(_desktop, false, &unselected); + sm.setupIgnoreSelection(_desktop, true, &unselected); } if (held_control(*event)) { Geom::Point origin = _last_drag_origin(); - Inkscape::SnappedPoint fp, bp, fpp, bpp; + std::vector constraints; if (held_alt(*event)) { // with Ctrl+Alt, constrain to handle lines // project the new position onto a handle line that is closer; // also snap to perpendiculars of handle lines - // TODO: this code is repetitive to the point of sillyness. Find a way - // to express this concisely by modifying the semantics of snapping calls. - // During a non-snap invocation, we should call constrainedSnap() - // anyway, but it should just return the closest point matching the constraint - // rather than snapping to an object. There should be comparison - // operators defined for snap results, to simplify determining the best one, - // or the snapping calls should take a reference to a snapping result and - // replace it with the current result if it's better. - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int snaps = prefs->getIntLimited("/options/rotationsnapsperpi/value", 12, 1, 1000); double min_angle = M_PI / snaps; boost::optional front_point, back_point, fperp_point, bperp_point; - boost::optional line_front, line_back, line_fperp, line_bperp; if (_front.isDegenerate()) { if (_is_line_segment(this, _next())) front_point = _next()->position() - origin; @@ -1003,11 +992,11 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) back_point = _back.relativePos(); } if (front_point) { - line_front = Inkscape::Snapper::SnapConstraint(origin, *front_point); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *front_point)); fperp_point = Geom::rot90(*front_point); } if (back_point) { - line_back = Inkscape::Snapper::SnapConstraint(origin, *back_point); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *back_point)); bperp_point = Geom::rot90(*back_point); } // perpendiculars only snap when they are further than snap increment away @@ -1016,100 +1005,26 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) (fabs(Geom::angle_between(*fperp_point, *back_point)) > min_angle && fabs(Geom::angle_between(*fperp_point, *back_point)) < M_PI - min_angle))) { - line_fperp = Inkscape::Snapper::SnapConstraint(origin, *fperp_point); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *fperp_point)); } if (bperp_point && (!front_point || (fabs(Geom::angle_between(*bperp_point, *front_point)) > min_angle && fabs(Geom::angle_between(*bperp_point, *front_point)) < M_PI - min_angle))) { - line_bperp = Inkscape::Snapper::SnapConstraint(origin, *bperp_point); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *bperp_point)); } - // TODO: combine the snap and non-snap branches by modifying snap.h / snap.cpp - if (snap) { - if (line_front) { - fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, - _snapSourceType()), *line_front); - } - if (line_back) { - bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, - _snapSourceType()), *line_back); - } - if (line_fperp) { - fpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, - _snapSourceType()), *line_fperp); - } - if (line_bperp) { - bpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, - _snapSourceType()), *line_bperp); - } - } - if (fp.getSnapped() || bp.getSnapped() || fpp.getSnapped() || bpp.getSnapped()) { - if (fp.isOtherSnapBetter(bp, false)) { - fp = bp; - } - if (fp.isOtherSnapBetter(fpp, false)) { - fp = fpp; - } - if (fp.isOtherSnapBetter(bpp, false)) { - fp = bpp; - } - fp.getPoint(new_pos); - _desktop->snapindicator->set_new_snaptarget(fp); - } else { - boost::optional pos; - if (line_front) { - pos = line_front->projection(new_pos); - } - if (line_back) { - Geom::Point pos2 = line_back->projection(new_pos); - if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) - pos = pos2; - } - if (line_fperp) { - Geom::Point pos2 = line_fperp->projection(new_pos); - if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) - pos = pos2; - } - if (line_bperp) { - Geom::Point pos2 = line_bperp->projection(new_pos); - if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2))) - pos = pos2; - } - if (pos) { - new_pos = *pos; - } else { - new_pos = origin; - } - } + sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints); } else { // with Ctrl, constrain to axes - // TODO combine the two branches - if (snap) { - Inkscape::Snapper::SnapConstraint line_x(origin, Geom::Point(1, 0)); - Inkscape::Snapper::SnapConstraint line_y(origin, Geom::Point(0, 1)); - fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_x); - bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_y); - } - if (fp.getSnapped() || bp.getSnapped()) { - if (fp.isOtherSnapBetter(bp, false)) { - fp = bp; - } - fp.getPoint(new_pos); - _desktop->snapindicator->set_new_snaptarget(fp); - } else { - Geom::Point origin = _last_drag_origin(); - Geom::Point delta = new_pos - origin; - Geom::Dim2 d = (fabs(delta[Geom::X]) < fabs(delta[Geom::Y])) ? Geom::X : Geom::Y; - new_pos[d] = origin[d]; - } + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0))); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1))); + sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints); } + new_pos = sp.getPoint(); } else if (snap) { - Inkscape::SnappedPoint p = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType())); - if (p.getSnapped()) { - p.getPoint(new_pos); - _desktop->snapindicator->set_new_snaptarget(p); - } + sp = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType())); + new_pos = sp.getPoint(); } SelectableControlPoint::dragged(new_pos, event); -- cgit v1.2.3