summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile_insert2
-rw-r--r--src/desktop-style.cpp23
-rw-r--r--src/device-manager.cpp361
-rw-r--r--src/device-manager.h20
-rw-r--r--src/dialogs/CMakeLists.txt1
-rw-r--r--src/dialogs/Makefile_insert2
-rw-r--r--src/dialogs/export.cpp12
-rw-r--r--src/dialogs/input.cpp607
-rw-r--r--src/dialogs/input.h31
-rw-r--r--src/display/canvas-axonomgrid.cpp16
-rw-r--r--src/display/curve.cpp13
-rw-r--r--src/display/curve.h2
-rw-r--r--src/display/nr-arena-glyphs.cpp12
-rw-r--r--src/display/nr-arena-image.cpp16
-rw-r--r--src/display/nr-arena-shape.cpp33
-rw-r--r--src/display/nr-filter-displacement-map.cpp92
-rw-r--r--src/display/nr-filter-gaussian.cpp22
-rw-r--r--src/display/nr-filter.cpp8
-rw-r--r--src/display/pixblock-transform.cpp5
-rw-r--r--src/display/snap-indicator.cpp8
-rw-r--r--src/ege-select-one-action.cpp311
-rw-r--r--src/ege-select-one-action.h27
-rw-r--r--src/eraser-context.cpp2
-rw-r--r--src/extension/implementation/script.cpp250
-rw-r--r--src/extension/implementation/script.h24
-rw-r--r--src/extension/internal/bitmap/solarize.cpp4
-rw-r--r--src/extension/internal/cairo-render-context.cpp6
-rw-r--r--src/extension/internal/cairo-renderer.cpp4
-rw-r--r--src/extension/internal/filter/filter-file.cpp2
-rw-r--r--src/extension/internal/filter/filter.cpp2
-rw-r--r--src/extension/internal/grid.cpp38
-rw-r--r--src/extension/internal/javafx-out.cpp3
-rw-r--r--src/extension/internal/latex-text-renderer.cpp12
-rw-r--r--src/fill-or-stroke.h2
-rw-r--r--src/flood-context.cpp4
-rw-r--r--src/gradient-context.cpp2
-rw-r--r--src/ink-comboboxentry-action.cpp605
-rw-r--r--src/ink-comboboxentry-action.h86
-rw-r--r--src/inkscape.cpp4
-rw-r--r--src/io/sys.cpp904
-rw-r--r--src/libgdl/gdl-switcher.c2
-rw-r--r--src/libnr/Makefile_insert8
-rw-r--r--src/libnr/have_mmx.S47
-rw-r--r--src/libnr/nr-compose-transform.cpp118
-rw-r--r--src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S125
-rw-r--r--src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S231
-rw-r--r--src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S227
-rw-r--r--src/libnrtype/FontFactory.cpp242
-rw-r--r--src/libnrtype/FontFactory.h2
-rw-r--r--src/libnrtype/FontInstance.cpp801
-rw-r--r--src/libnrtype/Layout-TNG-Input.cpp21
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp21
-rw-r--r--src/main.cpp222
-rw-r--r--src/menus-skeleton.h2
-rw-r--r--src/object-snapper.cpp6
-rw-r--r--src/preferences-skeleton.h10
-rw-r--r--src/prefix.cpp348
-rw-r--r--src/prefix.h15
-rw-r--r--src/registrytool.cpp53
-rw-r--r--src/select-context.cpp2
-rw-r--r--src/selection-chemistry.cpp6
-rw-r--r--src/seltrans.cpp20
-rw-r--r--src/snap-candidate.h1
-rw-r--r--src/snap.cpp17
-rw-r--r--src/snapped-point.cpp9
-rw-r--r--src/sp-filter.cpp18
-rw-r--r--src/sp-font-face.cpp106
-rw-r--r--src/sp-font.cpp43
-rw-r--r--src/sp-glyph-kerning.cpp36
-rw-r--r--src/sp-glyph.cpp48
-rw-r--r--src/sp-image.cpp2
-rw-r--r--src/sp-missing-glyph.cpp36
-rw-r--r--src/sp-object.h2
-rw-r--r--src/sp-shape.cpp303
-rw-r--r--src/splivarot.cpp244
-rw-r--r--src/splivarot.h1
-rw-r--r--src/style.cpp9
-rw-r--r--src/ui/dialog/Makefile_insert4
-rw-r--r--src/ui/dialog/align-and-distribute.h2
-rw-r--r--src/ui/dialog/desktop-tracker.cpp159
-rw-r--r--src/ui/dialog/desktop-tracker.h73
-rw-r--r--src/ui/dialog/dialog-manager.cpp7
-rw-r--r--src/ui/dialog/dialog.cpp1
-rw-r--r--src/ui/dialog/dialog.h10
-rw-r--r--src/ui/dialog/document-metadata.cpp2
-rw-r--r--src/ui/dialog/document-metadata.h11
-rw-r--r--src/ui/dialog/document-properties.h32
-rw-r--r--src/ui/dialog/filedialogimpl-gtkmm.cpp8
-rw-r--r--src/ui/dialog/fill-and-stroke.cpp45
-rw-r--r--src/ui/dialog/fill-and-stroke.h29
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp6
-rw-r--r--src/ui/dialog/filter-effects-dialog.h8
-rw-r--r--src/ui/dialog/floating-behavior.cpp89
-rw-r--r--src/ui/dialog/floating-behavior.h16
-rw-r--r--src/ui/dialog/glyphs.cpp749
-rw-r--r--src/ui/dialog/glyphs.h107
-rw-r--r--src/ui/dialog/icon-preview.cpp9
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp93
-rw-r--r--src/ui/dialog/inkscape-preferences.h382
-rw-r--r--src/ui/dialog/input.cpp552
-rw-r--r--src/ui/dialog/input.h2
-rw-r--r--src/ui/dialog/panel-dialog.h24
-rw-r--r--src/ui/dialog/tile.cpp60
-rw-r--r--src/ui/dialog/tile.h5
-rw-r--r--src/ui/dialog/transformation.h62
-rw-r--r--src/ui/tool/node-tool.cpp12
-rw-r--r--src/ui/tool/node-tool.h1
-rw-r--r--src/ui/widget/imageicon.cpp2
-rw-r--r--src/ui/widget/panel.cpp12
-rw-r--r--src/verbs.cpp12
-rw-r--r--src/verbs.h2
-rw-r--r--src/widgets/Makefile_insert1
-rw-r--r--src/widgets/fill-n-stroke-factory.h36
-rw-r--r--src/widgets/fill-style.cpp631
-rw-r--r--src/widgets/fill-style.h15
-rw-r--r--src/widgets/paint-selector.cpp15
-rw-r--r--src/widgets/paint-selector.h6
-rw-r--r--src/widgets/sp-color-icc-selector.cpp2
-rw-r--r--src/widgets/stroke-style.cpp463
-rw-r--r--src/widgets/stroke-style.h19
-rw-r--r--src/widgets/toolbox.cpp2433
-rw-r--r--src/winconsole.cpp153
123 files changed, 7301 insertions, 6044 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7cd194eea..8cbbbf21b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -194,6 +194,7 @@ EXTRA_DIST += \
extension/internal/emf-win32-print.h \
helper/sp-marshal.list \
show-preview.bmp \
+ winconsole.cpp \
$(jabber_whiteboard_SOURCES) \
$(CXXTEST_TEMPLATE)
diff --git a/src/Makefile_insert b/src/Makefile_insert
index fbaca931e..36c9de34f 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -78,6 +78,8 @@ ink_common_sources += \
ige-mac-menu.h ige-mac-menu.c \
ink-action.cpp \
ink-action.h \
+ ink-comboboxentry-action.cpp \
+ ink-comboboxentry-action.h \
inkscape.cpp inkscape.h inkscape-private.h \
interface.cpp interface.h \
isinf.h \
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index f3b1b833d..2225be5ee 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -891,16 +891,17 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
double size = 0;
double letterspacing = 0;
+ double wordspacing = 0;
double linespacing = 0;
- bool linespacing_normal = false;
bool letterspacing_normal = false;
+ bool wordspacing_normal = false;
+ bool linespacing_normal = false;
double size_prev = 0;
double letterspacing_prev = 0;
+ double wordspacing_prev = 0;
double linespacing_prev = 0;
- /// \todo FIXME: add word spacing, kerns? rotates?
-
int texts = 0;
for (GSList const *i = objects; i != NULL; i = i->next) {
@@ -925,6 +926,14 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
letterspacing_normal = false;
}
+ if (style->word_spacing.normal) {
+ if (!different && (wordspacing_prev == 0 || wordspacing_prev == wordspacing))
+ wordspacing_normal = true;
+ } else {
+ wordspacing += style->word_spacing.computed; /// \todo FIXME: we assume non-% units here
+ wordspacing_normal = false;
+ }
+
double linespacing_current;
if (style->line_height.normal) {
linespacing_current = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL;
@@ -941,12 +950,14 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
if ((size_prev != 0 && style->font_size.computed != size_prev) ||
(letterspacing_prev != 0 && style->letter_spacing.computed != letterspacing_prev) ||
+ (wordspacing_prev != 0 && style->word_spacing.computed != wordspacing_prev) ||
(linespacing_prev != 0 && linespacing_current != linespacing_prev)) {
different = true;
}
size_prev = style->font_size.computed;
letterspacing_prev = style->letter_spacing.computed;
+ wordspacing_prev = style->word_spacing.computed;
linespacing_prev = linespacing_current;
// FIXME: we must detect MULTIPLE_DIFFERENT for these too
@@ -960,6 +971,7 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
if (texts > 1) {
size /= texts;
letterspacing /= texts;
+ wordspacing /= texts;
linespacing /= texts;
}
@@ -969,6 +981,9 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
style_res->letter_spacing.normal = letterspacing_normal;
style_res->letter_spacing.computed = letterspacing;
+ style_res->word_spacing.normal = wordspacing_normal;
+ style_res->word_spacing.computed = wordspacing;
+
style_res->line_height.normal = linespacing_normal;
style_res->line_height.computed = linespacing;
style_res->line_height.value = linespacing;
@@ -1054,6 +1069,7 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res)
for (GSList const *i = objects; i != NULL; i = i->next) {
SPObject *obj = SP_OBJECT (i->data);
+ // std::cout << " " << SP_OBJECT_ID (i->data) << std::endl;
if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
&& !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
&& !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj))
@@ -1107,6 +1123,7 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res)
for (GSList const *i = objects; i != NULL; i = i->next) {
SPObject *obj = SP_OBJECT (i->data);
+ // std::cout << " " << SP_OBJECT_ID (i->data) << std::endl;
if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
&& !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
&& !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj))
diff --git a/src/device-manager.cpp b/src/device-manager.cpp
index 09fd7cb5f..62e0c2545 100644
--- a/src/device-manager.cpp
+++ b/src/device-manager.cpp
@@ -2,21 +2,33 @@
/*
* Inkscape::DeviceManager - a view of input devices available.
*
- * Copyright 2006 Jon A. Cruz <jon@joncruz.org>
+ * Copyright 2010 Jon A. Cruz <jon@joncruz.org>
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <glib.h>
#include <map>
+#include <set>
+#include <gtk/gtkaccelgroup.h>
#include "device-manager.h"
+#include "preferences.h"
+#define noDEBUG_VERBOSE 1
static void createFakeList();
GdkDevice fakeout[5];
static GList* fakeList = 0;
+static bool isValidDevice(GdkDevice *device)
+{
+ bool valid = true;
+ for (size_t i = 0; (i < G_N_ELEMENTS(fakeout)) && valid; i++) {
+ valid = (device != &fakeout[i]);
+ }
+ return valid;
+}
namespace Inkscape {
@@ -33,6 +45,88 @@ static pair<gint, gint> vals[] = {
static std::map<gint, gint> bitVals(vals, &vals[G_N_ELEMENTS(vals)]);
+static const int RUNAWAY_MAX = 1000;
+
+static Glib::ustring getBaseDeviceName(Gdk::InputSource source)
+{
+ Glib::ustring name;
+ switch (source) {
+ case GDK_SOURCE_MOUSE:
+ name ="pointer";
+ break;
+ case GDK_SOURCE_PEN:
+ name ="pen";
+ break;
+ case GDK_SOURCE_ERASER:
+ name ="eraser";
+ break;
+ case GDK_SOURCE_CURSOR:
+ name ="cursor";
+ break;
+ default:
+ name = "tablet";
+ }
+ return name;
+}
+
+static std::map<Glib::ustring, Gdk::AxisUse> &getStringToAxis()
+{
+ static bool init = false;
+ static std::map<Glib::ustring, Gdk::AxisUse> mapping;
+ if (!init) {
+ init = true;
+ mapping["ignore"] = Gdk::AXIS_IGNORE;
+ mapping["x"] = Gdk::AXIS_X;
+ mapping["y"] = Gdk::AXIS_Y;
+ mapping["pressure"] = Gdk::AXIS_PRESSURE;
+ mapping["xtilt"] = Gdk::AXIS_XTILT;
+ mapping["ytilt"] = Gdk::AXIS_YTILT;
+ mapping["wheel"] = Gdk::AXIS_WHEEL;
+ }
+ return mapping;
+}
+
+std::map<Gdk::AxisUse, Glib::ustring> &getAxisToString()
+{
+ static bool init = false;
+ static std::map<Gdk::AxisUse, Glib::ustring> mapping;
+ if (!init) {
+ init = true;
+ for (std::map<Glib::ustring, Gdk::AxisUse>::iterator it = getStringToAxis().begin(); it != getStringToAxis().end(); ++it) {
+ mapping.insert(std::make_pair(it->second, it->first));
+ }
+ }
+ return mapping;
+}
+
+static std::map<Glib::ustring, Gdk::InputMode> &getStringToMode()
+{
+ static bool init = false;
+ static std::map<Glib::ustring, Gdk::InputMode> mapping;
+ if (!init) {
+ init = true;
+ mapping["disabled"] = Gdk::MODE_DISABLED;
+ mapping["screen"] = Gdk::MODE_SCREEN;
+ mapping["window"] = Gdk::MODE_WINDOW;
+ }
+ return mapping;
+}
+
+std::map<Gdk::InputMode, Glib::ustring> &getModeToString()
+{
+ static bool init = false;
+ static std::map<Gdk::InputMode, Glib::ustring> mapping;
+ if (!init) {
+ init = true;
+ for (std::map<Glib::ustring, Gdk::InputMode>::iterator it = getStringToMode().begin(); it != getStringToMode().end(); ++it) {
+ mapping.insert(std::make_pair(it->second, it->first));
+ }
+ }
+ return mapping;
+}
+
+
+
InputDevice::InputDevice()
: Glib::Object()
{}
@@ -41,6 +135,9 @@ InputDevice::~InputDevice() {}
class InputDeviceImpl : public InputDevice {
public:
+ InputDeviceImpl(GdkDevice* device, std::set<Glib::ustring> &knownIDs);
+ virtual ~InputDeviceImpl() {}
+
virtual Glib::ustring getId() const {return id;}
virtual Glib::ustring getName() const {return name;}
virtual Gdk::InputSource getSource() const {return source;}
@@ -55,14 +152,15 @@ public:
virtual gint getLiveButtons() const {return liveButtons;}
virtual void setLiveButtons(gint buttons) {liveButtons = buttons;}
-
- InputDeviceImpl(GdkDevice* device);
- virtual ~InputDeviceImpl() {}
+ // internal methods not on public superclass:
+ virtual GdkDevice *getDevice() { return device; }
private:
InputDeviceImpl(InputDeviceImpl const &); // no copy
void operator=(InputDeviceImpl const &); // no assign
+ static Glib::ustring createId(Glib::ustring const &id, Gdk::InputSource source, std::set<Glib::ustring> &knownIDs);
+
GdkDevice* device;
Glib::ustring id;
Glib::ustring name;
@@ -72,25 +170,25 @@ private:
guint liveButtons;
};
-class IdMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+class IdMatcher : public std::unary_function<Glib::RefPtr<InputDeviceImpl>&, bool> {
public:
IdMatcher(Glib::ustring const& target):target(target) {}
- bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());}
+ bool operator ()(Glib::RefPtr<InputDeviceImpl>& dev) {return dev && (target == dev->getId());}
private:
Glib::ustring const& target;
};
-class LinkMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+class LinkMatcher : public std::unary_function<Glib::RefPtr<InputDeviceImpl>&, bool> {
public:
LinkMatcher(Glib::ustring const& target):target(target) {}
- bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());}
+ bool operator ()(Glib::RefPtr<InputDeviceImpl>& dev) {return dev && (target == dev->getLink());}
private:
Glib::ustring const& target;
};
-InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
+InputDeviceImpl::InputDeviceImpl(GdkDevice* device, std::set<Glib::ustring> &knownIDs)
: InputDevice(),
device(device),
id(),
@@ -100,27 +198,54 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
liveAxes(0),
liveButtons(0)
{
+ id = createId(name, source, knownIDs);
+}
+
+
+Glib::ustring InputDeviceImpl::createId(Glib::ustring const &id,
+ Gdk::InputSource source,
+ std::set<Glib::ustring> &knownIDs)
+{
+ // Start with only allowing printable ASCII. Check later for more refinements.
+ bool badName = id.empty() || !id.is_ascii();
+ for (Glib::ustring::const_iterator it = id.begin(); (it != id.end()) && !badName; ++it) {
+ badName = *it < 0x20;
+ }
+
+ Glib::ustring base;
switch ( source ) {
case Gdk::SOURCE_MOUSE:
- id = "M:";
+ base = "M:";
break;
case Gdk::SOURCE_CURSOR:
- id = "C:";
+ base = "C:";
break;
case Gdk::SOURCE_PEN:
- id = "P:";
+ base = "P:";
break;
case Gdk::SOURCE_ERASER:
- id = "E:";
+ base = "E:";
break;
default:
- id = "?:";
+ base = "?:";
}
- id += name;
-}
+ if (badName) {
+ base += getBaseDeviceName(source);
+ } else {
+ base += id;
+ }
+ // now ensure that all IDs become unique in a session.
+ int num = 1;
+ Glib::ustring result = base;
+ while ((knownIDs.find(result) != knownIDs.end()) && (num < RUNAWAY_MAX)) {
+ result = Glib::ustring::compose("%1%2", base, ++num);
+ }
+ knownIDs.insert(result);
+ return result;
+}
@@ -129,22 +254,32 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
class DeviceManagerImpl : public DeviceManager {
public:
DeviceManagerImpl();
- virtual std::list<InputDevice const *> getDevices();
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged();
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChanged();
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged();
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChanged();
+
+ virtual void loadConfig();
+ virtual void saveConfig();
+
+ virtual std::list<Glib::RefPtr<InputDevice const> > getDevices();
+
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalDeviceChanged();
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalAxesChanged();
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalButtonsChanged();
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalLinkChanged();
virtual void addAxis(Glib::ustring const & id, gint axis);
virtual void addButton(Glib::ustring const & id, gint button);
virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link);
+ virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode );
+ virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use );
+ virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods );
+
protected:
- std::list<InputDeviceImpl*> devices;
- sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChangedPriv;
- sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChangedPriv;
- sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChangedPriv;
- sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChangedPriv;
+ std::list<Glib::RefPtr<InputDeviceImpl> > devices;
+
+ sigc::signal<void, Glib::RefPtr<InputDevice const> > signalDeviceChangedPriv;
+ sigc::signal<void, Glib::RefPtr<InputDevice const> > signalAxesChangedPriv;
+ sigc::signal<void, Glib::RefPtr<InputDevice const> > signalButtonsChangedPriv;
+ sigc::signal<void, Glib::RefPtr<InputDevice const> > signalLinkChangedPriv;
};
@@ -157,46 +292,175 @@ DeviceManagerImpl::DeviceManagerImpl() :
if ( !fakeList ) {
createFakeList();
}
-// devList = fakeList;
+ //devList = fakeList;
+
+ std::set<Glib::ustring> knownIDs;
for ( GList* curr = devList; curr; curr = g_list_next(curr) ) {
GdkDevice* dev = reinterpret_cast<GdkDevice*>(curr->data);
if ( dev ) {
-// g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode,
-// dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys);
+#if DEBUG_VERBOSE
+ g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode,
+ dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys);
+#endif
+
+ InputDeviceImpl* device = new InputDeviceImpl(dev, knownIDs);
+ device->reference();
+ devices.push_back(Glib::RefPtr<InputDeviceImpl>(device));
+ }
+ }
+}
+
+void DeviceManagerImpl::loadConfig()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ for (std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = devices.begin(); it != devices.end(); ++it) {
+ if ((*it)->getSource() != Gdk::SOURCE_MOUSE) {
+ Glib::ustring path = "/devices/" + (*it)->getId();
+
+ Gdk::InputMode mode = Gdk::MODE_DISABLED;
+ Glib::ustring val = prefs->getString(path + "/mode");
+ if (getStringToMode().find(val) != getStringToMode().end()) {
+ mode = getStringToMode()[val];
+ }
+ if ((*it)->getMode() != mode) {
+ setMode( (*it)->getId(), mode );
+ }
+
+ //
+
+ val = prefs->getString(path + "/axes");
+ if (!val.empty()) {
+ std::vector<Glib::ustring> parts = Glib::Regex::split_simple(";", val);
+ for (size_t i = 0; i < parts.size(); ++i) {
+ Glib::ustring name = parts[i];
+ if (getStringToAxis().find(name) != getStringToAxis().end()) {
+ Gdk::AxisUse use = getStringToAxis()[name];
+ setAxisUse( (*it)->getId(), i, use );
+ }
+ }
+ }
+
+ val = prefs->getString(path + "/keys");
+ if (!val.empty()) {
+ std::vector<Glib::ustring> parts = Glib::Regex::split_simple(";", val);
+ for (size_t i = 0; i < parts.size(); ++i) {
+ Glib::ustring keyStr = parts[i];
+ if (!keyStr.empty()) {
+ guint key = 0;
+ GdkModifierType mods = static_cast<GdkModifierType>(0);
+ gtk_accelerator_parse( keyStr.c_str(), &key, &mods );
+ setKey( (*it)->getId(), i, key, static_cast<Gdk::ModifierType>(mods) );
+ }
+ }
+ }
+ }
+ }
+}
+
+void DeviceManagerImpl::saveConfig()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ for (std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = devices.begin(); it != devices.end(); ++it) {
+ if ((*it)->getSource() != Gdk::SOURCE_MOUSE) {
+ Glib::ustring path = "/devices/" + (*it)->getId();
+
+ prefs->setString( path + "/mode", getModeToString()[(*it)->getMode()].c_str() );
+
+ Glib::ustring tmp;
+ for (gint i = 0; i < (*it)->getNumAxes(); ++i) {
+ if (i > 0) {
+ tmp += ";";
+ }
+ tmp += getAxisToString()[static_cast<Gdk::AxisUse>((*it)->getDevice()->axes[i].use)];
+ }
+ prefs->setString( path + "/axes", tmp );
- InputDeviceImpl* device = new InputDeviceImpl(dev);
- devices.push_back(device);
+ tmp = "";
+ for (gint i = 0; i < (*it)->getNumKeys(); ++i) {
+ if (i > 0) {
+ tmp += ";";
+ }
+ tmp += gtk_accelerator_name((*it)->getDevice()->keys[i].keyval, (*it)->getDevice()->keys[i].modifiers);
+ }
+ prefs->setString( path + "/keys", tmp );
}
}
}
-std::list<InputDevice const *> DeviceManagerImpl::getDevices()
+std::list<Glib::RefPtr<InputDevice const> > DeviceManagerImpl::getDevices()
{
- std::list<InputDevice const *> tmp;
- for ( std::list<InputDeviceImpl*>::const_iterator it = devices.begin(); it != devices.end(); ++it ) {
+ std::list<Glib::RefPtr<InputDevice const> > tmp;
+ for ( std::list<Glib::RefPtr<InputDeviceImpl> >::const_iterator it = devices.begin(); it != devices.end(); ++it ) {
tmp.push_back(*it);
}
return tmp;
}
+void DeviceManagerImpl::setMode( Glib::ustring const & id, Gdk::InputMode mode )
+{
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ if ( it != devices.end() ) {
+ if (isValidDevice((*it)->getDevice()) && ((*it)->getMode() != mode) ) {
+ bool success = gdk_device_set_mode((*it)->getDevice(), static_cast<GdkInputMode>(mode));
+ if (success) {
+ signalDeviceChangedPriv.emit(*it);
+ } else {
+ g_warning("Unable to set mode on extended input device [%s]", (*it)->getId().c_str());
+ }
+ }
+ }
+}
+
+void DeviceManagerImpl::setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use )
+{
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ if ( it != devices.end() ) {
+ if (isValidDevice((*it)->getDevice())) {
+ if (static_cast<gint>(index) <= (*it)->getNumAxes()) {
+ if ((*it)->getDevice()->axes[index].use != static_cast<GdkAxisUse>(use)) {
+ gdk_device_set_axis_use((*it)->getDevice(), index, static_cast<GdkAxisUse>(use));
+ signalDeviceChangedPriv.emit(*it);
+ }
+ } else {
+ g_warning("Invalid device axis number %d on extended input device [%s]", index, (*it)->getId().c_str());
+ }
+ }
+ }
+}
+
+void DeviceManagerImpl::setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods )
+{
+ //static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers )
+ //
-sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalDeviceChanged()
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ if ( it != devices.end() ) {
+ if (isValidDevice((*it)->getDevice())) {
+ gdk_device_set_key((*it)->getDevice(), index, keyval, static_cast<GdkModifierType>(mods));
+ signalDeviceChangedPriv.emit(*it);
+ }
+ }
+}
+
+sigc::signal<void, Glib::RefPtr<InputDevice const> > DeviceManagerImpl::signalDeviceChanged()
{
return signalDeviceChangedPriv;
}
-sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalAxesChanged()
+sigc::signal<void, Glib::RefPtr<InputDevice const> > DeviceManagerImpl::signalAxesChanged()
{
return signalAxesChangedPriv;
}
-sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalButtonsChanged()
+sigc::signal<void, Glib::RefPtr<InputDevice const> > DeviceManagerImpl::signalButtonsChanged()
{
return signalButtonsChangedPriv;
}
-sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalLinkChanged()
+sigc::signal<void, Glib::RefPtr<InputDevice const> > DeviceManagerImpl::signalLinkChanged()
{
return signalLinkChangedPriv;
}
@@ -204,7 +468,7 @@ sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalL
void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
{
if ( axis >= 0 && axis < static_cast<gint>(bitVals.size()) ) {
- std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
if ( it != devices.end() ) {
gint mask = bitVals[axis];
if ( (mask & (*it)->getLiveAxes()) == 0 ) {
@@ -212,7 +476,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
// Only signal if a new axis was added
(*it)->reference();
- signalAxesChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
+ signalAxesChangedPriv.emit(*it);
}
}
}
@@ -221,7 +485,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
{
if ( button >= 0 && button < static_cast<gint>(bitVals.size()) ) {
- std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
if ( it != devices.end() ) {
gint mask = bitVals[button];
if ( (mask & (*it)->getLiveButtons()) == 0 ) {
@@ -229,7 +493,7 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
// Only signal if a new button was added
(*it)->reference();
- signalButtonsChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
+ signalButtonsChangedPriv.emit(*it);
}
}
}
@@ -237,12 +501,11 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link)
{
- std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+ std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
if ( it != devices.end() ) {
- InputDeviceImpl* dev = *it;
-
+ Glib::RefPtr<InputDeviceImpl> dev = *it;
- InputDeviceImpl* targetDev = 0;
+ Glib::RefPtr<InputDeviceImpl> targetDev;
if ( !link.empty() ) {
// Need to be sure the target of the link exists
it = std::find_if(devices.begin(), devices.end(), IdMatcher(link));
@@ -255,7 +518,7 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons
if ( (link.empty() && !dev->getLink().empty())
|| (targetDev && (targetDev->getLink() != id)) ) {
// only muck about if they aren't already linked
- std::list<InputDeviceImpl*> changedItems;
+ std::list<Glib::RefPtr<InputDeviceImpl> > changedItems;
if ( targetDev ) {
// Is something else already using that link?
@@ -277,9 +540,9 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons
dev->setLink(link);
changedItems.push_back(dev);
- for ( std::list<InputDeviceImpl*>::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
+ for ( std::list<Glib::RefPtr<InputDeviceImpl> >::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
(*iter)->reference();
- signalLinkChangedPriv.emit(Glib::RefPtr<InputDevice>(*iter));
+ signalLinkChangedPriv.emit(*iter);
}
}
}
diff --git a/src/device-manager.h b/src/device-manager.h
index 1bfb5120c..4aea99ac0 100644
--- a/src/device-manager.h
+++ b/src/device-manager.h
@@ -1,7 +1,7 @@
/*
* Inkscape::DeviceManager - a view of input devices available.
*
- * Copyright 2006 Jon A. Cruz <jon@joncruz.org>
+ * Copyright 2010 Jon A. Cruz <jon@joncruz.org>
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -42,16 +42,24 @@ class DeviceManager : public Glib::Object {
public:
static DeviceManager& getManager();
- virtual std::list<InputDevice const *> getDevices() = 0;
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged() = 0;
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChanged() = 0;
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged() = 0;
- virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChanged() = 0;
+ virtual void loadConfig() = 0;
+ virtual void saveConfig() = 0;
+
+ virtual std::list<Glib::RefPtr<InputDevice const> > getDevices() = 0;
+
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalDeviceChanged() = 0;
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalAxesChanged() = 0;
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalButtonsChanged() = 0;
+ virtual sigc::signal<void, Glib::RefPtr<InputDevice const> > signalLinkChanged() = 0;
virtual void addAxis(Glib::ustring const & id, gint axis) = 0;
virtual void addButton(Glib::ustring const & id, gint button) = 0;
virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) = 0;
+ virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode ) = 0;
+ virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use ) = 0;
+ virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods ) = 0;
+
protected:
DeviceManager();
virtual ~DeviceManager();
diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt
index 4e6b1ee3d..9bcb1cd5a 100644
--- a/src/dialogs/CMakeLists.txt
+++ b/src/dialogs/CMakeLists.txt
@@ -8,7 +8,6 @@ find.cpp
guidelinedialog.cpp
iconpreview.cpp
in-dt-coordsys.cpp
-input.cpp
item-properties.cpp
layer-properties.cpp
layers-panel.cpp
diff --git a/src/dialogs/Makefile_insert b/src/dialogs/Makefile_insert
index 32a11e831..8d7d3f21d 100644
--- a/src/dialogs/Makefile_insert
+++ b/src/dialogs/Makefile_insert
@@ -9,8 +9,6 @@ ink_common_sources += \
dialogs/export.h \
dialogs/find.cpp \
dialogs/find.h \
- dialogs/input.cpp \
- dialogs/input.h \
dialogs/item-properties.cpp \
dialogs/item-properties.h \
dialogs/object-attributes.cpp \
diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp
index 9e8a71c35..696f38b77 100644
--- a/src/dialogs/export.cpp
+++ b/src/dialogs/export.cpp
@@ -780,7 +780,7 @@ sp_export_selection_modified ( Inkscape::Application */*inkscape*/,
if ( SP_ACTIVE_DESKTOP ) {
SPDocument *doc;
doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
- Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
+ Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX);
if (bbox) {
sp_export_set_area (base, bbox->min()[Geom::X],
bbox->min()[Geom::Y],
@@ -792,7 +792,7 @@ sp_export_selection_modified ( Inkscape::Application */*inkscape*/,
case SELECTION_SELECTION:
if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
NRRect bbox;
- (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox);
+ (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox, SPItem::RENDERING_BBOX);
sp_export_set_area (base, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
}
break;
@@ -849,7 +849,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base)
case SELECTION_SELECTION:
if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false)
{
- bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds();
+ bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds(SPItem::RENDERING_BBOX);
/* Only if there is a selection that we can set
do we break, otherwise we fall through to the
drawing */
@@ -861,7 +861,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base)
/** \todo
* This returns wrong values if the document has a viewBox.
*/
- bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
+ bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX);
/* If the drawing is valid, then we'll use it and break
otherwise we drop through to the page settings */
if (bbox) {
@@ -1487,7 +1487,7 @@ sp_export_detect_size(GtkObject * base) {
switch (this_test[i]) {
case SELECTION_SELECTION:
if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
- Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds();
+ Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(SPItem::RENDERING_BBOX);
//std::cout << "Selection " << bbox;
if ( bbox && sp_export_bbox_equal(*bbox,current_bbox)) {
@@ -1498,7 +1498,7 @@ sp_export_detect_size(GtkObject * base) {
case SELECTION_DRAWING: {
SPDocument *doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
- Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
+ Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)), SPItem::RENDERING_BBOX);
// std::cout << "Drawing " << bbox2;
if ( bbox && sp_export_bbox_equal(*bbox,current_bbox) ) {
diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp
deleted file mode 100644
index 55e9704c3..000000000
--- a/src/dialogs/input.cpp
+++ /dev/null
@@ -1,607 +0,0 @@
-/** @file
- * @brief Extended input devices dialog
- */
-/* Authors:
- * Nicklas Lindgren <nili@lysator.liu.se>
- * Johan Engelen <goejendaagh@zonnet.nl>
- *
- * Copyright (C) 2005-2006 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <gtk/gtksignal.h>
-#include <gtk/gtkinputdialog.h>
-#include <glibmm/ustring.h>
-#include <list>
-#include <set>
-
-#include "macros.h"
-#include "verbs.h"
-#include "inkscape.h"
-#include "interface.h"
-#include "xml/repr.h"
-
-#include "dialogs/dialog-events.h"
-#include "preferences.h"
-
-#define MIN_ONSCREEN_DISTANCE 50
-
-static GtkWidget *dlg = NULL;
-static win_data wd;
-
-// impossible original values to make sure they are read from prefs
-static gint x = -1000, y = -1000, w = 0, h = 0;
-static Glib::ustring const prefs_path = "/dialogs/input/";
-
-#define noTEST_WITH_GOOD_TABLET 1
-#define noTEST_WITH_BAD_TABLET 1
-
-#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
-static int testDeviceCount = 0;
-static GdkDevice* testDevices = 0;
-
-// Defined at the end of the file to keep debugging out of the way.
-static void initTestDevices();
-#endif
-
-static std::list<GdkDevice *> getInputDevices()
-{
- std::list<GdkDevice*> devices;
-
-#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
- initTestDevices();
- for (int i = 0; i < testDeviceCount; i++) {
- devices.push_back(&testDevices[i]);
- }
-#else
- for (GList *ptr = gdk_devices_list(); ptr; ptr = ptr->next) {
- GdkDevice *device = static_cast<GdkDevice *>(ptr->data);
- devices.push_back(device);
- }
-#endif
-
- return devices;
-}
-
-// wrap these GDK calls to be able to intercept for testing.
-
-static bool setDeviceMode( GdkDevice *device, GdkInputMode mode )
-{
-#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
- (void)device;
- (void)mode;
- bool retVal = true; // Can't let the Gdk call be called with bad data
-#else
- bool retVal = gdk_device_set_mode(device, mode);
-#endif
- return retVal;
-}
-
-static void setDeviceAxisUse( GdkDevice *device, guint index, GdkAxisUse use )
-{
-#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET)
- (void)device;
- (void)index;
- (void)use;
-#else
- gdk_device_set_axis_use(device, index, use);
-#endif
-}
-
-static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers )
-{
-#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET)
- (void)device;
- (void)index;
- (void)keyval;
- (void)modifiers;
-#else
- gdk_device_set_key(device, index, keyval, modifiers);
-#endif
-}
-
-
-static void
-sp_input_dialog_destroy (GtkObject */*object*/, gpointer /*data*/)
-{
- sp_signal_disconnect_by_data (INKSCAPE, dlg);
- wd.win = dlg = NULL;
- wd.stop = 0;
-}
-
-static gboolean
-sp_input_dialog_delete (GtkObject */*object*/, GdkEvent */*event*/, gpointer /*data*/)
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
- gtk_window_get_size ((GtkWindow *) dlg, &w, &h);
-
- if (x<0) x=0;
- if (y<0) y=0;
-
- prefs->setInt(prefs_path + "x", x);
- prefs->setInt(prefs_path + "y", y);
- prefs->setInt(prefs_path + "w", w);
- prefs->setInt(prefs_path + "h", h);
-
- return FALSE; // which means, go ahead and destroy it
-
-}
-
-static gchar const *axis_use_strings[GDK_AXIS_LAST] = {
- "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel"
-};
-
-static const int RUNAWAY_MAX = 1000;
-
-static Glib::ustring getBaseDeviceName(GdkInputSource source)
-{
- Glib::ustring name;
- switch (source) {
- case GDK_SOURCE_MOUSE:
- name ="pointer";
- break;
- case GDK_SOURCE_PEN:
- name ="pen";
- break;
- case GDK_SOURCE_ERASER:
- name ="eraser";
- break;
- case GDK_SOURCE_CURSOR:
- name ="cursor";
- break;
- default:
- name = "tablet";
- }
- return name;
-}
-
-static Glib::ustring createSanitizedPath(GdkDevice* device, std::set<Glib::ustring> &seenPaths)
-{
- // LP #334800: tablet device names on Windows sometimes contain funny junk like
- // \x03, \xf2, etc. Moreover this junk changes between runs.
- // If the tablet name contains unprintable or non-ASCII characters,
- // we use some default name.
- // This might break if someone has two tablets with broken names, but it's
- // not possible to do anything 100% correct then.
- bool broken = false;
-
- if (!device->name || (*(device->name) == 0)) {
- broken = true;
- } else {
- for (gchar const *s = device->name; *s; ++s) {
- if ((*s < 0x20) || (*s >= 0x7f)) {
- broken = true;
- break;
- }
- }
- }
-
- Glib::ustring device_path;
- if (broken) {
- Glib::ustring base = Glib::ustring("/devices/") + getBaseDeviceName(device->source);
- int num = 1;
- device_path = base;
- while ((seenPaths.find(device_path) != seenPaths.end()) && (num < RUNAWAY_MAX)) {
- device_path = Glib::ustring::compose("%1%2", base, ++num);
- }
- } else {
- device_path += Glib::ustring("/devices/") + device->name;
- }
-
- seenPaths.insert(device_path);
-
- return device_path;
-}
-
-void sp_input_load_from_preferences(void)
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- std::list<GdkDevice *> devices = getInputDevices();
- std::set<Glib::ustring> seenPaths;
- for (std::list<GdkDevice *>::iterator it = devices.begin(); it != devices.end(); ++it) {
- GdkDevice *device = *it;
-
-// g_message(" s:%d m:%d hc:%d a:%d k:%d [%s]", device->source, device->mode, device->has_cursor, device->num_axes, device->num_keys, device->name);
-// for (int i = 0; i < device->num_axes; i++) {
-// GdkDeviceAxis &axis = device->axes[i];
-// g_message(" axis[%d] u:%d min:%f max:%f", i, axis.use, axis.min, axis.max);
-// }
-
- Glib::ustring device_path = createSanitizedPath(device, seenPaths);
-// if (device_path != (Glib::ustring("/devices/") + device->name)) {
-// g_message(" re-name [%s]", device_path.c_str());
-// }
-
- Glib::ustring device_mode = prefs->getString(device_path + "/mode");
-
- GdkInputMode mode = GDK_MODE_DISABLED;
- if (device_mode == "screen") {
- mode = GDK_MODE_SCREEN;
- } else if (device_mode == "window") {
- mode = GDK_MODE_WINDOW;
- }
-
- if (device->mode != mode) {
- setDeviceMode(device, mode);
- }
-
- Glib::ustring::size_type pos0, pos1;
- GdkAxisUse axis_use;
-
- //temp_ptr = repr->attribute("axes");
- Glib::ustring const axes_str = prefs->getString(device_path + "/axes");
- pos0 = pos1 = 0;
- for (gint i=0; i < device->num_axes; i++) {
- pos1 = axes_str.find(';', pos0);
- if (pos1 == Glib::ustring::npos) {
- break; // Too few axis specifications
- }
-
- axis_use = GDK_AXIS_IGNORE;
- for (gint j=0; j < GDK_AXIS_LAST; j++) {
- if (!strcmp(axes_str.substr(pos0, pos1-pos0).c_str(), axis_use_strings[j])) {
- axis_use = static_cast<GdkAxisUse>(j);
- break;
- }
- }
- setDeviceAxisUse(device, i, axis_use);
- pos0 = pos1 + 1;
- }
-
- guint keyval;
- GdkModifierType modifier;
-
- Glib::ustring const keys_str = prefs->getString(device_path + "/keys");
- pos0 = pos1 = 0;
- for (gint i=0; i < device->num_keys; i++) {
- pos1 = keys_str.find(';', pos0);
- if (pos1 == Glib::ustring::npos) {
- break; // Too few key specifications
- }
-
- gtk_accelerator_parse(keys_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier);
- setDeviceKey(device, i, keyval, modifier);
- pos0 = pos1 + 1;
- }
- }
-}
-
-void sp_input_save_to_preferences(void)
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- std::list<GdkDevice *> devices = getInputDevices();
- std::set<Glib::ustring> seenPaths;
- for (std::list<GdkDevice *>::iterator it = devices.begin(); it != devices.end(); ++it) {
- GdkDevice *device = *it;
-
- Glib::ustring device_path = createSanitizedPath(device, seenPaths);
-
- switch (device->mode) {
- default:
- case GDK_MODE_DISABLED: {
- prefs->setString(device_path + "/mode", "disabled");
- break;
- }
- case GDK_MODE_SCREEN: {
- prefs->setString(device_path + "/mode", "screen");
- break;
- }
- case GDK_MODE_WINDOW: {
- prefs->setString(device_path + "/mode", "window");
- break;
- }
- }
-
- Glib::ustring temp_attribute = "";
- for (gint i=0; i < device->num_axes; i++) {
- temp_attribute += axis_use_strings[device->axes[i].use];
- temp_attribute += ";";
- }
- prefs->setString(device_path + "/axes", temp_attribute);
-
- temp_attribute = "";
- for (gint i=0; i < device->num_keys; i++) {
- temp_attribute += gtk_accelerator_name(device->keys[i].keyval, device->keys[i].modifiers);
- temp_attribute += ";";
- }
- prefs->setString(device_path + "/keys", temp_attribute);
- }
-}
-
-static void
-sp_input_save_button (GtkObject */*object*/, gpointer /*data*/)
-{
- sp_input_save_to_preferences();
-}
-
-void
-sp_input_dialog (void)
-{
- if (dlg == NULL) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- gchar title[500];
- sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_INPUT), title);
-
- dlg = gtk_input_dialog_new();
-
- if (x == -1000 || y == -1000) {
- x = prefs->getInt(prefs_path + "x", -1000);
- y = prefs->getInt(prefs_path + "y", -1000);
- }
-
- if (w ==0 || h == 0) {
- w = prefs->getInt(prefs_path + "w", 0);
- h = prefs->getInt(prefs_path + "h", 0);
- }
-
-// if (x<0) x=0;
-// if (y<0) y=0;
-
- if (w && h) {
- gtk_window_resize ((GtkWindow *) dlg, w, h);
- }
- if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) {
- gtk_window_move ((GtkWindow *) dlg, x, y);
- } else {
- gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
- }
-
-
- sp_transientize (dlg);
- wd.win = dlg;
- wd.stop = 0;
-
- g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_transientize_callback), &wd);
- gtk_signal_connect ( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
- gtk_signal_connect ( GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_input_dialog_destroy), dlg);
- gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_input_dialog_delete), dlg);
- g_signal_connect ( G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_input_dialog_delete), dlg);
- g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg);
- g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg);
-
- // Dialog-specific stuff
- gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->close_button),
- "clicked",
- (GtkSignalFunc)gtk_widget_destroy,
- GTK_OBJECT(dlg));
- gtk_signal_connect (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->save_button),
- "clicked",
- (GtkSignalFunc)sp_input_save_button, NULL);
- }
-
- gtk_window_present ((GtkWindow *) dlg);
-}
-
-// /////////////////////////////////
-// For debugging:
-// /////////////////////////////////
-
-
-#if defined(TEST_WITH_GOOD_TABLET)
-static void initTestDevices()
-{
- static bool init = false;
- if (!init) {
- static GdkDevice devs[5] = {};
- int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc.
-
- {
- // Laptop trackpad
- devs[i].name = g_strdup("pointer");
- devs[i].source = GDK_SOURCE_MOUSE;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Tablet stylus
- devs[i].name = g_strdup("pen");
- devs[i].source = GDK_SOURCE_PEN;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Puck
- devs[i].name = g_strdup("cursor");
- devs[i].source = GDK_SOURCE_CURSOR;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Back of tablet stylus
- devs[i].name = g_strdup("eraser");
- devs[i].source = GDK_SOURCE_ERASER;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Main (composit) mouse device
- devs[i].name = g_strdup("Core Pointer");
- devs[i].source = GDK_SOURCE_MOUSE;
- devs[i].mode = GDK_MODE_SCREEN;
- devs[i].has_cursor = 1;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- testDeviceCount = i;
- testDevices = devs;
- init = true;
- }
-}
-#elif defined(TEST_WITH_BAD_TABLET)
-
-/**
- * Uses the current time in seconds to change a name to be unique from one
- * run of the program to the next.
- */
-void perturbName(gchar *str)
-{
- if (str) {
- GTimeVal when = {0,0};
- g_get_current_time(&when);
- gchar *tmp = g_strdup_printf("%ld", when.tv_sec);
-
- size_t partLen = strlen(tmp);
- size_t len = strlen(str);
- if (len > (partLen + 4)) {
- size_t pos = (len - partLen) / 2;
- for (size_t i = 0; i < partLen; i++) {
- str[pos + i] = tmp[i];
- }
- }
- g_free(tmp);
- }
-}
-
-static void initTestDevices()
-{
- static bool init = false;
- if (!init) {
- static GdkDevice devs[5] = {};
- int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc.
-
- {
- // Main (composit) mouse device
- devs[i].name = g_strdup("Core Pointer");
- devs[i].source = GDK_SOURCE_MOUSE;
- devs[i].mode = GDK_MODE_SCREEN;
- devs[i].has_cursor = 1;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Back of tablet stylus
- devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\356\232\210\307\255\350\271\214\310\201\350\222\200\310\201\356\202\250\310\200\350\223\260\310\201\356\202\250\310\200");
- perturbName(devs[i].name);
- devs[i].source = GDK_SOURCE_ERASER;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Tablet stylus
- devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\341\221\230\307\255\343\277\214\310\202\343\230\200\310\202\331\270\310\202\343\231\260\310\202\331\270\310\202");
- perturbName(devs[i].name);
- devs[i].source = GDK_SOURCE_PEN;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- {
- // Tablet stylus
- devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\341\221\230\307\255\343\277\214\310\202\343\230\200\310\202\331\270\310\202\343\231\260\310\202\331\270\310\202");
- perturbName(devs[i].name);
- devs[i].source = GDK_SOURCE_PEN;
- devs[i].mode = GDK_MODE_DISABLED;
- devs[i].has_cursor = 0;
- static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
- {GDK_AXIS_Y, 0, 0},
- {GDK_AXIS_PRESSURE, 0, 1},
- {GDK_AXIS_XTILT, -1, 1},
- {GDK_AXIS_YTILT, -1, 1}};
- devs[i].num_axes = G_N_ELEMENTS(tmp);
- devs[i].axes = tmp;
- devs[i].num_keys = 0;
- devs[i].keys = 0;
- i++;
- }
-
- testDeviceCount = i;
- testDevices = devs;
- init = true;
- }
-}
-#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 :
diff --git a/src/dialogs/input.h b/src/dialogs/input.h
deleted file mode 100644
index 0996d06ca..000000000
--- a/src/dialogs/input.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/** @file
- * @brief Extended input device dialog
- */
-/* Author:
- * Nicklas Lindgren <nili@lysator.liu.se>
- *
- * Copyright (C) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DIALOGS_INPUT_H
-#define SEEN_DIALOGS_INPUT_H
-
-void sp_input_load_from_preferences (void);
-void sp_input_save_to_preferences (void);
-void sp_input_dialog (void);
-
-
-#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 :
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index ee05cd01c..cf2883116 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -518,6 +518,9 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/)
{
ow = origin * affine;
sw = Geom::Point(fabs(affine[0]),fabs(affine[3]));
+ sw *= lengthy;
+
+ scaled = false;
for(int dim = 0; dim < 2; dim++) {
gint scaling_factor = empspacing;
@@ -525,10 +528,9 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/)
if (scaling_factor <= 1)
scaling_factor = 5;
- scaled = FALSE;
int watchdog = 0;
while ( (sw[dim] < 8.0) & (watchdog < 100) ) {
- scaled = TRUE;
+ scaled = true;
sw[dim] *= scaling_factor;
// First pass, go up to the major line spacing, then
// keep increasing by two.
@@ -538,13 +540,13 @@ CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/)
}
- spacing_ylines = sw[Geom::X] * lengthy /(tan_angle[X] + tan_angle[Z]);
- lyw = sw[Geom::Y] * lengthy;
- lxw_x = (lengthy / tan_angle[X]) * sw[Geom::X];
- lxw_z = (lengthy / tan_angle[Z]) * sw[Geom::X];
+ spacing_ylines = sw[Geom::X] /(tan_angle[X] + tan_angle[Z]);
+ lyw = sw[Geom::Y];
+ lxw_x = sw[Geom::X] / tan_angle[X];
+ lxw_z = sw[Geom::X] / tan_angle[Z];
if (empspacing == 0) {
- scaled = TRUE;
+ scaled = true;
}
}
diff --git a/src/display/curve.cpp b/src/display/curve.cpp
index 1b54c981c..73b8dc36d 100644
--- a/src/display/curve.cpp
+++ b/src/display/curve.cpp
@@ -44,7 +44,7 @@ SPCurve::SPCurve(Geom::PathVector const& pathv)
}
SPCurve *
-SPCurve::new_from_rect(Geom::Rect const &rect)
+SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides)
{
SPCurve *c = new SPCurve();
@@ -54,7 +54,16 @@ SPCurve::new_from_rect(Geom::Rect const &rect)
for (int i=3; i>=1; i--) {
c->lineto(rect.corner(i));
}
- c->closepath();
+
+ if (all_four_sides) {
+ // When _constrained_ snapping to a path, the 2geom::SimpleCrosser will be invoked which doesn't consider the closing segment.
+ // of a path. Consequently, in case we want to snap to for example the page border, we must provide all four sides of the
+ // rectangle explicitly
+ c->lineto(rect.corner(0));
+ } else {
+ // ... instead of just three plus a closing segment
+ c->closepath();
+ }
return c;
}
diff --git a/src/display/curve.h b/src/display/curve.h
index 79a385b09..fe0720195 100644
--- a/src/display/curve.h
+++ b/src/display/curve.h
@@ -27,7 +27,7 @@ public:
/* Constructors */
explicit SPCurve();
explicit SPCurve(Geom::PathVector const& pathv);
- static SPCurve * new_from_rect(Geom::Rect const &rect);
+ static SPCurve * new_from_rect(Geom::Rect const &rect, bool all_four_sides = false);
virtual ~SPCurve();
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
index db0922915..33b08a91c 100644
--- a/src/display/nr-arena-glyphs.cpp
+++ b/src/display/nr-arena-glyphs.cpp
@@ -211,10 +211,10 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s
}
if (nr_rect_d_test_empty(bbox)) return NR_ARENA_ITEM_STATE_ALL;
- item->bbox.x0 = (gint32)(bbox.x0 - 1.0);
- item->bbox.y0 = (gint32)(bbox.y0 - 1.0);
- item->bbox.x1 = (gint32)(bbox.x1 + 1.0);
- item->bbox.y1 = (gint32)(bbox.y1 + 1.0);
+ item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0));
+ item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0));
+ item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1));
+ item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1));
return NR_ARENA_ITEM_STATE_ALL;
}
@@ -234,7 +234,7 @@ nr_arena_glyphs_clip(NRArenaItem *item, NRRectL */*area*/, NRPixBlock */*pb*/)
}
static NRArenaItem *
-nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble /*delta*/, unsigned int /*sticky*/)
+nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned int /*sticky*/)
{
NRArenaGlyphs *glyphs;
@@ -246,7 +246,7 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble /*delta*/, unsign
double const x = p[Geom::X];
double const y = p[Geom::Y];
/* With text we take a simple approach: pick if the point is in a characher bbox */
- if ((x >= item->bbox.x0) && (y >= item->bbox.y0) && (x <= item->bbox.x1) && (y <= item->bbox.y1)) return item;
+ if ((x + delta >= item->bbox.x0) && (y + delta >= item->bbox.y0) && (x - delta <= item->bbox.x1) && (y - delta <= item->bbox.y1)) return item;
return NULL;
}
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index f45a2da4f..493943168 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -151,10 +151,10 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned
nr_rect_d_matrix_transform (&bbox, &bbox, gc->transform);
- item->bbox.x0 = (int) floor (bbox.x0);
- item->bbox.y0 = (int) floor (bbox.y0);
- item->bbox.x1 = (int) ceil (bbox.x1);
- item->bbox.y1 = (int) ceil (bbox.y1);
+ item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0)); // Floor gives the coordinate in which the point resides
+ item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0));
+ item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1)); // Ceil gives the first coordinate beyond the point
+ item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1));
} else {
item->bbox.x0 = (int) gc->transform[4];
item->bbox.y0 = (int) gc->transform[5];
@@ -211,13 +211,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixB
} else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
} else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
-
- //FIXME: The _N_N_N_ version gives a gray border around images, see bug 906376
- // This mode is only used when exporting, screen rendering always has _P_P_P_, so I decided to simply replace it for now
- // Feel free to propose a better fix
-
- //nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
+ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
}
pb->empty = FALSE;
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index e2a9e9580..a3b295a4e 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -254,12 +254,11 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
if (state & NR_ARENA_ITEM_STATE_BBOX) {
if (shape->curve) {
boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
- /// \todo just write item->bbox = boundingbox
if (boundingbox) {
- item->bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F);
- item->bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F);
- item->bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F);
- item->bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F);
+ item->bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0])); // Floor gives the coordinate in which the point resides
+ item->bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
+ item->bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1])); // Ceil gives the first coordinate beyond the point
+ item->bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
} else {
item->bbox = NR_RECT_L_EMPTY;
}
@@ -300,10 +299,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
/// \todo just write item->bbox = boundingbox
if (boundingbox) {
- shape->approx_bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F);
- shape->approx_bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F);
- shape->approx_bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F);
- shape->approx_bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F);
+ shape->approx_bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
+ shape->approx_bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
+ shape->approx_bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
+ shape->approx_bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
} else {
shape->approx_bbox = NR_RECT_L_EMPTY;
}
@@ -349,10 +348,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
/// \todo just write shape->approx_bbox = boundingbox
if (boundingbox) {
- shape->approx_bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F);
- shape->approx_bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F);
- shape->approx_bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.9999F);
- shape->approx_bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.9999F);
+ shape->approx_bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
+ shape->approx_bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
+ shape->approx_bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
+ shape->approx_bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
} else {
shape->approx_bbox = NR_RECT_L_EMPTY;
}
@@ -362,10 +361,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
return NR_ARENA_ITEM_STATE_ALL;
/// \todo just write item->bbox = boundingbox
- item->bbox.x0 = (gint32)((*boundingbox)[0][0] - 1.0F);
- item->bbox.y0 = (gint32)((*boundingbox)[1][0] - 1.0F);
- item->bbox.x1 = (gint32)((*boundingbox)[0][1] + 1.0F);
- item->bbox.y1 = (gint32)((*boundingbox)[1][1] + 1.0F);
+ item->bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
+ item->bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
+ item->bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
+ item->bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
item->render_opacity = TRUE;
if ( shape->_fill.paint.type() == NRArenaShape::Paint::SERVER ) {
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index 4de5e658c..a983fb840 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -43,9 +43,8 @@ struct pixel_t {
static inline pixel_t pixelValue(NRPixBlock const* pb, int x, int y) {
if ( x < pb->area.x0 || x >= pb->area.x1 || y < pb->area.y0 || y >= pb->area.y1 ) return pixel_t::blank(); // This assumes anything outside the defined range is (0,0,0,0)
- pixel_t const* data = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(pb));
- int offset = (x-pb->area.x0) + (pb->area.x1-pb->area.x0)*(y-pb->area.y0);
- return data[offset];
+ pixel_t const* rowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(pb) + (y-pb->area.y0)*pb->rs);
+ return rowData[x-pb->area.x0];
}
template<bool PREMULTIPLIED>
@@ -74,18 +73,9 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) {
* We might as well avoid premultiplication in this case, which still gives us a fully
* transparent result, but with interpolated RGB parts. */
- /* First calculate interpolated alpha value. */
- unsigned ra = 0;
- if (!PREMULTIPLIED) {
- unsigned const y0 = sf*p00[3] + xf*(p01[3]-p00[3]); // range [0,a*sf]
- unsigned const y1 = sf*p10[3] + xf*(p11[3]-p10[3]);
- ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
- }
-
pixel_t r;
- if (ra == 0) {
- /* Either premultiplied or the interpolated alpha value is zero,
- * so do simple interpolation. */
+ if (PREMULTIPLIED) {
+ /* Premultiplied, so do simple interpolation. */
for (unsigned i = 0; i != 4; ++i) {
// y0,y1 have range [0,a*sf]
unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
@@ -95,21 +85,39 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) {
r[i] = (ri + sf2h)>>(2*sfl); // range [0,a]
}
} else {
- /* Do premultiplication ourselves. */
- for (unsigned i = 0; i != 3; ++i) {
- // Premultiplied versions. Range [0,255*a].
- unsigned const c00 = p00[i]*p00[3];
- unsigned const c01 = p01[i]*p01[3];
- unsigned const c10 = p10[i]*p10[3];
- unsigned const c11 = p11[i]*p11[3];
-
- // Interpolation.
- unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
- unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
- unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
- r[i] = (ri + ra/2) / ra; // range [0,255]
+ /* First calculate interpolated alpha value. */
+ unsigned const y0 = sf*p00[3] + xf*((unsigned int)p01[3]-(unsigned int)p00[3]); // range [0,a*sf]
+ unsigned const y1 = sf*p10[3] + xf*((unsigned int)p11[3]-(unsigned int)p10[3]);
+ unsigned const ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
+
+ if (ra==0) {
+ /* Fully transparent, so do simple interpolation. */
+ for (unsigned i = 0; i != 3; ++i) {
+ // y0,y1 have range [0,255*sf]
+ unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
+ unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
+
+ unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*sf*sf]
+ r[i] = (ri + sf2h)>>(2*sfl); // range [0,255]
+ }
+ r[3] = 0;
+ } else {
+ /* Do premultiplication ourselves. */
+ for (unsigned i = 0; i != 3; ++i) {
+ // Premultiplied versions. Range [0,255*a].
+ unsigned const c00 = p00[i]*p00[3];
+ unsigned const c01 = p01[i]*p01[3];
+ unsigned const c10 = p10[i]*p10[3];
+ unsigned const c11 = p11[i]*p11[3];
+
+ // Interpolation.
+ unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
+ unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
+ unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
+ r[i] = (ri + ra/2) / ra; // range [0,255]
+ }
+ r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
}
- r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
}
return r;
@@ -117,19 +125,17 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) {
template<bool MAP_PREMULTIPLIED, bool DATA_PREMULTIPLIED>
static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map, int Xchannel, int Ychannel, NRPixBlock* out, double scalex, double scaley) {
- pixel_t *out_data = reinterpret_cast<pixel_t*>(NR_PIXBLOCK_PX(out));
-
bool Xneedsdemul = MAP_PREMULTIPLIED && Xchannel<3;
bool Yneedsdemul = MAP_PREMULTIPLIED && Ychannel<3;
if (!Xneedsdemul) scalex /= 255.0;
if (!Yneedsdemul) scaley /= 255.0;
for (int yout=out->area.y0; yout < out->area.y1; yout++){
+ pixel_t const* mapRowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(map) + (yout-map->area.y0)*map->rs);
+ pixel_t* outRowData = reinterpret_cast<pixel_t*>(NR_PIXBLOCK_PX(out) + (yout-out->area.y0)*out->rs);
for (int xout=out->area.x0; xout < out->area.x1; xout++){
- int xmap = xout;
- int ymap = yout;
+ pixel_t const mapValue = mapRowData[xout-map->area.x0];
- pixel_t mapValue = pixelValue(map, xmap, ymap);
double xtex = xout + (Xneedsdemul ? // Although the value of the pixel corresponds to the MIDDLE of the pixel, no +0.5 is needed because we're interpolating pixels anyway (so to get the actual pixel locations 0.5 would have to be subtracted again).
(mapValue[3]==0?0:(scalex * (mapValue[Xchannel] - mapValue[3]*0.5) / mapValue[3])) :
(scalex * (mapValue[Xchannel] - 127.5)));
@@ -137,7 +143,7 @@ static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map
(mapValue[3]==0?0:(scaley * (mapValue[Ychannel] - mapValue[3]*0.5) / mapValue[3])) :
(scaley * (mapValue[Ychannel] - 127.5)));
- out_data[(xout-out->area.x0) + (out->area.x1-out->area.x0)*(yout-out->area.y0)] = interpolatePixels<DATA_PREMULTIPLIED>(texture, xtex, ytex);
+ outRowData[xout-out->area.x0] = interpolatePixels<DATA_PREMULTIPLIED>(texture, xtex, ytex);
}
}
}
@@ -152,8 +158,14 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
return 1;
}
- //TODO: check whether do we really need this check:
- if (map->area.x1 <= map->area.x0 || map->area.y1 <= map->area.y0) return 0; //nothing to do!
+ NR::IRect area = units.get_pixblock_filterarea_paraller();
+ int x0 = std::max(map->area.x0,area.min()[NR::X]);
+ int y0 = std::max(map->area.y0,area.min()[NR::Y]);
+ int x1 = std::min(map->area.x1,area.max()[NR::X]);
+ int y1 = std::min(map->area.y1,area.max()[NR::Y]);
+
+ //TODO: check whether we really need this check:
+ if (x1 <= x0 || y1 <= y0) return 0; //nothing to do!
if (texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
g_warning("Source images without an alpha channel are not supported by feDisplacementMap at the moment.");
@@ -161,13 +173,7 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
}
NRPixBlock *out = new NRPixBlock;
-
- out->area.x0 = map->area.x0;
- out->area.y0 = map->area.y0;
- out->area.x1 = map->area.x1;
- out->area.y1 = map->area.y1;
-
- nr_pixblock_setup_fast(out, texture->mode, out->area.x0, out->area.y0, out->area.x1, out->area.y1, true);
+ nr_pixblock_setup_fast(out, texture->mode, x0, y0, x1, y1, true);
// convert to a suitable format
bool free_map_on_exit = false;
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index d80782d20..9509eaef7 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -345,7 +345,7 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2,
// Filters over 1st dimension
// Assumes kernel is symmetric
-// scr_len should be size of kernel - 1
+// Kernel should have scr_len+1 elements
template<typename PT, unsigned int PC>
static void
filter2D_FIR(PT *const dst, int const dstr1, int const dstr2,
@@ -377,7 +377,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2,
for ( int c1 = 0 ; c1 < n1 ; c1++ ) {
int const src_disp = src_line + c1 * sstr1;
- int const dst_disp = dst_line + c1 * sstr1;
+ int const dst_disp = dst_line + c1 * dstr1;
// update history
for(int i=scr_len; i>0; i--) copy_n(history[i-1], PC, history[i]);
@@ -433,7 +433,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2,
// optimization: if there was no variation within this point's neighborhood,
// skip ahead while we keep seeing the same last_in byte:
// blurring flat color would not change it anyway
- if (different_count <= 1) {
+ if (different_count <= 1) { // note that different_count is at least 1, because last_in is initialized to -1
int pos = c1 + 1;
int nb_src_disp = src_disp + (1+scr_len)*sstr1 + byte; // src_line + (pos+scr_len) * sstr1 + byte
int nb_dst_disp = dst_disp + (1) *dstr1 + byte; // dst_line + (pos) * sstr1 + byte
@@ -441,7 +441,7 @@ filter2D_FIR(PT *const dst, int const dstr1, int const dstr2,
dst[nb_dst_disp] = last_in;
pos++;
nb_src_disp += sstr1;
- nb_dst_disp += sstr1;
+ nb_dst_disp += dstr1;
}
skipbuf[byte] = pos;
}
@@ -645,6 +645,8 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
}
}
}
+
+ // Resampling (if necessary), goes from in -> out (setting ssin to out if used)
NRPixBlock *ssin = in;
if ( resampling ) {
ssin = out;
@@ -667,6 +669,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
};
}
+ // Horizontal filtering, goes from ssin -> out (ssin might be equal to out, but these algorithms can be used in-place)
if (use_IIR_x) {
// Filter variables
IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point)
@@ -702,9 +705,9 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
default:
assert(false);
};
- } else if ( scr_len_x > 1 ) { // !use_IIR_x
+ } else if ( scr_len_x > 0 ) { // !use_IIR_x
// Filter kernel for x direction
- FIRValue kernel[scr_len_x];
+ FIRValue kernel[scr_len_x+1];
_make_kernel(kernel, deviation_x);
// Filter (x)
@@ -728,6 +731,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
nr_blit_pixblock_pixblock(out, ssin);
}
+ // Vertical filtering, goes from out -> out
if (use_IIR_y) {
// Filter variables
IIRValue b[N+1]; // scaling coefficient + filter coefficients (can be 10.21 fixed point)
@@ -763,9 +767,9 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
default:
assert(false);
};
- } else if ( scr_len_y > 1 ) { // !use_IIR_y
+ } else if ( scr_len_y > 0 ) { // !use_IIR_y
// Filter kernel for y direction
- FIRValue kernel[scr_len_y];
+ FIRValue kernel[scr_len_y+1];
_make_kernel(kernel, deviation_y);
// Filter (y)
@@ -791,6 +795,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
delete[] tmpdata[i]; // deleting a nullptr has no effect, so this is safe
}
+ // Upsampling, stores (the upsampled) out using slot.set(_output, ...)
if ( !resampling ) {
// No upsampling needed
out->empty = FALSE;
@@ -835,6 +840,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
slot.set(_output, finalout);
}
+ // If we downsampled the input, clean up the downsampled data
if (in != original_in) nr_pixblock_free(in);
return 0;
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index d0e0ec11e..3b19ff69b 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -223,6 +223,14 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
return 0;
}
+void Filter::set_filter_units(SPFilterUnits unit) {
+ _filter_units = unit;
+}
+
+void Filter::set_primitive_units(SPFilterUnits unit) {
+ _primitive_units = unit;
+}
+
void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
for (int i = 0 ; i < _primitive_count ; i++) {
if (_primitive[i]) _primitive[i]->area_enlarge(bbox, item->ctm);
diff --git a/src/display/pixblock-transform.cpp b/src/display/pixblock-transform.cpp
index 73b467d5a..af05a9b88 100644
--- a/src/display/pixblock-transform.cpp
+++ b/src/display/pixblock-transform.cpp
@@ -148,6 +148,11 @@ void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra
nr_blit_pixblock_pixblock(from, o_from);
free_from_on_exit = true;
}
+
+ if (from->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
+ // TODO: Fix this... (The problem is that for interpolation non-premultiplied colors should be premultiplied...)
+ g_warning("transform_bicubic does not properly support non-premultiplied images");
+ }
// Precalculate sizes of source and destination pixblocks
int from_width = from->area.x1 - from->area.x0;
diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp
index 1e4ca12a8..fe5bd0371 100644
--- a/src/display/snap-indicator.cpp
+++ b/src/display/snap-indicator.cpp
@@ -55,6 +55,14 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
return; // If we haven't snapped, then it is of no use to draw a snapindicator
}
+ if (p.getTarget() == SNAPTARGET_CONSTRAINT) {
+ // This is not a real snap, although moving along the constraint did affect the mouse pointer's position.
+ // Maybe we should only show a snap indicator when the user explicitly asked for a constraint by pressing ctrl?
+ // We should not show a snap indicator when stretching a selection box, which is also constrained. That would be
+ // too much information.
+ return;
+ }
+
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool value = prefs->getBool("/options/snapindicator/value", true);
diff --git a/src/ege-select-one-action.cpp b/src/ege-select-one-action.cpp
index 6de22495d..ebc7ea26d 100644
--- a/src/ege-select-one-action.cpp
+++ b/src/ege-select-one-action.cpp
@@ -18,7 +18,7 @@
*
* The Initial Developer of the Original Code is
* Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2007
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
@@ -64,7 +64,11 @@ static void ege_select_one_action_init( EgeSelectOneAction* action );
static void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
static void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
-static void resync_active( EgeSelectOneAction* act, gint active );
+static gint find_text_index(EgeSelectOneAction *act, gchar const* text);
+static void commit_pending_change(EgeSelectOneAction *act);
+static void resync_active( EgeSelectOneAction* act, gint active, gboolean override );
+static void combo_entry_changed_cb( GtkEntry* widget, gpointer user_data );
+static gboolean combo_entry_focus_lost_cb( GtkWidget *widget, GdkEventFocus *event, gpointer data );
static void combo_changed_cb( GtkComboBox* widget, gpointer user_data );
static void menu_toggled_cb( GtkWidget* obj, gpointer data );
static void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data );
@@ -74,6 +78,8 @@ static GtkWidget* create_tool_item( GtkAction* action );
static void connect_proxy( GtkAction *action, GtkWidget *proxy );
static void disconnect_proxy( GtkAction *action, GtkWidget *proxy );
+static int scan_max_width( GtkTreeModel *model, gint labelColumn );
+
static GtkActionClass* gParentClass = 0;
static guint signals[LAST_SIGNAL] = {0};
static GQuark gDataName = 0;
@@ -82,9 +88,15 @@ static GQuark gDataName = 0;
enum {
APPEARANCE_UNKNOWN = -1,
APPEARANCE_NONE = 0,
- APPEARANCE_FULL, // label, then all choices represented by separate buttons
- APPEARANCE_COMPACT, // label, then choices in a drop-down menu
- APPEARANCE_MINIMAL, // no label, just choices in a drop-down menu
+ APPEARANCE_FULL, /* label, then all choices represented by separate buttons */
+ APPEARANCE_COMPACT, /* label, then choices in a drop-down menu */
+ APPEARANCE_MINIMAL, /* no label, just choices in a drop-down menu */
+};
+
+enum {
+ SELECTION_UNKNOWN = -1,
+ SELECTION_CLOSED = 0,
+ SELECTION_OPEN,
};
struct _EgeSelectOneActionPrivate
@@ -94,11 +106,15 @@ struct _EgeSelectOneActionPrivate
gint iconColumn;
gint tooltipColumn;
gint appearanceMode;
+ gint selectionMode;
gint iconSize;
GType radioActionType;
GtkTreeModel* model;
- gchar* iconProperty;
- gchar* appearance;
+ gchar *iconProperty;
+ gchar *appearance;
+ gchar *selection;
+ gchar *activeText;
+ gchar *pendingText;
};
#define EGE_SELECT_ONE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_SELECT_ONE_ACTION_TYPE, EgeSelectOneActionPrivate ) )
@@ -111,7 +127,8 @@ enum {
PROP_TOOLTIP_COLUMN,
PROP_ICON_PROP,
PROP_ICON_SIZE,
- PROP_APPEARANCE
+ PROP_APPEARANCE,
+ PROP_SELECTION
};
GType ege_select_one_action_get_type( void )
@@ -169,7 +186,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
g_param_spec_int( "active",
"Active Selection",
"The index of the selected item",
- 0, 20, 0,
+ -1, G_MAXINT, 0,
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
g_object_class_install_property( objClass,
@@ -177,7 +194,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
g_param_spec_int( "label-column",
"Display Column",
"The column of the model that holds display strings",
- 0, 20, 0,
+ 0, G_MAXINT, 0,
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
g_object_class_install_property( objClass,
@@ -185,7 +202,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
g_param_spec_int( "icon-column",
"Icon Column",
"The column of the model that holds display icon name",
- -1, 20, -1,
+ -1, G_MAXINT, -1,
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
g_object_class_install_property( objClass,
@@ -193,7 +210,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
g_param_spec_int( "tooltip-column",
"Tooltip Column",
"The column of the model that holds tooltip strings",
- -1, 20, -1,
+ -1, G_MAXINT, -1,
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
g_object_class_install_property( objClass,
@@ -209,7 +226,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
g_param_spec_int( "icon-size",
"Icon Size",
"Target icon size",
- -1, 20, -1,
+ -1, G_MAXINT, -1,
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
g_object_class_install_property( objClass,
@@ -220,6 +237,14 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
"",
(GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
+ g_object_class_install_property( objClass,
+ PROP_SELECTION,
+ g_param_spec_string( "selection",
+ "Selection set open or closed",
+ "'open' to allow edits/additions, 'closed' to disallow.",
+ "",
+ (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
+
signals[CHANGED] = g_signal_new( "changed",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
@@ -241,11 +266,15 @@ void ege_select_one_action_init( EgeSelectOneAction* action )
action->private_data->iconColumn = -1;
action->private_data->tooltipColumn = -1;
action->private_data->appearanceMode = APPEARANCE_NONE;
+ action->private_data->selectionMode = SELECTION_CLOSED;
action->private_data->radioActionType = 0;
action->private_data->model = 0;
action->private_data->iconProperty = g_strdup("stock-id");
action->private_data->iconSize = -1;
action->private_data->appearance = 0;
+ action->private_data->selection = 0;
+ action->private_data->activeText = 0;
+ action->private_data->pendingText = 0;
/* g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */
}
@@ -278,6 +307,41 @@ gint ege_select_one_action_get_active( EgeSelectOneAction* action )
return action->private_data->active;
}
+gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action )
+{
+ GtkTreeIter iter;
+ gchar *str = 0;
+ g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
+
+ if ( action->private_data->active >= 0) {
+ if ( gtk_tree_model_iter_nth_child( action->private_data->model, &iter, NULL, action->private_data->active ) ) {
+ gtk_tree_model_get( action->private_data->model, &iter,
+ action->private_data->labelColumn, &str,
+ -1 );
+ }
+ } else if ( (action->private_data->active == -1) && action->private_data->activeText ) {
+ str = g_strdup(action->private_data->activeText);
+ }
+
+ return str;
+}
+
+void ege_select_one_action_set_active_text( EgeSelectOneAction* action, gchar const *text )
+{
+ g_return_if_fail( IS_EGE_SELECT_ONE_ACTION(action) );
+
+ if (action->private_data->activeText) {
+ g_free( action->private_data->activeText );
+ }
+ action->private_data->activeText = g_strdup(text);
+
+ if (action->private_data->active != -1) {
+ g_object_set( G_OBJECT(action), "active", -1, NULL );
+ } else {
+ resync_active( action, -1, TRUE );
+ }
+}
+
void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val )
{
g_object_set( G_OBJECT(action), "active", val, NULL );
@@ -332,6 +396,11 @@ void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar con
g_object_set( G_OBJECT(action), "appearance", val, NULL );
}
+void ege_select_one_action_set_selection( EgeSelectOneAction* action, gchar const* val )
+{
+ g_object_set( G_OBJECT(action), "selection", val, NULL );
+}
+
void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
{
EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
@@ -368,6 +437,10 @@ void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* val
g_value_set_string( value, action->private_data->appearance );
break;
+ case PROP_SELECTION:
+ g_value_set_string( value, action->private_data->selection );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
}
@@ -385,7 +458,7 @@ void ege_select_one_action_set_property( GObject* obj, guint propId, const GValu
case PROP_ACTIVE:
{
- resync_active( action, g_value_get_int( value ) );
+ resync_active( action, g_value_get_int( value ), FALSE );
}
break;
@@ -443,6 +516,23 @@ void ege_select_one_action_set_property( GObject* obj, guint propId, const GValu
}
break;
+ case PROP_SELECTION:
+ {
+ gchar* tmp = action->private_data->selection;
+ gchar* newVal = g_value_dup_string( value );
+ action->private_data->selection = newVal;
+ g_free( tmp );
+
+ if ( !action->private_data->selection || (strcmp("closed", newVal) == 0) ) {
+ action->private_data->selectionMode = SELECTION_CLOSED;
+ } else if ( strcmp("open", newVal) == 0 ) {
+ action->private_data->selectionMode = SELECTION_OPEN;
+ } else {
+ action->private_data->selectionMode = SELECTION_UNKNOWN;
+ }
+ }
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
}
@@ -480,6 +570,7 @@ GtkWidget* create_menu_item( GtkAction* action )
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), index == act->private_data->active );
g_free(str);
+ str = 0;
g_signal_connect( G_OBJECT(item), "toggled", G_CALLBACK(menu_toggled_cb), GINT_TO_POINTER(index) );
@@ -575,7 +666,7 @@ GtkWidget* create_tool_item( GtkAction* action )
g_object_set( G_OBJECT(obj), act->private_data->iconProperty, iconId, NULL );
}
- if ( act->private_data->iconProperty >= 0 ) {
+ if ( act->private_data->iconProperty ) {
/* TODO get this string to be set instead of hardcoded */
if ( act->private_data->iconSize >= 0 ) {
g_object_set( G_OBJECT(obj), "iconSize", act->private_data->iconSize, NULL );
@@ -614,24 +705,50 @@ GtkWidget* create_tool_item( GtkAction* action )
gtk_container_add( GTK_CONTAINER(item), holder );
} else {
- GtkWidget* holder = gtk_hbox_new( FALSE, 4 );
- GtkWidget* normal = gtk_combo_box_new_with_model( act->private_data->model );
-
GtkCellRenderer * renderer = 0;
+ GtkWidget *holder = gtk_hbox_new( FALSE, 4 );
+ GtkEntry *entry = 0;
+ GtkWidget *normal = (act->private_data->selectionMode == SELECTION_OPEN) ?
+ gtk_combo_box_entry_new_with_model( act->private_data->model, act->private_data->labelColumn ) :
+ gtk_combo_box_new_with_model( act->private_data->model );
+ if ((act->private_data->selectionMode == SELECTION_OPEN)) {
+ GtkWidget *child = gtk_bin_get_child( GTK_BIN(normal) );
+ if (GTK_IS_ENTRY(child)) {
+ int maxUsed = scan_max_width( act->private_data->model, act->private_data->labelColumn );
+ GtkEntryCompletion *complete = 0;
+ entry = GTK_ENTRY(child);
+ gtk_entry_set_width_chars(entry, maxUsed); /* replace with property */
+
+ complete = gtk_entry_completion_new();
+ gtk_entry_completion_set_model( complete, act->private_data->model );
+ gtk_entry_completion_set_text_column( complete, act->private_data->labelColumn );
+ gtk_entry_completion_set_inline_completion( complete, FALSE );
+ gtk_entry_completion_set_inline_selection( complete, FALSE );
+ gtk_entry_completion_set_popup_completion( complete, TRUE );
+ gtk_entry_completion_set_popup_set_width( complete, FALSE );
+ gtk_entry_set_completion( entry, complete );
+
+ g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(combo_entry_changed_cb), act );
+ g_signal_connect( G_OBJECT(child), "focus-out-event", G_CALLBACK(combo_entry_focus_lost_cb), act );
+ }
+ } else {
+ if ( act->private_data->iconColumn >= 0 ) {
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
- if ( act->private_data->iconColumn >= 0 ) {
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
+ /* "icon-name" */
+ gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn );
+ }
- // "icon-name"
- gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn );
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
+ gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn );
}
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
- gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn );
-
gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active );
+ if ( entry && (act->private_data->active == -1) ) {
+ gtk_entry_set_text( entry, act->private_data->activeText );
+ }
g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action );
@@ -649,7 +766,11 @@ GtkWidget* create_tool_item( GtkAction* action )
gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 );
- gtk_container_add( GTK_CONTAINER(item), holder );
+ {
+ GtkWidget *align = gtk_alignment_new(0, 0.5, 0, 0);
+ gtk_container_add( GTK_CONTAINER(align), holder);
+ gtk_container_add( GTK_CONTAINER(item), align );
+ }
}
gtk_widget_show_all( item );
@@ -672,9 +793,9 @@ void disconnect_proxy( GtkAction *action, GtkWidget *proxy )
}
-void resync_active( EgeSelectOneAction* act, gint active )
+void resync_active( EgeSelectOneAction* act, gint active, gboolean override )
{
- if ( act->private_data->active != active ) {
+ if ( override || (act->private_data->active != active) ) {
act->private_data->active = active;
GSList* proxies = gtk_action_get_proxies( GTK_ACTION(act) );
while ( proxies ) {
@@ -683,9 +804,15 @@ void resync_active( EgeSelectOneAction* act, gint active )
GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) );
if ( children && children->data ) {
gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" );
+ if (!combodata && GTK_IS_ALIGNMENT(children->data)) {
+ GList *other = gtk_container_get_children( GTK_CONTAINER(children->data) );
+ combodata = g_object_get_data( G_OBJECT(other->data), "ege-combo-box" );
+ }
if ( GTK_IS_COMBO_BOX(combodata) ) {
GtkComboBox* combo = GTK_COMBO_BOX(combodata);
- if ( gtk_combo_box_get_active(combo) != active ) {
+ if ((active == -1) && (GTK_IS_COMBO_BOX_ENTRY(combo))) {
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))), act->private_data->activeText);
+ } else if ( gtk_combo_box_get_active(combo) != active ) {
gtk_combo_box_set_active( combo, active );
}
} else if ( GTK_IS_HBOX(children->data) ) {
@@ -732,9 +859,107 @@ void combo_changed_cb( GtkComboBox* widget, gpointer user_data )
{
EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
gint newActive = gtk_combo_box_get_active(widget);
- if (newActive != act->private_data->active && newActive != -1) {
+ gchar *text = gtk_combo_box_get_active_text(widget);
+
+ if (newActive == -1) {
+ /* indicates the user is entering text for a custom aka "open" value */
+ if (act->private_data->pendingText && text && (strcmp(act->private_data->pendingText, text) == 0) ) {
+ /* The currently entered data matches the last seen */
+ } else {
+ if (act->private_data->pendingText) {
+ g_free(act->private_data->pendingText);
+ }
+ act->private_data->pendingText = text;
+ text = 0;
+ }
+ } else if (newActive != act->private_data->active) {
+ if (act->private_data->pendingText) {
+ g_free(act->private_data->pendingText);
+ act->private_data->pendingText = 0;
+ }
g_object_set( G_OBJECT(act), "active", newActive, NULL );
}
+
+ if (text) {
+ g_free(text);
+ text = 0;
+ }
+}
+
+gboolean combo_entry_focus_lost_cb( GtkWidget *widget, GdkEventFocus *event, gpointer data )
+{
+ EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(data);
+ (void)widget;
+ (void)event;
+
+ commit_pending_change(act);
+
+ return FALSE;
+}
+
+void combo_entry_changed_cb( GtkEntry* widget, gpointer user_data )
+{
+ EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
+ (void)widget;
+ commit_pending_change(act);
+}
+
+void commit_pending_change(EgeSelectOneAction *act)
+{
+ if (act->private_data->pendingText) {
+ if (act->private_data->activeText && (strcmp(act->private_data->pendingText, act->private_data->activeText) == 0)) {
+ /* Was the same value */
+ g_free(act->private_data->pendingText);
+ act->private_data->pendingText = 0;
+ } else {
+ gint matching = find_text_index(act, act->private_data->pendingText);
+
+ if (act->private_data->activeText) {
+ g_free(act->private_data->activeText);
+ }
+ act->private_data->activeText = act->private_data->pendingText;
+ act->private_data->pendingText = 0;
+
+ if (matching >= 0) {
+ g_free(act->private_data->activeText);
+ act->private_data->activeText = 0;
+ g_object_set( G_OBJECT(act), "active", matching, NULL );
+ } else if (act->private_data->active != -1) {
+ g_object_set( G_OBJECT(act), "active", -1, NULL );
+ } else {
+ resync_active( act, -1, TRUE );
+ }
+ }
+ }
+}
+
+gint find_text_index(EgeSelectOneAction *act, gchar const* text)
+{
+ gint index = -1;
+
+ if (text) {
+ GtkTreeIter iter;
+ gboolean valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
+ gint curr = 0;
+ while ( valid && (index < 0) ) {
+ gchar* str = 0;
+ gtk_tree_model_get( act->private_data->model, &iter,
+ act->private_data->labelColumn, &str,
+ -1 );
+
+ if (str && (strcmp(text, str) == 0)) {
+ index = curr;
+ }
+
+ g_free(str);
+ str = 0;
+
+ curr++;
+ valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
+ }
+ }
+
+ return index;
}
void menu_toggled_cb( GtkWidget* obj, gpointer data )
@@ -758,3 +983,25 @@ void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, g
}
}
}
+
+int scan_max_width( GtkTreeModel *model, gint labelColumn )
+{
+ int maxUsed = 0;
+ GtkTreeIter iter;
+ gboolean valid = gtk_tree_model_get_iter_first( model, &iter );
+ while ( valid ) {
+ gchar* str = 0;
+ int count = 0;
+ gtk_tree_model_get( model, &iter,
+ labelColumn, &str,
+ -1 );
+ count = strlen(str);
+ if (count > maxUsed) {
+ maxUsed = count;
+ }
+ g_free( str );
+
+ valid = gtk_tree_model_iter_next( model, &iter );
+ }
+ return maxUsed;
+}
diff --git a/src/ege-select-one-action.h b/src/ege-select-one-action.h
index d0c9d6de7..aa20d55a7 100644
--- a/src/ege-select-one-action.h
+++ b/src/ege-select-one-action.h
@@ -20,7 +20,7 @@
*
* The Initial Developer of the Original Code is
* Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2007
+ * Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
@@ -122,6 +122,22 @@ GtkTreeModel *ege_select_one_action_get_model(EgeSelectOneAction* action );
gint ege_select_one_action_get_active( EgeSelectOneAction* action );
/**
+ * Returns the text of the currently selected item.
+ *
+ * @param action The action to fetch the text for.
+ * @return the selected text. The caller is responsible to call g_free() on it when done.
+ */
+gchar *ege_select_one_action_get_active_text( EgeSelectOneAction* action );
+
+/**
+ * Sets the text of the currently selected item.
+ *
+ * @param action The action to fetch the text for.
+ * @param text the text to set.
+ */
+void ege_select_one_action_set_active_text( EgeSelectOneAction* action, gchar const *text );
+
+/**
* Sets the currently selected item.
*
* @param action The action to fetch the selected index for.
@@ -191,6 +207,15 @@ void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint
*/
void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val );
+/**
+ * Sets to allow or disallow free entry additions to the list.
+ * The default is "closed" selections that do not allow additions/edits.
+ * This is the XForms functional 'selection' attribute: "open", "closed".
+ *
+ * @param action The action to set the tooltip column for.
+ * @param val The value of the selection attribute.
+ */
+void ege_select_one_action_set_selection( EgeSelectOneAction *action, gchar const* val );
/* bit of a work-around */
void ege_select_one_action_set_radio_action_type( EgeSelectOneAction* action, GType radioActionType );
diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp
index 022de4090..6afa07d77 100644
--- a/src/eraser-context.cpp
+++ b/src/eraser-context.cpp
@@ -749,7 +749,7 @@ set_to_accumulated(SPEraserContext *dc)
if ( eraserMode ) {
toWorkOn = sp_document_partial_items_in_box(sp_desktop_document(desktop), desktop->dkey, bounds);
} else {
- Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
toWorkOn = sp_document_items_at_points(sp_desktop_document(desktop), desktop->dkey, r->getPoints());
}
toWorkOn = g_slist_remove( toWorkOn, acid );
diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp
index 60623191f..53a666e25 100644
--- a/src/extension/implementation/script.cpp
+++ b/src/extension/implementation/script.cpp
@@ -21,6 +21,8 @@
#include <unistd.h>
#include <errno.h>
+#include <glib.h>
+#include <glib/gstdio.h>
#include <gtkmm.h>
#include "ui/view/view.h"
@@ -101,14 +103,12 @@ Script::interpreter_t const Script::interpreterTab[] = {
\param interpNameArg The name of the interpreter that we're looking
for, should be an entry in interpreterTab
*/
-Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg)
+std::string Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg)
{
- Glib::ustring interpName = interpNameArg;
-
interpreter_t const *interp = 0;
bool foundInterp = false;
for (interp = interpreterTab ; interp->identity ; interp++ ){
- if (interpName == interp->identity) {
+ if (interpNameArg == interp->identity) {
foundInterp = true;
break;
}
@@ -118,55 +118,25 @@ Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNa
if (!foundInterp) {
return "";
}
- interpName = interp->defaultval;
+ std::string interpreter_path = Glib::filename_from_utf8(interp->defaultval);
- // 1. Check preferences
+ // 1. Check preferences for an override.
+ // Note: this must be an absolute path.
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
Glib::ustring prefInterp = prefs->getString("/extensions/" + Glib::ustring(interp->prefstring));
if (!prefInterp.empty()) {
- interpName = prefInterp;
- return interpName;
- }
-
-#ifdef WIN32
-
- // 2. Windows. Try looking relative to inkscape.exe
- RegistryTool rt;
- Glib::ustring fullPath;
- Glib::ustring path;
- Glib::ustring exeName;
- if (rt.getExeInfo(fullPath, path, exeName)) {
-// TODO replace with proper glib/glibmm path building routines:
- Glib::ustring interpPath = path;
- interpPath.append("\\");
- interpPath.append(interpNameArg);
- interpPath.append("\\");
- interpPath.append(interpName);
- interpPath.append(".exe");
- struct stat finfo;
- if (stat(interpPath .c_str(), &finfo) == 0) {
- g_message("Found local interpreter, '%s', Size: %d",
- interpPath .c_str(),
- (int)finfo.st_size);
- return interpPath;
- }
+ interpreter_path = Glib::filename_from_utf8(prefInterp);
}
- // 3. Try searching the path
- char szExePath[MAX_PATH] = {0};
- char szCurrentDir[MAX_PATH] = {0};
- GetCurrentDirectory(sizeof(szCurrentDir), szCurrentDir);
- HINSTANCE ret = FindExecutable(interpName.c_str(), szCurrentDir, szExePath);
- if (ret > reinterpret_cast<HINSTANCE>(32)) {
- interpName = szExePath;
- return interpName;
+ // 2. Search the path.
+ // Do this on all systems, for consistency.
+ // PATH is set up to contain the Python and Perl binary directories
+ // on Windows, so no extra code is necessary.
+ if (!Glib::path_is_absolute(interpreter_path)) {
+ interpreter_path = Glib::find_program_in_path(interpreter_path);
}
-
-#endif // win32
-
-
- return interpName;
+ return interpreter_path;
}
/** \brief This function creates a script object and sets up the
@@ -206,38 +176,33 @@ Script::~Script()
string. This means that the caller of this function can always
free what they are given (and should do it too!).
*/
-Glib::ustring
+std::string
Script::solve_reldir(Inkscape::XML::Node *reprin) {
gchar const *s = reprin->attribute("reldir");
- if (!s) {
+ // right now the only recognized relative directory is "extensions"
+ if (!s || Glib::ustring(s) != "extensions") {
Glib::ustring str = sp_repr_children(reprin)->content();
return str;
}
Glib::ustring reldir = s;
- if (reldir == "extensions") {
-
- for (unsigned int i=0;
- i < Inkscape::Extension::Extension::search_path.size();
- i++) {
+ for (unsigned int i=0;
+ i < Inkscape::Extension::Extension::search_path.size();
+ i++) {
- gchar * fname = g_build_filename(
- Inkscape::Extension::Extension::search_path[i],
- sp_repr_children(reprin)->content(),
- NULL);
- Glib::ustring filename = fname;
- g_free(fname);
+ gchar * fname = g_build_filename(
+ Inkscape::Extension::Extension::search_path[i],
+ sp_repr_children(reprin)->content(),
+ NULL);
+ Glib::ustring filename = fname;
+ g_free(fname);
- if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) {
- return filename;
- }
+ if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) {
+ return Glib::filename_from_utf8(filename);
}
- } else {
- Glib::ustring str = sp_repr_children(reprin)->content();
- return str;
}
return "";
@@ -261,29 +226,25 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) {
then a TRUE is returned. If we get all the way through the path
then a FALSE is returned, the command could not be found.
*/
-bool Script::check_existance(const Glib::ustring &command)
+bool Script::check_existence(const std::string &command)
{
// Check the simple case first
- if (command.size() == 0) {
+ if (command.empty()) {
return false;
}
- //Don't search when it contains a slash. */
- if (command.find(G_DIR_SEPARATOR) != command.npos) {
- if (Inkscape::IO::file_test(command.c_str(), G_FILE_TEST_EXISTS)) {
+ //Don't search when it is an absolute path. */
+ if (!Glib::path_is_absolute(command)) {
+ if (Glib::file_test(command, Glib::FILE_TEST_EXISTS)) {
return true;
} else {
return false;
}
}
-
- Glib::ustring path;
- gchar *s = (gchar *) g_getenv("PATH");
- if (s) {
- path = s;
- } else {
+ std::string path = Glib::getenv("PATH");
+ if (path.empty()) {
/* There is no `PATH' in the environment.
The default search path is the current directory */
path = G_SEARCHPATH_SEPARATOR_S;
@@ -293,7 +254,7 @@ bool Script::check_existance(const Glib::ustring &command)
std::string::size_type pos2 = 0;
while ( pos < path.size() ) {
- Glib::ustring localPath;
+ std::string localPath;
pos2 = path.find(G_SEARCHPATH_SEPARATOR, pos);
if (pos2 == path.npos) {
@@ -305,11 +266,11 @@ bool Script::check_existance(const Glib::ustring &command)
}
//printf("### %s\n", localPath.c_str());
- Glib::ustring candidatePath =
+ std::string candidatePath =
Glib::build_filename(localPath, command);
- if (Inkscape::IO::file_test(candidatePath .c_str(),
- G_FILE_TEST_EXISTS)) {
+ if (Glib::file_test(candidatePath,
+ Glib::FILE_TEST_EXISTS)) {
return true;
}
@@ -357,16 +318,10 @@ bool Script::load(Inkscape::Extension::Extension *module)
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "command")) {
const gchar *interpretstr = child_repr->attribute("interpreter");
if (interpretstr != NULL) {
- Glib::ustring interpString =
- resolveInterpreterExecutable(interpretstr);
- //g_message("Found: %s and %s",interpString.c_str(),interpretstr);
- command.insert(command.end(), interpretstr);
+ std::string interpString = resolveInterpreterExecutable(interpretstr);
+ command.insert(command.end(), interpString);
}
- Glib::ustring tmp = "\"";
- tmp += solve_reldir(child_repr);
- tmp += "\"";
-
- command.insert(command.end(), tmp);
+ command.insert(command.end(), solve_reldir(child_repr));
}
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "helper_extension")) {
helper_extension = sp_repr_children(child_repr)->content();
@@ -419,10 +374,10 @@ Script::check(Inkscape::Extension::Extension *module)
child_repr = sp_repr_children(child_repr);
while (child_repr != NULL) {
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "check")) {
- Glib::ustring command_text = solve_reldir(child_repr);
- if (command_text.size() > 0) {
+ std::string command_text = solve_reldir(child_repr);
+ if (!command_text.empty()) {
/* I've got the command */
- bool existance = check_existance(command_text);
+ bool existance = check_existence(command_text);
if (!existance)
return false;
}
@@ -763,8 +718,7 @@ void Script::effect(Inkscape::Extension::Effect *module,
// make sure we don't leak file descriptors from g_file_open_tmp
close(tempfd_out);
- // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name
- unlink(tempfilename_out.c_str());
+ g_unlink(tempfilename_out.c_str());
/* Do something with mydoc.... */
if (mydoc) {
@@ -937,89 +891,61 @@ int Script::execute (const std::list<std::string> &in_command,
const Glib::ustring &filein,
file_listener &fileout)
{
- g_return_val_if_fail(in_command.size() > 0, 0);
+ g_return_val_if_fail(!in_command.empty(), 0);
// printf("Executing\n");
- std::vector <std::string> argv;
-
-/*
- for (std::list<std::string>::const_iterator i = in_command.begin();
- i != in_command.end(); i++) {
- argv.push_back(*i);
- }
-*/
- // according to http://www.gtk.org/api/2.6/glib/glib-Spawning-Processes.html spawn quotes parameter containing spaces
- // we tokenize so that spwan does not need to quote over all params
- for (std::list<std::string>::const_iterator i = in_command.begin();
- i != in_command.end(); i++) {
- std::string param_str = *i;
- do {
- //g_message("param: %s", param_str.c_str());
- size_t first_space = param_str.find_first_of(' ');
- size_t first_quote = param_str.find_first_of('"');
- //std::cout << "first space " << first_space << std::endl;
- //std::cout << "first quote " << first_quote << std::endl;
-
- if ((first_quote != std::string::npos) && (first_quote == 0)) {
- size_t next_quote = param_str.find_first_of('"', first_quote + 1);
- //std::cout << "next quote " << next_quote << std::endl;
-
- if (next_quote != std::string::npos) {
- //std::cout << "now split " << next_quote << std::endl;
- //std::cout << "now split " << param_str.substr(1, next_quote - 1) << std::endl;
- //std::cout << "now split " << param_str.substr(next_quote + 1) << std::endl;
- std::string part_str = param_str.substr(1, next_quote - 1);
- if (part_str.size() > 0)
- argv.push_back(part_str);
- param_str = param_str.substr(next_quote + 1);
-
- } else {
- if (param_str.size() > 0)
- argv.push_back(param_str);
- param_str = "";
- }
-
- } else if (first_space != std::string::npos) {
- //std::cout << "now split " << first_space << std::endl;
- //std::cout << "now split " << param_str.substr(0, first_space) << std::endl;
- //std::cout << "now split " << param_str.substr(first_space + 1) << std::endl;
- std::string part_str = param_str.substr(0, first_space);
- if (part_str.size() > 0) {
- argv.push_back(part_str);
- }
- param_str = param_str.substr(first_space + 1);
- } else {
- if (param_str.size() > 0) {
- argv.push_back(param_str);
- }
- param_str = "";
- }
- } while (param_str.size() > 0);
- }
-
- for (std::list<std::string>::const_iterator i = in_params.begin();
- i != in_params.end(); i++) {
- //g_message("Script parameter: %s",(*i)g.c_str());
- argv.push_back(*i);
- }
-
- if (!(filein.empty())) {
+ std::vector<std::string> argv;
+
+ bool interpreted = (in_command.size() == 2);
+ std::string program = in_command.front();
+ std::string script = interpreted ? in_command.back() : "";
+ std::string working_directory = "";
+
+ // Use Glib::find_program_in_path instead of the equivalent
+ // Glib::spawn_* functionality, because _wspawnp is broken on Windows:
+ // it doesn't work when PATH contains Unicode directories
+ if (!Glib::path_is_absolute(program)) {
+ program = Glib::find_program_in_path(program);
+ }
+ argv.push_back(program);
+
+ if (interpreted) {
+ // On Windows, Python garbles Unicode command line parameters
+ // in an useless way. This means extensions fail when Inkscape
+ // is run from an Unicode directory.
+ // As a workaround, we set the working directory to the one
+ // containing the script.
+ working_directory = Glib::path_get_dirname(script);
+ script = Glib::path_get_basename(script);
+ #ifdef G_OS_WIN32
+ // ANNOYING: glibmm does not wrap g_win32_locale_filename_from_utf8
+ gchar *workdir_s = g_win32_locale_filename_from_utf8(working_directory.data());
+ working_directory = workdir_s;
+ g_free(workdir_s);
+ #endif
+
+ argv.push_back(script);
+ }
+
+ // assemble the rest of argv
+ std::copy(in_params.begin(), in_params.end(), std::back_inserter(argv));
+ if (!filein.empty()) {
argv.push_back(filein);
}
int stdout_pipe, stderr_pipe;
try {
- Inkscape::IO::spawn_async_with_pipes(Glib::get_current_dir(), // working directory
+ Glib::spawn_async_with_pipes(working_directory, // working directory
argv, // arg v
- Glib::SPAWN_SEARCH_PATH /*| Glib::SPAWN_DO_NOT_REAP_CHILD*/,
+ static_cast<Glib::SpawnFlags>(0), // no flags
sigc::slot<void>(),
&_pid, // Pid
NULL, // STDIN
&stdout_pipe, // STDOUT
&stderr_pipe); // STDERR
- } catch (Glib::SpawnError e) {
- printf("Can't Spawn!!! spawn returns: %d\n", e.code());
+ } catch (Glib::Error e) {
+ printf("Can't Spawn!!! spawn returns: %s\n", e.what().data());
return 0;
}
diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h
index e0b6701bf..f37f27966 100644
--- a/src/extension/implementation/script.h
+++ b/src/extension/implementation/script.h
@@ -115,31 +115,14 @@ private:
*/
Glib::ustring helper_extension;
- /**
- * Just a quick function to find and resolve relative paths for
- * the incoming scripts
- */
- Glib::ustring solve_reldir (Inkscape::XML::Node *reprin);
-
- /**
- *
- */
- bool check_existance (const Glib::ustring &command);
-
- /**
- *
- */
+ std::string solve_reldir (Inkscape::XML::Node *reprin);
+ bool check_existence (const std::string &command);
void copy_doc (Inkscape::XML::Node * olddoc,
Inkscape::XML::Node * newdoc);
-
- /**
- *
- */
void checkStderr (const Glib::ustring &filename,
Gtk::MessageType type,
const Glib::ustring &message);
-
class file_listener {
Glib::ustring _string;
sigc::connection _conn;
@@ -184,7 +167,6 @@ private:
return true;
};
- // Note, doing a copy here, on purpose
Glib::ustring string (void) { return _string; };
bool toFile (const Glib::ustring &name) {
@@ -215,7 +197,7 @@ private:
};
static interpreter_t const interpreterTab[];
- Glib::ustring resolveInterpreterExecutable(const Glib::ustring &interpNameArg);
+ std::string resolveInterpreterExecutable(const Glib::ustring &interpNameArg);
}; // class Script
diff --git a/src/extension/internal/bitmap/solarize.cpp b/src/extension/internal/bitmap/solarize.cpp
index 147c4f0b5..ea9ec42f3 100644
--- a/src/extension/internal/bitmap/solarize.cpp
+++ b/src/extension/internal/bitmap/solarize.cpp
@@ -18,7 +18,9 @@ namespace Bitmap {
void
Solarize::applyEffect(Magick::Image* image) {
- image->solarize(_factor);
+ // Image Magick Quantum depth = 16
+ // 655.35 = (2^16 - 1) / 100
+ image->solarize(_factor * 655.35);
}
void
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 877bdb952..cf3c72432 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -80,7 +80,8 @@
#include <pango/pangofc-fontmap.h>
//#define TRACE(_args) g_printf _args
-#define TRACE(_args) g_message _args
+//#define TRACE(_args) g_message _args
+#define TRACE(_args)
//#define TEST(_args) _args
#define TEST(_args)
@@ -819,7 +820,6 @@ CairoRenderContext::setSurfaceTarget(cairo_surface_t *surface, bool is_vector, c
bool
CairoRenderContext::_finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t *ctm)
{
-g_message("enter");
if(surface == NULL) {
return false;
}
@@ -846,7 +846,7 @@ g_message("enter");
}
_is_valid = TRUE;
-g_message("leave");
+
return true;
}
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 6e4bb3b7e..ebdb82a69 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -608,8 +608,8 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page
NRRect d;
if (pageBoundingBox) {
d.x0 = d.y0 = 0;
- d.x1 = ceil(sp_document_width(doc));
- d.y1 = ceil(sp_document_height(doc));
+ d.x1 = sp_document_width(doc);
+ d.y1 = sp_document_height(doc);
} else {
sp_item_invoke_bbox(base, &d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX);
}
diff --git a/src/extension/internal/filter/filter-file.cpp b/src/extension/internal/filter/filter-file.cpp
index 7cb671f51..89afca133 100644
--- a/src/extension/internal/filter/filter-file.cpp
+++ b/src/extension/internal/filter/filter-file.cpp
@@ -161,7 +161,7 @@ Filter::filters_load_node (Inkscape::XML::Node * node, gchar * menuname)
mywriter writer;
sp_repr_write_stream(node, writer, 0, FALSE, g_quark_from_static_string("svg"), 0, 0);
- Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(g_strdup(writer.c_str())));
+ Inkscape::Extension::build_from_mem(xml_str, new Filter(g_strdup(writer.c_str())));
g_free(xml_str);
return;
}
diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp
index 30e622507..c2d80b28b 100644
--- a/src/extension/internal/filter/filter.cpp
+++ b/src/extension/internal/filter/filter.cpp
@@ -219,7 +219,7 @@ Filter::filter_init (gchar const * id, gchar const * name, gchar const * submenu
"<menu-tip>%s</menu-tip>\n"
"</effect>\n"
"</inkscape-extension>\n", name, id, submenu, tip);
- Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(filter));
+ Inkscape::Extension::build_from_mem(xml_str, new Filter(filter));
g_free(xml_str);
return;
}
diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp
index d4b35b261..39bca52d8 100644
--- a/src/extension/internal/grid.cpp
+++ b/src/extension/internal/grid.cpp
@@ -46,25 +46,29 @@ Grid::load (Inkscape::Extension::Extension */*module*/)
namespace {
-Glib::ustring build_lines(int axis, Geom::Rect bounding_area,
- float offset, float spacing)
+Glib::ustring build_lines(Geom::Rect bounding_area,
+ float offset[], float spacing[])
{
Geom::Point point_offset(0.0, 0.0);
- point_offset[axis] = offset;
SVG::PathString path_data;
- for (Geom::Point start_point = bounding_area.min();
- start_point[axis] + offset <= (bounding_area.max())[axis];
- start_point[axis] += spacing) {
- Geom::Point end_point = start_point;
- end_point[1-axis] = (bounding_area.max())[1-axis];
-
- path_data.moveTo(start_point + point_offset)
- .lineTo(end_point + point_offset);
- }
- return path_data;
-}
+ for ( int axis = 0 ; axis < 2 ; ++axis ) {
+ point_offset[axis] = offset[axis];
+
+ for (Geom::Point start_point = bounding_area.min();
+ start_point[axis] + offset[axis] <= (bounding_area.max())[axis];
+ start_point[axis] += spacing[axis]) {
+ Geom::Point end_point = start_point;
+ end_point[1-axis] = (bounding_area.max())[1-axis];
+
+ path_data.moveTo(start_point + point_offset)
+ .lineTo(end_point + point_offset);
+ }
+ }
+ // std::cout << "Path data:" << path_data.c_str() << std::endl;
+ return path_data;
+ }
}
@@ -104,11 +108,9 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc
module->get_param_float("yoffset") };
Glib::ustring path_data("");
- for ( int axis = 0 ; axis < 2 ; ++axis ) {
- path_data += build_lines(axis, bounding_area,
- offsets[axis], spacings[axis]);
- }
+ path_data = build_lines(bounding_area,
+ offsets, spacings);
Inkscape::XML::Document * xml_doc = sp_document_repr_doc(document->doc());
Inkscape::XML::Node * current_layer = static_cast<SPDesktop *>(document)->currentLayer()->repr;
Inkscape::XML::Node * path = xml_doc->createElement("svg:path");
diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp
index ca061a63a..a4d348940 100644
--- a/src/extension/internal/javafx-out.cpp
+++ b/src/extension/internal/javafx-out.cpp
@@ -791,7 +791,8 @@ bool JavaFXOutput::doBody(SPDocument *doc, SPObject *obj)
SPShape *shape = SP_SHAPE(item);
SPCurve *curve = shape->curve;
if (!curve->is_empty()) {
- out(" %s(),\n", id.c_str());
+ String jfxid = sanatize(id);
+ out(" %s(),\n", jfxid.c_str());
}
}
}
diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp
index 28bba1beb..c6c597b7a 100644
--- a/src/extension/internal/latex-text-renderer.cpp
+++ b/src/extension/internal/latex-text-renderer.cpp
@@ -350,13 +350,13 @@ Flowing in rectangle is possible, not in arb shape.
g_free(strtext);
g_strfreev(splitstr);
- if (!flowtext->has_internal_frame()) {
- // has_internal_frame includes a check that frame is a SPRect
+ SPItem *frame_item = flowtext->get_frame(NULL);
+ if (!frame_item || !SP_IS_RECT(frame_item)) {
g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text.");
return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think
}
- SPRect *frame = SP_RECT(flowtext->get_frame(NULL));
+ SPRect *frame = SP_RECT(frame_item);
Geom::Rect framebox = sp_rect_get_rect(frame) * transform();
// get position and alignment
@@ -365,13 +365,13 @@ Flowing in rectangle is possible, not in arb shape.
gchar const *justification = "";
switch (flowtext->layout.paragraphAlignment(flowtext->layout.begin())) {
case Inkscape::Text::Layout::LEFT:
- justification = "\\raggedright";
+ justification = "\\raggedright ";
break;
case Inkscape::Text::Layout::RIGHT:
- justification = "\\raggedleft";
+ justification = "\\raggedleft ";
break;
case Inkscape::Text::Layout::CENTER:
- justification = "\\centering";
+ justification = "\\centering ";
case Inkscape::Text::Layout::FULL:
default:
// no need to add LaTeX code for standard justified output :)
diff --git a/src/fill-or-stroke.h b/src/fill-or-stroke.h
index e4195324f..a38dfc32d 100644
--- a/src/fill-or-stroke.h
+++ b/src/fill-or-stroke.h
@@ -8,4 +8,4 @@
/** \post STROKE == 0, FILL != 0. */
enum FillOrStroke { STROKE = 0, FILL = 1 };
-#endif /* !SEEN_FILL_OR_STROKE_H */
+#endif // !SEEN_FILL_OR_STROKE_H
diff --git a/src/flood-context.cpp b/src/flood-context.cpp
index 7b6223384..612ae1cfc 100644
--- a/src/flood-context.cpp
+++ b/src/flood-context.cpp
@@ -900,7 +900,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
if (is_point_fill) {
fill_points.push_back(Geom::Point(event->button.x, event->button.y));
} else {
- Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
fill_points = r->getPoints();
}
@@ -1206,7 +1206,7 @@ static gint sp_flood_context_root_handler(SPEventContext *event_context, GdkEven
case GDK_BUTTON_RELEASE:
if (event->button.button == 1 && !event_context->space_panning) {
- Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
if (r->is_started()) {
// set "busy" cursor
desktop->setWaitingCursor();
diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp
index ed20f9b61..ddb153ffd 100644
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
@@ -650,7 +650,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
if (!event_context->within_tolerance) {
// we've been dragging, either do nothing (grdrag handles that),
// or rubberband-select if we have rubberband
- Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
if (r->is_started() && !event_context->within_tolerance) {
// this was a rubberband drag
if (r->getMode() == RUBBERBAND_MODE_RECT) {
diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp
new file mode 100644
index 000000000..61d6bb9c4
--- /dev/null
+++ b/src/ink-comboboxentry-action.cpp
@@ -0,0 +1,605 @@
+/*
+ * A subclass of GtkAction that wraps a GtkComboBoxEntry.
+ * Features:
+ * Setting GtkEntryBox width in characters.
+ * Passing a function for formatting cells.
+ * Displaying a warning if text isn't in list.
+ *
+ * Author(s):
+ * Tavmjong Bah
+ *
+ * Copyright (C) 2010 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+/*
+ * We must provide for both a toolbar item and a menu item.
+ * As we don't know which widgets are used (or even constructed),
+ * we must keep track of things like active entry ourselves.
+ */
+
+#include <iostream>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gtk/gtktoolitem.h>
+#include <gtk/gtkcomboboxentry.h>
+#include <gtk/gtkentrycompletion.h>
+
+#include "ink-comboboxentry-action.h"
+
+// Must handle both tool and menu items!
+static GtkWidget* create_tool_item( GtkAction* action );
+static GtkWidget* create_menu_item( GtkAction* action );
+
+// Internal
+static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, gchar* target_text );
+
+// Callbacks
+static void combo_box_changed_cb( GtkComboBoxEntry* widget, gpointer data );
+static void entry_activate_cb( GtkEntry* widget, gpointer data );
+static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data );
+
+enum {
+ PROP_MODEL = 1,
+ PROP_COMBOBOX,
+ PROP_ENTRY,
+ PROP_WIDTH,
+ PROP_CELL_DATA_FUNC,
+ PROP_POPUP
+};
+
+enum {
+ CHANGED = 0,
+ ACTIVATED,
+ N_SIGNALS
+};
+static guint signals[N_SIGNALS] = {0};
+
+static GtkActionClass *ink_comboboxentry_action_parent_class = NULL;
+static GQuark gDataName = 0;
+
+static void ink_comboboxentry_action_finalize (GObject *object)
+{
+ // Free any allocated resources.
+
+ G_OBJECT_CLASS (ink_comboboxentry_action_parent_class)->finalize (object);
+}
+
+
+static void ink_comboboxentry_action_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION (object);
+
+ switch(property_id) {
+
+ case PROP_MODEL:
+ action->model = GTK_TREE_MODEL( g_value_get_object( value ));
+ break;
+
+ case PROP_COMBOBOX:
+ action->combobox = GTK_COMBO_BOX_ENTRY( g_value_get_object( value ));
+ break;
+
+ case PROP_ENTRY:
+ action->entry = GTK_ENTRY( g_value_get_object( value ));
+ break;
+
+ case PROP_WIDTH:
+ action->width = g_value_get_int( value );
+ break;
+
+ case PROP_CELL_DATA_FUNC:
+ action->cell_data_func = g_value_get_pointer( value );
+ break;
+
+ case PROP_POPUP:
+ action->popup = g_value_get_boolean( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+
+static void ink_comboboxentry_action_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION (object);
+
+ switch(property_id) {
+
+ case PROP_MODEL:
+ g_value_set_object (value, action->model);
+ break;
+
+ case PROP_COMBOBOX:
+ g_value_set_object (value, action->combobox);
+ break;
+
+ case PROP_ENTRY:
+ g_value_set_object (value, action->entry);
+ break;
+
+ case PROP_WIDTH:
+ g_value_set_int (value, action->width);
+ break;
+
+ case PROP_CELL_DATA_FUNC:
+ g_value_set_pointer (value, action->cell_data_func);
+ break;
+
+ case PROP_POPUP:
+ g_value_set_boolean (value, action->popup);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+ink_comboboxentry_action_connect_proxy (GtkAction *action,
+ GtkWidget *proxy)
+{
+ /* Override any proxy properties. */
+ // if (GTK_IS_MENU_ITEM (proxy)) {
+ // }
+
+ GTK_ACTION_CLASS (ink_comboboxentry_action_parent_class)->connect_proxy (action, proxy);
+}
+
+
+static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass)
+{
+
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkActionClass *gtkaction_class = GTK_ACTION_CLASS (klass);
+
+ gtkaction_class->connect_proxy = ink_comboboxentry_action_connect_proxy;
+
+ gobject_class->finalize = ink_comboboxentry_action_finalize;
+ gobject_class->set_property = ink_comboboxentry_action_set_property;
+ gobject_class->get_property = ink_comboboxentry_action_get_property;
+
+ gDataName = g_quark_from_string("ink_comboboxentry-action");
+
+ klass->parent_class.create_tool_item = create_tool_item;
+ klass->parent_class.create_menu_item = create_menu_item;
+
+ ink_comboboxentry_action_parent_class = GTK_ACTION_CLASS(g_type_class_peek_parent (klass) );
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_MODEL,
+ g_param_spec_object ("model",
+ "Tree Model",
+ "Tree Model",
+ GTK_TYPE_TREE_MODEL,
+ (GParamFlags)G_PARAM_READWRITE));
+ g_object_class_install_property (
+ gobject_class,
+ PROP_COMBOBOX,
+ g_param_spec_object ("combobox",
+ "GtkComboBoxEntry",
+ "GtkComboBoxEntry",
+ GTK_TYPE_WIDGET,
+ (GParamFlags)G_PARAM_READABLE));
+ g_object_class_install_property (
+ gobject_class,
+ PROP_ENTRY,
+ g_param_spec_object ("entry",
+ "GtkEntry",
+ "GtkEntry",
+ GTK_TYPE_WIDGET,
+ (GParamFlags)G_PARAM_READABLE));
+ g_object_class_install_property (
+ gobject_class,
+ PROP_WIDTH,
+ g_param_spec_int ("width",
+ "EntryBox width",
+ "EntryBox width (characters)",
+ -1.0, 100, -1.0,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_CELL_DATA_FUNC,
+ g_param_spec_pointer ("cell_data_func",
+ "Cell Data Func",
+ "Cell Deta Function",
+ (GParamFlags)G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_POPUP,
+ g_param_spec_boolean ("popup",
+ "Entry Popup",
+ "Entry Popup",
+ false,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ // We need to know when GtkComboBoxEvent or Menu ready for reading
+ signals[CHANGED] = g_signal_new( "changed",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(Ink_ComboBoxEntry_ActionClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ // Probably not needed... originally to keep track of key-presses.
+ signals[ACTIVATED] = g_signal_new( "activated",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(Ink_ComboBoxEntry_ActionClass, activated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+}
+
+static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action)
+{
+ action->active = -1;
+ action->text = NULL;
+ action->entry_completion = NULL;
+ action->popup = false;
+ action->warning = NULL;
+}
+
+GType ink_comboboxentry_action_get_type ()
+{
+ static GType ink_comboboxentry_action_type = 0;
+
+ if (!ink_comboboxentry_action_type) {
+ static const GTypeInfo ink_comboboxentry_action_info = {
+ sizeof(Ink_ComboBoxEntry_ActionClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ink_comboboxentry_action_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(Ink_ComboBoxEntry_Action),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc)ink_comboboxentry_action_init, /* instance_init */
+ NULL /* value_table */
+ };
+
+ ink_comboboxentry_action_type = g_type_register_static (GTK_TYPE_ACTION,
+ "Ink_ComboBoxEntry_Action",
+ &ink_comboboxentry_action_info,
+ (GTypeFlags)0 );
+ }
+
+ return ink_comboboxentry_action_type;
+}
+
+
+Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name,
+ const gchar *label,
+ const gchar *tooltip,
+ const gchar *stock_id,
+ GtkTreeModel *model,
+ gint width,
+ void *cell_data_func )
+{
+ g_return_val_if_fail (name != NULL, NULL);
+
+ return (Ink_ComboBoxEntry_Action*)g_object_new (INK_COMBOBOXENTRY_TYPE_ACTION,
+ "name", name,
+ "label", label,
+ "tooltip", tooltip,
+ "stock-id", stock_id,
+ "model", model,
+ "width", width,
+ "cell_data_func", cell_data_func,
+ NULL);
+}
+
+// Create a widget for a toolbar.
+GtkWidget* create_tool_item( GtkAction* action )
+{
+ GtkWidget* item = 0;
+
+ if ( INK_COMBOBOXENTRY_IS_ACTION( action ) && INK_COMBOBOXENTRY_ACTION(action)->model ) {
+
+ Ink_ComboBoxEntry_Action* ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( action );
+
+ item = GTK_WIDGET( gtk_tool_item_new() );
+
+ GtkWidget* comboBoxEntry = gtk_combo_box_entry_new_with_model( ink_comboboxentry_action->model, 0 );
+
+ gtk_container_add( GTK_CONTAINER(item), comboBoxEntry );
+
+ ink_comboboxentry_action->combobox = GTK_COMBO_BOX_ENTRY(comboBoxEntry);
+
+ gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active );
+
+ g_signal_connect( G_OBJECT(comboBoxEntry), "changed", G_CALLBACK(combo_box_changed_cb), action );
+
+ // Optionally add formatting...
+ if( ink_comboboxentry_action->cell_data_func != NULL ) {
+ GtkCellRenderer *cell = gtk_cell_renderer_text_new();
+ gtk_cell_layout_clear( GTK_CELL_LAYOUT( comboBoxEntry ) );
+ gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( comboBoxEntry ), cell, true );
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT( comboBoxEntry ), cell,
+ GtkCellLayoutDataFunc (ink_comboboxentry_action->cell_data_func),
+ NULL, NULL );
+ }
+
+ // Get reference to GtkEntry and fiddle a bit with it.
+ GtkWidget *child = gtk_bin_get_child( GTK_BIN(comboBoxEntry) );
+ if( child && GTK_IS_ENTRY( child ) ) {
+ ink_comboboxentry_action->entry = GTK_ENTRY(child);
+
+ // Change width
+ if( ink_comboboxentry_action->width > 0 ) {
+ gtk_entry_set_width_chars (GTK_ENTRY (child), ink_comboboxentry_action->width );
+ }
+
+ // Add pop-up entry completion if required
+ if( ink_comboboxentry_action->popup ) {
+ ink_comboboxentry_action_popup_enable( ink_comboboxentry_action );
+ }
+
+ // Add signal for GtkEntry to check if finished typing.
+ g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action );
+
+ }
+
+ gtk_action_connect_proxy( GTK_ACTION( action ), item );
+
+ gtk_widget_show_all( item );
+
+ } else {
+
+ item = ink_comboboxentry_action_parent_class->create_tool_item( action );
+
+ }
+
+ return item;
+}
+
+// Create a drop-down menu.
+GtkWidget* create_menu_item( GtkAction* action )
+{
+ GtkWidget* item = 0;
+
+ item = ink_comboboxentry_action_parent_class->create_menu_item( action );
+ g_warning( "ink_comboboxentry_action: create_menu_item not implemented" );
+ // One can easily modify ege-select-one-action routine to implement this.
+ return item;
+}
+
+// Setters/Getters ---------------------------------------------------
+
+GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action ) {
+
+ return action->model;
+}
+
+GtkComboBoxEntry *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action ) {
+
+ return action->combobox;
+}
+
+gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* action ) {
+
+ gchar* text = g_strdup( action->text );
+ return text;
+}
+
+gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* ink_comboboxentry_action, gchar* text ) {
+
+ g_free( ink_comboboxentry_action->text );
+ ink_comboboxentry_action->text = g_strdup( text );
+
+ // Get active row or -1 if none
+ ink_comboboxentry_action->active = get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+
+ // Set active row, check that combobox has been created.
+ if( ink_comboboxentry_action->combobox ) {
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox ), ink_comboboxentry_action->active );
+ }
+
+ // Fiddle with entry
+ if( ink_comboboxentry_action->entry ) {
+
+ // Explicitly set text in GtkEntry box (won't be set if text not in list).
+ gtk_entry_set_text( ink_comboboxentry_action->entry, text );
+
+ // Show or hide warning
+ if( ink_comboboxentry_action->active == -1 && ink_comboboxentry_action->warning != NULL ) {
+ gtk_entry_set_icon_from_icon_name( ink_comboboxentry_action->entry,
+ GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_DIALOG_WARNING );
+ // Can't add tooltip until icon set
+ gtk_entry_set_icon_tooltip_text( ink_comboboxentry_action->entry,
+ GTK_ENTRY_ICON_SECONDARY,
+ ink_comboboxentry_action->warning );
+
+ } else {
+ gtk_entry_set_icon_from_icon_name( GTK_ENTRY(ink_comboboxentry_action->entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ NULL );
+ }
+ }
+
+ // Return if active text in list
+ gboolean found = ( ink_comboboxentry_action->active != -1 );
+ return found;
+}
+
+void ink_comboboxentry_action_set_width( Ink_ComboBoxEntry_Action* action, gint width ) {
+
+ action->width = width;
+
+ // Widget may not have been created....
+ if( action->entry ) {
+ gtk_entry_set_width_chars( GTK_ENTRY(action->entry), width );
+ }
+}
+
+void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action ) {
+
+ action->popup = true;
+
+ // Widget may not have been created....
+ if( action->entry ) {
+
+ // Check we don't already have a GtkEntryCompletion
+ if( action->entry_completion ) return;
+
+ action->entry_completion = gtk_entry_completion_new();
+
+ gtk_entry_set_completion( action->entry, action->entry_completion );
+ gtk_entry_completion_set_model( action->entry_completion, action->model );
+ gtk_entry_completion_set_text_column( action->entry_completion, 0 );
+ gtk_entry_completion_set_popup_completion( action->entry_completion, true );
+ gtk_entry_completion_set_inline_completion( action->entry_completion, false );
+ gtk_entry_completion_set_inline_selection( action->entry_completion, true );
+
+ g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action );
+
+ }
+}
+
+void ink_comboboxentry_action_popup_disable( Ink_ComboBoxEntry_Action* action ) {
+
+ action->popup = false;
+
+ if( action->entry_completion ) {
+ gtk_object_destroy( GTK_OBJECT( action->entry_completion ) );
+ }
+}
+
+void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, gchar* warning ) {
+
+ g_free( action->warning );
+ action->warning = g_strdup( warning );
+
+ // Widget may not have been created....
+ if( action->entry ) {
+ gtk_entry_set_icon_tooltip_text( GTK_ENTRY(action->entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ action->warning );
+ }
+}
+
+// Internal ---------------------------------------------------
+
+// Return row of active text or -1 if not found.
+gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, gchar* target_text ) {
+
+ // Check if text in list
+ gint row = 0;
+ gboolean found = false;
+ GtkTreeIter iter;
+ gboolean valid = gtk_tree_model_get_iter_first( action->model, &iter );
+ while ( valid ) {
+
+ // Get text from list entry
+ gchar* text = 0;
+ gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0
+
+ // Check for match
+ if( strcmp( target_text, text ) == 0 ){
+ found = true;
+ break;
+ }
+ ++row;
+ valid = gtk_tree_model_iter_next( action->model, &iter );
+ }
+
+ if( !found ) row = -1;
+
+ return row;
+
+}
+
+
+// Callbacks ---------------------------------------------------
+
+static void combo_box_changed_cb( GtkComboBoxEntry* widget, gpointer data ) {
+
+ // Two things can happen to get here:
+ // An item is selected in the drop-down menu.
+ // Text is typed.
+ // We only react here if an item is selected.
+
+ // Get action
+ Ink_ComboBoxEntry_Action *act = INK_COMBOBOXENTRY_ACTION( data );
+
+ // Check if item selected:
+ gint newActive = gtk_combo_box_get_active( GTK_COMBO_BOX( widget ));
+ if( newActive >= 0 ) {
+
+ if( newActive != act->active ) {
+ act->active = newActive;
+ g_free( act->text );
+ act->text = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ));
+
+ // Now let the world know
+ g_signal_emit( G_OBJECT(act), signals[CHANGED], 0 );
+
+ }
+ }
+}
+
+static void entry_activate_cb( GtkEntry* widget, gpointer data ) {
+
+ // Get text from entry box.. check if it matches a menu entry.
+
+ // Get action
+ Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data );
+
+ // Get text
+ g_free( ink_comboboxentry_action->text );
+ ink_comboboxentry_action->text = g_strdup( gtk_entry_get_text( widget ) );
+
+ // Get row
+ ink_comboboxentry_action->active =
+ get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+
+ // Set active row
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
+
+ // Now let the world know
+ g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 );
+
+}
+
+static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data )
+{
+ // Get action
+ Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data );
+ GtkEntry *entry = ink_comboboxentry_action->entry;
+
+ if( entry) {
+ gchar *family = 0;
+ gtk_tree_model_get(model, iter, 0, &family, -1);
+
+ // Set text in GtkEntry
+ gtk_entry_set_text (GTK_ENTRY (entry), family );
+
+ // Set text in GtkAction
+ g_free( ink_comboboxentry_action->text );
+ ink_comboboxentry_action->text = family;
+
+ // Get row
+ ink_comboboxentry_action->active =
+ get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
+
+ // Set active row
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
+
+ // Now let the world know
+ g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 );
+
+ return true;
+ }
+ return false;
+}
+
diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h
new file mode 100644
index 000000000..433eb2fdc
--- /dev/null
+++ b/src/ink-comboboxentry-action.h
@@ -0,0 +1,86 @@
+/*
+ * A subclass of GtkAction that wraps a GtkComboBoxEntry.
+ * Features:
+ * Setting GtkEntryBox width in characters.
+ * Passing a function for formatting cells.
+ * Displaying a warning if text isn't in list.
+ *
+ * Author(s):
+ * Tavmjong Bah
+ *
+ * Copyright (C) 2010 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INK_COMBOBOXENTRY_ACTION
+#define SEEN_INK_COMBOBOXENTRY_ACTION
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtkaction.h>
+#include <gtk/gtktreemodel.h>
+
+
+#define INK_COMBOBOXENTRY_TYPE_ACTION (ink_comboboxentry_action_get_type())
+#define INK_COMBOBOXENTRY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_Action))
+#define INK_COMBOBOXENTRY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass))
+#define INK_COMBOBOXENTRY_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INK_COMBOBOXENTRY_TYPE_ACTION))
+#define INK_COMBOBOXENTRY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INK_COMBOBOXENTRY_TYPE_ACTION, Ink_ComboBoxEntry_ActionClass))
+
+typedef struct _Ink_ComboBoxEntry_ActionClass Ink_ComboBoxEntry_ActionClass;
+typedef struct _Ink_ComboBoxEntry_Action Ink_ComboBoxEntry_Action;
+
+struct _Ink_ComboBoxEntry_ActionClass {
+ GtkActionClass parent_class;
+
+ void (*changed) (Ink_ComboBoxEntry_Action* action);
+ void (*activated) (Ink_ComboBoxEntry_Action* action);
+};
+
+struct _Ink_ComboBoxEntry_Action {
+ GtkAction parent_instance;
+
+ GtkTreeModel *model;
+ GtkComboBoxEntry *combobox;
+ GtkEntry *entry;
+ GtkEntryCompletion *entry_completion;
+
+ gpointer cell_data_func; // drop-down menu format
+
+ gint active; // Index of active menu item (-1 if not in list).
+ gchar *text; // Text of active menu item or entry box.
+ gint width; // Width of GtkComboBoxEntry in characters.
+ gboolean popup; // Do we pop-up an entry-completion dialog?
+ gchar *warning; // Text for warning that entry isn't in list.
+};
+
+
+GType ink_comboboxentry_action_get_type (void);
+
+/**
+ * Creates a GtkAction subclass that wraps a GtkComboBoxEntry object.
+ */
+Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new ( const gchar *name,
+ const gchar *label,
+ const gchar *tooltip,
+ const gchar *stock_id,
+ GtkTreeModel *model,
+ gint width = -1,
+ gpointer cell_data_func = NULL );
+
+GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action );
+GtkComboBoxEntry *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action );
+
+gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* action );
+gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* action, gchar* text );
+
+void ink_comboboxentry_action_set_width( Ink_ComboBoxEntry_Action* action, gint width );
+
+void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action );
+void ink_comboboxentry_action_popup_disable( Ink_ComboBoxEntry_Action* action );
+
+void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, gchar* warning );
+
+#endif /* SEEN_INK_COMBOBOXENTRY_ACTION */
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 8506f05de..d0f9a11fc 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -49,7 +49,7 @@ using Inkscape::Extension::Internal::PrintWin32;
#include "application/editor.h"
#include "desktop.h"
#include "desktop-handles.h"
-#include "dialogs/input.h"
+#include "device-manager.h"
#include "document.h"
#include "event-context.h"
#include "extension/db.h"
@@ -807,7 +807,7 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
if (use_gui) {
inkscape_load_menus(inkscape);
- sp_input_load_from_preferences();
+ Inkscape::DeviceManager::getManager().loadConfig();
}
/* set language for user interface according setting in preferences */
diff --git a/src/io/sys.cpp b/src/io/sys.cpp
index 34160b648..a68d02707 100644
--- a/src/io/sys.cpp
+++ b/src/io/sys.cpp
@@ -29,41 +29,9 @@
#include "sys.h"
#ifdef WIN32
-
-#define BYPASS_GLIB_SPAWN 1
-
-#ifdef BYPASS_GLIB_SPAWN
-
-#include <process.h> // declares spawn functions
-#include <wchar.h> // declares _wspawn functions
-
-#ifndef __MINGW32__
-# ifdef __cplusplus
-extern "C" {
-# endif
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnl (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnle (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlp (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlpe (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnv (int, const wchar_t*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnve (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvp (int, const wchar_t*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvpe (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*);
-# ifdef __cplusplus
-}
-# endif
-#endif
-#include <unistd.h>
-#include <glibmm/i18n.h>
-#include <fcntl.h>
-#include <io.h>
-
-#endif // BYPASS_GLIB_SPAWN
-
// For now to get at is_os_wide().
#include "extension/internal/win32.h"
using Inkscape::Extension::Internal::PrintWin32;
-
#endif // WIN32
//#define INK_DUMP_FILENAME_CONV 1
@@ -217,32 +185,7 @@ int Inkscape::IO::mkdir_utf8name( char const *utf8name )
* */
int Inkscape::IO::file_open_tmp(std::string& name_used, const std::string& prefix)
{
-#ifndef WIN32
return Glib::file_open_tmp(name_used, prefix);
-#else
- /* Special case for WIN32 due to a bug in glibmm
- * (only needed for Windows Vista, but since there is only one windows build all builds get the workaround)
- * The workaround can be removed if the bug is fixed in glibmm
- *
- * The code is mostly identical to the implementation in glibmm
- * http://svn.gnome.org/svn/glibmm/branches/glibmm-2-12/glib/src/fileutils.ccg
- * */
-
- std::string basename_template (prefix);
- basename_template += "XXXXXX"; // this sillyness shouldn't be in the interface
-
- GError* error = 0;
- gchar *buf_name_used;
-
- gint fileno = g_file_open_tmp(basename_template.c_str(), &buf_name_used, &error);
-
- if(error)
- Glib::Error::throw_exception(error);
-
- name_used = g_strdup(buf_name_used);
- g_free(buf_name_used);
- return fileno;
-#endif
}
bool Inkscape::IO::file_test( char const *utf8name, GFileTest test )
@@ -372,842 +315,6 @@ gchar* Inkscape::IO::locale_to_utf8_fallback( const gchar *opsysstring,
return result;
}
-#ifdef BYPASS_GLIB_SPAWN
-/*
- this code was taken from the original glib sources
-*/
-#define GSPAWN_HELPER
-
-enum
-{
- CHILD_NO_ERROR,
- CHILD_CHDIR_FAILED,
- CHILD_SPAWN_FAILED,
-};
-
-enum {
- ARG_CHILD_ERR_REPORT = 1,
- ARG_HELPER_SYNC,
- ARG_STDIN,
- ARG_STDOUT,
- ARG_STDERR,
- ARG_WORKING_DIRECTORY,
- ARG_CLOSE_DESCRIPTORS,
- ARG_USE_PATH,
- ARG_WAIT,
- ARG_PROGRAM,
- ARG_COUNT = ARG_PROGRAM
-};
-static int debug = 0;
-#define HELPER_PROCESS "gspawn-win32-helper"
-
-
-static int
-dup_noninherited (int fd,
- int mode)
-{
- HANDLE filehandle;
-
- DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd),
- GetCurrentProcess (), &filehandle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- close (fd);
- return _open_osfhandle(reinterpret_cast<LONG_PTR>(filehandle), mode | _O_NOINHERIT);
-}
-
-/* The helper process writes a status report back to us, through a
- * pipe, consisting of two ints.
- */
-static gboolean
-read_helper_report (int fd,
- gint report[2],
- GError **error)
-{
- gint bytes = 0;
-
- while (bytes < sizeof(gint)*2)
- {
- gint chunk;
-
- if (debug)
- g_print ("%s:read_helper_report: read %d...\n",
- __FILE__,
- sizeof(gint)*2 - bytes);
-
- chunk = read (fd, ((gchar*)report) + bytes,
- sizeof(gint)*2 - bytes);
-
- if (debug)
- g_print ("...got %d bytes\n", chunk);
-
- if (chunk < 0)
- {
- /* Some weird shit happened, bail out */
-
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- g_strerror (errno));
-
- return FALSE;
- }
- else if (chunk == 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- "EOF");
- break; /* EOF */
- }
- else
- bytes += chunk;
- }
-
- if (bytes < sizeof(gint)*2)
- return FALSE;
-
- return TRUE;
-}
-
-
-static void
-set_child_error (gint report[2],
- const gchar *working_directory,
- GError **error)
-{
- switch (report[0])
- {
- case CHILD_CHDIR_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Failed to change to directory '%s' (%s)"),
- working_directory,
- g_strerror (report[1]));
- break;
- case CHILD_SPAWN_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (report[1]));
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static gchar *
-protect_argv_string (const gchar *string)
-{
- const gchar *p = string;
- gchar *retval, *q;
- gint len = 0;
- gboolean need_dblquotes = FALSE;
- while (*p)
- {
- if (*p == ' ' || *p == '\t')
- need_dblquotes = TRUE;
- else if (*p == '"')
- len++;
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- len++;
- }
- len++;
- p++;
- }
-
- q = retval = (gchar *)g_malloc (len + need_dblquotes*2 + 1);
- p = string;
-
- if (need_dblquotes)
- *q++ = '"';
-
- while (*p)
- {
- if (*p == '"')
- *q++ = '\\';
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- *q++ = '\\';
- }
- *q++ = *p;
- p++;
- }
-
- if (need_dblquotes)
- *q++ = '"';
- *q++ = '\0';
-
- return retval;
-}
-
-
-static gint
-protect_argv (gchar **argv,
- gchar ***new_argv)
-{
- gint i;
- gint argc = 0;
-
- while (argv[argc])
- ++argc;
- *new_argv = g_new (gchar *, argc+1);
-
- /* Quote each argv element if necessary, so that it will get
- * reconstructed correctly in the C runtime startup code. Note that
- * the unquoting algorithm in the C runtime is really weird, and
- * rather different than what Unix shells do. See stdargv.c in the C
- * runtime sources (in the Platform SDK, in src/crt).
- *
- * Note that an new_argv[0] constructed by this function should
- * *not* be passed as the filename argument to a spawn* or exec*
- * family function. That argument should be the real file name
- * without any quoting.
- */
- for (i = 0; i < argc; i++)
- (*new_argv)[i] = protect_argv_string (argv[i]);
-
- (*new_argv)[argc] = NULL;
-
- return argc;
-}
-
-
-static gboolean
-utf8_charv_to_wcharv (char **utf8_charv,
- wchar_t ***wcharv,
- int *error_index,
- GError **error)
-{
- wchar_t **retval = NULL;
-
- *wcharv = NULL;
- if (utf8_charv != NULL)
- {
- int n = 0, i;
-
- while (utf8_charv[n])
- n++;
- retval = g_new (wchar_t *, n + 1);
-
- for (i = 0; i < n; i++)
- {
- retval[i] = (wchar_t *)g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
- if (retval[i] == NULL)
- {
- if (error_index)
- *error_index = i;
- while (i)
- g_free (retval[--i]);
- g_free (retval);
- return FALSE;
- }
- }
-
- retval[n] = NULL;
- }
- *wcharv = retval;
- return TRUE;
-}
-
-
-/* Avoids a danger in threaded situations (calling close()
- * on a file descriptor twice, and another thread has
- * re-opened it since the first close)
- */
-static void
-close_and_invalidate (gint *fd)
-{
- if (*fd < 0)
- return;
-
- close (*fd);
- *fd = -1;
-}
-
-
-static gboolean
-do_spawn_directly (gint *exit_status,
- gboolean do_return_handle,
- GSpawnFlags flags,
- gchar **argv,
- char **envp,
- char **protected_argv,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- GError **error)
-{
- const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
- char **new_argv;
- int rc = -1;
- int saved_errno;
- GError *conv_error = NULL;
- gint conv_error_index;
- wchar_t *wargv0, **wargv, **wenvp;
-
- new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
-
- wargv0 = (wchar_t *)g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
- if (wargv0 == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid program name: %s"),
- conv_error->message);
- g_error_free (conv_error);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index, conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
-
- return FALSE;
- }
-
- if (child_setup)
- (* child_setup) (user_data);
-
- if (flags & G_SPAWN_SEARCH_PATH)
- if (wenvp != NULL)
- rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
- else
- if (wenvp != NULL)
- rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
-
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- saved_errno = errno;
-
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (saved_errno));
- return FALSE;
- }
-
- if (exit_status == NULL)
- {
- if (child_handle && do_return_handle)
- *child_handle = (GPid) rc;
- else
- {
- CloseHandle ((HANDLE) rc);
- if (child_handle)
- *child_handle = 0;
- }
- }
- else
- *exit_status = rc;
-
- return TRUE;
-}
-
-static gboolean
-make_pipe (gint p[2],
- GError **error)
-{
- if (_pipe (p, 4096, _O_BINARY) < 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to create pipe for communicating with child process (%s)"),
- g_strerror (errno));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-
-static gboolean
-do_spawn_with_pipes (gint *exit_status,
- gboolean do_return_handle,
- const gchar *working_directory,
- gchar **argv,
- char **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- gint *err_report,
- GError **error)
-{
- char **protected_argv;
- char args[ARG_COUNT][10];
- char **new_argv;
- int i;
- int rc = -1;
- int saved_errno;
- int argc;
- int stdin_pipe[2] = { -1, -1 };
- int stdout_pipe[2] = { -1, -1 };
- int stderr_pipe[2] = { -1, -1 };
- int child_err_report_pipe[2] = { -1, -1 };
- int helper_sync_pipe[2] = { -1, -1 };
- int helper_report[2];
- static gboolean warned_about_child_setup = FALSE;
- GError *conv_error = NULL;
- gint conv_error_index;
- gchar *helper_process;
- CONSOLE_CURSOR_INFO cursor_info;
- wchar_t *whelper, **wargv, **wenvp;
- //extern gchar *_glib_get_installation_directory (void);
- gchar *glib_top;
-
- if (child_setup && !warned_about_child_setup)
- {
- warned_about_child_setup = TRUE;
- g_warning ("passing a child setup function to the g_spawn functions is pointless and dangerous on Win32");
- }
-
- argc = protect_argv (argv, &protected_argv);
-
- if (!standard_input && !standard_output && !standard_error &&
- (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
- (working_directory == NULL || !*working_directory) &&
- (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- {
- /* We can do without the helper process */
- gboolean retval =
- do_spawn_directly (exit_status, do_return_handle, flags,
- argv, envp, protected_argv,
- child_setup, user_data, child_handle,
- error);
- g_strfreev (protected_argv);
- return retval;
- }
-
- if (standard_input && !make_pipe (stdin_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_output && !make_pipe (stdout_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_error && !make_pipe (stderr_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (child_err_report_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (helper_sync_pipe, error))
- goto cleanup_and_fail;
-
- new_argv = g_new (char *, argc + 1 + ARG_COUNT);
- if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
- helper_process = HELPER_PROCESS "-console.exe";
- else
- helper_process = HELPER_PROCESS ".exe";
-
- glib_top = NULL;
- if (glib_top != NULL)
- {
- helper_process = g_build_filename (glib_top, "bin", helper_process, NULL);
- g_free (glib_top);
- }
- else
- helper_process = g_strdup (helper_process);
-
- new_argv[0] = protect_argv_string (helper_process);
-
- sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
- new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
-
- /* Make the read end of the child error report pipe
- * noninherited. Otherwise it will needlessly be inherited by the
- * helper process, and the started actual user process. As such that
- * shouldn't harm, but it is unnecessary.
- */
- child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY);
-
- if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
- {
- /* Overload ARG_CHILD_ERR_REPORT to also encode the
- * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
- */
- strcat (args[ARG_CHILD_ERR_REPORT], "#");
- }
-
- sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
- new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
-
- /* Make the write end of the sync pipe noninherited. Otherwise the
- * helper process will inherit it, and thus if this process happens
- * to crash before writing the sync byte to the pipe, the helper
- * process won't read but won't get any EOF either, as it has the
- * write end open itself.
- */
- helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY);
-
- if (standard_input)
- {
- sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
- new_argv[ARG_STDIN] = args[ARG_STDIN];
- }
- else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
- {
- /* Let stdin be alone */
- new_argv[ARG_STDIN] = "-";
- }
- else
- {
- /* Keep process from blocking on a read of stdin */
- new_argv[ARG_STDIN] = "z";
- }
-
- if (standard_output)
- {
- sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
- new_argv[ARG_STDOUT] = args[ARG_STDOUT];
- }
- else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
- {
- new_argv[ARG_STDOUT] = "z";
- }
- else
- {
- new_argv[ARG_STDOUT] = "-";
- }
-
- if (standard_error)
- {
- sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
- new_argv[ARG_STDERR] = args[ARG_STDERR];
- }
- else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
- {
- new_argv[ARG_STDERR] = "z";
- }
- else
- {
- new_argv[ARG_STDERR] = "-";
- }
-
- if (working_directory && *working_directory)
- new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
- else
- new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
-
- if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
- else
- new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
-
- if (flags & G_SPAWN_SEARCH_PATH)
- new_argv[ARG_USE_PATH] = "y";
- else
- new_argv[ARG_USE_PATH] = "-";
-
- if (exit_status == NULL)
- new_argv[ARG_WAIT] = "-";
- else
- new_argv[ARG_WAIT] = "w";
-
- for (i = 0; i <= argc; i++)
- new_argv[ARG_PROGRAM + i] = protected_argv[i];
-
- //SETUP_DEBUG();
-
- if (debug)
- {
- g_print ("calling %s with argv:\n", helper_process);
- for (i = 0; i < argc + 1 + ARG_COUNT; i++)
- g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- if (conv_error_index == ARG_WORKING_DIRECTORY)
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Invalid working directory: %s"),
- conv_error->message);
- else
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index - ARG_PROGRAM, conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
-
- goto cleanup_and_fail;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
- g_strfreev ((gchar **) wargv);
-
- goto cleanup_and_fail;
- }
-
- if (child_setup)
- (* child_setup) (user_data);
-
- whelper = (wchar_t *)g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
- g_free (helper_process);
-
- if (wenvp != NULL)
- rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
-
- saved_errno = errno;
-
- g_free (whelper);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- /* Close the other process's ends of the pipes in this process,
- * otherwise the reader will never get EOF.
- */
- close_and_invalidate (&child_err_report_pipe[1]);
- close_and_invalidate (&helper_sync_pipe[0]);
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[1]);
-
- g_strfreev (protected_argv);
-
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
-
- /* Check if gspawn-win32-helper couldn't be run */
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute helper program (%s)"),
- g_strerror (saved_errno));
- goto cleanup_and_fail;
- }
-
- if (exit_status != NULL)
- {
- /* Synchronous case. Pass helper's report pipe back to caller,
- * which takes care of reading it after the grandchild has
- * finished.
- */
- g_assert (err_report != NULL);
- *err_report = child_err_report_pipe[0];
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- }
- else
- {
- /* Asynchronous case. We read the helper's report right away. */
- if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
- goto cleanup_and_fail;
-
- close_and_invalidate (&child_err_report_pipe[0]);
-
- switch (helper_report[0])
- {
- case CHILD_NO_ERROR:
- if (child_handle && do_return_handle)
- {
- /* rc is our HANDLE for gspawn-win32-helper. It has
- * told us the HANDLE of its child. Duplicate that into
- * a HANDLE valid in this process.
- */
- if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
- GetCurrentProcess (), (LPHANDLE) child_handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- char *emsg = g_win32_error_message (GetLastError ());
- g_print("%s\n", emsg);
- *child_handle = 0;
- }
- }
- else if (child_handle)
- *child_handle = 0;
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- break;
-
- default:
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- set_child_error (helper_report, working_directory, error);
- goto cleanup_and_fail;
- }
- }
-
- /* Success against all odds! return the information */
-
- if (standard_input)
- *standard_input = stdin_pipe[1];
- if (standard_output)
- *standard_output = stdout_pipe[0];
- if (standard_error)
- *standard_error = stderr_pipe[0];
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
-
- return TRUE;
-
- cleanup_and_fail:
-
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
- if (child_err_report_pipe[0] != -1)
- close (child_err_report_pipe[0]);
- if (child_err_report_pipe[1] != -1)
- close (child_err_report_pipe[1]);
- if (helper_sync_pipe[0] != -1)
- close (helper_sync_pipe[0]);
- if (helper_sync_pipe[1] != -1)
- close (helper_sync_pipe[1]);
- if (stdin_pipe[0] != -1)
- close (stdin_pipe[0]);
- if (stdin_pipe[1] != -1)
- close (stdin_pipe[1]);
- if (stdout_pipe[0] != -1)
- close (stdout_pipe[0]);
- if (stdout_pipe[1] != -1)
- close (stdout_pipe[1]);
- if (stderr_pipe[0] != -1)
- close (stderr_pipe[0]);
- if (stderr_pipe[1] != -1)
- close (stderr_pipe[1]);
-
- return FALSE;
-}
-
-gboolean
-my_spawn_async_with_pipes_utf8 (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
- /* can't inherit stdin if we have an input pipe. */
- g_return_val_if_fail (standard_input == NULL ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
-
- return do_spawn_with_pipes (NULL,
- (flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- user_data,
- child_handle,
- standard_input,
- standard_output,
- standard_error,
- NULL,
- error);
-}
-
-typedef GPid Pid;
-
-// _WRAP_ENUM(SpawnFlags, GSpawnFlags, NO_GTYPE)
-
-/* Helper callback to invoke the actual sigc++ slot.
- * We don't need to worry about (un)referencing, since the
- * child process gets its own copy of the parent's memory anyway.
- */
-static void child_setup_callback(void* user_data)
-{
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- try
- {
- #endif //GLIBMM_EXCEPTIONS_ENABLED
- (*reinterpret_cast<sigc::slot<void>*>(user_data))();
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- }
- catch(...)
- {
- Glib::exception_handlers_invoke();
- }
- #endif //GLIBMM_EXCEPTIONS_ENABLED
-}
-
-
-void my_spawn_async_with_pipes(const std::string& working_directory,
- const Glib::ArrayHandle<std::string>& argv,
- GSpawnFlags flags,
- const sigc::slot<void>& child_setup,
- Pid* child_pid,
- int* standard_input,
- int* standard_output,
- int* standard_error)
-{
- const bool setup_slot = !child_setup.empty();
- sigc::slot<void> child_setup_ = child_setup;
- GError* error = 0;
-
- my_spawn_async_with_pipes_utf8(
- working_directory.c_str(),
- const_cast<char**>(argv.data()), 0,
- static_cast<GSpawnFlags>(unsigned(flags)),
- (setup_slot) ? &child_setup_callback : 0,
- (setup_slot) ? &child_setup_ : 0,
- child_pid,
- standard_input, standard_output, standard_error,
- &error);
-
- if(error)
- Glib::Error::throw_exception(error);
-}
-
-#endif
-
void
Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory,
const Glib::ArrayHandle<std::string>& argv,
@@ -1218,7 +325,6 @@ Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory,
int* standard_output,
int* standard_error)
{
-#ifndef BYPASS_GLIB_SPAWN
Glib::spawn_async_with_pipes(working_directory,
argv,
flags,
@@ -1227,16 +333,6 @@ Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory,
standard_input,
standard_output,
standard_error);
-#else
- my_spawn_async_with_pipes(working_directory,
- argv,
- static_cast<GSpawnFlags>(flags),
- child_setup,
- child_pid,
- standard_input,
- standard_output,
- standard_error);
-#endif
}
diff --git a/src/libgdl/gdl-switcher.c b/src/libgdl/gdl-switcher.c
index 28b9fe661..43768bbdf 100644
--- a/src/libgdl/gdl-switcher.c
+++ b/src/libgdl/gdl-switcher.c
@@ -521,7 +521,7 @@ gdl_switcher_expose (GtkWidget *widget, GdkEventExpose *event)
button, event);
}
}
- GDL_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS, expose_event,
+ return GDL_CALL_PARENT_WITH_DEFAULT (GTK_WIDGET_CLASS, expose_event,
(widget, event), FALSE);
}
diff --git a/src/libnr/Makefile_insert b/src/libnr/Makefile_insert
index 4b19028f9..8dd3c46e3 100644
--- a/src/libnr/Makefile_insert
+++ b/src/libnr/Makefile_insert
@@ -1,13 +1,5 @@
## Makefile.am fragment sourced by src/Makefile.am.
-if USE_MMX
-libnr_mmx_sources = \
- libnr/have_mmx.S \
- libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S \
- libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S \
- libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S
-endif
-
ink_common_sources += \
libnr/in-svg-plane.h \
libnr/nr-blit.cpp \
diff --git a/src/libnr/have_mmx.S b/src/libnr/have_mmx.S
deleted file mode 100644
index d6428191e..000000000
--- a/src/libnr/have_mmx.S
+++ /dev/null
@@ -1,47 +0,0 @@
- .file "have_mmx.S"
-
-# Ensure Inkscape is execshield protected
- .section .note.GNU-stack
- .previous
-
- .version "01.01"
-gcc2_compiled.:
-.text
- .align 16
-.globl nr_have_mmx
- .type nr_have_mmx,@function
-
-nr_have_mmx:
- push %ebx
-
-# Check if bit 21 in flags word is writeable
-
- pushfl
- popl %eax
- movl %eax,%ebx
- xorl $0x00200000, %eax
- pushl %eax
- popfl
- pushfl
- popl %eax
-
- cmpl %eax, %ebx
-
- je .notfound
-
-# OK, we have CPUID
-
- movl $1, %eax
- cpuid
-
- test $0x00800000, %edx
- jz .notfound
-
- movl $1, %eax
- jmp .out
-
-.notfound:
- movl $0, %eax
-.out:
- popl %ebx
- ret
diff --git a/src/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp
index 6e03faf2f..e7c286569 100644
--- a/src/libnr/nr-compose-transform.cpp
+++ b/src/libnr/nr-compose-transform.cpp
@@ -66,18 +66,25 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h,
if (alpha == 0) return;
+ // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow
+ if (xd+yd>16) {
+ xd = 8;
+ yd = 8;
+ }
+
xsize = (1 << xd);
ysize = (1 << yd);
size = xsize * ysize;
dbits = xd + yd;
+ unsigned int rounding_fix = size/2;
/* Set up fixed point matrix */
- FFs_x_x = (long) (d2s[0] * (1 << FBITS) + 0.5);
- FFs_x_y = (long) (d2s[1] * (1 << FBITS) + 0.5);
- FFs_y_x = (long) (d2s[2] * (1 << FBITS) + 0.5);
- FFs_y_y = (long) (d2s[3] * (1 << FBITS) + 0.5);
- FFs__x = (long) (d2s[4] * (1 << FBITS) + 0.5);
- FFs__y = (long) (d2s[5] * (1 << FBITS) + 0.5);
+ FFs_x_x = (long) floor(d2s[0] * (1 << FBITS) + 0.5);
+ FFs_x_y = (long) floor(d2s[1] * (1 << FBITS) + 0.5);
+ FFs_y_x = (long) floor(d2s[2] * (1 << FBITS) + 0.5);
+ FFs_y_y = (long) floor(d2s[3] * (1 << FBITS) + 0.5);
+ FFs__x = (long) floor(d2s[4] * (1 << FBITS) + 0.5);
+ FFs__y = (long) floor(d2s[5] * (1 << FBITS) + 0.5);
FFs_x_x_S = FFs_x_x >> xd;
FFs_x_y_S = FFs_x_y >> xd;
@@ -114,35 +121,40 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h,
sy = (FFsy + FF_sy_S[i]) >> FBITS;
if ((sy >= 0) && (sy < sh)) {
const unsigned char *s;
- unsigned int ca;
s = spx + sy * srs + sx * 4;
- ca = NR_PREMUL_112 (s[3], alpha);
- r += NR_PREMUL_121 (s[0], ca);
- g += NR_PREMUL_121 (s[1], ca);
- b += NR_PREMUL_121 (s[2], ca);
- a += NR_NORMALIZE_21(ca);
+ r += NR_PREMUL_112 (s[0], s[3]);
+ g += NR_PREMUL_112 (s[1], s[3]);
+ b += NR_PREMUL_112 (s[2], s[3]);
+ a += s[3];
}
}
}
- a >>= dbits;
+ a = (a*alpha + rounding_fix) >> dbits;
+ // Compare to nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P
if (a != 0) {
- r = r >> dbits;
- g = g >> dbits;
- b = b >> dbits;
- if (a == 255) {
- /* Transparent BG, premul src */
- d[0] = r;
- d[1] = g;
- d[2] = b;
- d[3] = a;
+ r = (r + rounding_fix) >> dbits;
+ g = (g + rounding_fix) >> dbits;
+ b = (b + rounding_fix) >> dbits;
+ if (a == 255*255) {
+ /* Full coverage, demul src */
+ d[0] = NR_NORMALIZE_21(r);
+ d[1] = NR_NORMALIZE_21(g);
+ d[2] = NR_NORMALIZE_21(b);
+ d[3] = NR_NORMALIZE_21(a);
+ } else if (d[3] == 0) {
+ /* Only foreground, demul src */
+ d[0] = NR_DEMUL_221(r,a);
+ d[1] = NR_DEMUL_221(g,a);
+ d[2] = NR_DEMUL_221(b,a);
+ d[3] = NR_NORMALIZE_21(a);
} else {
unsigned int ca;
/* Full composition */
- ca = NR_COMPOSEA_112(a, d[3]);
- d[0] = NR_COMPOSENNN_111121 (r, a, d[0], d[3], ca);
- d[1] = NR_COMPOSENNN_111121 (g, a, d[1], d[3], ca);
- d[2] = NR_COMPOSENNN_111121 (b, a, d[2], d[3], ca);
- d[3] = NR_NORMALIZE_21(ca);
+ ca = NR_COMPOSEA_213(a, d[3]);
+ d[0] = NR_COMPOSEPNN_221131 (r, a, d[0], d[3], ca);
+ d[1] = NR_COMPOSEPNN_221131 (g, a, d[1], d[3], ca);
+ d[2] = NR_COMPOSEPNN_221131 (b, a, d[2], d[3], ca);
+ d[3] = NR_NORMALIZE_31(ca);
}
}
/* Advance pointers */
@@ -227,9 +239,7 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h
int x, y;
size = (1 << dbits);
- unsigned alpha_rounding_fix = size * 255;
- unsigned rgb_rounding_fix = size * (255 * 256);
- if (alpha > 127) ++alpha;
+ unsigned int rounding_fix = size/2;
d0 = px;
FFsx0 = FFd2s[4];
@@ -252,32 +262,30 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h
sy = (long (FFsy >> (FBITS_HP - FBITS)) + FF_S[2 * i + 1]) >> FBITS;
if ((sy >= 0) && (sy < sh)) {
const unsigned char *s;
- unsigned int ca;
s = spx + sy * srs + sx * 4;
- ca = NR_PREMUL_112(s[3], alpha);
- r += NR_PREMUL_123(s[0], ca);
- g += NR_PREMUL_123(s[1], ca);
- b += NR_PREMUL_123(s[2], ca);
- a += ca;
+ r += NR_PREMUL_112(s[0], s[3]);
+ g += NR_PREMUL_112(s[1], s[3]);
+ b += NR_PREMUL_112(s[2], s[3]);
+ a += s[3];
}
}
}
- a = (a + alpha_rounding_fix) >> (8 + dbits);
+ a = (a*alpha + rounding_fix) >> dbits;
if (a != 0) {
- r = (r + rgb_rounding_fix) >> (16 + dbits);
- g = (g + rgb_rounding_fix) >> (16 + dbits);
- b = (b + rgb_rounding_fix) >> (16 + dbits);
- if ((a == 255) || (d[3] == 0)) {
+ r = (r + rounding_fix) >> dbits;
+ g = (g + rounding_fix) >> dbits;
+ b = (b + rounding_fix) >> dbits;
+ if ((a == 255*255) || (d[3] == 0)) {
/* Transparent BG, premul src */
- d[0] = r;
- d[1] = g;
- d[2] = b;
- d[3] = a;
+ d[0] = NR_NORMALIZE_21(r);
+ d[1] = NR_NORMALIZE_21(g);
+ d[2] = NR_NORMALIZE_21(b);
+ d[3] = NR_NORMALIZE_21(a);
} else {
- d[0] = NR_COMPOSEPPP_1111 (r, a, d[0]);
- d[1] = NR_COMPOSEPPP_1111 (g, a, d[1]);
- d[2] = NR_COMPOSEPPP_1111 (b, a, d[2]);
- d[3] = NR_COMPOSEA_111(a, d[3]);
+ d[0] = NR_COMPOSEPPP_2211 (r, a, d[0]);
+ d[1] = NR_COMPOSEPPP_2211 (g, a, d[1]);
+ d[2] = NR_COMPOSEPPP_2211 (b, a, d[2]);
+ d[3] = NR_COMPOSEA_211(a, d[3]);
}
}
/* Advance pointers */
@@ -302,11 +310,17 @@ void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, in
if (alpha == 0) return;
- dbits = xd + yd;
+ // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow
+ if (xd+yd>16) {
+ xd = 8;
+ yd = 8;
+ }
+
+ dbits = xd + yd;
for (i = 0; i < 6; i++) {
- FFd2s[i] = (long) (d2s[i] * (1 << FBITS) + 0.5);
- FFd2s_HP[i] = (long long) (d2s[i] * (1 << FBITS_HP) + 0.5);;
+ FFd2s[i] = (long) floor(d2s[i] * (1 << FBITS) + 0.5);
+ FFd2s_HP[i] = (long long) floor(d2s[i] * (1 << FBITS_HP) + 0.5);;
}
if (dbits == 0) {
diff --git a/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S b/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S
deleted file mode 100644
index db2cbec5a..000000000
--- a/src/libnr/nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP.S
+++ /dev/null
@@ -1,125 +0,0 @@
- .file "nr-compose.c"
-
-# Ensure Inkscape is execshield protected
- .section .note.GNU-stack
- .previous
-
- .text
- .align 2
-.globl nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP
- .type nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP,@function
-
-/*
- * This code is in public domain
- *
- * c 32(%ebp)
- * srs 28(%ebp)
- * spx 24(%ebp)
- * rs 20(%ebp)
- * h 16(%ebp)
- * w 12(%ebp)
- * px 8(%ebp)
- * r -8(%ebp)
- * g -12(%ebp)
- * b -16(%ebp)
- * a -20(%ebp)
- * s -24(%ebp) -> %esi
- * d -28(%ebp) -> %edi
- * x -32(%ebp) -> %ebx
- * y -36(%ebp)
- * ca -40(%ebp)
- *
- * mm0 Fg
- * mm1 FgA
- * mm2 FgPre
- * mm3
- * mm4
- * mm5
- * mm6 128
- * mm7 0
- *
-*/
-
-nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP:
- pushl %ebp
- movl %esp, %ebp
- pushl %ebx
- subl $36, %esp
- pushl %edi
- pushl %esi
-
-/* Load %mm7 with [0 0 0 0] */
- movl $0, %eax
- movd %eax, %mm7
-
-/* Load %mm6 with [128 128 128 128] */
- movl $0x80808080, %eax
- movd %eax, %mm6
- punpcklbw %mm7, %mm6
-
-/* FgC -> %mm0 */
- movl 32(%ebp), %eax
- movd (%eax), %mm0
- punpcklbw %mm7, %mm0
-
-/* for (y = ...) */
- movl 16(%ebp), %ecx
-.fory:
-
-/* d = px */
-/* s = spx */
- movl 8(%ebp), %edi
- movl 24(%ebp), %esi
-
-/* for (x = ...) */
- movl 12(%ebp), %ebx
-.forx:
-
-/* [m m m m] -> %mm1 */
- movzbl (%esi), %eax
- testb $0xff, %al
- jz .clip
- movd %eax, %mm1
- punpcklwd %mm1, %mm1
- punpckldq %mm1, %mm1
-
-/* Fg -> mm2 */
- movq %mm0, %mm2
- pmullw %mm1, %mm2
- paddw %mm6, %mm2
- movq %mm2, %mm3
- psrlw $8, %mm3
- paddw %mm3, %mm2
- psrlw $8, %mm2
-
-/* Store pixel */
- packuswb %mm2, %mm2
- movd %mm2, (%edi)
-
-.clip:
- addl $4, %edi
- incl %esi
-
- decl %ebx
- jnz .forx
-
- movl 20(%ebp), %eax
- addl %eax, 8(%ebp)
- movl 28(%ebp), %eax
- addl %eax, 24(%ebp)
-
- decl %ecx
- jnz .fory
-
-.exit:
- emms
- popl %esi
- popl %edi
- addl $36, %esp
- popl %ebx
- popl %ebp
- ret
-
-.Lfe1:
- .size nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP,.Lfe1-nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP
- .ident "GCC: (GNU) 3.2"
diff --git a/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S b/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S
deleted file mode 100644
index fe1d9be57..000000000
--- a/src/libnr/nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP.S
+++ /dev/null
@@ -1,231 +0,0 @@
- .file "nr-compose.c"
-
-# Ensure Inkscape is execshield protected
- .section .note.GNU-stack
- .previous
-
- .text
- .align 2
-.globl nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP
- .type nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP,@function
-
-/*
- * This code is in public domain
- *
- * c 32(%ebp)
- * srs 28(%ebp)
- * spx 24(%ebp)
- * rs 20(%ebp)
- * h 16(%ebp)
- * w 12(%ebp)
- * px 8(%ebp)
- * r -8(%ebp)
- * g -12(%ebp)
- * b -16(%ebp)
- * a -20(%ebp)
- * s -24(%ebp) -> %esi
- * d -28(%ebp) -> %edi
- * x -32(%ebp) -> %ebx
- * y -36(%ebp)
- * ca -40(%ebp)
- *
- * mm0 Fg
- * mm1 MMMM
- * mm2 FgM
- * mm3
- * mm4
- * mm5 255
- * mm6 128
- * mm7 0
- *
-*/
-
-nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP:
- pushl %ebp
- movl %esp, %ebp
- pushl %ebx
- subl $36, %esp
- pushl %edi
- pushl %esi
-
-/* Load %mm7 with [0 0 0 0] */
- movl $0, %eax
- movd %eax, %mm7
-
-/* Load %mm6 with [128 128 128 128] */
- movl $0x80808080, %eax
- movd %eax, %mm6
- punpcklbw %mm7, %mm6
-
-/* Load %mm5 with [255 255 255 255] */
- movl $0xffffffff, %eax
- movd %eax, %mm5
- punpcklbw %mm7, %mm5
-
-/* FgC -> %mm0 */
- movl 32(%ebp), %eax
- movd (%eax), %mm0
- punpcklbw %mm7, %mm0
-
-/* Check full opacity */
- cmpb $0xff, %al
- jz .opaque
-
-/* for (y = ...) */
- movl 16(%ebp), %ecx
-.fory:
-
-/* d = px */
-/* s = spx */
- movl 8(%ebp), %edi
- movl 24(%ebp), %esi
-
-/* for (x = ...) */
- movl 12(%ebp), %ebx
-.forx:
-
-/* [m m m m] -> %mm1 */
- movzbl (%esi), %eax
- testb $0xff, %al
- jz .clip
- movd %eax, %mm1
- punpcklwd %mm1, %mm1
- punpckldq %mm1, %mm1
-
-/* Fg -> mm2 */
- movq %mm0, %mm2
- pmullw %mm1, %mm2
- paddw %mm6, %mm2
- movq %mm2, %mm3
- psrlw $8, %mm3
- paddw %mm3, %mm2
- psrlw $8, %mm2
-
-/* [255 - FgA] -> mm1 */
- movq %mm2, %mm1
- punpckhwd %mm1, %mm1
- punpckhdq %mm1, %mm1
- pxor %mm5, %mm1
-
-/* Bg -> mm3 */
- movd (%edi), %mm3
- punpcklbw %mm7, %mm3
-
-/* Fg + ((255 - FgA) * Bg) / 255 */
- pmullw %mm1, %mm3
- paddw %mm6, %mm3
- movq %mm3, %mm4
- psrlw $8, %mm4
- paddw %mm4, %mm3
- psrlw $8, %mm3
- paddw %mm2, %mm3
-
-/* Store pixel */
- packuswb %mm3, %mm3
- movd %mm3, (%edi)
-
-.clip:
- addl $4, %edi
- incl %esi
-
- decl %ebx
- jnz .forx
-
- movl 20(%ebp), %eax
- addl %eax, 8(%ebp)
- movl 28(%ebp), %eax
- addl %eax, 24(%ebp)
-
- decl %ecx
- jnz .fory
-
-.exit:
- emms
- popl %esi
- popl %edi
- addl $36, %esp
- popl %ebx
- popl %ebp
- ret
-
-.opaque:
-/* for (y = ...) */
- movl 16(%ebp), %ecx
-.o_fory:
-
-/* d = px */
-/* s = spx */
- movl 8(%ebp), %edi
- movl 24(%ebp), %esi
-
-/* for (x = ...) */
- movl 12(%ebp), %ebx
-.o_forx:
-
-/* [m m m m] -> %mm1 */
- movzbl (%esi), %eax
- testb $0xff, %al
- jz .o_clip
- cmpb $0xff, %al
- jz .o_full
- movd %eax, %mm1
- punpcklwd %mm1, %mm1
- punpckldq %mm1, %mm1
-
-/* Fg -> mm2 */
- movq %mm0, %mm2
- pmullw %mm1, %mm2
- paddw %mm6, %mm2
- movq %mm2, %mm3
- psrlw $8, %mm3
- paddw %mm3, %mm2
- psrlw $8, %mm2
-
-/* [255 - FgA] -> mm1 */
- movq %mm2, %mm1
- punpckhwd %mm1, %mm1
- punpckhdq %mm1, %mm1
- pxor %mm5, %mm1
-
-/* Bg -> mm3 */
- movd (%edi), %mm3
- punpcklbw %mm7, %mm3
-
-/* Fg + ((255 - FgA) * Bg) / 255 */
- pmullw %mm1, %mm3
- paddw %mm6, %mm3
- movq %mm3, %mm4
- psrlw $8, %mm4
- paddw %mm4, %mm3
- psrlw $8, %mm3
- paddw %mm2, %mm3
-
- jmp .o_store
-
-.o_full:
- movq %mm0, %mm3
-
-.o_store:
-/* Store pixel */
- packuswb %mm3, %mm3
- movd %mm3, (%edi)
-
-.o_clip:
- addl $4, %edi
- incl %esi
-
- decl %ebx
- jnz .o_forx
-
- movl 20(%ebp), %eax
- addl %eax, 8(%ebp)
- movl 28(%ebp), %eax
- addl %eax, 24(%ebp)
-
- decl %ecx
- jnz .o_fory
- jmp .exit
-
-.Lfe1:
- .size nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP,.Lfe1-nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP
- .ident "GCC: (GNU) 3.2"
diff --git a/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S b/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S
deleted file mode 100644
index 37261e572..000000000
--- a/src/libnr/nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P.S
+++ /dev/null
@@ -1,227 +0,0 @@
- .file "nr-compose.c"
-
-# Ensure Inkscape is execshield protected
- .section .note.GNU-stack
- .previous
-
- .text
- .align 2
-.globl nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P
- .type nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P,@function
-
-/*
- * This code is in public domain
- *
- * alpha 32(%ebp)
- * srs 28(%ebp)
- * spx 24(%ebp)
- * rs 20(%ebp)
- * h 16(%ebp)
- * w 12(%ebp)
- * px 8(%ebp)
- * r -8(%ebp)
- * g -12(%ebp)
- * b -16(%ebp)
- * a -20(%ebp)
- * s -24(%ebp) -> %esi
- * d -28(%ebp) -> %edi
- * x -32(%ebp) -> %ebx
- * y -36(%ebp)
- * ca -40(%ebp)
- *
- * mm0 A
- * mm1 FgA
- * mm2 FgPre
- * mm3
- * mm4
- * mm5 255
- * mm6 128
- * mm7 0
- *
-*/
-
-nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P:
- pushl %ebp
- movl %esp, %ebp
- pushl %ebx
- subl $36, %esp
- pushl %edi
- pushl %esi
-
-/* Load %mm7 with [0 0 0 0] */
- movl $0, %eax
- movd %eax, %mm7
-
-/* Load %mm6 with [128 128 128 128] */
- movl $0x80808080, %eax
- movd %eax, %mm6
- punpcklbw %mm7, %mm6
-
-/* Load %mm5 with [255 255 255 255] */
- movl $0xffffffff, %eax
- movd %eax, %mm5
- punpcklbw %mm7, %mm5
-
-/* Load %mm0 with [a a a a] */
-/* Check full opacity */
- movzbl 32(%ebp), %eax
- cmpb $0xff, %al
- jz .opaque
- movd %eax, %mm0
- punpcklwd %mm0, %mm0
- punpckldq %mm0, %mm0
-
-/* for (y = ...) */
- movl 16(%ebp), %ecx
-.fory:
-
-/* d = px */
-/* s = spx */
- movl 8(%ebp), %edi
- movl 24(%ebp), %esi
-
-/* for (x = ...) */
- movl 12(%ebp), %ebx
-.forx:
-
-/* Fg -> %mm1 */
-/* fixme: Do we have to bother about alignment here? (Lauris) */
- movl (%esi), %eax
- testl $0xff000000, %eax
- jz .clip
- movd %eax, %mm1
- punpcklbw %mm7, %mm1
-
-/* [Fg * a] -> mm1 */
- pmullw %mm0, %mm1
- paddw %mm6, %mm1
- movq %mm1, %mm2
- psrlw $8, %mm2
- paddw %mm2, %mm1
- psrlw $8, %mm1
-
-/* [255 - FgA] -> mm2 */
- movq %mm1, %mm2
- punpckhwd %mm2, %mm2
- punpckhdq %mm2, %mm2
- pxor %mm5, %mm2
-
-/* Bg -> mm3 */
- movd (%edi), %mm3
- punpcklbw %mm7, %mm3
-
-/* Fg + ((255 - FgA) * Bg) / 255 */
- pmullw %mm2, %mm3
- paddw %mm6, %mm3
- movq %mm3, %mm4
- psrlw $8, %mm4
- paddw %mm4, %mm3
- psrlw $8, %mm3
- paddw %mm1, %mm3
-
-/* Store pixel */
- packuswb %mm3, %mm3
- movd %mm3, %eax
- movb %al, 0(%edi)
- shrl $8, %eax
- movb %al, 1(%edi)
- shrl $8, %eax
- movb %al, 2(%edi)
-
-.clip:
- addl $3, %edi
- addl $4, %esi
-
- decl %ebx
- jnz .forx
-
- movl 20(%ebp), %eax
- addl %eax, 8(%ebp)
- movl 28(%ebp), %eax
- addl %eax, 24(%ebp)
-
- decl %ecx
- jnz .fory
-
-.exit:
- emms
- popl %esi
- popl %edi
- addl $36, %esp
- popl %ebx
- popl %ebp
- ret
-
-.opaque:
-/* for (y = ...) */
- movl 16(%ebp), %ecx
-.o_fory:
-
-/* d = px */
-/* s = spx */
- movl 8(%ebp), %edi
- movl 24(%ebp), %esi
-
-/* for (x = ...) */
- movl 12(%ebp), %ebx
-.o_forx:
-
-/* Fg -> %mm1 */
-/* fixme: Do we have to bother about alignment here? (Lauris) */
- movl (%esi), %eax
- testl $0xff000000, %eax
- jz .o_clip
- cmpl $0xff000000, %eax
- jnb .o_store
- movd %eax, %mm1
- punpcklbw %mm7, %mm1
-
-/* [255 - FgA] -> mm2 */
- movq %mm1, %mm2
- punpckhwd %mm2, %mm2
- punpckhdq %mm2, %mm2
- pxor %mm5, %mm2
-
-/* Bg -> mm3 */
- movd (%edi), %mm3
- punpcklbw %mm7, %mm3
-
-/* Fg + ((255 - FgA) * Bg) / 255 */
- pmullw %mm2, %mm3
- paddw %mm6, %mm3
- movq %mm3, %mm4
- psrlw $8, %mm4
- paddw %mm4, %mm3
- psrlw $8, %mm3
- paddw %mm1, %mm3
-
-/* Store pixel */
- packuswb %mm3, %mm3
- movd %mm3, %eax
-.o_store:
- movb %al, 0(%edi)
- shrl $8, %eax
- movb %al, 1(%edi)
- shrl $8, %eax
- movb %al, 2(%edi)
-
-.o_clip:
- addl $3, %edi
- addl $4, %esi
-
- decl %ebx
- jnz .o_forx
-
- movl 20(%ebp), %eax
- addl %eax, 8(%ebp)
- movl 28(%ebp), %eax
- addl %eax, 24(%ebp)
-
- decl %ecx
- jnz .o_fory
-
- jmp .exit
-
-.Lfe1:
- .size nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P,.Lfe1-nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P
- .ident "GCC: (GNU) 3.2"
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 06fb93f2d..067254b9e 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -22,6 +22,13 @@
#include "libnrtype/font-instance.h"
#include "util/unordered-containers.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
typedef INK_UNORDERED_MAP<PangoFontDescription*, font_instance*, font_descr_hash, font_descr_equal> FaceMapType;
// need to avoid using the size field
@@ -421,6 +428,14 @@ Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDes
return style;
}
+/**
+ Replace font family leaving style alone (if possible).
+ @param fontSpec the given font
+ @param newFamily
+ @return the changed fontspec, if the property can not be set return an empty string
+ The routine first searches for an exact match.
+ If no exact match found, calls FontSpecificationBestMatch().
+*/
Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily)
{
Glib::ustring newFontSpec;
@@ -431,10 +446,14 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
// what constitutes a "family" in our own UI may be different from how Pango
// sees it.
- // Find the PangoFontDescription associated to this fontSpec
+ // Find the PangoFontDescription associated with the font specification string.
PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
if (it != fontInstanceMap.end()) {
+ // Description found!
+
+ // Make copy
PangoFontDescription *descr = pango_font_description_copy((*it).second);
// Grab the UI Family string from the descr
@@ -452,46 +471,9 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
it = fontInstanceMap.find(newFontSpec);
if (it == fontInstanceMap.end()) {
- PangoFontDescription *newFontDescr = pango_font_description_from_string(newFontSpec.c_str());
-
- PangoFontDescription *bestMatchForNewDescr = NULL;
- Glib::ustring bestMatchFontDescription;
-
- bool setFirstFamilyMatch = false;
- for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) {
-
- Glib::ustring currentFontSpec = (*it).first;
-
- // Save some time by only looking at the right family
- if (currentFontSpec.find(newFamily) != Glib::ustring::npos) {
- if (!setFirstFamilyMatch) {
- // This ensures that the closest match is at least within the correct
- // family rather than the first font in the list
- bestMatchForNewDescr = pango_font_description_copy((*it).second);
- bestMatchFontDescription = currentFontSpec;
- setFirstFamilyMatch = true;
- } else {
- // Get the font description that corresponds, and
- // then see if we've found a better match
- PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second);
-
- if (pango_font_description_better_match(
- newFontDescr, bestMatchForNewDescr, possibleMatch)) {
-
- pango_font_description_free(bestMatchForNewDescr);
- bestMatchForNewDescr = possibleMatch;
- bestMatchFontDescription = currentFontSpec;
- } else {
- pango_font_description_free(possibleMatch);
- }
- }
- }
- }
-
- newFontSpec = bestMatchFontDescription;
+ // Search for best match, empty string returned if not found.
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
- pango_font_description_free(newFontDescr);
- pango_font_description_free(bestMatchForNewDescr);
}
}
@@ -502,92 +484,182 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
}
/**
- apply style property to the given font
+ Apply style property to the given font
@param fontSpec the given font
@param turnOn true to set italic style
@return the changed fontspec, if the property can not be set return an empty string
+ The routine first searches for an exact match to "FontFamily Italic" or
+ "Font Family Oblique" (turnOn is true) or "FontFamily" (turnOn is false).
+ If no exact match found, calls FontSpecificationBestMatch().
*/
Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn)
{
Glib::ustring newFontSpec;
- // Find the PangoFontDesecription that goes with this font specification string
+ // Find the PangoFontDescription associated with the font specification string.
PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
if (it != fontInstanceMap.end()) {
- // If we did find one, make a copy and set/unset the italic as needed
+ // Description found!
+
+ // Make copy.
PangoFontDescription *descr = pango_font_description_copy((*it).second);
PangoStyle style;
if (turnOn) {
- style = PANGO_STYLE_ITALIC;
+ // First try Oblique, we'll try Italic later
+ style = PANGO_STYLE_OBLIQUE;
} else {
style = PANGO_STYLE_NORMAL;
}
+
pango_font_description_set_style(descr, style);
newFontSpec = ConstructFontSpecification(descr);
+
+ bool exactMatchFound = true;
if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- if(turnOn) {
- // there is no PANGO_STYLE_ITALIC let's test for PANGO_STYLE_OBLIQUE
- style = PANGO_STYLE_OBLIQUE;
+
+ exactMatchFound = false;
+ if (turnOn) {
+ // Next try Italic
+ style = PANGO_STYLE_ITALIC;
pango_font_description_set_style(descr, style);
- newFontSpec = ConstructFontSpecification(descr);
+ exactMatchFound = true;
if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- // If the new font does not have even an oblique face, don't
- // allow italics to be set!
- newFontSpec = Glib::ustring("");
+ exactMatchFound = false;
}
-
- } else {
- // If the new font does not have an italic face, don't
- // allow italics to be set!
- newFontSpec = Glib::ustring("");
}
}
+ // Search for best match, empty string returned if not found.
+ if( !exactMatchFound ) {
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
+ }
+
pango_font_description_free(descr);
}
- return newFontSpec;
+ return newFontSpec; // Empty if not found.
}
/**
- apply width property to the given font
+ Apply weight property to the given font
@param fontSpec the given font
@param turnOn true to set bold
@return the changed fontspec, if the property can not be set return an empty string
+ This routine first searches for an exact match, if none found
+ it calls FontSpecificationBestMatch().
*/
Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn)
{
Glib::ustring newFontSpec;
- // Find the PangoFontDesecription that goes with this font specification string
+ // Find the PangoFontDescription associated with the font specification string.
PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
if (it != fontInstanceMap.end()) {
- // If we did find one, make a copy and set/unset the bold as needed
+ // Description found!
+
+ // Make copy.
PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
PangoWeight weight;
if (turnOn) {
weight = PANGO_WEIGHT_BOLD;
} else {
weight = PANGO_WEIGHT_NORMAL;
}
+
pango_font_description_set_weight(descr, weight);
newFontSpec = ConstructFontSpecification(descr);
+
if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- // If the new font does not have a bold face, don't
- // allow bold to be set!
- newFontSpec = Glib::ustring("");
+ // Search for best match, empty string returned if not found.
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
}
pango_font_description_free(descr);
}
+ return newFontSpec; // Empty if not found.
+}
+
+/**
+ Use pango_font_description_better_match() to find best font match.
+ This handles cases like Century Schoolbook L where the "normal"
+ font is Century Schoolbook L Medium so just removing Italic
+ from the font name doesn't yield the correct name.
+ @param fontSpec the given font
+ @return the changed fontspec, if the property can not be set return an empty string
+*/
+// http://library.gnome.org/devel/pango/1.28/pango-Fonts.html#pango-font-description-better-match
+Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fontSpec )
+{
+
+ Glib::ustring newFontSpec;
+
+ // Look for exact match
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
+ // If there is no exact match, look for the best match.
+ if (it != fontInstanceMap.end()) {
+
+ newFontSpec = fontSpec;
+
+ } else {
+
+ PangoFontDescription *fontDescr = pango_font_description_from_string(fontSpec.c_str());
+ PangoFontDescription *bestMatchDescr = NULL;
+
+ // Grab the UI Family string from the descr
+ Glib::ustring family = GetUIFamilyString(fontDescr);
+ Glib::ustring bestMatchDescription;
+
+ bool setFirstFamilyMatch = false;
+ for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) {
+
+ Glib::ustring currentFontSpec = (*it).first;
+ Glib::ustring currentFamily = GetUIFamilyString((*it).second);
+
+ // Save some time by only looking at the right family.
+ // Must use family name rather than fontSpec
+ // (otherwise DejaVu Sans matches DejaVu Sans Mono).
+ if (currentFamily == family) {
+ if (!setFirstFamilyMatch) {
+ // This ensures that the closest match is at least within the correct
+ // family rather than the first font in the list
+ bestMatchDescr = pango_font_description_copy((*it).second);
+ bestMatchDescription = currentFontSpec;
+ setFirstFamilyMatch = true;
+ } else {
+ // Get the font description that corresponds, and
+ // then see if we've found a better match
+ PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second);
+
+ if (pango_font_description_better_match(
+ fontDescr, bestMatchDescr, possibleMatch)) {
+
+ pango_font_description_free(bestMatchDescr);
+ bestMatchDescr = possibleMatch;
+ bestMatchDescription = currentFontSpec;
+ } else {
+ pango_font_description_free(possibleMatch);
+ }
+ }
+ }
+ } // for
+
+ newFontSpec = bestMatchDescription; // If NULL, then no match found
+
+ pango_font_description_free(fontDescr);
+ pango_font_description_free(bestMatchDescr);
+
+ }
+
return newFontSpec;
}
@@ -689,6 +761,7 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style)
g_assert(style);
if (style) {
+
// First try to use the font specification if it is set
if (style->text->font_specification.set
&& style->text->font_specification.value
@@ -699,7 +772,16 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style)
// If that failed, try using the CSS information in the style
if (!font) {
+
font = Face(style->text->font_family.value, font_style_to_pos(*style));
+
+ // That was a hatchet job... so we need to check if this font exists!!
+ Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font);
+ Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec );
+ if( fontSpec != newFontSpec ) {
+ font->Unref();
+ font = FaceFromFontSpecification( newFontSpec.c_str() );
+ }
}
}
@@ -899,12 +981,20 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL);
}
- if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) {
+ if ( apos.weight <= NR_POS_WEIGHT_THIN ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN);
+ } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT);
} else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT);
+ } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK);
} else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL);
+ } else if ( apos.weight <= NR_POS_WEIGHT_MEDIUM ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM);
+ } else if ( apos.weight <= NR_POS_WEIGHT_SEMIBOLD ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD);
} else if ( apos.weight <= NR_POS_WEIGHT_BOLD ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD);
} else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_BOLD ) {
@@ -912,6 +1002,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
} else {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY);
}
+ // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2)
if ( apos.stretch <= NR_POS_STRETCH_ULTRA_CONDENSED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED);
@@ -919,7 +1010,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED);
} else if ( apos.stretch <= NR_POS_STRETCH_SEMI_CONDENSED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED);
- } else if ( apos.stretch <= NR_POS_WEIGHT_NORMAL ) {
+ } else if ( apos.stretch <= NR_POS_STRETCH_NORMAL ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL);
} else if ( apos.stretch <= NR_POS_STRETCH_SEMI_EXPANDED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED);
@@ -946,7 +1037,7 @@ void font_factory::UnrefFace(font_instance *who)
g_free(tc);
} else {
loadedFaces.erase(loadedFaces.find(who->descr));
- // printf("unrefFace %p: success\n",who);
+ // printf("unrefFace %p: success\n",who);
}
}
}
@@ -957,7 +1048,7 @@ void font_factory::AddInCache(font_instance *who)
for (int i = 0;i < nbEnt;i++) ents[i].age *= 0.9;
for (int i = 0;i < nbEnt;i++) {
if ( ents[i].f == who ) {
- // printf("present\n");
+ // printf("present\n");
ents[i].age += 1.0;
return;
}
@@ -984,6 +1075,23 @@ void font_factory::AddInCache(font_instance *who)
nbEnt++;
}
+/*
+ {
+ std::cout << " Printing out fontInstanceMap: " << std::endl;
+ PangoStringToDescrMap::iterator it = fontInstanceMap.begin();
+ while (it != fontInstanceMap.end()) {
+
+ PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
+ // Grab the UI Family string from the descr
+ Glib::ustring uiFamily = GetUIFamilyString(descr);
+ Glib::ustring uiStyle = GetUIStyleString(descr);
+ std::cout << " " << uiFamily << " " << uiStyle << std::endl;
+
+ it++;
+ }
+ }
+*/
/*
Local Variables:
diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h
index 0118c862d..632ea565f 100644
--- a/src/libnrtype/FontFactory.h
+++ b/src/libnrtype/FontFactory.h
@@ -102,6 +102,8 @@ public:
Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn);
Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn);
+ Glib::ustring FontSpecificationBestMatch(const Glib::ustring& fontSpec );
+
// Gathers all strings needed for UI while storing pango information in
// fontInstanceMap and fontStringMap
void GetUIFamiliesAndStyles(FamilyToStylesMap *map);
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index be5eb86c8..b958e899d 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -28,6 +28,13 @@
#include "livarot/Path.h"
#include "util/unordered-containers.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
struct font_style_hash : public std::unary_function<font_style, size_t> {
size_t operator()(font_style const &x) const;
@@ -39,57 +46,59 @@ struct font_style_equal : public std::binary_function<font_style, font_style, bo
typedef INK_UNORDERED_MAP<font_style, raster_font*, font_style_hash, font_style_equal> StyleMap;
-
-
-size_t font_style_hash::operator()(const font_style &x) const {
- int h=0,n;
- n=(int)floor(100*x.stroke_width);
- h*=12186;
- h+=n;
- n=(x.vertical)?1:0;
- h*=12186;
- h+=n;
- if ( x.stroke_width >= 0.01 ) {
- n=x.stroke_cap*10+x.stroke_join+(int)(x.stroke_miter_limit*100);
- h*=12186;
- h+=n;
- if ( x.nbDash > 0 ) {
- n=x.nbDash;
- h*=12186;
- h+=n;
- n=(int)floor(100*x.dash_offset);
- h*=12186;
- h+=n;
- for (int i=0;i<x.nbDash;i++) {
- n=(int)floor(100*x.dashes[i]);
- h*=12186;
- h+=n;
- }
- }
- }
- return h;
+static const double STROKE_WIDTH_THREASHOLD = 0.01;
+
+
+
+size_t font_style_hash::operator()(const font_style &x) const {
+ int h = 0;
+ int n = static_cast<int>(floor(100 * x.stroke_width));
+ h *= 12186;
+ h += n;
+ n = (x.vertical) ? 1:0;
+ h *= 12186;
+ h += n;
+ if ( x.stroke_width >= STROKE_WIDTH_THREASHOLD ) {
+ n = x.stroke_cap * 10 + x.stroke_join + static_cast<int>(x.stroke_miter_limit * 100);
+ h *= 12186;
+ h += n;
+ if ( x.nbDash > 0 ) {
+ n = x.nbDash;
+ h *= 12186;
+ h += n;
+ n = static_cast<int>(floor(100 * x.dash_offset));
+ h *= 12186;
+ h += n;
+ for (int i = 0; i < x.nbDash; i++) {
+ n = static_cast<int>(floor(100 * x.dashes[i]));
+ h *= 12186;
+ h += n;
+ }
+ }
+ }
+ return h;
}
-bool font_style_equal::operator()(const font_style &a,const font_style &b) const {
- for (int i=0;i<6;i++) {
- if ( (int)(100*a.transform[i]) != (int)(100*b.transform[i]) ) return false;
- }
- if ( a.vertical && b.vertical == false ) return false;
- if ( a.vertical == false && b.vertical ) return false;
- if ( a.stroke_width > 0.01 && b.stroke_width <= 0.01 ) return false;
- if ( a.stroke_width <= 0.01 && b.stroke_width > 0.01 ) return false;
- if ( a.stroke_width <= 0.01 && b.stroke_width <= 0.01 ) return true;
-
- if ( a.stroke_cap != b.stroke_cap ) return false;
- if ( a.stroke_join != b.stroke_join ) return false;
- if ( (int)(a.stroke_miter_limit*100) != (int)(b.stroke_miter_limit*100) ) return false;
- if ( a.nbDash != b.nbDash ) return false;
- if ( a.nbDash <= 0 ) return true;
- if ( (int)floor(100*a.dash_offset) != (int)floor(100*b.dash_offset) ) return false;
- for (int i=0;i<a.nbDash;i++) {
- if ( (int)floor(100*a.dashes[i]) != (int)floor(100*b.dashes[i]) ) return false;
- }
- return true;
+bool font_style_equal::operator()(const font_style &a,const font_style &b) const {
+ bool same = true;
+ for (int i = 0; (i < 6) && same; i++) {
+ same = ( static_cast<int>(100 * a.transform[i]) == static_cast<int>(100 * b.transform[i]) );
+ }
+ same &= ( a.vertical == b.vertical )
+ && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) == ( b.stroke_width > STROKE_WIDTH_THREASHOLD );
+ if ( same && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) ) {
+ same = ( a.stroke_cap == b.stroke_cap )
+ && ( a.stroke_join == b.stroke_join )
+ && ( static_cast<int>(a.stroke_miter_limit * 100) == static_cast<int>(b.stroke_miter_limit * 100) )
+ && ( a.nbDash == b.nbDash );
+ if ( same && ( a.nbDash > 0 ) ) {
+ same = ( static_cast<int>(floor(100 * a.dash_offset)) == static_cast<int>(floor(100 * b.dash_offset)) );
+ for (int i = 0; (i < a.nbDash) && same; i++) {
+ same = ( static_cast<int>(floor(100 * a.dashes[i])) == static_cast<int>(floor(100 * b.dashes[i])) );
+ }
+ }
+ }
+ return same;
}
#ifndef USE_PANGO_WIN32
@@ -97,9 +106,9 @@ bool font_style_equal::operator()(const font_style &a,const font_style &b) cons
* Outline extraction
*/
typedef struct ft2_to_liv {
- Path* theP;
- double scale;
- Geom::Point last;
+ Path* theP;
+ double scale;
+ Geom::Point last;
} ft2_to_liv;
// Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an
@@ -116,46 +125,46 @@ typedef FT_Vector FREETYPE_VECTOR;
// outline as returned by freetype -> livarot Path
// see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based
static int ft2_move_to(FREETYPE_VECTOR *to, void * i_user) {
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
- // printf("m t=%f %f\n",p[0],p[1]);
- user->theP->MoveTo(p);
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ // printf("m t=%f %f\n",p[0],p[1]);
+ user->theP->MoveTo(p);
+ user->last=p;
+ return 0;
}
static int ft2_line_to(FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
- // printf("l t=%f %f\n",p[0],p[1]);
- user->theP->LineTo(p);
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ // printf("l t=%f %f\n",p[0],p[1]);
+ user->theP->LineTo(p);
+ user->last=p;
+ return 0;
}
static int ft2_conic_to(FREETYPE_VECTOR *control, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y);
- // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
- user->theP->BezierTo(p);
- user->theP->IntermBezierTo(c);
- user->theP->EndBezierTo();
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y);
+ // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
+ user->theP->BezierTo(p);
+ user->theP->IntermBezierTo(c);
+ user->theP->EndBezierTo();
+ user->last=p;
+ return 0;
}
static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y),
- c1(user->scale*control1->x,user->scale*control1->y),
- c2(user->scale*control2->x,user->scale*control2->y);
- // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
- user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ Geom::Point c1(user->scale*control1->x,user->scale*control1->y);
+ Geom::Point c2(user->scale*control2->x,user->scale*control2->y);
+ // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
+ user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
+ user->last=p;
+ return 0;
}
#endif
@@ -203,7 +212,7 @@ font_instance::~font_instance(void)
descr = 0;
}
- // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
+ // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
theFace = 0;
for (int i=0;i<nbGlyph;i++) {
@@ -224,56 +233,60 @@ font_instance::~font_instance(void)
void font_instance::Ref(void)
{
- refCount++;
- //char *tc=pango_font_description_to_string(descr);
- //printf("font %x %s ref'd %i\n",this,tc,refCount);
- //free(tc);
+ refCount++;
+ //char *tc=pango_font_description_to_string(descr);
+ //printf("font %x %s ref'd %i\n",this,tc,refCount);
+ //free(tc);
}
void font_instance::Unref(void)
{
- refCount--;
- //char *tc=pango_font_description_to_string(descr);
- //printf("font %x %s unref'd %i\n",this,tc,refCount);
- //free(tc);
- if ( refCount <= 0 ) {
- if ( daddy ) daddy->UnrefFace(this);
- daddy=NULL;
- delete this;
- }
+ refCount--;
+ //char *tc=pango_font_description_to_string(descr);
+ //printf("font %x %s unref'd %i\n",this,tc,refCount);
+ //free(tc);
+ if ( refCount <= 0 ) {
+ if ( daddy ) {
+ daddy->UnrefFace(this);
+ }
+ daddy=NULL;
+ delete this;
+ }
}
unsigned int font_instance::Name(gchar *str, unsigned int size)
{
- return Attribute("name", str, size);
+ return Attribute("name", str, size);
}
unsigned int font_instance::Family(gchar *str, unsigned int size)
{
- return Attribute("family", str, size);
+ return Attribute("family", str, size);
}
unsigned int font_instance::PSName(gchar *str, unsigned int size)
{
- return Attribute("psname", str, size);
+ return Attribute("psname", str, size);
}
unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size)
{
- if ( descr == NULL ) {
- if ( size > 0 ) str[0]=0;
- return 0;
- }
- char* res=NULL;
- bool free_res=false;
-
- if ( strcmp(key,"name") == 0 ) {
- PangoFontDescription* td=pango_font_description_copy(descr);
- pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
- res=pango_font_description_to_string (td);
- pango_font_description_free(td);
- free_res=true;
- } else if ( strcmp(key,"psname") == 0 ) {
+ if ( descr == NULL ) {
+ if ( size > 0 ) {
+ str[0]=0;
+ }
+ return 0;
+ }
+ char* res=NULL;
+ bool free_res=false;
+
+ if ( strcmp(key,"name") == 0 ) {
+ PangoFontDescription* td=pango_font_description_copy(descr);
+ pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
+ res=pango_font_description_to_string (td);
+ pango_font_description_free(td);
+ free_res=true;
+ } else if ( strcmp(key,"psname") == 0 ) {
#ifndef USE_PANGO_WIN32
res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work
#endif
@@ -292,81 +305,97 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int
(i) ? "Italic" : ((o) ? "Oblique" : "") );
free_res = true;
}
- } else if ( strcmp(key,"family") == 0 ) {
- res=(char*)pango_font_description_get_family(descr);
- free_res=false;
- } else if ( strcmp(key,"style") == 0 ) {
- PangoStyle v=pango_font_description_get_style(descr);
- if ( v == PANGO_STYLE_ITALIC ) {
- res=(char*)"italic";
- } else if ( v == PANGO_STYLE_OBLIQUE ) {
- res=(char*)"oblique";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else if ( strcmp(key,"weight") == 0 ) {
- PangoWeight v=pango_font_description_get_weight(descr);
- if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
- res=(char*)"200";
- } else if ( v <= PANGO_WEIGHT_LIGHT ) {
- res=(char*)"300";
- } else if ( v <= PANGO_WEIGHT_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_WEIGHT_BOLD ) {
- res=(char*)"bold";
- } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
- res=(char*)"800";
- } else { // HEAVY
- res=(char*)"900";
- }
- free_res=false;
- } else if ( strcmp(key,"stretch") == 0 ) {
- PangoStretch v=pango_font_description_get_stretch(descr);
- if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
- res=(char*)"extra-condensed";
- } else if ( v <= PANGO_STRETCH_CONDENSED ) {
- res=(char*)"condensed";
- } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
- res=(char*)"semi-condensed";
- } else if ( v <= PANGO_STRETCH_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
- res=(char*)"semi-expanded";
- } else if ( v <= PANGO_STRETCH_EXPANDED ) {
- res=(char*)"expanded";
- } else {
- res=(char*)"extra-expanded";
- }
- free_res=false;
- } else if ( strcmp(key,"variant") == 0 ) {
- PangoVariant v=pango_font_description_get_variant(descr);
- if ( v == PANGO_VARIANT_SMALL_CAPS ) {
- res=(char*)"small-caps";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else {
- res = NULL;
- free_res=false;
- }
- if ( res == NULL ) {
- if ( size > 0 ) str[0]=0;
- return 0;
- }
-
- if (res) {
- unsigned int len=strlen(res);
- unsigned int rlen=(size-1<len)?size-1:len;
- if ( str ) {
- if ( rlen > 0 ) memcpy(str,res,rlen);
- if ( size > 0 ) str[rlen]=0;
- }
- if (free_res) free(res);
- return len;
- }
- return 0;
+ } else if ( strcmp(key,"family") == 0 ) {
+ res=(char*)pango_font_description_get_family(descr);
+ free_res=false;
+ } else if ( strcmp(key,"style") == 0 ) {
+ PangoStyle v=pango_font_description_get_style(descr);
+ if ( v == PANGO_STYLE_ITALIC ) {
+ res=(char*)"italic";
+ } else if ( v == PANGO_STYLE_OBLIQUE ) {
+ res=(char*)"oblique";
+ } else {
+ res=(char*)"normal";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"weight") == 0 ) {
+ PangoWeight v=pango_font_description_get_weight(descr);
+ if ( v <= PANGO_WEIGHT_THIN ) {
+ res=(char*)"100";
+ } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
+ res=(char*)"200";
+ } else if ( v <= PANGO_WEIGHT_LIGHT ) {
+ res=(char*)"300";
+ } else if ( v <= PANGO_WEIGHT_BOOK ) {
+ res=(char*)"380";
+ } else if ( v <= PANGO_WEIGHT_NORMAL ) {
+ res=(char*)"normal";
+ } else if ( v <= PANGO_WEIGHT_MEDIUM ) {
+ res=(char*)"500";
+ } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) {
+ res=(char*)"600";
+ } else if ( v <= PANGO_WEIGHT_BOLD ) {
+ res=(char*)"bold";
+ } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
+ res=(char*)"800";
+ } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2
+ res=(char*)"900";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"stretch") == 0 ) {
+ PangoStretch v=pango_font_description_get_stretch(descr);
+ if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
+ res=(char*)"extra-condensed";
+ } else if ( v <= PANGO_STRETCH_CONDENSED ) {
+ res=(char*)"condensed";
+ } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
+ res=(char*)"semi-condensed";
+ } else if ( v <= PANGO_STRETCH_NORMAL ) {
+ res=(char*)"normal";
+ } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
+ res=(char*)"semi-expanded";
+ } else if ( v <= PANGO_STRETCH_EXPANDED ) {
+ res=(char*)"expanded";
+ } else {
+ res=(char*)"extra-expanded";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"variant") == 0 ) {
+ PangoVariant v=pango_font_description_get_variant(descr);
+ if ( v == PANGO_VARIANT_SMALL_CAPS ) {
+ res=(char*)"small-caps";
+ } else {
+ res=(char*)"normal";
+ }
+ free_res=false;
+ } else {
+ res = NULL;
+ free_res=false;
+ }
+ if ( res == NULL ) {
+ if ( size > 0 ) {
+ str[0] = 0;
+ }
+ return 0;
+ }
+
+ if (res) {
+ unsigned int len=strlen(res);
+ unsigned int rlen=(size-1<len)?size-1:len;
+ if ( str ) {
+ if ( rlen > 0 ) {
+ memcpy(str, res, rlen);
+ }
+ if ( size > 0 ) {
+ str[rlen] = 0;
+ }
+ }
+ if (free_res) {
+ free(res);
+ }
+ return len;
+ }
+ return 0;
}
void font_instance::InitTheFace()
@@ -383,9 +412,10 @@ void font_instance::InitTheFace()
SetGraphicsMode(daddy->hScreenDC, GM_COMPATIBLE);
SelectObject(daddy->hScreenDC,theFace);
#else
- theFace=pango_ft2_font_get_face(pFont);
- if ( theFace )
+ theFace=pango_ft2_font_get_face(pFont);
+ if ( theFace ) {
FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol);
+ }
#endif
}
@@ -400,46 +430,52 @@ void font_instance::FreeTheFace()
void font_instance::InstallFace(PangoFont* iFace)
{
- if ( !iFace )
- return;
- pFont=iFace;
+ if ( !iFace ) {
+ return;
+ }
+ pFont=iFace;
InitTheFace();
- if ( pFont && IsOutlineFont() == false ) {
+ if ( pFont && IsOutlineFont() == false ) {
FreeTheFace();
- if ( pFont ) g_object_unref(pFont);
- pFont=NULL;
- }
+ if ( pFont ) {
+ g_object_unref(pFont);
+ }
+ pFont=NULL;
+ }
}
-bool font_instance::IsOutlineFont(void)
+bool font_instance::IsOutlineFont(void)
{
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
#ifdef USE_PANGO_WIN32
TEXTMETRIC tm;
return GetTextMetrics(daddy->hScreenDC,&tm) && tm.tmPitchAndFamily&(TMPF_TRUETYPE|TMPF_DEVICE);
#else
- return FT_IS_SCALABLE(theFace);
+ return FT_IS_SCALABLE(theFace);
#endif
}
int font_instance::MapUnicodeChar(gunichar c)
{
- if ( pFont == NULL ) return 0;
+ int res = 0;
+ if ( pFont ) {
#ifdef USE_PANGO_WIN32
- return pango_win32_font_get_glyph_index(pFont,c);
+ res = pango_win32_font_get_glyph_index(pFont, c);
#else
- int res=0;
- theFace=pango_ft2_font_get_face(pFont);
- if ( c > 0xf0000 ) {
- res=CLAMP(c,0xf0000,0x1fffff)-0xf0000;
- } else {
- res=FT_Get_Char_Index(theFace, c);
- }
- return res;
+ theFace = pango_ft2_font_get_face(pFont);
+ if ( c > 0xf0000 ) {
+ res = CLAMP(c, 0xf0000, 0x1fffff) - 0xf0000;
+ } else {
+ res = FT_Get_Char_Index(theFace, c);
+ }
#endif
+ }
+ return res;
}
@@ -453,22 +489,26 @@ static inline Geom::Point pointfx_to_nrpoint(const POINTFX &p, double scale)
void font_instance::LoadGlyph(int glyph_id)
{
- if ( pFont == NULL ) return;
+ if ( pFont == NULL ) {
+ return;
+ }
InitTheFace();
#ifndef USE_PANGO_WIN32
- if ( !FT_IS_SCALABLE(theFace) ) return; // bitmap font
+ if ( !FT_IS_SCALABLE(theFace) ) {
+ return; // bitmap font
+ }
#endif
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- if ( nbGlyph >= maxGlyph ) {
- maxGlyph=2*nbGlyph+1;
- glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
- }
- font_glyph n_g;
- n_g.outline=NULL;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ if ( nbGlyph >= maxGlyph ) {
+ maxGlyph=2*nbGlyph+1;
+ glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
+ }
+ font_glyph n_g;
+ n_g.outline=NULL;
n_g.pathvector=NULL;
- n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
- bool doAdd=false;
+ n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
+ bool doAdd=false;
#ifdef USE_PANGO_WIN32
@@ -493,15 +533,15 @@ void font_instance::LoadGlyph(int glyph_id)
// character has no visual representation, but is valid (eg whitespace)
doAdd=true;
} else {
- std::auto_ptr<char> buffer(new char[bufferSize]);
- if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer.get(), &identity) <= 0 ) {
+ char *buffer = new char[bufferSize];
+ if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
// shit happened
} else {
// Platform SDK is rubbish, read KB87115 instead
n_g.outline=new Path;
DWORD polyOffset=0;
while ( polyOffset < bufferSize ) {
- TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer.get()+polyOffset);
+ TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
if (polyOffset+polyHeader->cb > bufferSize) break;
if (polyHeader->dwType == TT_POLYGON_TYPE) {
@@ -509,7 +549,7 @@ void font_instance::LoadGlyph(int glyph_id)
DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);
while ( curveOffset < polyOffset+polyHeader->cb ) {
- TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer.get()+curveOffset);
+ TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
POINTFX const *p=polyCurve->apfx;
POINTFX const *endp=p+polyCurve->cpfx;
@@ -526,15 +566,15 @@ void font_instance::LoadGlyph(int glyph_id)
Geom::Point this_mid=pointfx_to_nrpoint(p[0], scale);
while ( p != endp ) {
Geom::Point next_mid=pointfx_to_nrpoint(p[1], scale);
- n_g.outline->BezierTo((next_mid+this_mid)/2);
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
+ n_g.outline->BezierTo((next_mid+this_mid)/2);
+ n_g.outline->IntermBezierTo(this_mid);
+ n_g.outline->EndBezierTo();
++p;
this_mid=next_mid;
}
- n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale));
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
+ n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale));
+ n_g.outline->IntermBezierTo(this_mid);
+ n_g.outline->EndBezierTo();
break;
}
@@ -554,75 +594,84 @@ void font_instance::LoadGlyph(int glyph_id)
}
doAdd=true;
}
+ delete [] buffer;
}
#else
- if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
- // shit happened
- } else {
- if ( FT_HAS_HORIZONTAL(theFace) ) {
- n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
- n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
- } else {
- n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
- }
- if ( FT_HAS_VERTICAL(theFace) ) {
- n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
- n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
- } else {
- n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
- }
- if ( theFace->glyph->format == ft_glyph_format_outline ) {
- FT_Outline_Funcs ft2_outline_funcs = {
- ft2_move_to,
- ft2_line_to,
- ft2_conic_to,
- ft2_cubic_to,
- 0, 0
- };
- n_g.outline=new Path;
- ft2_to_liv tData;
- tData.theP=n_g.outline;
- tData.scale=1.0/((double)theFace->units_per_EM);
- tData.last=Geom::Point(0,0);
- FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData);
- }
- doAdd=true;
- }
+ if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
+ // shit happened
+ } else {
+ if ( FT_HAS_HORIZONTAL(theFace) ) {
+ n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
+ n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
+ } else {
+ n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
+ }
+ if ( FT_HAS_VERTICAL(theFace) ) {
+ n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
+ n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
+ } else {
+ n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
+ }
+ if ( theFace->glyph->format == ft_glyph_format_outline ) {
+ FT_Outline_Funcs ft2_outline_funcs = {
+ ft2_move_to,
+ ft2_line_to,
+ ft2_conic_to,
+ ft2_cubic_to,
+ 0, 0
+ };
+ n_g.outline=new Path;
+ ft2_to_liv tData;
+ tData.theP=n_g.outline;
+ tData.scale=1.0/((double)theFace->units_per_EM);
+ tData.last=Geom::Point(0,0);
+ FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData);
+ }
+ doAdd=true;
+ }
#endif
- if ( doAdd ) {
- if ( n_g.outline ) {
- n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]);
+ if ( doAdd ) {
+ if ( n_g.outline ) {
+ n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]);
n_g.pathvector=n_g.outline->MakePathVector();
- }
- glyphs[nbGlyph]=n_g;
- id_to_no[glyph_id]=nbGlyph;
- nbGlyph++;
- }
+ }
+ glyphs[nbGlyph]=n_g;
+ id_to_no[glyph_id]=nbGlyph;
+ nbGlyph++;
+ }
} else {
}
}
bool font_instance::FontMetrics(double &ascent,double &descent,double &leading)
{
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
- if ( theFace == NULL ) return false;
+ if ( theFace == NULL ) {
+ return false;
+ }
#ifdef USE_PANGO_WIN32
OUTLINETEXTMETRIC otm;
- if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) return false;
+ if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) {
+ return false;
+ }
double scale=1.0/daddy->fontSize;
ascent=fabs(otm.otmAscent*scale);
descent=fabs(otm.otmDescent*scale);
leading=fabs(otm.otmLineGap*scale);
#else
- if ( theFace->units_per_EM == 0 ) return false; // bitmap font
- ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM));
- descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM));
- leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM));
- leading-=ascent+descent;
+ if ( theFace->units_per_EM == 0 ) {
+ return false; // bitmap font
+ }
+ ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM));
+ descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM));
+ leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM));
+ leading-=ascent+descent;
#endif
- return true;
+ return true;
}
bool font_instance::FontSlope(double &run, double &rise)
@@ -630,9 +679,13 @@ bool font_instance::FontSlope(double &run, double &rise)
run = 0.0;
rise = 1.0;
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
- if ( theFace == NULL ) return false;
+ if ( theFace == NULL ) {
+ return false;
+ }
#ifdef USE_PANGO_WIN32
OUTLINETEXTMETRIC otm;
@@ -640,59 +693,63 @@ bool font_instance::FontSlope(double &run, double &rise)
run=otm.otmsCharSlopeRun;
rise=otm.otmsCharSlopeRise;
#else
- if ( !FT_IS_SCALABLE(theFace) ) return false; // bitmap font
+ if ( !FT_IS_SCALABLE(theFace) ) {
+ return false; // bitmap font
+ }
TT_HoriHeader *hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(theFace, ft_sfnt_hhea);
- if (hhea == NULL) return false;
+ if (hhea == NULL) {
+ return false;
+ }
run = hhea->caret_Slope_Run;
rise = hhea->caret_Slope_Rise;
#endif
- return true;
+ return true;
}
Geom::OptRect font_instance::BBox(int glyph_id)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no < 0 ) {
- return Geom::OptRect();
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
} else {
- Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]);
- Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]);
- return Geom::Rect(rmin, rmax);
+ no = id_to_no[glyph_id];
}
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no < 0 ) {
+ return Geom::OptRect();
+ } else {
+ Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]);
+ Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]);
+ return Geom::Rect(rmin, rmax);
+ }
}
Path* font_instance::Outline(int glyph_id,Path* copyInto)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no < 0 ) return NULL;
- Path* src_o=glyphs[no].outline;
- if ( copyInto ) {
- copyInto->Reset();
- copyInto->Copy(src_o);
- return copyInto;
- }
- return src_o;
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no < 0 ) return NULL;
+ Path *src_o = glyphs[no].outline;
+ if ( copyInto ) {
+ copyInto->Reset();
+ copyInto->Copy(src_o);
+ return copyInto;
+ }
+ return src_o;
}
Geom::PathVector* font_instance::PathVector(int glyph_id)
@@ -714,70 +771,74 @@ Geom::PathVector* font_instance::PathVector(int glyph_id)
double font_instance::Advance(int glyph_id,bool vertical)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no >= 0 ) {
- if ( vertical ) {
- return glyphs[no].v_advance;
- } else {
- return glyphs[no].h_advance;
- }
- }
- return 0;
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
+ } else {
+ no=id_to_no[glyph_id];
+ }
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no >= 0 ) {
+ if ( vertical ) {
+ return glyphs[no].v_advance;
+ } else {
+ return glyphs[no].h_advance;
+ }
+ }
+ return 0;
}
raster_font* font_instance::RasterFont(const Geom::Matrix &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/)
{
- font_style nStyle;
- nStyle.transform=trs;
- nStyle.vertical=vertical;
- nStyle.stroke_width=stroke_width;
- nStyle.stroke_cap=stroke_cap;
- nStyle.stroke_join=stroke_join;
- nStyle.nbDash=0;
- nStyle.dash_offset=0;
- nStyle.dashes=NULL;
- return RasterFont(nStyle);
+ font_style nStyle;
+ nStyle.transform=trs;
+ nStyle.vertical=vertical;
+ nStyle.stroke_width=stroke_width;
+ nStyle.stroke_cap=stroke_cap;
+ nStyle.stroke_join=stroke_join;
+ nStyle.nbDash=0;
+ nStyle.dash_offset=0;
+ nStyle.dashes=NULL;
+ return RasterFont(nStyle);
}
raster_font* font_instance::RasterFont(const font_style &inStyle)
{
- raster_font *res=NULL;
- double *savDashes=NULL;
- font_style nStyle=inStyle;
+ raster_font *res=NULL;
+ double *savDashes=NULL;
+ font_style nStyle=inStyle;
// for some evil reason font_style doesn't have a copy ctor, so the
// stuff that should be done there is done here instead (because the
// raster_font ctor copies nStyle).
- if ( nStyle.stroke_width > 0 && nStyle.nbDash > 0 && nStyle.dashes ) {
- savDashes=nStyle.dashes;
- nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double));
- memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double));
- }
- StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
- if ( loadedStyles.find(nStyle) == loadedStyles.end() ) {
- raster_font *nR = new raster_font(nStyle);
- nR->Ref();
- nR->daddy=this;
- loadedStyles[nStyle]=nR;
- res=nR;
- if ( res ) Ref();
- } else {
- res=loadedStyles[nStyle];
- res->Ref();
- if ( nStyle.dashes ) free(nStyle.dashes); // since they're not taken by a new rasterfont
- }
- nStyle.dashes=savDashes;
- return res;
+ if ( (nStyle.stroke_width > 0) && (nStyle.nbDash > 0) && nStyle.dashes ) {
+ savDashes=nStyle.dashes;
+ nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double));
+ memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double));
+ }
+ StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
+ if ( loadedStyles.find(nStyle) == loadedStyles.end() ) {
+ raster_font *nR = new raster_font(nStyle);
+ nR->Ref();
+ nR->daddy=this;
+ loadedStyles[nStyle]=nR;
+ res=nR;
+ if ( res ) {
+ Ref();
+ }
+ } else {
+ res=loadedStyles[nStyle];
+ res->Ref();
+ if ( nStyle.dashes ) {
+ free(nStyle.dashes); // since they're not taken by a new rasterfont
+ }
+ }
+ nStyle.dashes=savDashes;
+ return res;
}
void font_instance::RemoveRasterFont(raster_font* who)
diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp
index fb2769edc..d16c6457d 100644
--- a/src/libnrtype/Layout-TNG-Input.cpp
+++ b/src/libnrtype/Layout-TNG-Input.cpp
@@ -19,6 +19,13 @@
#include "sp-string.h"
#include "FontFactory.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
namespace Inkscape {
namespace Text {
@@ -237,18 +244,16 @@ static const Layout::EnumConversionItem enum_convert_spstyle_style_to_pango_styl
{SP_CSS_FONT_STYLE_OBLIQUE, PANGO_STYLE_OBLIQUE}};
static const Layout::EnumConversionItem enum_convert_spstyle_weight_to_pango_weight[] = {
+ // NB: The Pango web page calls 500 "the normal font" but both CSS2 and the Pango
+ // enumeration define 400 as normal.
{SP_CSS_FONT_WEIGHT_NORMAL, PANGO_WEIGHT_NORMAL},
- {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_ULTRALIGHT},
+ {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD},
+ {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_THIN},
{SP_CSS_FONT_WEIGHT_200, PANGO_WEIGHT_ULTRALIGHT},
{SP_CSS_FONT_WEIGHT_300, PANGO_WEIGHT_LIGHT},
{SP_CSS_FONT_WEIGHT_400, PANGO_WEIGHT_NORMAL},
-#if GTK_CHECK_VERSION(2,6,0)
- {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_SEMIBOLD},
-#else
- {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_NORMAL},
-#endif
- {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_BOLD},
- {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD},
+ {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_MEDIUM},
+ {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_SEMIBOLD},
{SP_CSS_FONT_WEIGHT_700, PANGO_WEIGHT_BOLD},
{SP_CSS_FONT_WEIGHT_800, PANGO_WEIGHT_ULTRABOLD},
{SP_CSS_FONT_WEIGHT_900, PANGO_WEIGHT_HEAVY}};
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index d6b68ab40..f34b93d6e 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -24,6 +24,13 @@
#include "display/curve.h"
#include <2geom/pathvector.h>
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
namespace Inkscape {
namespace Extension {
namespace Internal {
@@ -117,10 +124,10 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
Geom::Matrix total_transform = glyph_matrix;
total_transform *= transform;
if(_glyphs[glyph_index].span(this).font) {
- Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
+ Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
if (glyph_rect) {
- Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max();
- Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]);
+ Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max();
+ Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]);
tlp *= total_transform;
trp *= total_transform;
blp *= total_transform;
@@ -133,7 +140,7 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
if ( (glyph_rect->min())[1] < bounding_box->y0 ) bounding_box->y0=(glyph_rect->min())[1];
if ( (glyph_rect->max())[1] > bounding_box->y1 ) bounding_box->y1=(glyph_rect->max())[1];
}
- }
+ }
}
}
@@ -333,13 +340,17 @@ static char const *style_to_text(PangoStyle s)
static char const *weight_to_text(PangoWeight w)
{
switch (w) {
+ case PANGO_WEIGHT_THIN : return "thin";
case PANGO_WEIGHT_ULTRALIGHT: return "ultralight";
case PANGO_WEIGHT_LIGHT : return "light";
- case PANGO_WEIGHT_SEMIBOLD : return "semibold";
+ case PANGO_WEIGHT_BOOK : return "book";
case PANGO_WEIGHT_NORMAL : return "normalweight";
+ case PANGO_WEIGHT_MEDIUM : return "medium";
+ case PANGO_WEIGHT_SEMIBOLD : return "semibold";
case PANGO_WEIGHT_BOLD : return "bold";
case PANGO_WEIGHT_ULTRABOLD : return "ultrabold";
case PANGO_WEIGHT_HEAVY : return "heavy";
+ case PANGO_WEIGHT_ULTRAHEAVY: return "ultraheavy";
}
return "???";
}
diff --git a/src/main.cpp b/src/main.cpp
index d11222203..9f7bc9ad3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -47,6 +47,8 @@
#endif /* Not def: POPT_TABLEEND */
#include <libxml/tree.h>
+#include <glib.h>
+#include <glib/gprintf.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gtk/gtkmain.h>
@@ -472,80 +474,109 @@ gchar * blankParam = g_strdup("");
#ifdef WIN32
/**
- * Return the directory of the .exe that is currently running
+ * Set up the PATH and PYTHONPATH environment variables on Windows
+ * @param exe Inkscape executable directory in UTF-8
*/
-static Glib::ustring _win32_getExePath()
+static void _win32_set_inkscape_env(gchar const *exe)
{
- char exeName[MAX_PATH+1];
- // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
- GetModuleFileName(NULL, exeName, MAX_PATH);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos) {
- *slashPos = '\0';
- }
- Glib::ustring s = exeName;
- return s;
-}
-
-/**
- * Set up the PATH and PYTHONPATH environment variables on
- * win32
- */
-static int _win32_set_inkscape_env(const Glib::ustring &exePath)
-{
- // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
-
- char *oldenv = getenv("PATH");
- Glib::ustring tmp = "PATH=";
- tmp += exePath;
- tmp += ";";
- tmp += exePath;
- tmp += "\\python;";
- tmp += exePath;
- tmp += "\\python\\Scripts;"; // for uniconv.cmd
- tmp += exePath;
- tmp += "\\perl";
- if(oldenv != NULL) {
- tmp += ";";
- tmp += oldenv;
+ gchar const *path = g_getenv("PATH");
+ gchar const *pythonpath = g_getenv("PYTHONPATH");
+
+ gchar *python = g_build_filename(exe, "python", NULL);
+ gchar *scripts = g_build_filename(exe, "python", "Scripts", NULL);
+ gchar *perl = g_build_filename(exe, "python", NULL);
+ gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL);
+ gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL);
+
+ // Python 2.x needs short paths in PYTHONPATH.
+ // Otherwise it doesn't work when Inkscape is installed in Unicode directories.
+ // g_win32_locale_filename_from_utf8 is the GLib wrapper for GetShortPathName.
+ // Remove this once we move to Python 3.0.
+ gchar *python_s = g_win32_locale_filename_from_utf8(python);
+ gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib);
+ gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll);
+
+ gchar *new_path;
+ gchar *new_pythonpath;
+ if (path) {
+ new_path = g_strdup_printf("%s;%s;%s;%s;%s", exe, python, scripts, perl, path);
+ } else {
+ new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl);
}
- _putenv(tmp.c_str());
-
- oldenv = getenv("PYTHONPATH");
- tmp = "PYTHONPATH=";
- tmp += exePath;
- tmp += "\\python;";
- tmp += exePath;
- tmp += "\\python\\Lib;";
- tmp += exePath;
- tmp += "\\python\\DLLs";
- if(oldenv != NULL) {
- tmp += ";";
- tmp += oldenv;
+ if (pythonpath) {
+ new_pythonpath = g_strdup_printf("%s;%s;%s;%s",
+ python_s, pythonlib_s, pythondll_s, pythonpath);
+ } else {
+ new_pythonpath = g_strdup_printf("%s;%s;%s",
+ python_s, pythonlib_s, pythondll_s);
}
- _putenv(tmp.c_str());
- return 0;
+ g_setenv("PATH", new_path, TRUE);
+ g_setenv("PYTHONPATH", new_pythonpath, TRUE);
+
+ /*
+ printf("PATH = %s\n\n", g_getenv("PATH"));
+ printf("PYTHONPATH = %s\n\n", g_getenv("PYTHONPATH"));
+
+ gchar *p = g_find_program_in_path("python");
+ if (p) {
+ printf("python in %s\n\n", p);
+ g_free(p);
+ } else {
+ printf("python not found\n\n");
+ }*/
+
+ g_free(python);
+ g_free(scripts);
+ g_free(perl);
+ g_free(pythonlib);
+ g_free(pythondll);
+
+ g_free(python_s);
+ g_free(pythonlib_s);
+ g_free(pythondll_s);
+
+ g_free(new_path);
+ g_free(new_pythonpath);
}
#endif
-/**
- * Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home
- * can find inkex.py et al. (Bug #197475)
- */
-static int set_extensions_env()
+static void set_extensions_env()
{
- char *oldenv = getenv("PYTHONPATH");
- Glib::ustring tmp = INKSCAPE_EXTENSIONDIR;
- if (oldenv != NULL) {
- tmp += G_SEARCHPATH_SEPARATOR;
- tmp += oldenv;
+ gchar const *pythonpath = g_getenv("PYTHONPATH");
+ gchar *extdir;
+ gchar *new_pythonpath;
+
+#ifdef WIN32
+ extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR);
+#else
+ extdir = g_strdup(INKSCAPE_EXTENSIONDIR);
+#endif
+
+ // On some platforms, INKSCAPE_EXTENSIONDIR is not absolute,
+ // but relative to the directory that contains the Inkscape executable.
+ // Since we spawn Python chdir'ed into the script's directory,
+ // we need to obtain the absolute path here.
+ if (!g_path_is_absolute(extdir)) {
+ gchar *curdir = g_get_current_dir();
+ gchar *extdir_new = g_build_filename(curdir, extdir, NULL);
+ g_free(extdir);
+ g_free(curdir);
+ extdir = extdir_new;
}
- g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
- return 0;
-}
+ if (pythonpath) {
+ new_pythonpath = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s",
+ extdir, pythonpath);
+ g_free(extdir);
+ } else {
+ new_pythonpath = extdir;
+ }
+ g_setenv("PYTHONPATH", new_pythonpath, TRUE);
+ g_free(new_pythonpath);
+ //printf("PYTHONPATH = %s\n", g_getenv("PYTHONPATH"));
+}
/**
* This is the classic main() entry point of the program, though on some
@@ -562,61 +593,53 @@ main(int argc, char **argv)
#endif
#ifdef WIN32
- /*
- Set the current directory to the directory of the
- executable. This seems redundant, but is needed for
- when inkscape.exe is executed from another directory.
- We use relative paths on win32.
- HKCR\svgfile\shell\open\command is a good example
- */
- Glib::ustring homedir = _win32_getExePath();
- // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
- SetCurrentDirectory(homedir.c_str());
- _win32_set_inkscape_env(homedir);
+ gchar *exedir = g_strdup(win32_getExePath().data());
+ _win32_set_inkscape_env(exedir);
+
+# ifdef ENABLE_NLS
+ // obtain short path to executable dir and pass it
+ // to bindtextdomain (it doesn't understand UTF-8)
+ gchar *shortexedir = g_win32_locale_filename_from_utf8(exedir);
+ gchar *localepath = g_build_filename(shortexedir, PACKAGE_LOCALE_DIR, NULL);
+ bindtextdomain(GETTEXT_PACKAGE, localepath);
+ g_free(shortexedir);
+ g_free(localepath);
+# endif
+ g_free(exedir);
+
// Don't touch the registry (works fine without it) for Inkscape Portable
gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR");
if (!val) {
RegistryTool rt;
rt.setPathInfo();
}
-#endif
-
- // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
- Gtk::Main::init_gtkmm_internals();
-
- // Bug #197475
- set_extensions_env();
-
- /**
- * Call bindtextdomain() for various machines's paths
- */
-#ifdef ENABLE_NLS
-#ifdef WIN32
- Glib::ustring localePath = homedir;
- localePath += "\\";
- localePath += PACKAGE_LOCALE_DIR;
- bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
-#else
-#ifdef ENABLE_BINRELOC
+#elif defined(ENABLE_NLS)
+# ifdef ENABLE_BINRELOC
bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
-#else
+# else
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+# endif
#endif
-#endif
+
+ // the bit below compiles regardless of platform
+#ifdef ENABLE_NLS
// Allow the user to override the locale directory by setting
// the environment variable INKSCAPE_LOCALEDIR.
- char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
+ char const *inkscape_localedir = g_getenv("INKSCAPE_LOCALEDIR");
if (inkscape_localedir != NULL) {
bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
}
-#endif
+ // common setup
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
-
-#ifdef ENABLE_NLS
textdomain(GETTEXT_PACKAGE);
#endif
+ set_extensions_env();
+
+ // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
+ Gtk::Main::init_gtkmm_internals();
+
LIBXML_TEST_VERSION
Inkscape::GC::init();
@@ -626,8 +649,7 @@ main(int argc, char **argv)
gboolean use_gui;
#ifndef WIN32
- // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
- use_gui = (getenv("DISPLAY") != NULL);
+ use_gui = (g_getenv("DISPLAY") != NULL);
#else
use_gui = TRUE;
#endif
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 581b8b39c..0a9aa2751 100644
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
@@ -40,7 +40,6 @@ static char const menus_skeleton[] =
" <verb verb-id=\"DialogMetadata\" />\n"
" <verb verb-id=\"DialogPreferences\" />\n"
" <verb verb-id=\"DialogInput\" />\n"
-" <verb verb-id=\"DialogInput2\" />\n"
" <separator/>\n"
" <verb verb-id=\"FileClose\" />\n"
" <verb verb-id=\"FileQuit\" />\n"
@@ -228,6 +227,7 @@ static char const menus_skeleton[] =
#ifdef ENABLE_SVG_FONTS
" <verb verb-id=\"DialogSVGFonts\" />\n"
#endif // ENABLE_SVG_FONTS
+" <verb verb-id=\"DialogGlyphs\" />\n"
" <separator/>\n"
" <verb verb-id=\"SelectionTextToPath\" />\n"
" <verb verb-id=\"SelectionTextFromPath\" />\n"
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 7d79a5e91..77449ddc3 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -151,8 +151,8 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
// 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
- //SPObject *obj = (SPObject*)item;
- //std::cout << "Snap candidate added: " << obj->id << std::endl;
+ // SPObject *obj = (SPObject*)item;
+ // std::cout << "Snap candidate added: " << obj->getId() << std::endl;
}
}
}
@@ -733,7 +733,7 @@ Geom::PathVector* Inkscape::ObjectSnapper::_getBorderPathv() const
Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const rect) const
{
- SPCurve const *border_curve = SPCurve::new_from_rect(rect);
+ SPCurve const *border_curve = SPCurve::new_from_rect(rect, true);
if (border_curve) {
Geom::PathVector *dummy = new Geom::PathVector(border_curve->get_pathvector());
return dummy;
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 297d19c10..73e7bd2ac 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -9,7 +9,7 @@
#define N_(x) x
/* The root's "version" attribute describes the preferences file format version.
- * It should only increase when a backwards-incompatible change is made,
+ * It should only increase when a backwards-incompatible change is made,
* and special handling has to be added to the preferences class to update
* obsolete versions the user might have. */
static char const preferences_skeleton[] =
@@ -101,7 +101,7 @@ static char const preferences_skeleton[] =
" <group id=\"cp3\" name=\"" N_("Wiggly") "\" usetilt=\"1\" tracebackground=\"0\" usepressure=\"1\" cap_rounding=\"0.1\" flatness=\"16\" tremor=\"18\" thinning=\"-30\" angle=\"30\" wiggle=\"50\" mass=\"0\" />\n"
" <group id=\"cp4\" name=\"" N_("Splotchy") "\" width=\"100\" usetilt=\"1\" tracebackground=\"0\" usepressure=\"0\" cap_rounding=\"1\" flatness=\"0\" tremor=\"10\" thinning=\"30\" angle=\"30\" wiggle=\"0\" mass=\"0\" />\n"
" <group id=\"cp5\" name=\"" N_("Tracing") "\" width=\"50\" mass=\"0\" wiggle=\"0.0\" angle=\"0.0\" thinning=\"0.0\" tremor=\"0.0\" flatness=\"0\" cap_rounding=\"0.0\" tracebackground=\"1\" usepressure=\"1\" usetilt=\"1\"/>\n"
-" </group>\n"
+" </group>\n"
" </eventcontext>\n"
" <eventcontext id=\"eraser\" mode=\"0\" style=\"fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;\"\n"
" mass=\"0.02\" drag=\"1\" angle=\"30\" width=\"0.15\" thinning=\"0.1\" flatness=\"0.0\" cap_rounding=\"1.4\" usecurrent=\"0\"\n"
@@ -112,10 +112,10 @@ static char const preferences_skeleton[] =
" <eventcontext id=\"text\" usecurrent=\"0\" gradientdrag=\"1\"\n"
" font_sample=\"AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()\"\n"
" show_sample_in_list=\"1\"\n"
-" style=\"fill:black;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n"
-" <eventcontext id=\"nodes\" selcue=\"1\" gradientdrag=\"1\" highlight_color=\"4278190335\" pathflash_enabled=\"1\" pathflash_unselected=\"0\" pathflash_timeout=\"500\" show_handles=\"1\" show_outline=\"0\" sculpting_profile=\"1\" single_node_transform_handles=\"0\" show_transform_handles=\"0\" live_outline=\"1\" live_objects=\"1\" />\n"
+" style=\"fill:black;fill-opacity:1;stroke:none;font-family:Sans;font-style:normal;font-weight:normal;font-size:40px;\" selcue=\"1\"/>\n"
+" <eventcontext id=\"nodes\" selcue=\"1\" gradientdrag=\"1\" highlight_color=\"4278190335\" pathflash_enabled=\"1\" pathflash_unselected=\"0\" pathflash_timeout=\"500\" show_handles=\"1\" show_outline=\"0\" sculpting_profile=\"1\" single_node_transform_handles=\"0\" show_transform_handles=\"0\" live_outline=\"1\" live_objects=\"1\" show_helperpath=\"0\" x=\"0\" y=\"0\" edit_clipping_paths=\"0\" edit_masks=\"0\" />\n"
" <eventcontext id=\"tweak\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
-" <eventcontext id=\"spray\" selcue=\"0\" gradientdrag=\"0\" show_handles=\"0\" width=\"0.2\" force=\"0.2\" fidelity=\"0.5\" usepressure=\"1\" style=\"fill:red;stroke:none;\" usecurrent=\"0\"/>\n"
+" <eventcontext id=\"spray\" usepressure=\"1\" width=\"15\" population=\"70\" mode=\"1\" rotation_variation=\"0\" scale_variation=\"0\" standard_deviation=\"70\" mean=\"0\"/>\n"
" <eventcontext id=\"gradient\" selcue=\"1\"/>\n"
" <eventcontext id=\"zoom\" selcue=\"1\" gradientdrag=\"0\"/>\n"
" <eventcontext id=\"dropper\" selcue=\"1\" gradientdrag=\"1\" pick=\"1\" setalpha=\"1\"/>\n"
diff --git a/src/prefix.cpp b/src/prefix.cpp
index f1fa3c2cd..92409a7d2 100644
--- a/src/prefix.cpp
+++ b/src/prefix.cpp
@@ -31,14 +31,7 @@
#endif
-/* PLEASE NOTE: We use GThreads now for portability */
-/* @see http://developer.gnome.org/doc/API/2.0/glib/glib-Threads.html */
-#ifndef BR_THREADS
- /* Change 1 to 0 if you don't want thread support */
- #define BR_THREADS 1
- #include <glib.h> //for GThreads
-#endif /* BR_THREADS */
-
+#include <glib.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
@@ -55,9 +48,9 @@ extern "C" {
#define NULL ((void *) 0)
#ifdef __GNUC__
- #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
+ #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
#else
- #define br_return_val_if_fail(expr,val) if (!(expr)) return val
+ #define br_return_val_if_fail(expr,val) if (!(expr)) return val
#endif /* __GNUC__ */
@@ -72,8 +65,8 @@ extern "C" {
* br_locate:
* symbol: A symbol that belongs to the app/library you want to locate.
* Returns: A newly allocated string containing the full path of the
- * app/library that func belongs to, or NULL on error. This
- * string should be freed when not when no longer needed.
+ * app/library that func belongs to, or NULL on error. This
+ * string should be freed when not when no longer needed.
*
* Finds out to which application or library symbol belongs, then locate
* the full path of that application or library.
@@ -85,70 +78,70 @@ extern "C" {
* #include "libfoo.h"
*
* int main (int argc, char *argv[]) {
- * printf ("Full path of this app: %s\n", br_locate (&argc));
- * libfoo_start ();
- * return 0;
+ * printf ("Full path of this app: %s\n", br_locate (&argc));
+ * libfoo_start ();
+ * return 0;
* }
*
* --> libfoo.c starts here
* #include "prefix.h"
*
* void libfoo_start () {
- * --> "" is a symbol that belongs to libfoo (because it's called
- * --> from libfoo_start()); that's why this works.
- * printf ("libfoo is located in: %s\n", br_locate (""));
+ * --> "" is a symbol that belongs to libfoo (because it's called
+ * --> from libfoo_start()); that's why this works.
+ * printf ("libfoo is located in: %s\n", br_locate (""));
* }
*/
char *
br_locate (void *symbol)
{
- char line[5000];
- FILE *f;
- char *path;
-
- br_return_val_if_fail (symbol != NULL, NULL);
-
- f = fopen ("/proc/self/maps", "r");
- if (!f)
- return NULL;
-
- while (!feof (f))
- {
- unsigned long start, end;
-
- if (!fgets (line, sizeof (line), f))
- continue;
- if (!strstr (line, " r-xp ") || !strchr (line, '/'))
- continue;
-
- sscanf (line, "%lx-%lx ", &start, &end);
- if (symbol >= (void *) start && symbol < (void *) end)
- {
- char *tmp;
- size_t len;
-
- /* Extract the filename; it is always an absolute path */
- path = strchr (line, '/');
-
- /* Get rid of the newline */
- tmp = strrchr (path, '\n');
- if (tmp) *tmp = 0;
-
- /* Get rid of "(deleted)" */
- len = strlen (path);
- if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
- {
- tmp = path + len - 10;
- *tmp = 0;
- }
-
- fclose(f);
- return strdup (path);
- }
- }
-
- fclose (f);
- return NULL;
+ char line[5000];
+ FILE *f;
+ char *path;
+
+ br_return_val_if_fail (symbol != NULL, NULL);
+
+ f = fopen ("/proc/self/maps", "r");
+ if (!f)
+ return NULL;
+
+ while (!feof (f))
+ {
+ unsigned long start, end;
+
+ if (!fgets (line, sizeof (line), f))
+ continue;
+ if (!strstr (line, " r-xp ") || !strchr (line, '/'))
+ continue;
+
+ sscanf (line, "%lx-%lx ", &start, &end);
+ if (symbol >= (void *) start && symbol < (void *) end)
+ {
+ char *tmp;
+ size_t len;
+
+ /* Extract the filename; it is always an absolute path */
+ path = strchr (line, '/');
+
+ /* Get rid of the newline */
+ tmp = strrchr (path, '\n');
+ if (tmp) *tmp = 0;
+
+ /* Get rid of "(deleted)" */
+ len = strlen (path);
+ if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
+ {
+ tmp = path + len - 10;
+ *tmp = 0;
+ }
+
+ fclose(f);
+ return strdup (path);
+ }
+ }
+
+ fclose (f);
+ return NULL;
}
@@ -168,16 +161,16 @@ br_locate (void *symbol)
char *
br_locate_prefix (void *symbol)
{
- char *path, *prefix;
+ char *path, *prefix;
- br_return_val_if_fail (symbol != NULL, NULL);
+ br_return_val_if_fail (symbol != NULL, NULL);
- path = br_locate (symbol);
- if (!path) return NULL;
+ path = br_locate (symbol);
+ if (!path) return NULL;
- prefix = br_extract_prefix (path);
- free (path);
- return prefix;
+ prefix = br_extract_prefix (path);
+ free (path);
+ return prefix;
}
@@ -186,7 +179,7 @@ br_locate_prefix (void *symbol)
* symbol: A symbol that belongs to the app/library you want to locate.
* path: The path that you want to prepend the prefix to.
* Returns: The new path, or NULL on error. This string should be freed when no
- * longer needed.
+ * longer needed.
*
* Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
* Note that symbol cannot be a pointer to a function. That will not work.
@@ -198,24 +191,24 @@ br_locate_prefix (void *symbol)
char *
br_prepend_prefix (void *symbol, char *path)
{
- char *tmp, *newpath;
+ char *tmp, *newpath;
- br_return_val_if_fail (symbol != NULL, NULL);
- br_return_val_if_fail (path != NULL, NULL);
+ br_return_val_if_fail (symbol != NULL, NULL);
+ br_return_val_if_fail (path != NULL, NULL);
- tmp = br_locate_prefix (symbol);
- if (!tmp) return NULL;
+ tmp = br_locate_prefix (symbol);
+ if (!tmp) return NULL;
- if (strcmp (tmp, "/") == 0)
- newpath = strdup (path);
- else
- newpath = br_strcat (tmp, path);
+ if (strcmp (tmp, "/") == 0)
+ newpath = strdup (path);
+ else
+ newpath = br_strcat (tmp, path);
- /* Get rid of compiler warning ("br_prepend_prefix never used") */
- if (0) br_prepend_prefix (NULL, NULL);
+ /* Get rid of compiler warning ("br_prepend_prefix never used") */
+ if (0) br_prepend_prefix (NULL, NULL);
- free (tmp);
- return newpath;
+ free (tmp);
+ return newpath;
}
#endif /* ENABLE_BINRELOC */
@@ -264,33 +257,33 @@ br_free_last_value ()
const char *
br_thread_local_store (char *str)
{
- #if BR_THREADS
+ #if BR_THREADS
if (!g_thread_supported ())
{
g_thread_init ((GThreadFunctions *)NULL);
br_thread_key = g_private_new (g_free);
}
- char *specific = (char *) g_private_get (br_thread_key);
- if (specific)
+ char *specific = (char *) g_private_get (br_thread_key);
+ if (specific)
free (specific);
g_private_set (br_thread_key, str);
- #else /* !BR_THREADS */
- static int initialized = 0;
+ #else /* !BR_THREADS */
+ static int initialized = 0;
- if (!initialized)
- {
- atexit (br_free_last_value);
- initialized = 1;
- }
+ if (!initialized)
+ {
+ atexit (br_free_last_value);
+ initialized = 1;
+ }
- if (br_last_value)
- free (br_last_value);
- br_last_value = str;
- #endif /* BR_THREADS */
+ if (br_last_value)
+ free (br_last_value);
+ br_last_value = str;
+ #endif /* BR_THREADS */
- return (const char *) str;
+ return (const char *) str;
}
@@ -305,21 +298,21 @@ br_thread_local_store (char *str)
char *
br_strcat (const char *str1, const char *str2)
{
- char *result;
- size_t len1, len2;
+ char *result;
+ size_t len1, len2;
- if (!str1) str1 = "";
- if (!str2) str2 = "";
+ if (!str1) str1 = "";
+ if (!str2) str2 = "";
- len1 = strlen (str1);
- len2 = strlen (str2);
+ len1 = strlen (str1);
+ len2 = strlen (str2);
- result = (char *) malloc (len1 + len2 + 1);
- memcpy (result, str1, len1);
- memcpy (result + len1, str2, len2);
- result[len1 + len2] = '\0';
+ result = (char *) malloc (len1 + len2 + 1);
+ memcpy (result, str1, len1);
+ memcpy (result + len1, str2, len2);
+ result[len1 + len2] = '\0';
- return result;
+ return result;
}
@@ -327,18 +320,18 @@ br_strcat (const char *str1, const char *str2)
static char *
br_strndup (char *str, size_t size)
{
- char *result = (char*)NULL;
- size_t len;
+ char *result = (char*)NULL;
+ size_t len;
- br_return_val_if_fail (str != (char*)NULL, (char*)NULL);
+ br_return_val_if_fail (str != (char*)NULL, (char*)NULL);
- len = strlen (str);
- if (!len) return strdup ("");
- if (size > len) size = len;
+ len = strlen (str);
+ if (!len) return strdup ("");
+ if (size > len) size = len;
- result = (char *) calloc (sizeof (char), len + 1);
- memcpy (result, str, size);
- return result;
+ result = (char *) calloc (sizeof (char), len + 1);
+ memcpy (result, str, size);
+ return result;
}
@@ -356,23 +349,23 @@ br_strndup (char *str, size_t size)
char *
br_extract_dir (const char *path)
{
- const char *end;
- char *result;
-
- br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
-
- end = strrchr (path, '/');
- if (!end) return strdup (".");
-
- while (end > path && *end == '/')
- end--;
- result = br_strndup ((char *) path, end - path + 1);
- if (!*result)
- {
- free (result);
- return strdup ("/");
- } else
- return result;
+ const char *end;
+ char *result;
+
+ br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
+
+ end = strrchr (path, '/');
+ if (!end) return strdup (".");
+
+ while (end > path && *end == '/')
+ end--;
+ result = br_strndup ((char *) path, end - path + 1);
+ if (!*result)
+ {
+ free (result);
+ return strdup ("/");
+ } else
+ return result;
}
@@ -392,34 +385,34 @@ br_extract_dir (const char *path)
char *
br_extract_prefix (const char *path)
{
- const char *end;
- char *tmp, *result;
-
- br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
-
- if (!*path) return strdup ("/");
- end = strrchr (path, '/');
- if (!end) return strdup (path);
-
- tmp = br_strndup ((char *) path, end - path);
- if (!*tmp)
- {
- free (tmp);
- return strdup ("/");
- }
- end = strrchr (tmp, '/');
- if (!end) return tmp;
-
- result = br_strndup (tmp, end - tmp);
- free (tmp);
-
- if (!*result)
- {
- free (result);
- result = strdup ("/");
- }
-
- return result;
+ const char *end;
+ char *tmp, *result;
+
+ br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
+
+ if (!*path) return strdup ("/");
+ end = strrchr (path, '/');
+ if (!end) return strdup (path);
+
+ tmp = br_strndup ((char *) path, end - path);
+ if (!*tmp)
+ {
+ free (tmp);
+ return strdup ("/");
+ }
+ end = strrchr (tmp, '/');
+ if (!end) return tmp;
+
+ result = br_strndup (tmp, end - tmp);
+ free (tmp);
+
+ if (!*result)
+ {
+ free (result);
+ result = strdup ("/");
+ }
+
+ return result;
}
@@ -442,15 +435,16 @@ br_extract_prefix (const char *path)
/**
* Return the directory of the .exe that is currently running
*/
-static Glib::ustring win32_getExePath()
+Glib::ustring win32_getExePath()
{
- char exeName[MAX_PATH+1];
- GetModuleFileName(NULL, exeName, MAX_PATH);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos)
- *slashPos = '\0';
- Glib::ustring s = exeName;
- return s;
+ gunichar2 path[2048];
+ GetModuleFileNameW(0, (WCHAR*) path, 2048);
+ gchar *exe = g_utf16_to_utf8(path, -1, 0,0,0);
+ gchar *dir = g_path_get_dirname(exe);
+ Glib::ustring ret = dir;
+ g_free(dir);
+ g_free(exe);
+ return ret;
}
@@ -461,8 +455,8 @@ static Glib::ustring win32_getExePath()
static Glib::ustring win32_getDataDir()
{
Glib::ustring dir = win32_getExePath();
- if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR &&
- strcmp(INKSCAPE_DATADIR, ".") != 0)
+ if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR &&
+ strcmp(INKSCAPE_DATADIR, ".") != 0)
{
dir += "\\";
dir += INKSCAPE_DATADIR;
@@ -487,7 +481,7 @@ static Glib::ustring win32_getResourcePath(const Glib::ustring &childPath)
*/
char *win32_relative_path(const char *childPath)
{
- static char *returnPath = NULL;
+ static char *returnPath = 0;
if (!childPath)
childPath = "";
Glib::ustring resourcePath = win32_getResourcePath(childPath);
diff --git a/src/prefix.h b/src/prefix.h
index 0c2db5b58..af96fa746 100644
--- a/src/prefix.h
+++ b/src/prefix.h
@@ -114,20 +114,19 @@ char *br_strcat (const char *str1, const char *str2);
char *br_extract_dir (const char *path);
char *br_extract_prefix(const char *path);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
#ifdef __WIN32__
-/**
- * Win32 version of a relocatable function
- */
+#include <glibmm/ustring.h>
+
+Glib::ustring win32_getExePath();
char *win32_relative_path(const char *childPath);
#define WIN32_DATADIR(suffix) (win32_relative_path(suffix))
#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
#endif /* _PREFIX_H_ */
diff --git a/src/registrytool.cpp b/src/registrytool.cpp
index 2017f50c7..af41c3eaf 100644
--- a/src/registrytool.cpp
+++ b/src/registrytool.cpp
@@ -60,6 +60,7 @@ bool RegistryTool::setStringValue(const Glib::ustring &keyNameArg,
const Glib::ustring &value)
{
Glib::ustring keyName = keyNameArg;
+ bool ret = false;
HKEY rootKey = HKEY_LOCAL_MACHINE; //default root
//Trim out the root key if necessary
@@ -74,28 +75,35 @@ bool RegistryTool::setStringValue(const Glib::ustring &keyNameArg,
//printf("trimmed string: '%s'\n", keyName.c_str());
//Get or create the key
+ gunichar2 *keyw = g_utf8_to_utf16(keyName.data(), -1, 0,0,0);
+ gunichar2 *valuenamew = g_utf8_to_utf16(valueName.data(), -1, 0,0,0);
+
HKEY key;
- if (RegCreateKeyEx(rootKey, keyName.c_str(),
+ if (RegCreateKeyExW(rootKey, (WCHAR*) keyw,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &key, NULL))
- {
+ {
fprintf(stderr, "RegistryTool: Could not create the registry key '%s'\n", keyName.c_str());
- return false;
- }
+ goto fail;
+ }
- //Set the value
- if (RegSetValueEx(key, valueName.c_str(),
- 0, REG_SZ, (LPBYTE) value.c_str(), (DWORD) value.size()))
- {
+ // Set the value
+ if (RegSetValueExW(key, (WCHAR*) valuenamew,
+ 0, REG_SZ, (LPBYTE) value.data(), (DWORD) (value.size() + 1)))
+ {
fprintf(stderr, "RegistryTool: Could not set the value '%s'\n", value.c_str());
- RegCloseKey(key);
- return false;
- }
-
+ goto failkey;
+ }
+ ret = true;
+
+ failkey:
RegCloseKey(key);
-
- return true;
+
+ fail:
+ g_free(keyw);
+ g_free(valuenamew);
+ return ret;
}
@@ -107,19 +115,14 @@ bool RegistryTool::getExeInfo(Glib::ustring &fullPath,
Glib::ustring &path,
Glib::ustring &exeName)
{
+ const int pathbuf = 2048;
+ gunichar2 pathw[pathbuf];
+ GetModuleFileNameW(NULL, (WCHAR*) pathw, pathbuf);
- char buf[MAX_PATH+1];
- if (!GetModuleFileName(NULL, buf, MAX_PATH))
- {
- fprintf(stderr, "Could not fetch executable file name\n");
- return false;
- }
- else
- {
- //printf("Executable file name: '%s'\n", buf);
- }
+ gchar *utf8path = g_utf16_to_utf8(pathw, -1, 0,0,0);
+ fullPath = utf8path;
+ g_free(utf8path);
- fullPath = buf;
path = "";
exeName = "";
Glib::ustring::size_type pos = fullPath.rfind('\\');
diff --git a/src/select-context.cpp b/src/select-context.cpp
index a9e1ff623..028c8634b 100644
--- a/src/select-context.cpp
+++ b/src/select-context.cpp
@@ -608,7 +608,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
}
sc->item = NULL;
} else {
- Inkscape::Rubberband::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
if (r->is_started() && !within_tolerance) {
// this was a rubberband drag
GSList *items = NULL;
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 730467ee5..cc153aa71 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -2266,7 +2266,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
}
sp_document_ensure_up_to_date(doc);
- Geom::OptRect r = selection->bounds();
+ Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX);
boost::optional<Geom::Point> c = selection->center();
if ( !r || !c ) {
return;
@@ -2390,7 +2390,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
}
sp_document_ensure_up_to_date(doc);
- Geom::OptRect r = selection->bounds();
+ Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX);
if ( !r ) {
return;
}
@@ -3173,7 +3173,7 @@ fit_canvas_to_selection(SPDesktop *desktop, bool with_margins)
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to fit canvas to."));
return false;
}
- Geom::OptRect const bbox(desktop->selection->bounds());
+ Geom::OptRect const bbox(desktop->selection->bounds(SPItem::RENDERING_BBOX));
if (bbox) {
doc->fitToRect(*bbox, with_margins);
return true;
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 7a08e0a7e..aef608420 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -999,8 +999,6 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
m.setup(_desktop, false, _items_const);
Inkscape::SnappedPoint bb, sn;
- Geom::Coord bd(NR_HUGE);
- Geom::Coord sd(NR_HUGE);
if ((state & GDK_CONTROL_MASK) || _desktop->isToolboxButtonActive ("lock")) {
// Scale is locked to a 1:1 aspect ratio, so that s[X] must be made to equal s[Y].
@@ -1017,27 +1015,17 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
// Snap along a suitable constraint vector from the origin.
bb = m.constrainedSnapScale(_bbox_points, _point, default_scale, _origin_for_bboxpoints);
sn = m.constrainedSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints);
-
- /* Choose the smaller difference in scale. Since s[X] == s[Y] we can
- ** just compare difference in s[X].
- */
- bd = bb.getSnapped() ? fabs(bb.getTransformation()[Geom::X] - default_scale[Geom::X]) : NR_HUGE;
- sd = sn.getSnapped() ? fabs(sn.getTransformation()[Geom::X] - geom_scale[Geom::X]) : NR_HUGE;
} else {
/* Scale aspect ratio is unlocked */
bb = m.freeSnapScale(_bbox_points, _point, default_scale, _origin_for_bboxpoints);
sn = m.freeSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints);
-
- /* Pick the snap that puts us closest to the original scale */
- bd = bb.getSnapped() ? fabs(Geom::L2(bb.getTransformation()) - Geom::L2(Geom::Point(default_scale[Geom::X], default_scale[Geom::Y]))) : NR_HUGE;
- sd = sn.getSnapped() ? fabs(Geom::L2(sn.getTransformation()) - Geom::L2(Geom::Point(geom_scale[Geom::X], geom_scale[Geom::Y]))) : NR_HUGE;
}
if (!(bb.getSnapped() || sn.getSnapped())) {
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bd < sd) {
+ } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
// We snapped the bbox (which is either visual or geometric)
_desktop->snapindicator->set_new_snaptarget(bb);
default_scale = Geom::Scale(bb.getTransformation());
@@ -1109,8 +1097,6 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
Inkscape::SnappedPoint bb, sn;
g_assert(bb.getSnapped() == false); // Check initialization to catch any regression
- Geom::Coord bd(NR_HUGE);
- Geom::Coord sd(NR_HUGE);
bool symmetrical = state & GDK_CONTROL_MASK;
@@ -1119,12 +1105,10 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
if (bb.getSnapped()) {
// We snapped the bbox (which is either visual or geometric)
- bd = fabs(bb.getTransformation()[axis] - default_scale[axis]);
default_scale[axis] = bb.getTransformation()[axis];
}
if (sn.getSnapped()) {
- sd = fabs(sn.getTransformation()[axis] - geom_scale[axis]);
geom_scale[axis] = sn.getTransformation()[axis];
}
@@ -1139,7 +1123,7 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bd < sd) {
+ } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
_desktop->snapindicator->set_new_snaptarget(bb);
// Calculate the new transformation and update the handle position
pt = _calcAbsAffineDefault(default_scale);
diff --git a/src/snap-candidate.h b/src/snap-candidate.h
index bd378bec8..a0fc3290c 100644
--- a/src/snap-candidate.h
+++ b/src/snap-candidate.h
@@ -55,6 +55,7 @@ public:
inline Inkscape::SnapSourceType getSourceType() const {return _source_type;}
inline Inkscape::SnapTargetType getTargetType() const {return _target_type;}
inline long getSourceNum() const {return _source_num;}
+ void setSourceNum(long num) {_source_num = num;}
inline Geom::OptRect const getTargetBBox() const {return _target_bbox;}
private:
diff --git a/src/snap.cpp b/src/snap.cpp
index b8b08dad5..8704ce3bb 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -524,7 +524,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
/* Quick check to see if we have any snappers that are enabled
** Also used to globally disable all snapping
*/
- if (someSnapperMightSnap() == false) {
+ if (someSnapperMightSnap() == false || points.size() == 0) {
return Inkscape::SnappedPoint(pointer);
}
@@ -559,10 +559,11 @@ 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<Inkscape::SnapCandidatePoint>::const_iterator j = transformed_points.begin();
+ std::vector<Inkscape::SnapCandidatePoint>::iterator j = transformed_points.begin();
// std::cout << std::endl;
+ bool first_free_snap = true;
for (std::vector<Inkscape::SnapCandidatePoint>::const_iterator i = points.begin(); i != points.end(); i++) {
/* Snap it */
@@ -599,6 +600,17 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
dedicated_constraint = Inkscape::Snapper::ConstraintLine(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
+ // requirements, then freeSnap might never see the SnapCandidatePoint with source_num == 0. The freeSnap()
+ // method in the object snapper depends on this, because only for source-num == 0 the target nodes will
+ // be collected. Therefore we enforce that the first SnapCandidatePoint that is to be freeSnapped always
+ // has source_num == 0;
+ // TODO: This is a bit ugly so fix this; do we need sourcenum for anything else? if we don't then get rid
+ // of it and explicitely communicate to the object snapper that this is a first point
+ if (first_free_snap) {
+ (*j).setSourceNum(0);
+ first_free_snap = false;
+ }
snapped_point = freeSnap(*j, bbox);
}
}
@@ -902,6 +914,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Inkscape::SnapCandidatePoint co
bool allowOffScreen) const
{
+
/*
std::cout << "Type and number of snapped constraints: " << std::endl;
std::cout << " Points : " << sc.points.size() << std::endl;
diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp
index 089aa4323..508ec8f62 100644
--- a/src/snapped-point.cpp
+++ b/src/snapped-point.cpp
@@ -164,6 +164,15 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth
}
}
+ // When snapping to a constraint line only, which is not really a snap but merely a projection
+ // to the constraint line, then give this snap a very low priority. Basically, any other snap will do
+ if (other_one.getTarget() == SNAPTARGET_CONSTRAINT) {
+ dist_other += NR_HUGE/2;
+ }
+ if (getTarget() == SNAPTARGET_CONSTRAINT) {
+ dist_this += NR_HUGE/2;
+ }
+
// If it's closer
bool c1 = dist_other < dist_this;
// or, if it's for a snapper with "always snap" turned on, and the previous wasn't
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index 7197c1ec9..4cbafe50c 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -108,7 +108,7 @@ sp_filter_init(SPFilter *filter)
filter->height = 0;
filter->filterUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
- filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
+ filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE;
filter->filterUnits_set = FALSE;
filter->primitiveUnits_set = FALSE;
@@ -204,14 +204,14 @@ sp_filter_set(SPObject *object, unsigned int key, gchar const *value)
break;
case SP_ATTR_PRIMITIVEUNITS:
if (value) {
- if (!strcmp(value, "userSpaceOnUse")) {
- filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE;
- } else {
+ if (!strcmp(value, "objectBoundingBox")) {
filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
+ } else {
+ filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE;
}
filter->primitiveUnits_set = TRUE;
} else {
- filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
+ filter->primitiveUnits = SP_FILTER_UNITS_USERSPACEONUSE;
filter->primitiveUnits_set = FALSE;
}
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
@@ -322,11 +322,11 @@ sp_filter_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::N
if ((flags & SP_OBJECT_WRITE_ALL) || filter->primitiveUnits_set) {
switch (filter->primitiveUnits) {
- case SP_FILTER_UNITS_USERSPACEONUSE:
- repr->setAttribute("primitiveUnits", "userSpaceOnUse");
+ case SP_FILTER_UNITS_OBJECTBOUNDINGBOX:
+ repr->setAttribute("primitiveUnits", "objectBoundingBox");
break;
default:
- repr->setAttribute("primitiveUnits", "objectBoundingBox");
+ repr->setAttribute("primitiveUnits", "userSpaceOnUse");
break;
}
}
@@ -446,6 +446,8 @@ void sp_filter_build_renderer(SPFilter *sp_filter, Inkscape::Filters::Filter *nr
sp_filter->_renderer = nr_filter;
+ nr_filter->set_filter_units(sp_filter->filterUnits);
+ nr_filter->set_primitive_units(sp_filter->primitiveUnits);
nr_filter->set_x(sp_filter->x);
nr_filter->set_y(sp_filter->y);
nr_filter->set_width(sp_filter->width);
diff --git a/src/sp-font-face.cpp b/src/sp-font-face.cpp
index 704985b8c..1912676d4 100644
--- a/src/sp-font-face.cpp
+++ b/src/sp-font-face.cpp
@@ -24,7 +24,6 @@
#include "attributes.h"
#include "sp-font-face.h"
#include "document.h"
-#include "helper-fns.h"
//TODO: apparently unused. Maybe should be removed.
class ObjectContainer
@@ -486,7 +485,6 @@ static void sp_fontface_release(SPObject *object)
static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *value)
{
SPFontFace *face = SP_FONTFACE(object);
- double number;
std::vector<FontFaceStyleType> style;
std::vector<FontFaceVariantType> variant;
std::vector<FontFaceWeightType> weight;
@@ -494,7 +492,9 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
switch (key) {
case SP_PROP_FONT_FAMILY:
- if (face->font_family) g_free(face->font_family);
+ if (face->font_family) {
+ g_free(face->font_family);
+ }
face->font_family = g_strdup(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -505,7 +505,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
} else {
for (unsigned int i=0;i<style.size();i++){
- if(style[i] != face->font_style[i]){
+ if (style[i] != face->font_style[i]){
face->font_style = style;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -520,7 +520,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
} else {
for (unsigned int i=0;i<variant.size();i++){
- if(variant[i] != face->font_variant[i]){
+ if (variant[i] != face->font_variant[i]){
face->font_variant = variant;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -535,7 +535,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
} else {
for (unsigned int i=0;i<weight.size();i++){
- if(weight[i] != face->font_weight[i]){
+ if (weight[i] != face->font_weight[i]){
face->font_weight = weight;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -550,7 +550,7 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
} else {
for (unsigned int i=0;i<stretch.size();i++){
- if(stretch[i] != face->font_stretch[i]){
+ if (stretch[i] != face->font_stretch[i]){
face->font_stretch = stretch;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -559,166 +559,212 @@ static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *val
}
break;
case SP_ATTR_UNITS_PER_EM:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->units_per_em){
face->units_per_em = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_STEMV:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->stemv){
face->stemv = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_STEMH:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->stemh){
face->stemh = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_SLOPE:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->slope){
face->slope = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_CAP_HEIGHT:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->cap_height){
face->cap_height = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_X_HEIGHT:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->x_height){
face->x_height = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_ACCENT_HEIGHT:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->accent_height){
face->accent_height = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_ASCENT:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->ascent){
face->ascent = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_DESCENT:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->descent){
face->descent = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_IDEOGRAPHIC:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->ideographic){
face->ideographic = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_ALPHABETIC:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->alphabetic){
face->alphabetic = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_MATHEMATICAL:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->mathematical){
face->mathematical = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_HANGING:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->hanging){
face->hanging = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_V_IDEOGRAPHIC:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->v_ideographic){
face->v_ideographic = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_V_ALPHABETIC:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->v_alphabetic){
face->v_alphabetic = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_V_MATHEMATICAL:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->v_mathematical){
face->v_mathematical = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_V_HANGING:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->v_hanging){
face->v_hanging = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_UNDERLINE_POSITION:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->underline_position){
face->underline_position = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_UNDERLINE_THICKNESS:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->underline_thickness){
face->underline_thickness = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_STRIKETHROUGH_POSITION:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->strikethrough_position){
face->strikethrough_position = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_STRIKETHROUGH_THICKNESS:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->strikethrough_thickness){
face->strikethrough_thickness = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_OVERLINE_POSITION:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->overline_position){
face->overline_position = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_OVERLINE_THICKNESS:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != face->overline_thickness){
face->overline_thickness = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
default:
if (((SPObjectClass *) (parent_class))->set) {
((SPObjectClass *) (parent_class))->set(object, key, value);
diff --git a/src/sp-font.cpp b/src/sp-font.cpp
index de272c72f..b2003cf08 100644
--- a/src/sp-font.cpp
+++ b/src/sp-font.cpp
@@ -21,7 +21,6 @@
#include "sp-glyph.h"
#include "sp-missing-glyph.h"
#include "document.h"
-#include "helper-fns.h"
#include "display/nr-svgfonts.h"
@@ -79,15 +78,21 @@ static void sp_font_class_init(SPFontClass *fc)
sp_object_class->update = sp_font_update;
}
+//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html
+
+// TODO determine better values and/or make these dynamic:
+double FNT_DEFAULT_ADV = 90; // TODO determine proper default
+double FNT_DEFAULT_ASCENT = 90; // TODO determine proper default
+double FNT_UNITS_PER_EM = 90; // TODO determine proper default
+
static void sp_font_init(SPFont *font)
{
font->horiz_origin_x = 0;
font->horiz_origin_y = 0;
- font->horiz_adv_x = 0;
-//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html
- font->vert_origin_x = 0;
- font->vert_origin_y = 0;
- font->vert_adv_y = 0;
+ font->horiz_adv_x = FNT_DEFAULT_ADV;
+ font->vert_origin_x = FNT_DEFAULT_ADV / 2.0;
+ font->vert_origin_y = FNT_DEFAULT_ASCENT;
+ font->vert_adv_y = FNT_UNITS_PER_EM;
}
static void sp_font_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
@@ -155,51 +160,63 @@ static void sp_font_release(SPObject *object)
static void sp_font_set(SPObject *object, unsigned int key, const gchar *value)
{
SPFont *font = SP_FONT(object);
- double number;
+ // TODO these are floating point, so some epsilon comparison would be good
switch (key) {
case SP_ATTR_HORIZ_ORIGIN_X:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != font->horiz_origin_x){
font->horiz_origin_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_HORIZ_ORIGIN_Y:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != font->horiz_origin_y){
font->horiz_origin_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_HORIZ_ADV_X:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ADV;
if (number != font->horiz_adv_x){
font->horiz_adv_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_VERT_ORIGIN_X:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ADV / 2.0;
if (number != font->vert_origin_x){
font->vert_origin_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_VERT_ORIGIN_Y:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : FNT_DEFAULT_ASCENT;
if (number != font->vert_origin_y){
font->vert_origin_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_VERT_ADV_Y:
- number = helperfns_read_number(value);
+ {
+ double number = value ? g_ascii_strtod(value, 0) : FNT_UNITS_PER_EM;
if (number != font->vert_adv_y){
font->vert_adv_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
default:
if (((SPObjectClass *) (parent_class))->set) {
((SPObjectClass *) (parent_class))->set(object, key, value);
diff --git a/src/sp-glyph-kerning.cpp b/src/sp-glyph-kerning.cpp
index 872efc853..d62fbb2c2 100644
--- a/src/sp-glyph-kerning.cpp
+++ b/src/sp-glyph-kerning.cpp
@@ -22,7 +22,6 @@
#include "sp-glyph-kerning.h"
#include "document.h"
-#include "helper-fns.h"
#include <string>
static void sp_glyph_kerning_class_init(SPGlyphKerningClass *gc);
@@ -149,41 +148,60 @@ bool GlyphNames::contains(const char* name){
static void sp_glyph_kerning_set(SPObject *object, unsigned int key, const gchar *value)
{
SPGlyphKerning * glyphkern = (SPGlyphKerning*) object; //even if it is a VKern this will work. I did it this way just to avoind warnings.
- double number;
switch (key) {
case SP_ATTR_U1:
- if (glyphkern->u1) delete glyphkern->u1;
+ {
+ if (glyphkern->u1) {
+ delete glyphkern->u1;
+ }
glyphkern->u1 = new UnicodeRange(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_U2:
- if (glyphkern->u2) delete glyphkern->u2;
+ {
+ if (glyphkern->u2) {
+ delete glyphkern->u2;
+ }
glyphkern->u2 = new UnicodeRange(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_G1:
- if (glyphkern->g1) delete glyphkern->g1;
+ {
+ if (glyphkern->g1) {
+ delete glyphkern->g1;
+ }
glyphkern->g1 = new GlyphNames(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_G2:
- if (glyphkern->g2) delete glyphkern->g2;
+ {
+ if (glyphkern->g2) {
+ delete glyphkern->g2;
+ }
glyphkern->g2 = new GlyphNames(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
- case SP_ATTR_K:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_K:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyphkern->k){
glyphkern->k = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- default:
+ }
+ default:
+ {
if (((SPObjectClass *) (parent_class))->set) {
((SPObjectClass *) (parent_class))->set(object, key, value);
}
break;
+ }
}
}
diff --git a/src/sp-glyph.cpp b/src/sp-glyph.cpp
index 37e266da0..0b3b85d3f 100644
--- a/src/sp-glyph.cpp
+++ b/src/sp-glyph.cpp
@@ -20,7 +20,6 @@
#include "attributes.h"
#include "sp-glyph.h"
#include "document.h"
-#include "helper-fns.h"
static void sp_glyph_class_init(SPGlyphClass *gc);
static void sp_glyph_init(SPGlyph *glyph);
@@ -146,78 +145,97 @@ static glyphOrientation sp_glyph_read_orientation(gchar const *value){
static void sp_glyph_set(SPObject *object, unsigned int key, const gchar *value)
{
SPGlyph *glyph = SP_GLYPH(object);
- double number;
- glyphOrientation orient;
- glyphArabicForm form;
switch (key) {
case SP_ATTR_UNICODE:
+ {
glyph->unicode.clear();
if (value) glyph->unicode.append(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_GLYPH_NAME:
+ {
glyph->glyph_name.clear();
if (value) glyph->glyph_name.append(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_D:
+ {
if (glyph->d) g_free(glyph->d);
glyph->d = g_strdup(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ }
case SP_ATTR_ORIENTATION:
- orient = sp_glyph_read_orientation(value);
+ {
+ glyphOrientation orient = sp_glyph_read_orientation(value);
if (glyph->orientation != orient){
glyph->orientation = orient;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_ARABIC_FORM:
- form = sp_glyph_read_arabic_form(value);
+ {
+ glyphArabicForm form = sp_glyph_read_arabic_form(value);
if (glyph->arabic_form != form){
glyph->arabic_form = form;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
+ }
case SP_ATTR_LANG:
+ {
if (glyph->lang) g_free(glyph->lang);
glyph->lang = g_strdup(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
- case SP_ATTR_HORIZ_ADV_X:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_HORIZ_ADV_X:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->horiz_adv_x){
glyph->horiz_adv_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ORIGIN_X:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ORIGIN_X:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_origin_x){
glyph->vert_origin_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ORIGIN_Y:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ORIGIN_Y:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_origin_y){
glyph->vert_origin_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ADV_Y:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ADV_Y:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_adv_y){
glyph->vert_adv_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- default:
+ }
+ default:
+ {
if (((SPObjectClass *) (parent_class))->set) {
((SPObjectClass *) (parent_class))->set(object, key, value);
}
break;
+ }
}
}
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index bb867e969..68bafdeab 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -1552,7 +1552,7 @@ sp_image_set_curve(SPImage *image)
NRRect rect;
sp_image_bbox(image, &rect, Geom::identity(), 0);
Geom::Rect rect2 = to_2geom(*rect.upgrade());
- SPCurve *c = SPCurve::new_from_rect(rect2);
+ SPCurve *c = SPCurve::new_from_rect(rect2, true);
if (image->curve) {
image->curve = image->curve->unref();
diff --git a/src/sp-missing-glyph.cpp b/src/sp-missing-glyph.cpp
index d25a5f812..7d5c42763 100644
--- a/src/sp-missing-glyph.cpp
+++ b/src/sp-missing-glyph.cpp
@@ -20,7 +20,6 @@
#include "attributes.h"
#include "sp-missing-glyph.h"
#include "document.h"
-#include "helper-fns.h"
static void sp_missing_glyph_class_init(SPMissingGlyphClass *gc);
static void sp_missing_glyph_init(SPMissingGlyph *glyph);
@@ -102,47 +101,60 @@ static void sp_missing_glyph_release(SPObject *object)
static void sp_missing_glyph_set(SPObject *object, unsigned int key, const gchar *value)
{
SPMissingGlyph *glyph = SP_MISSING_GLYPH(object);
- double number;
switch (key) {
case SP_ATTR_D:
- if (glyph->d) g_free(glyph->d);
+ {
+ if (glyph->d) {
+ g_free(glyph->d);
+ }
glyph->d = g_strdup(value);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
- case SP_ATTR_HORIZ_ADV_X:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_HORIZ_ADV_X:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->horiz_adv_x){
glyph->horiz_adv_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ORIGIN_X:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ORIGIN_X:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_origin_x){
glyph->vert_origin_x = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ORIGIN_Y:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ORIGIN_Y:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_origin_y){
glyph->vert_origin_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- case SP_ATTR_VERT_ADV_Y:
- number = helperfns_read_number(value);
+ }
+ case SP_ATTR_VERT_ADV_Y:
+ {
+ double number = value ? g_ascii_strtod(value, 0) : 0;
if (number != glyph->vert_adv_y){
glyph->vert_adv_y = number;
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
break;
- default:
+ }
+ default:
+ {
if (((SPObjectClass *) (parent_class))->set) {
((SPObjectClass *) (parent_class))->set(object, key, value);
}
break;
+ }
}
}
diff --git a/src/sp-object.h b/src/sp-object.h
index f7ca0f3a3..633091668 100644
--- a/src/sp-object.h
+++ b/src/sp-object.h
@@ -45,7 +45,7 @@
#define SP_OBJECT_WRITE_ALL (1 << 2)
/* Convenience stuff */
-#define SP_OBJECT_ID(o) (((SPObject *) (o))->id)
+#define SP_OBJECT_ID(o) (((SPObject *) (o))->getId())
#define SP_OBJECT_REPR(o) (((SPObject *) (o))->repr)
#define SP_OBJECT_DOCUMENT(o) (((SPObject *) (o))->document)
#define SP_OBJECT_PARENT(o) (((SPObject *) (o))->parent)
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index de5648137..dadcb5f57 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -50,6 +50,8 @@
#include "util/mathfns.h" // for triangle_area()
+#include "splivarot.h" // for bounding box calculation
+
#define noSHAPE_VERBOSE
static void sp_shape_class_init (SPShapeClass *klass);
@@ -541,166 +543,193 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &
cbbox.x1 = (*geombbox)[0][1];
cbbox.y1 = (*geombbox)[1][1];
- if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) {
-
- SPStyle* style=SP_OBJECT_STYLE (item);
- if (!style->stroke.isNone()) {
- double const scale = transform.descrim();
- if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
- double const width = MAX(0.125, style->stroke_width.computed * scale);
- if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
- cbbox.x0-=0.5*width;
- cbbox.x1+=0.5*width;
- cbbox.y0-=0.5*width;
- cbbox.y1+=0.5*width;
+ switch ((SPItem::BBoxType) flags) {
+ case SPItem::GEOMETRIC_BBOX: {
+ // do nothing
+ break;
+ }
+ case SPItem::RENDERING_BBOX: {
+ // convert the stroke to a path and calculate that path's geometric bbox
+ SPStyle* style=SP_OBJECT_STYLE (item);
+ if (!style->stroke.isNone()) {
+ Geom::PathVector *pathv = item_outline(item);
+ if (pathv) {
+ Geom::OptRect geomstrokebbox = bounds_exact_transformed(*pathv, transform);
+ if (geomstrokebbox) {
+ NRRect strokebbox;
+ strokebbox.x0 = (*geomstrokebbox)[0][0];
+ strokebbox.y0 = (*geomstrokebbox)[1][0];
+ strokebbox.x1 = (*geomstrokebbox)[0][1];
+ strokebbox.y1 = (*geomstrokebbox)[1][1];
+ nr_rect_d_union (&cbbox, &cbbox, &strokebbox);
+ }
+ delete pathv;
}
}
+ break;
}
-
- // Union with bboxes of the markers, if any
- if (sp_shape_has_markers (shape)) {
- /** \todo make code prettier! */
- Geom::PathVector const & pathv = shape->curve->get_pathvector();
- // START marker
- for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
- if ( shape->marker[i] ) {
- SPMarker* marker = SP_MARKER (shape->marker[i]);
- SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
-
- if (marker_item) {
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
- if (!marker->orient_auto) {
- Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
- }
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
- tr = Geom::Scale(style->stroke_width.computed) * tr;
- }
-
- // total marker transform
- tr = marker_item->transform * marker->c2p * tr * transform;
-
- // get bbox of the marker with that transform
- NRRect marker_bbox;
- sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
- // union it with the shape bbox
- nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+ default:
+ case SPItem::APPROXIMATE_BBOX: {
+ SPStyle* style=SP_OBJECT_STYLE (item);
+ if (!style->stroke.isNone()) {
+ double const scale = transform.descrim();
+ if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
+ double const width = MAX(0.125, style->stroke_width.computed * scale);
+ if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
+ cbbox.x0-=0.5*width;
+ cbbox.x1+=0.5*width;
+ cbbox.y0-=0.5*width;
+ cbbox.y1+=0.5*width;
}
}
}
- // MID marker
- for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
- SPMarker* marker = SP_MARKER (shape->marker[i]);
- if ( !shape->marker[i] ) continue;
- SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
- if ( !marker_item ) continue;
-
- for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
- // START position
- if ( path_it != pathv.begin()
- && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
- {
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front()));
- if (!marker->orient_auto) {
- Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
- }
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
- tr = Geom::Scale(style->stroke_width.computed) * tr;
- }
- tr = marker_item->transform * marker->c2p * tr * transform;
- NRRect marker_bbox;
- sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
- nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
- }
- // MID position
- if ( path_it->size_default() > 1) {
- 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_default())
- {
- /* Put marker between curve_it1 and curve_it2.
- * Loop to end_default (so including closing segment), because when a path is closed,
- * there should be a midpoint marker between last segment and closing straight line segment */
-
- SPMarker* marker = SP_MARKER (shape->marker[i]);
- SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
-
- if (marker_item) {
- Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
- if (!marker->orient_auto) {
- Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
- }
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
- tr = Geom::Scale(style->stroke_width.computed) * tr;
- }
- tr = marker_item->transform * marker->c2p * tr * transform;
- NRRect marker_bbox;
- sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
- nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+
+ // Union with bboxes of the markers, if any
+ if (sp_shape_has_markers (shape)) {
+ /** \todo make code prettier! */
+ Geom::PathVector const & pathv = shape->curve->get_pathvector();
+ // START marker
+ for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
+ if ( shape->marker[i] ) {
+ SPMarker* marker = SP_MARKER (shape->marker[i]);
+ SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
+
+ if (marker_item) {
+ Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
+ if (!marker->orient_auto) {
+ Geom::Point transl = tr.translation();
+ tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ }
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = Geom::Scale(style->stroke_width.computed) * tr;
}
- ++curve_it1;
- ++curve_it2;
- }
- }
- // END position
- if ( path_it != (pathv.end()-1) && !path_it->empty()) {
- Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
- if (!marker->orient_auto) {
- Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
- }
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
- tr = Geom::Scale(style->stroke_width.computed) * tr;
+ // total marker transform
+ tr = marker_item->transform * marker->c2p * tr * transform;
+
+ // get bbox of the marker with that transform
+ NRRect marker_bbox;
+ sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
+ // union it with the shape bbox
+ nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
- tr = marker_item->transform * marker->c2p * tr * transform;
- NRRect marker_bbox;
- sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
- nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
}
- }
- // END marker
- for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
- if ( shape->marker[i] ) {
+ // MID marker
+ for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
SPMarker* marker = SP_MARKER (shape->marker[i]);
+ if ( !shape->marker[i] ) continue;
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
+ if ( !marker_item ) continue;
- if (marker_item) {
- /* Get reference to last curve in the path.
- * For moveto-only path, this returns the "closing line segment". */
- Geom::Path const &path_last = pathv.back();
- unsigned int index = path_last.size_default();
- if (index > 0) {
- index--;
+ for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
+ // START position
+ if ( path_it != pathv.begin()
+ && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
+ {
+ Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front()));
+ if (!marker->orient_auto) {
+ Geom::Point transl = tr.translation();
+ tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ }
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = Geom::Scale(style->stroke_width.computed) * tr;
+ }
+ tr = marker_item->transform * marker->c2p * tr * transform;
+ NRRect marker_bbox;
+ sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
+ nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
- Geom::Curve const &lastcurve = path_last[index];
+ // MID position
+ if ( path_it->size_default() > 1) {
+ 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_default())
+ {
+ /* Put marker between curve_it1 and curve_it2.
+ * Loop to end_default (so including closing segment), because when a path is closed,
+ * there should be a midpoint marker between last segment and closing straight line segment */
+
+ SPMarker* marker = SP_MARKER (shape->marker[i]);
+ SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
+
+ if (marker_item) {
+ Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ if (!marker->orient_auto) {
+ Geom::Point transl = tr.translation();
+ tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ }
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = Geom::Scale(style->stroke_width.computed) * tr;
+ }
+ tr = marker_item->transform * marker->c2p * tr * transform;
+ NRRect marker_bbox;
+ sp_item_invoke_bbox (marker_item, &marker_bbox, from_2geom(tr), true);
+ nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+ }
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
- if (!marker->orient_auto) {
- Geom::Point transl = tr.translation();
- tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ ++curve_it1;
+ ++curve_it2;
+ }
}
- if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
- tr = Geom::Scale(style->stroke_width.computed) * tr;
+ // END position
+ if ( path_it != (pathv.end()-1) && !path_it->empty()) {
+ Geom::Curve const &lastcurve = path_it->back_default();
+ Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ if (!marker->orient_auto) {
+ Geom::Point transl = tr.translation();
+ tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ }
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = Geom::Scale(style->stroke_width.computed) * tr;
+ }
+ tr = marker_item->transform * marker->c2p * tr * transform;
+ NRRect marker_bbox;
+ sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
+ nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
}
+ }
+ }
+ // END marker
+ for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
+ if ( shape->marker[i] ) {
+ SPMarker* marker = SP_MARKER (shape->marker[i]);
+ SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
+
+ if (marker_item) {
+ /* Get reference to last curve in the path.
+ * For moveto-only path, this returns the "closing line segment". */
+ Geom::Path const &path_last = pathv.back();
+ unsigned int index = path_last.size_default();
+ if (index > 0) {
+ index--;
+ }
+ Geom::Curve const &lastcurve = path_last[index];
+
+ Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ if (!marker->orient_auto) {
+ Geom::Point transl = tr.translation();
+ tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
+ }
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = Geom::Scale(style->stroke_width.computed) * tr;
+ }
- // total marker transform
- tr = marker_item->transform * marker->c2p * tr * transform;
+ // total marker transform
+ tr = marker_item->transform * marker->c2p * tr * transform;
- // get bbox of the marker with that transform
- NRRect marker_bbox;
- sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
- // union it with the shape bbox
- nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+ // get bbox of the marker with that transform
+ NRRect marker_bbox;
+ sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
+ // union it with the shape bbox
+ nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
+ }
}
}
}
- }
- }
+ break;
+ } // end case approximate bbox type
+ } // end switch bboxtype
// copy our bbox to the variable we're given
*bbox = cbbox;
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 085dfeda0..db9f72975 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -624,6 +624,250 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix
}
}
+static
+void item_outline_add_marker( SPObject const *marker_object, Geom::Matrix marker_transform,
+ Geom::Scale stroke_scale, Geom::Matrix transform,
+ Geom::PathVector* pathv_in )
+{
+ SPMarker* marker = SP_MARKER (marker_object);
+ SPItem* marker_item = sp_item_first_item_child(SP_OBJECT(marker_object));
+
+ Geom::Matrix tr(marker_transform);
+ if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
+ tr = stroke_scale * tr;
+ }
+ // total marker transform
+ tr = marker_item->transform * marker->c2p * tr * transform;
+
+ Geom::PathVector* marker_pathv = item_outline(marker_item);
+
+ if (marker_pathv) {
+ for (unsigned int j=0; j < marker_pathv->size(); j++) {
+ pathv_in->push_back((*marker_pathv)[j] * tr);
+ }
+ delete marker_pathv;
+ }
+}
+
+/**
+ * Returns a pathvector that is the outline of the stroked item, with markers.
+ * item must be SPShape of SPText.
+ */
+Geom::PathVector* item_outline(SPItem const *item)
+{
+ Geom::PathVector *ret_pathv = NULL;
+
+ if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item))
+ return ret_pathv;
+
+ // no stroke: no outline
+ if (!SP_OBJECT_STYLE(item) || SP_OBJECT_STYLE(item)->stroke.noneSet) {
+ return ret_pathv;
+ }
+
+ SPCurve *curve = NULL;
+ if (SP_IS_SHAPE(item)) {
+ curve = sp_shape_get_curve(SP_SHAPE(item));
+ } else if (SP_IS_TEXT(item)) {
+ curve = SP_TEXT(item)->getNormalizedBpath();
+ }
+ if (curve == NULL) {
+ return ret_pathv;
+ }
+
+ // remember old stroke style, to be set on fill
+ SPStyle *i_style = SP_OBJECT_STYLE(item);
+
+ Geom::Matrix const transform(item->transform);
+ float const scale = transform.descrim();
+
+ float o_width, o_miter;
+ JoinType o_join;
+ ButtType o_butt;
+ {
+ o_width = i_style->stroke_width.computed;
+ if (o_width < 0.1) {
+ o_width = 0.1;
+ }
+ o_miter = i_style->stroke_miterlimit.value * o_width;
+
+ switch (i_style->stroke_linejoin.computed) {
+ case SP_STROKE_LINEJOIN_MITER:
+ o_join = join_pointy;
+ break;
+ case SP_STROKE_LINEJOIN_ROUND:
+ o_join = join_round;
+ break;
+ default:
+ o_join = join_straight;
+ break;
+ }
+
+ switch (i_style->stroke_linecap.computed) {
+ case SP_STROKE_LINECAP_SQUARE:
+ o_butt = butt_square;
+ break;
+ case SP_STROKE_LINECAP_ROUND:
+ o_butt = butt_round;
+ break;
+ default:
+ o_butt = butt_straight;
+ break;
+ }
+ }
+
+ // Livarots outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly.
+ Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() );
+
+ Path *orig = new Path;
+ orig->LoadPathVector(pathv);
+
+ Path *res = new Path;
+ res->SetBackData(false);
+
+ if (i_style->stroke_dash.n_dash) {
+ // For dashed strokes, use Stroke method, because Outline can't do dashes
+ // However Stroke adds lots of extra nodes _or_ makes the path crooked, so consider this a temporary workaround
+
+ orig->ConvertWithBackData(0.1);
+
+ orig->DashPolylineFromStyle(i_style, scale, 0);
+
+ Shape* theShape = new Shape;
+ orig->Stroke(theShape, false, 0.5*o_width, o_join, o_butt,
+ 0.5 * o_miter);
+ orig->Outline(res, 0.5 * o_width, o_join, o_butt, 0.5 * o_miter);
+
+ Shape *theRes = new Shape;
+
+ theRes->ConvertToShape(theShape, fill_positive);
+
+ Path *originaux[1];
+ originaux[0] = res;
+ theRes->ConvertToForme(orig, 1, originaux);
+
+ res->Coalesce(5.0);
+
+ delete theShape;
+ delete theRes;
+ } else {
+ orig->Outline(res, 0.5 * o_width, o_join, o_butt, 0.5 * o_miter);
+
+ orig->Coalesce(0.5 * o_width);
+
+ Shape *theShape = new Shape;
+ Shape *theRes = new Shape;
+
+ res->ConvertWithBackData(1.0);
+ res->Fill(theShape, 0);
+ theRes->ConvertToShape(theShape, fill_positive);
+
+ Path *originaux[1];
+ originaux[0] = res;
+ theRes->ConvertToForme(orig, 1, originaux);
+
+ delete theShape;
+ delete theRes;
+ }
+
+ if (orig->descr_cmd.size() <= 1) {
+ // ca a merdÂŽ, ou bien le resultat est vide
+ delete res;
+ delete orig;
+ curve->unref();
+ return ret_pathv;
+ }
+
+
+ if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether
+ ret_pathv = orig->MakePathVector();
+
+ if (SP_IS_SHAPE(item) && sp_shape_has_markers (SP_SHAPE(item))) {
+ SPShape *shape = SP_SHAPE(item);
+
+ Geom::PathVector const & pathv = curve->get_pathvector();
+
+ // START marker
+ for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
+ if ( SPObject *marker_obj = shape->marker[i] ) {
+ Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front()));
+ item_outline_add_marker( marker_obj, m,
+ Geom::Scale(i_style->stroke_width.computed), transform,
+ ret_pathv );
+ }
+ }
+ // MID marker
+ for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
+ SPObject *midmarker_obj = shape->marker[i];
+ if (!midmarker_obj) continue;
+ for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) {
+ // START position
+ if ( path_it != pathv.begin()
+ && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
+ {
+ Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
+ item_outline_add_marker( midmarker_obj, m,
+ Geom::Scale(i_style->stroke_width.computed), transform,
+ ret_pathv );
+ }
+ // MID position
+ if (path_it->size_default() > 1) {
+ 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_default())
+ {
+ /* Put marker between curve_it1 and curve_it2.
+ * Loop to end_default (so including closing segment), because when a path is closed,
+ * there should be a midpoint marker between last segment and closing straight line segment
+ */
+ Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ item_outline_add_marker( midmarker_obj, m,
+ Geom::Scale(i_style->stroke_width.computed), transform,
+ ret_pathv);
+
+ ++curve_it1;
+ ++curve_it2;
+ }
+ }
+ // END position
+ if ( path_it != (pathv.end()-1) && !path_it->empty()) {
+ Geom::Curve const &lastcurve = path_it->back_default();
+ Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ item_outline_add_marker( midmarker_obj, m,
+ Geom::Scale(i_style->stroke_width.computed), transform,
+ ret_pathv );
+ }
+ }
+ }
+ // END marker
+ for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
+ if ( SPObject *marker_obj = shape->marker[i] ) {
+ /* Get reference to last curve in the path.
+ * For moveto-only path, this returns the "closing line segment". */
+ Geom::Path const &path_last = pathv.back();
+ unsigned int index = path_last.size_default();
+ if (index > 0) {
+ index--;
+ }
+ Geom::Curve const &lastcurve = path_last[index];
+
+ Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ item_outline_add_marker( marker_obj, m,
+ Geom::Scale(i_style->stroke_width.computed), transform,
+ ret_pathv );
+ }
+ }
+ }
+
+ curve->unref();
+ }
+
+ delete res;
+ delete orig;
+
+ return ret_pathv;
+}
+
void
sp_selected_path_outline(SPDesktop *desktop)
{
diff --git a/src/splivarot.h b/src/splivarot.h
index dce31a1ad..ff9f4f577 100644
--- a/src/splivarot.h
+++ b/src/splivarot.h
@@ -43,6 +43,7 @@ void sp_selected_path_create_updating_offset_object_zero (SPDesktop *desktop);
// outline of a curve
// uses the stroke-width
void sp_selected_path_outline (SPDesktop *desktop);
+Geom::PathVector* item_outline(SPItem const *item);
// simplifies a path (removes small segments and the like)
void sp_selected_path_simplify (SPDesktop *desktop);
diff --git a/src/style.cpp b/src/style.cpp
index 6d73e62ea..a05cef252 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -1446,16 +1446,19 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
}
if (!style->line_height.set || style->line_height.inherit) {
+ style->line_height.value = parent->line_height.value;
style->line_height.computed = parent->line_height.computed;
style->line_height.normal = parent->line_height.normal;
}
if (!style->letter_spacing.set || style->letter_spacing.inherit) {
+ style->letter_spacing.value = parent->letter_spacing.value;
style->letter_spacing.computed = parent->letter_spacing.computed;
style->letter_spacing.normal = parent->letter_spacing.normal;
}
if (!style->word_spacing.set || style->word_spacing.inherit) {
+ style->word_spacing.value = parent->word_spacing.value;
style->word_spacing.computed = parent->word_spacing.computed;
style->word_spacing.normal = parent->word_spacing.normal;
}
@@ -2780,9 +2783,9 @@ sp_text_style_new()
ts->refcount = 1;
sp_text_style_clear(ts);
- ts->font_specification.value = g_strdup("Bitstream Vera Sans");
- ts->font.value = g_strdup("Bitstream Vera Sans");
- ts->font_family.value = g_strdup("Bitstream Vera Sans");
+ ts->font_specification.value = g_strdup("Sans");
+ ts->font.value = g_strdup("Sans");
+ ts->font_family.value = g_strdup("Sans");
return ts;
}
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index 033bec875..da9be1e7c 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -22,6 +22,8 @@ ink_common_sources += \
ui/dialog/color-item.h \
ui/dialog/debug.cpp \
ui/dialog/debug.h \
+ ui/dialog/desktop-tracker.cpp \
+ ui/dialog/desktop-tracker.h \
ui/dialog/dialog.cpp \
ui/dialog/dialog.h \
ui/dialog/dialog-manager.cpp \
@@ -50,6 +52,8 @@ ink_common_sources += \
ui/dialog/find.h \
ui/dialog/floating-behavior.cpp \
ui/dialog/floating-behavior.h \
+ ui/dialog/glyphs.cpp \
+ ui/dialog/glyphs.h \
ui/dialog/guides.cpp \
ui/dialog/guides.h \
ui/dialog/icon-preview.cpp \
diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
index 0d41bb221..297b3d2a1 100644
--- a/src/ui/dialog/align-and-distribute.h
+++ b/src/ui/dialog/align-and-distribute.h
@@ -32,8 +32,6 @@
#include "ui/widget/panel.h"
#include "ui/widget/notebook-page.h"
-using namespace Inkscape::UI::Widget;
-
class SPItem;
diff --git a/src/ui/dialog/desktop-tracker.cpp b/src/ui/dialog/desktop-tracker.cpp
new file mode 100644
index 000000000..f527f1c05
--- /dev/null
+++ b/src/ui/dialog/desktop-tracker.cpp
@@ -0,0 +1,159 @@
+/**
+ * Glyph selector dialog.
+ */
+
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2010 Jon A. Cruz
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib-object.h>
+
+#include "desktop-tracker.h"
+
+#include "inkscape.h"
+#include "desktop.h"
+#include "widgets/desktop-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+DesktopTracker::DesktopTracker() :
+ base(0),
+ desktop(0),
+ widget(0),
+ hierID(0),
+ inkID(0),
+ trackActive(false),
+ desktopChangedSig()
+{
+}
+
+DesktopTracker::~DesktopTracker()
+{
+ disconnect();
+}
+
+void DesktopTracker::connect(GtkWidget *widget)
+{
+ disconnect();
+
+ this->widget = widget;
+
+ // Use C/gobject callbacks to avoid gtkmm rewrap-during-destruct issues:
+ hierID = g_signal_connect( G_OBJECT(widget), "hierarchy-changed", G_CALLBACK(hierarchyChangeCB), this );
+ inkID = g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(activateDesktopCB), this );
+
+ GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET);
+ if (wdgt && !base) {
+ SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
+ if (dtw && dtw->desktop) {
+ setBase(dtw->desktop); // may also set desktop
+ }
+ }
+}
+
+void DesktopTracker::disconnect()
+{
+ if (hierID) {
+ if (widget) {
+ g_signal_handler_disconnect(G_OBJECT(widget), hierID);
+ }
+ hierID = 0;
+ }
+ if (inkID) {
+ if (INKSCAPE) {
+ g_signal_handler_disconnect(G_OBJECT(INKSCAPE), inkID);
+ }
+ inkID = 0;
+ }
+}
+
+void DesktopTracker::setBase(SPDesktop *desktop)
+{
+ if (this->base != desktop) {
+ base = desktop;
+ // Do not override an existing target desktop
+ if (!this->desktop) {
+ setDesktop(desktop);
+ }
+ }
+}
+
+SPDesktop *DesktopTracker::getBase() const
+{
+ return base;
+}
+
+SPDesktop *DesktopTracker::getDesktop() const
+{
+ return desktop;
+}
+
+sigc::connection DesktopTracker::connectDesktopChanged( const sigc::slot<void, SPDesktop*> & slot )
+{
+ return desktopChangedSig.connect(slot);
+}
+
+gboolean DesktopTracker::activateDesktopCB(Inkscape::Application */*inkscape*/, SPDesktop *desktop, DesktopTracker *self )
+{
+ if (self && self->trackActive) {
+ self->setDesktop(desktop);
+ }
+ return FALSE;
+}
+
+bool DesktopTracker::hierarchyChangeCB(GtkWidget * /*widget*/, GtkWidget* /*prev*/, DesktopTracker *self)
+{
+ if (self) {
+ self->handleHierarchyChange();
+ }
+ return false;
+}
+
+void DesktopTracker::handleHierarchyChange()
+{
+ GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET);
+ bool newFlag = (wdgt == 0); // true means not in an SPDesktopWidget, thus floating.
+ if (wdgt && !base) {
+ SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
+ if (dtw && dtw->desktop) {
+ setBase(dtw->desktop); // may also set desktop
+ }
+ }
+ if (newFlag != trackActive) {
+ trackActive = newFlag;
+ if (trackActive) {
+ setDesktop(SP_ACTIVE_DESKTOP);
+ } else if (desktop != base) {
+ setDesktop(getBase());
+ }
+ }
+}
+
+void DesktopTracker::setDesktop(SPDesktop *desktop)
+{
+ if (desktop != this->desktop) {
+ this->desktop = desktop;
+ desktopChangedSig.emit(desktop);
+ }
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // 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/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h
new file mode 100644
index 000000000..7a5bc39c2
--- /dev/null
+++ b/src/ui/dialog/desktop-tracker.h
@@ -0,0 +1,73 @@
+/**
+ * Glyph selector dialog.
+ */
+
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2010 Jon A. Cruz
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef SEEN_DIALOG_DESKTOP_TRACKER
+#define SEEN_DIALOG_DESKTOP_TRACKER
+
+#include <sigc++/connection.h>
+#include <glib/gtypes.h>
+
+typedef struct _GtkWidget GtkWidget;
+class SPDesktop;
+
+namespace Inkscape {
+
+class Application;
+
+namespace UI {
+namespace Dialog {
+
+class DesktopTracker
+{
+public:
+ DesktopTracker();
+ virtual ~DesktopTracker();
+
+ void connect(GtkWidget *widget);
+ void disconnect();
+
+ SPDesktop *getDesktop() const;
+
+ void setBase(SPDesktop *desktop);
+ SPDesktop *getBase() const;
+
+ sigc::connection connectDesktopChanged( const sigc::slot<void, SPDesktop*> & slot );
+
+private:
+ static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, DesktopTracker *self );
+ static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, DesktopTracker *self);
+
+ void handleHierarchyChange();
+ void setDesktop(SPDesktop *desktop);
+
+ SPDesktop *base;
+ SPDesktop *desktop;
+ GtkWidget *widget;
+ gulong hierID;
+ gulong inkID;
+ bool trackActive;
+ sigc::signal<void, SPDesktop*> desktopChangedSig;
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_DIALOG_DESKTOP_TRACKER
+/*
+ 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/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 30cbed649..6d3bc817e 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -25,6 +25,7 @@
#include "ui/dialog/fill-and-stroke.h"
#include "ui/dialog/filter-effects-dialog.h"
#include "ui/dialog/find.h"
+#include "ui/dialog/glyphs.h"
#include "ui/dialog/inkscape-preferences.h"
#include "ui/dialog/input.h"
#include "ui/dialog/livepatheffect-editor.h"
@@ -96,6 +97,7 @@ DialogManager::DialogManager() {
registerFactory("FillAndStroke", &create<FillAndStroke, FloatingBehavior>);
registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog, FloatingBehavior>);
registerFactory("Find", &create<Find, FloatingBehavior>);
+ registerFactory("Glyphs", &create<GlyphsPanel, FloatingBehavior>);
registerFactory("IconPreviewPanel", &create<IconPreviewPanel, FloatingBehavior>);
registerFactory("InkscapePreferences", &create<InkscapePreferences, FloatingBehavior>);
registerFactory("LayersPanel", &create<LayersPanel, FloatingBehavior>);
@@ -123,6 +125,7 @@ DialogManager::DialogManager() {
registerFactory("FillAndStroke", &create<FillAndStroke, DockBehavior>);
registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog, DockBehavior>);
registerFactory("Find", &create<Find, DockBehavior>);
+ registerFactory("Glyphs", &create<GlyphsPanel, DockBehavior>);
registerFactory("IconPreviewPanel", &create<IconPreviewPanel, DockBehavior>);
registerFactory("InkscapePreferences", &create<InkscapePreferences, DockBehavior>);
registerFactory("LayersPanel", &create<LayersPanel, DockBehavior>);
@@ -159,11 +162,11 @@ DialogManager &DialogManager::getInstance()
/* Use singleton behavior for floating dialogs */
if (dialogs_type == FLOATING) {
static DialogManager *instance = 0;
-
+
if (!instance)
instance = new DialogManager();
return *instance;
- }
+ }
return *new DialogManager();
}
diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp
index 2b39eb3c9..2483dc50e 100644
--- a/src/ui/dialog/dialog.cpp
+++ b/src/ui/dialog/dialog.cpp
@@ -139,6 +139,7 @@ Dialog::~Dialog()
save_geometry();
delete _behavior;
+ _behavior = 0;
}
diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h
index 1a59a236c..f07c1bc86 100644
--- a/src/ui/dialog/dialog.h
+++ b/src/ui/dialog/dialog.h
@@ -21,9 +21,9 @@
class SPDesktop;
-namespace Inkscape {
-class Selection;
-class Application;
+namespace Inkscape {
+class Selection;
+class Application;
}
namespace Inkscape {
@@ -36,7 +36,7 @@ void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpoi
gboolean sp_retransientize_again(gpointer dlgPtr);
void sp_dialog_shutdown(GtkObject *object, gpointer dlgPtr);
-/**
+/**
* @brief Base class for Inkscape dialogs
* This class provides certain common behaviors and styles wanted of all dialogs
* in the application. Fundamental parts of the dialog's behavior are controlled by
@@ -46,7 +46,7 @@ class Dialog {
public:
- Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path = NULL,
+ Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path = NULL,
int verb_num = 0, Glib::ustring const &apply_label = "");
virtual ~Dialog();
diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp
index 96cad1fbe..55eb94f92 100644
--- a/src/ui/dialog/document-metadata.cpp
+++ b/src/ui/dialog/document-metadata.cpp
@@ -148,6 +148,8 @@ attach_all (Gtk::Table &table, const Gtk::Widget *arr[], unsigned size, int star
void
DocumentMetadata::build_metadata()
{
+ using Inkscape::UI::Widget::EntityEntry;
+
_page_metadata1.show();
Gtk::Label *label = manage (new Gtk::Label);
diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h
index 7f718e9f7..f21bb0d83 100644
--- a/src/ui/dialog/document-metadata.h
+++ b/src/ui/dialog/document-metadata.h
@@ -23,8 +23,6 @@
#include "ui/widget/notebook-page.h"
#include "ui/widget/registry.h"
-using namespace Inkscape::UI::Widget;
-
namespace Inkscape {
namespace XML {
class Node;
@@ -35,7 +33,7 @@ namespace Inkscape {
}
namespace Dialog {
-typedef std::list<EntityEntry*> RDElist;
+typedef std::list<UI::Widget::EntityEntry*> RDElist;
class DocumentMetadata : public Inkscape::UI::Widget::Panel {
public:
@@ -56,13 +54,14 @@ protected:
Gtk::Tooltips _tt;
Gtk::Notebook _notebook;
- NotebookPage _page_metadata1, _page_metadata2;
+ UI::Widget::NotebookPage _page_metadata1;
+ UI::Widget::NotebookPage _page_metadata2;
//---------------------------------------------------------------
RDElist _rdflist;
- Licensor _licensor;
+ UI::Widget::Licensor _licensor;
- Registry _wr;
+ UI::Widget::Registry _wr;
private:
virtual ~DocumentMetadata();
diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h
index 136ae2c89..c67dc9706 100644
--- a/src/ui/dialog/document-properties.h
+++ b/src/ui/dialog/document-properties.h
@@ -28,8 +28,6 @@
#include "xml/helper-observer.h"
-using namespace Inkscape::UI::Widget;
-
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -78,21 +76,31 @@ protected:
Gtk::Tooltips _tt;
Gtk::Notebook _notebook;
- NotebookPage _page_page, _page_guides;
- NotebookPage _page_snap, _page_cms, _page_scripting;
+ UI::Widget::NotebookPage _page_page;
+ UI::Widget::NotebookPage _page_guides;
+ UI::Widget::NotebookPage _page_snap;
+ UI::Widget::NotebookPage _page_cms;
+ UI::Widget::NotebookPage _page_scripting;
Gtk::VBox _grids_vbox;
- Registry _wr;
+ UI::Widget::Registry _wr;
//---------------------------------------------------------------
- RegisteredCheckButton _rcb_canb, _rcb_bord, _rcb_shad;
- RegisteredColorPicker _rcp_bg, _rcp_bord;
- RegisteredUnitMenu _rum_deflt;
- PageSizer _page_sizer;
+ UI::Widget::RegisteredCheckButton _rcb_canb;
+ UI::Widget::RegisteredCheckButton _rcb_bord;
+ UI::Widget::RegisteredCheckButton _rcb_shad;
+ UI::Widget::RegisteredColorPicker _rcp_bg;
+ UI::Widget::RegisteredColorPicker _rcp_bord;
+ UI::Widget::RegisteredUnitMenu _rum_deflt;
+ UI::Widget::PageSizer _page_sizer;
//---------------------------------------------------------------
- RegisteredCheckButton _rcb_sgui, _rcbsng;
- RegisteredColorPicker _rcp_gui, _rcp_hgui;
+ UI::Widget::RegisteredCheckButton _rcb_sgui;
+ UI::Widget::RegisteredCheckButton _rcbsng;
+ UI::Widget::RegisteredColorPicker _rcp_gui;
+ UI::Widget::RegisteredColorPicker _rcp_hgui;
//---------------------------------------------------------------
- ToleranceSlider _rsu_sno, _rsu_sn, _rsu_gusn;
+ UI::Widget::ToleranceSlider _rsu_sno;
+ UI::Widget::ToleranceSlider _rsu_sn;
+ UI::Widget::ToleranceSlider _rsu_gusn;
//---------------------------------------------------------------
Gtk::Menu _menu;
Gtk::OptionMenu _combo_avail;
diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp
index 916e3ec97..6f83a706f 100644
--- a/src/ui/dialog/filedialogimpl-gtkmm.cpp
+++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp
@@ -271,7 +271,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
"<text\n"
" style=\"font-size:24.000000;font-style:normal;font-weight:normal;"
" fill:#000000;fill-opacity:1.0000000;stroke:none;"
- " font-family:Bitstream Vera Sans\"\n"
+ " font-family:Sans\"\n"
" x=\"10\" y=\"26\">%d x %d</text>\n" //# VALUES HERE
"</svg>\n\n";
@@ -374,7 +374,7 @@ void SVGPreview::showNoPreview()
"style=\"font-size:32.000000;font-style:normal;font-variant:normal;font-weight:bold;"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
- "font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
+ "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n"
"x=\"190\" y=\"240\">%s</text></g>\n" //# VALUE HERE
"</svg>\n\n";
@@ -471,13 +471,13 @@ void SVGPreview::showTooLarge(long fileLength)
"style=\"font-size:32.000000;font-style:normal;font-variant:normal;font-weight:bold;"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
- "font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
+ "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n"
"x=\"170\" y=\"215\">%5.1f MB</text>\n" //# VALUE HERE
"<text xml:space=\"preserve\"\n"
"style=\"font-size:24.000000;font-style:normal;font-variant:normal;font-weight:bold;"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
- "font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
+ "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n"
"x=\"180\" y=\"245\">%s</text>\n" //# VALUE HERE
"</svg>\n\n";
diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp
index fe63c6e24..8c86e1ca4 100644
--- a/src/ui/dialog/fill-and-stroke.cpp
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -6,8 +6,10 @@
/* Authors:
* Bryce W. Harrington <bryce@bryceharrington.org>
* Gustav Broberg <broberg@kth.se>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2004--2007 Authors
+ * Copyright (C) 2010 Jon A. Cruz
*
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
@@ -29,6 +31,8 @@
#include "widgets/stroke-style.h"
#include "xml/repr.h"
+#include "ui/view/view-widget.h"
+
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -38,7 +42,12 @@ FillAndStroke::FillAndStroke()
_page_fill(1, 1, true, true),
_page_stroke_paint(1, 1, true, true),
_page_stroke_style(1, 1, true, true),
- _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", SimpleFilterModifier::BLUR)
+ _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke", UI::Widget::SimpleFilterModifier::BLUR),
+ deskTrack(),
+ targetDesktop(0),
+ fillWdgt(0),
+ strokeWdgt(0),
+ desktopChangeConn()
{
Gtk::Box *contents = _getContents();
contents->set_spacing(0);
@@ -58,25 +67,51 @@ FillAndStroke::FillAndStroke()
show_all_children();
_composite_settings.setSubject(&_subject);
+
+ // Connect this up last
+ desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &FillAndStroke::setTargetDesktop) );
+ deskTrack.connect(GTK_WIDGET(gobj()));
}
FillAndStroke::~FillAndStroke()
{
_composite_settings.setSubject(NULL);
+
+ desktopChangeConn.disconnect();
+ deskTrack.disconnect();
+}
+
+void FillAndStroke::setDesktop(SPDesktop *desktop)
+{
+ Panel::setDesktop(desktop);
+ deskTrack.setBase(desktop);
+}
+
+void FillAndStroke::setTargetDesktop(SPDesktop *desktop)
+{
+ if (targetDesktop != desktop) {
+ targetDesktop = desktop;
+ if (fillWdgt) {
+ sp_fill_style_widget_set_desktop(fillWdgt, desktop);
+ }
+ if (strokeWdgt) {
+ sp_stroke_style_widget_set_desktop(strokeWdgt, desktop);
+ }
+ }
}
void
FillAndStroke::_layoutPageFill()
{
- Gtk::Widget *fs = manage(Glib::wrap(sp_fill_style_widget_new()));
- _page_fill.table().attach(*fs, 0, 1, 0, 1);
+ fillWdgt = manage(sp_fill_style_widget_new());
+ _page_fill.table().attach(*fillWdgt, 0, 1, 0, 1);
}
void
FillAndStroke::_layoutPageStrokePaint()
{
- Gtk::Widget *ssp = manage(Glib::wrap(sp_stroke_style_paint_widget_new()));
- _page_stroke_paint.table().attach(*ssp, 0, 1, 0, 1);
+ strokeWdgt = manage(sp_stroke_style_paint_widget_new());
+ _page_stroke_paint.table().attach(*strokeWdgt, 0, 1, 0, 1);
}
void
diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h
index 7dc892fea..2d4e90d73 100644
--- a/src/ui/dialog/fill-and-stroke.h
+++ b/src/ui/dialog/fill-and-stroke.h
@@ -4,8 +4,10 @@
/* Authors:
* Bryce W. Harrington <bryce@bryceharrington.org>
* Gustav Broberg <broberg@kth.se>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2004--2007 Authors
+ * Copyright (C) 2010 Jon A. Cruz
*
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
@@ -23,8 +25,7 @@
#include "ui/widget/panel.h"
#include "ui/widget/notebook-page.h"
#include "ui/widget/object-composite-settings.h"
-
-using namespace Inkscape::UI::Widget;
+#include "ui/dialog/desktop-tracker.h"
namespace Inkscape {
namespace UI {
@@ -37,6 +38,9 @@ public:
static FillAndStroke &getInstance() { return *new FillAndStroke(); }
+
+ virtual void setDesktop(SPDesktop *desktop);
+
void selectionChanged(Inkscape::Application *inkscape,
Inkscape::Selection *selection);
@@ -47,14 +51,14 @@ public:
protected:
Gtk::Notebook _notebook;
- NotebookPage _page_fill;
- NotebookPage _page_stroke_paint;
- NotebookPage _page_stroke_style;
+ UI::Widget::NotebookPage _page_fill;
+ UI::Widget::NotebookPage _page_stroke_paint;
+ UI::Widget::NotebookPage _page_stroke_style;
- StyleSubject::Selection _subject;
- ObjectCompositeSettings _composite_settings;
+ UI::Widget::StyleSubject::Selection _subject;
+ UI::Widget::ObjectCompositeSettings _composite_settings;
- Gtk::HBox &_createPageTabLabel(const Glib::ustring &label,
+ Gtk::HBox &_createPageTabLabel(const Glib::ustring &label,
const char *label_image);
void _layoutPageFill();
@@ -64,12 +68,21 @@ protected:
private:
FillAndStroke(FillAndStroke const &d);
FillAndStroke& operator=(FillAndStroke const &d);
+
+ void setTargetDesktop(SPDesktop *desktop);
+
+ DesktopTracker deskTrack;
+ SPDesktop *targetDesktop;
+ Gtk::Widget *fillWdgt;
+ Gtk::Widget *strokeWdgt;
+ sigc::connection desktopChangeConn;
};
} // namespace Dialog
} // namespace UI
} // namespace Inkscape
+
#endif // INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H
/*
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 132e5fd4e..1672c4b69 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -74,6 +74,12 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
+using Inkscape::UI::Widget::AttrWidget;
+using Inkscape::UI::Widget::ComboBoxEnum;
+using Inkscape::UI::Widget::DualSpinSlider;
+using Inkscape::UI::Widget::SpinSlider;
+
+
// Returns the number of inputs available for the filter primitive type
int input_count(const SPFilterPrimitive* prim)
{
diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h
index 3fb9a46fb..a14c85a91 100644
--- a/src/ui/dialog/filter-effects-dialog.h
+++ b/src/ui/dialog/filter-effects-dialog.h
@@ -35,8 +35,6 @@
#include "ui/widget/spin-slider.h"
#include "xml/helper-observer.h"
-using namespace Inkscape::UI::Widget;
-
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -214,9 +212,9 @@ private:
void duplicate_primitive();
void convolve_order_changed();
- void set_attr_direct(const AttrWidget*);
- void set_child_attr_direct(const AttrWidget*);
- void set_filternode_attr(const AttrWidget*);
+ void set_attr_direct(const UI::Widget::AttrWidget*);
+ void set_child_attr_direct(const UI::Widget::AttrWidget*);
+ void set_filternode_attr(const UI::Widget::AttrWidget*);
void set_attr(SPObject*, const SPAttributeEnum, const gchar* val);
void update_settings_view();
void update_filter_general_settings_view();
diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp
index 19147f2c7..85f078439 100644
--- a/src/ui/dialog/floating-behavior.cpp
+++ b/src/ui/dialog/floating-behavior.cpp
@@ -33,11 +33,11 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) :
Behavior(dialog),
_d (new Gtk::Dialog(_dialog._title))
#if GTK_VERSION_GE(2, 12)
- ,_dialog_active(_d->property_is_active())
- ,_steps(0)
- ,_trans_focus(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0))
- ,_trans_blur(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0))
- ,_trans_time(Inkscape::Preferences::get()->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000))
+ ,_dialog_active(_d->property_is_active())
+ ,_steps(0)
+ ,_trans_focus(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0))
+ ,_trans_blur(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0))
+ ,_trans_time(Inkscape::Preferences::get()->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000))
#endif
{
hide();
@@ -49,8 +49,8 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) :
_dialog.retransientize_suppress = false;
#if GTK_VERSION_GE(2, 12)
- _focus_event();
- _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event));
+ _focus_event();
+ _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event));
#endif
}
@@ -58,12 +58,12 @@ FloatingBehavior::FloatingBehavior(Dialog &dialog) :
#if GTK_VERSION_GE(2, 12)
/** \brief A function called when the window gets focus
- This function gets called on a focus event. It figures out how much
- time is required for a transition, and the number of steps that'll take,
- and sets up the _trans_timer function to do the work. If the transition
- time is set to 0 ms it just calls _trans_timer once with _steps equal to
- zero so that the transition happens instantaneously. This occurs on
- windows as opacity changes cause flicker there.
+ This function gets called on a focus event. It figures out how much
+ time is required for a transition, and the number of steps that'll take,
+ and sets up the _trans_timer function to do the work. If the transition
+ time is set to 0 ms it just calls _trans_timer once with _steps equal to
+ zero so that the transition happens instantaneously. This occurs on
+ windows as opacity changes cause flicker there.
*/
void FloatingBehavior::_focus_event (void)
{
@@ -93,42 +93,43 @@ void FloatingBehavior::_focus_event (void)
/** \brief Move the opacity of a window towards our goal
- This is a timer function that is set up by _focus_event to slightly
- move the opacity of the window along in an animated fashion. It moves
- the opacity half way to the goal until it runs out of steps, and then
- it just forces the goal.
+ This is a timer function that is set up by _focus_event to slightly
+ move the opacity of the window along in an animated fashion. It moves
+ the opacity half way to the goal until it runs out of steps, and then
+ it just forces the goal.
*/
bool FloatingBehavior::_trans_timer (void) {
- // printf("Go go gadget timer: %d\n", _steps);
- if (_steps == 0) {
- if (_dialog_active.get_value()) {
- _d->set_opacity(_trans_focus);
- } else {
- _d->set_opacity(_trans_blur);
- }
-
- return false;
- }
-
- float goal, current;
- goal = current = _d->get_opacity();
-
- if (_dialog_active.get_value()) {
- goal = _trans_focus;
- } else {
- goal = _trans_blur;
- }
-
- _d->set_opacity(current - ((current - goal) / 2));
- _steps--;
- return true;
+ // printf("Go go gadget timer: %d\n", _steps);
+ if (_steps == 0) {
+ if (_dialog_active.get_value()) {
+ _d->set_opacity(_trans_focus);
+ } else {
+ _d->set_opacity(_trans_blur);
+ }
+
+ return false;
+ }
+
+ float goal, current;
+ goal = current = _d->get_opacity();
+
+ if (_dialog_active.get_value()) {
+ goal = _trans_focus;
+ } else {
+ goal = _trans_blur;
+ }
+
+ _d->set_opacity(current - ((current - goal) / 2));
+ _steps--;
+ return true;
}
#endif
-FloatingBehavior::~FloatingBehavior()
-{
+FloatingBehavior::~FloatingBehavior()
+{
delete _d;
+ _d = 0;
}
Behavior *
@@ -184,9 +185,9 @@ FloatingBehavior::onDesktopActivated (SPDesktop *desktop)
#ifdef WIN32 // Win32 special code to enable transient dialogs
transient_policy = 2;
-#endif
+#endif
- if (!transient_policy)
+ if (!transient_policy)
return;
GtkWindow *dialog_win = GTK_WINDOW(_d->gobj());
diff --git a/src/ui/dialog/floating-behavior.h b/src/ui/dialog/floating-behavior.h
index 0360ccf49..30ecaa053 100644
--- a/src/ui/dialog/floating-behavior.h
+++ b/src/ui/dialog/floating-behavior.h
@@ -64,14 +64,14 @@ private:
Gtk::Dialog *_d; //< the actual dialog
#if GTK_VERSION_GE(2, 12)
- void _focus_event (void);
- bool _trans_timer (void);
-
- Glib::PropertyProxy_ReadOnly<bool> _dialog_active; //< Variable proxy to track whether the dialog is the active window
- int _steps; //< Number of steps for the timer to animate the transparent dialog
- float _trans_focus; //< The percentage opacity when the dialog is focused
- float _trans_blur; //< The percentage opactiy when the dialog is not focused
- int _trans_time; //< The amount of time (in ms) for the dialog to change it's transparency
+ void _focus_event (void);
+ bool _trans_timer (void);
+
+ Glib::PropertyProxy_ReadOnly<bool> _dialog_active; //< Variable proxy to track whether the dialog is the active window
+ int _steps; //< Number of steps for the timer to animate the transparent dialog
+ float _trans_focus; //< The percentage opacity when the dialog is focused
+ float _trans_blur; //< The percentage opactiy when the dialog is not focused
+ int _trans_time; //< The amount of time (in ms) for the dialog to change it's transparency
#endif
};
diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp
new file mode 100644
index 000000000..8ed502aae
--- /dev/null
+++ b/src/ui/dialog/glyphs.cpp
@@ -0,0 +1,749 @@
+/**
+ * Glyph selector dialog.
+ */
+
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2010 Jon A. Cruz
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <vector>
+
+#include <glibmm/i18n.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/iconview.h>
+#include <gtkmm/label.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/table.h>
+#include <gtkmm/treemodelcolumn.h>
+#include <gtkmm/widget.h>
+
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkversion.h>
+
+#include "glyphs.h"
+
+#include "desktop.h"
+#include "document.h" // for sp_document_done()
+#include "libnrtype/font-instance.h"
+#include "sp-flowtext.h"
+#include "sp-text.h"
+#include "verbs.h"
+#include "widgets/font-selector.h"
+#include "text-editing.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+GlyphsPanel &GlyphsPanel::getInstance()
+{
+ return *new GlyphsPanel();
+}
+
+
+#if GLIB_CHECK_VERSION(2,14,0)
+static std::map<GUnicodeScript, Glib::ustring> & getScriptToName()
+{
+ static bool init = false;
+ static std::map<GUnicodeScript, Glib::ustring> mappings;
+ if (!init) {
+ init = true;
+ mappings[G_UNICODE_SCRIPT_INVALID_CODE] = _("all");
+ mappings[G_UNICODE_SCRIPT_COMMON] = _("common");
+ mappings[G_UNICODE_SCRIPT_INHERITED] = _("inherited");
+ mappings[G_UNICODE_SCRIPT_ARABIC] = _("Arabic");
+ mappings[G_UNICODE_SCRIPT_ARMENIAN] = _("Armenian");
+ mappings[G_UNICODE_SCRIPT_BENGALI] = _("Bengali");
+ mappings[G_UNICODE_SCRIPT_BOPOMOFO] = _("Bopomofo");
+ mappings[G_UNICODE_SCRIPT_CHEROKEE] = _("Cherokee");
+ mappings[G_UNICODE_SCRIPT_COPTIC] = _("Coptic");
+ mappings[G_UNICODE_SCRIPT_CYRILLIC] = _("Cyrillic");
+ mappings[G_UNICODE_SCRIPT_DESERET] = _("Deseret");
+ mappings[G_UNICODE_SCRIPT_DEVANAGARI] = _("Devanagari");
+ mappings[G_UNICODE_SCRIPT_ETHIOPIC] = _("Ethiopic");
+ mappings[G_UNICODE_SCRIPT_GEORGIAN] = _("Georgian");
+ mappings[G_UNICODE_SCRIPT_GOTHIC] = _("Gothic");
+ mappings[G_UNICODE_SCRIPT_GREEK] = _("Greek");
+ mappings[G_UNICODE_SCRIPT_GUJARATI] = _("Gujarati");
+ mappings[G_UNICODE_SCRIPT_GURMUKHI] = _("Gurmukhi");
+ mappings[G_UNICODE_SCRIPT_HAN] = _("Han");
+ mappings[G_UNICODE_SCRIPT_HANGUL] = _("Hangul");
+ mappings[G_UNICODE_SCRIPT_HEBREW] = _("Hebrew");
+ mappings[G_UNICODE_SCRIPT_HIRAGANA] = _("Hiragana");
+ mappings[G_UNICODE_SCRIPT_KANNADA] = _("Kannada");
+ mappings[G_UNICODE_SCRIPT_KATAKANA] = _("Katakana");
+ mappings[G_UNICODE_SCRIPT_KHMER] = _("Khmer");
+ mappings[G_UNICODE_SCRIPT_LAO] = _("Lao");
+ mappings[G_UNICODE_SCRIPT_LATIN] = _("Latin");
+ mappings[G_UNICODE_SCRIPT_MALAYALAM] = _("Malayalam");
+ mappings[G_UNICODE_SCRIPT_MONGOLIAN] = _("Mongolian");
+ mappings[G_UNICODE_SCRIPT_MYANMAR] = _("Myanmar");
+ mappings[G_UNICODE_SCRIPT_OGHAM] = _("Ogham");
+ mappings[G_UNICODE_SCRIPT_OLD_ITALIC] = _("Old Italic");
+ mappings[G_UNICODE_SCRIPT_ORIYA] = _("Oriya");
+ mappings[G_UNICODE_SCRIPT_RUNIC] = _("Runic");
+ mappings[G_UNICODE_SCRIPT_SINHALA] = _("Sinhala");
+ mappings[G_UNICODE_SCRIPT_SYRIAC] = _("Syriac");
+ mappings[G_UNICODE_SCRIPT_TAMIL] = _("Tamil");
+ mappings[G_UNICODE_SCRIPT_TELUGU] = _("Telugu");
+ mappings[G_UNICODE_SCRIPT_THAANA] = _("Thaana");
+ mappings[G_UNICODE_SCRIPT_THAI] = _("Thai");
+ mappings[G_UNICODE_SCRIPT_TIBETAN] = _("Tibetan");
+ mappings[G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL] = _("Canadian Aboriginal");
+ mappings[G_UNICODE_SCRIPT_YI] = _("Yi");
+ mappings[G_UNICODE_SCRIPT_TAGALOG] = _("Tagalog");
+ mappings[G_UNICODE_SCRIPT_HANUNOO] = _("Hanunoo");
+ mappings[G_UNICODE_SCRIPT_BUHID] = _("Buhid");
+ mappings[G_UNICODE_SCRIPT_TAGBANWA] = _("Tagbanwa");
+ mappings[G_UNICODE_SCRIPT_BRAILLE] = _("Braille");
+ mappings[G_UNICODE_SCRIPT_CYPRIOT] = _("Cypriot");
+ mappings[G_UNICODE_SCRIPT_LIMBU] = _("Limbu");
+ mappings[G_UNICODE_SCRIPT_OSMANYA] = _("Osmanya");
+ mappings[G_UNICODE_SCRIPT_SHAVIAN] = _("Shavian");
+ mappings[G_UNICODE_SCRIPT_LINEAR_B] = _("Linear B");
+ mappings[G_UNICODE_SCRIPT_TAI_LE] = _("Tai Le");
+ mappings[G_UNICODE_SCRIPT_UGARITIC] = _("Ugaritic");
+ mappings[G_UNICODE_SCRIPT_NEW_TAI_LUE] = _("New Tai Lue");
+ mappings[G_UNICODE_SCRIPT_BUGINESE] = _("Buginese");
+ mappings[G_UNICODE_SCRIPT_GLAGOLITIC] = _("Glagolitic");
+ mappings[G_UNICODE_SCRIPT_TIFINAGH] = _("Tifinagh");
+ mappings[G_UNICODE_SCRIPT_SYLOTI_NAGRI] = _("Syloti Nagri");
+ mappings[G_UNICODE_SCRIPT_OLD_PERSIAN] = _("Old Persian");
+ mappings[G_UNICODE_SCRIPT_KHAROSHTHI] = _("Kharoshthi");
+ mappings[G_UNICODE_SCRIPT_UNKNOWN] = _("unassigned");
+ mappings[G_UNICODE_SCRIPT_BALINESE] = _("Balinese");
+ mappings[G_UNICODE_SCRIPT_CUNEIFORM] = _("Cuneiform");
+ mappings[G_UNICODE_SCRIPT_PHOENICIAN] = _("Phoenician");
+ mappings[G_UNICODE_SCRIPT_PHAGS_PA] = _("Phags-pa");
+ mappings[G_UNICODE_SCRIPT_NKO] = _("N'Ko");
+
+#if GLIB_CHECK_VERSION(2,14,0)
+ mappings[G_UNICODE_SCRIPT_KAYAH_LI] = _("Kayah Li");
+ mappings[G_UNICODE_SCRIPT_LEPCHA] = _("Lepcha");
+ mappings[G_UNICODE_SCRIPT_REJANG] = _("Rejang");
+ mappings[G_UNICODE_SCRIPT_SUNDANESE] = _("Sundanese");
+ mappings[G_UNICODE_SCRIPT_SAURASHTRA] = _("Saurashtra");
+ mappings[G_UNICODE_SCRIPT_CHAM] = _("Cham");
+ mappings[G_UNICODE_SCRIPT_OL_CHIKI] = _("Ol Chiki");
+ mappings[G_UNICODE_SCRIPT_VAI] = _("Vai");
+ mappings[G_UNICODE_SCRIPT_CARIAN] = _("Carian");
+ mappings[G_UNICODE_SCRIPT_LYCIAN] = _("Lycian");
+ mappings[G_UNICODE_SCRIPT_LYDIAN] = _("Lydian");
+#endif // GLIB_CHECK_VERSION(2,14,0)
+ }
+ return mappings;
+}
+#endif // GLIB_CHECK_VERSION(2,14,0)
+
+typedef std::pair<gunichar, gunichar> Range;
+typedef std::pair<Range, Glib::ustring> NamedRange;
+
+static std::vector<NamedRange> & getRanges()
+{
+ static bool init = false;
+ static std::vector<NamedRange> ranges;
+ if (!init) {
+ init = true;
+ ranges.push_back(std::make_pair(std::make_pair(0x0000, 0xFFFD), _("all")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0000, 0x007F), _("Basic Latin")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0080, 0x00FF), _("Latin-1 Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0100, 0x017F), _("Latin Extended-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0180, 0x024F), _("Latin Extended-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0250, 0x02AF), _("IPA Extensions")));
+ ranges.push_back(std::make_pair(std::make_pair(0x02B0, 0x02FF), _("Spacing Modifier Letters")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0300, 0x036F), _("Combining Diacritical Marks")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0370, 0x03FF), _("Greek and Coptic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0400, 0x04FF), _("Cyrillic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0500, 0x052F), _("Cyrillic Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0530, 0x058F), _("Armenian")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0590, 0x05FF), _("Hebrew")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0600, 0x06FF), _("Arabic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0700, 0x074F), _("Syriac")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0750, 0x077F), _("Arabic Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0780, 0x07BF), _("Thaana")));
+ ranges.push_back(std::make_pair(std::make_pair(0x07C0, 0x07FF), _("NKo")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0800, 0x083F), _("Samaritan")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0900, 0x097F), _("Devanagari")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0980, 0x09FF), _("Bengali")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0A00, 0x0A7F), _("Gurmukhi")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0A80, 0x0AFF), _("Gujarati")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0B00, 0x0B7F), _("Oriya")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0B80, 0x0BFF), _("Tamil")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0C00, 0x0C7F), _("Telugu")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0C80, 0x0CFF), _("Kannada")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0D00, 0x0D7F), _("Malayalam")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0D80, 0x0DFF), _("Sinhala")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0E00, 0x0E7F), _("Thai")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0E80, 0x0EFF), _("Lao")));
+ ranges.push_back(std::make_pair(std::make_pair(0x0F00, 0x0FFF), _("Tibetan")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1000, 0x109F), _("Myanmar")));
+ ranges.push_back(std::make_pair(std::make_pair(0x10A0, 0x10FF), _("Georgian")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1100, 0x11FF), _("Hangul Jamo")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1200, 0x137F), _("Ethiopic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1380, 0x139F), _("Ethiopic Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x13A0, 0x13FF), _("Cherokee")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1400, 0x167F), _("Unified Canadian Aboriginal Syllabics")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1680, 0x169F), _("Ogham")));
+ ranges.push_back(std::make_pair(std::make_pair(0x16A0, 0x16FF), _("Runic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1700, 0x171F), _("Tagalog")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1720, 0x173F), _("Hanunoo")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1740, 0x175F), _("Buhid")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1760, 0x177F), _("Tagbanwa")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1780, 0x17FF), _("Khmer")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1800, 0x18AF), _("Mongolian")));
+ ranges.push_back(std::make_pair(std::make_pair(0x18B0, 0x18FF), _("Unified Canadian Aboriginal Syllabics Extended")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1900, 0x194F), _("Limbu")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1950, 0x197F), _("Tai Le")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1980, 0x19DF), _("New Tai Lue")));
+ ranges.push_back(std::make_pair(std::make_pair(0x19E0, 0x19FF), _("Khmer Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1A00, 0x1A1F), _("Buginese")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1A20, 0x1AAF), _("Tai Tham")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1B00, 0x1B7F), _("Balinese")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1B80, 0x1BBF), _("Sundanese")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1C00, 0x1C4F), _("Lepcha")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1C50, 0x1C7F), _("Ol Chiki")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1CD0, 0x1CFF), _("Vedic Extensions")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1D00, 0x1D7F), _("Phonetic Extensions")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1D80, 0x1DBF), _("Phonetic Extensions Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1DC0, 0x1DFF), _("Combining Diacritical Marks Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1E00, 0x1EFF), _("Latin Extended Additional")));
+ ranges.push_back(std::make_pair(std::make_pair(0x1F00, 0x1FFF), _("Greek Extended")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2000, 0x206F), _("General Punctuation")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2070, 0x209F), _("Superscripts and Subscripts")));
+ ranges.push_back(std::make_pair(std::make_pair(0x20A0, 0x20CF), _("Currency Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x20D0, 0x20FF), _("Combining Diacritical Marks for Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2100, 0x214F), _("Letterlike Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2150, 0x218F), _("Number Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2190, 0x21FF), _("Arrows")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2200, 0x22FF), _("Mathematical Operators")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2300, 0x23FF), _("Miscellaneous Technical")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2400, 0x243F), _("Control Pictures")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2440, 0x245F), _("Optical Character Recognition")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2460, 0x24FF), _("Enclosed Alphanumerics")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2500, 0x257F), _("Box Drawing")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2580, 0x259F), _("Block Elements")));
+ ranges.push_back(std::make_pair(std::make_pair(0x25A0, 0x25FF), _("Geometric Shapes")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2600, 0x26FF), _("Miscellaneous Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2700, 0x27BF), _("Dingbats")));
+ ranges.push_back(std::make_pair(std::make_pair(0x27C0, 0x27EF), _("Miscellaneous Mathematical Symbols-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0x27F0, 0x27FF), _("Supplemental Arrows-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2800, 0x28FF), _("Braille Patterns")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2900, 0x297F), _("Supplemental Arrows-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2980, 0x29FF), _("Miscellaneous Mathematical Symbols-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2A00, 0x2AFF), _("Supplemental Mathematical Operators")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2B00, 0x2BFF), _("Miscellaneous Symbols and Arrows")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2C00, 0x2C5F), _("Glagolitic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2C60, 0x2C7F), _("Latin Extended-C")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2C80, 0x2CFF), _("Coptic")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2D00, 0x2D2F), _("Georgian Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2D30, 0x2D7F), _("Tifinagh")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2D80, 0x2DDF), _("Ethiopic Extended")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2DE0, 0x2DFF), _("Cyrillic Extended-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2E00, 0x2E7F), _("Supplemental Punctuation")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2E80, 0x2EFF), _("CJK Radicals Supplement")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2F00, 0x2FDF), _("Kangxi Radicals")));
+ ranges.push_back(std::make_pair(std::make_pair(0x2FF0, 0x2FFF), _("Ideographic Description Characters")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3000, 0x303F), _("CJK Symbols and Punctuation")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3040, 0x309F), _("Hiragana")));
+ ranges.push_back(std::make_pair(std::make_pair(0x30A0, 0x30FF), _("Katakana")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3100, 0x312F), _("Bopomofo")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3130, 0x318F), _("Hangul Compatibility Jamo")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3190, 0x319F), _("Kanbun")));
+ ranges.push_back(std::make_pair(std::make_pair(0x31A0, 0x31BF), _("Bopomofo Extended")));
+ ranges.push_back(std::make_pair(std::make_pair(0x31C0, 0x31EF), _("CJK Strokes")));
+ ranges.push_back(std::make_pair(std::make_pair(0x31F0, 0x31FF), _("Katakana Phonetic Extensions")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3200, 0x32FF), _("Enclosed CJK Letters and Months")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3300, 0x33FF), _("CJK Compatibility")));
+ ranges.push_back(std::make_pair(std::make_pair(0x3400, 0x4DBF), _("CJK Unified Ideographs Extension A")));
+ ranges.push_back(std::make_pair(std::make_pair(0x4DC0, 0x4DFF), _("Yijing Hexagram Symbols")));
+ ranges.push_back(std::make_pair(std::make_pair(0x4E00, 0x9FFF), _("CJK Unified Ideographs")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA000, 0xA48F), _("Yi Syllables")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA490, 0xA4CF), _("Yi Radicals")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA4D0, 0xA4FF), _("Lisu")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA500, 0xA63F), _("Vai")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA640, 0xA69F), _("Cyrillic Extended-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA6A0, 0xA6FF), _("Bamum")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA700, 0xA71F), _("Modifier Tone Letters")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA720, 0xA7FF), _("Latin Extended-D")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA800, 0xA82F), _("Syloti Nagri")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA830, 0xA83F), _("Common Indic Number Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA840, 0xA87F), _("Phags-pa")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA880, 0xA8DF), _("Saurashtra")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA8E0, 0xA8FF), _("Devanagari Extended")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA900, 0xA92F), _("Kayah Li")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA930, 0xA95F), _("Rejang")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA960, 0xA97F), _("Hangul Jamo Extended-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0xA980, 0xA9DF), _("Javanese")));
+ ranges.push_back(std::make_pair(std::make_pair(0xAA00, 0xAA5F), _("Cham")));
+ ranges.push_back(std::make_pair(std::make_pair(0xAA60, 0xAA7F), _("Myanmar Extended-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0xAA80, 0xAADF), _("Tai Viet")));
+ ranges.push_back(std::make_pair(std::make_pair(0xABC0, 0xABFF), _("Meetei Mayek")));
+ ranges.push_back(std::make_pair(std::make_pair(0xAC00, 0xD7AF), _("Hangul Syllables")));
+ ranges.push_back(std::make_pair(std::make_pair(0xD7B0, 0xD7FF), _("Hangul Jamo Extended-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0xD800, 0xDB7F), _("High Surrogates")));
+ ranges.push_back(std::make_pair(std::make_pair(0xDB80, 0xDBFF), _("High Private Use Surrogates")));
+ ranges.push_back(std::make_pair(std::make_pair(0xDC00, 0xDFFF), _("Low Surrogates")));
+ ranges.push_back(std::make_pair(std::make_pair(0xE000, 0xF8FF), _("Private Use Area")));
+ ranges.push_back(std::make_pair(std::make_pair(0xF900, 0xFAFF), _("CJK Compatibility Ideographs")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFB00, 0xFB4F), _("Alphabetic Presentation Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFB50, 0xFDFF), _("Arabic Presentation Forms-A")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE00, 0xFE0F), _("Variation Selectors")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE10, 0xFE1F), _("Vertical Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE20, 0xFE2F), _("Combining Half Marks")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE30, 0xFE4F), _("CJK Compatibility Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE50, 0xFE6F), _("Small Form Variants")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFE70, 0xFEFF), _("Arabic Presentation Forms-B")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFF00, 0xFFEF), _("Halfwidth and Fullwidth Forms")));
+ ranges.push_back(std::make_pair(std::make_pair(0xFFF0, 0xFFFF), _("Specials")));
+ }
+
+ return ranges;
+}
+
+class GlyphColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+ Gtk::TreeModelColumn<gunichar> code;
+ Gtk::TreeModelColumn<Glib::ustring> name;
+
+ GlyphColumns()
+ {
+ add(code);
+ add(name);
+ }
+};
+
+GlyphColumns *GlyphsPanel::getColumns()
+{
+ static GlyphColumns *columns = new GlyphColumns();
+
+ return columns;
+}
+
+/**
+ * Constructor
+ */
+GlyphsPanel::GlyphsPanel(gchar const *prefsPath) :
+ Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_GLYPHS, "", false),
+ store(Gtk::ListStore::create(*getColumns())),
+ iconView(0),
+ entry(0),
+ label(0),
+ insertBtn(0),
+#if GLIB_CHECK_VERSION(2,14,0)
+ scriptCombo(0),
+#endif // GLIB_CHECK_VERSION(2,14,0)
+ fsel(0),
+ targetDesktop(0),
+ deskTrack(),
+ instanceConns(),
+ desktopConns()
+{
+ Gtk::Table *table = new Gtk::Table(3, 1, false);
+ _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET);
+ guint row = 0;
+
+// -------------------------------
+
+ GtkWidget *fontsel = sp_font_selector_new();
+ fsel = SP_FONT_SELECTOR(fontsel);
+ sp_font_selector_set_font(fsel, sp_font_selector_get_font(fsel), 12.0);
+
+ g_signal_connect( G_OBJECT(fontsel), "font_set", G_CALLBACK(fontChangeCB), this );
+
+ table->attach(*Gtk::manage(Glib::wrap(fontsel)),
+ 0, 3, row, row + 1,
+ Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL);
+ row++;
+
+
+// -------------------------------
+
+#if GLIB_CHECK_VERSION(2,14,0)
+ {
+ Gtk::Label *label = new Gtk::Label(_("Script: "));
+ table->attach( *Gtk::manage(label),
+ 0, 1, row, row + 1,
+ Gtk::SHRINK, Gtk::SHRINK);
+
+ scriptCombo = new Gtk::ComboBoxText();
+ for (std::map<GUnicodeScript, Glib::ustring>::iterator it = getScriptToName().begin(); it != getScriptToName().end(); ++it)
+ {
+ scriptCombo->append_text(it->second);
+ }
+
+ scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]);
+ sigc::connection conn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild));
+ instanceConns.push_back(conn);
+
+ Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0);
+ align->add(*Gtk::manage(scriptCombo));
+ table->attach( *Gtk::manage(align),
+ 1, 2, row, row + 1,
+ Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+ }
+
+ row++;
+#endif // GLIB_CHECK_VERSION(2,14,0)
+
+// -------------------------------
+
+ {
+ Gtk::Label *label = new Gtk::Label(_("Range: "));
+ table->attach( *Gtk::manage(label),
+ 0, 1, row, row + 1,
+ Gtk::SHRINK, Gtk::SHRINK);
+
+ rangeCombo = new Gtk::ComboBoxText();
+ for ( std::vector<NamedRange>::iterator it = getRanges().begin(); it != getRanges().end(); ++it ) {
+ rangeCombo->append_text(it->second);
+ }
+
+ rangeCombo->set_active_text(getRanges()[1].second);
+ sigc::connection conn = rangeCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild));
+ instanceConns.push_back(conn);
+
+ Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0);
+ align->add(*Gtk::manage(rangeCombo));
+ table->attach( *Gtk::manage(align),
+ 1, 2, row, row + 1,
+ Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+ }
+
+ row++;
+
+// -------------------------------
+
+ GlyphColumns *columns = getColumns();
+
+ iconView = new Gtk::IconView(store);
+ iconView->set_text_column(columns->name);
+ //iconView->set_columns(16);
+
+ sigc::connection conn;
+ conn = iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated));
+ instanceConns.push_back(conn);
+ conn = iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged));
+ instanceConns.push_back(conn);
+
+
+ Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow();
+ scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
+ scroller->add(*Gtk::manage(iconView));
+ table->attach(*Gtk::manage(scroller),
+ 0, 3, row, row + 1,
+ Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL);
+ row++;
+
+// -------------------------------
+
+ Gtk::HBox *box = new Gtk::HBox();
+
+ entry = new Gtk::Entry();
+ conn = entry->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::calcCanInsert));
+ instanceConns.push_back(conn);
+ entry->set_width_chars(18);
+ box->pack_start(*Gtk::manage(entry), Gtk::PACK_SHRINK);
+
+ Gtk::Label *pad = new Gtk::Label(" ");
+ box->pack_start(*Gtk::manage(pad), Gtk::PACK_SHRINK);
+
+ label = new Gtk::Label(" ");
+ box->pack_start(*Gtk::manage(label), Gtk::PACK_SHRINK);
+
+ pad = new Gtk::Label("");
+ box->pack_start(*Gtk::manage(pad), Gtk::PACK_EXPAND_WIDGET);
+
+ insertBtn = new Gtk::Button(_("Append"));
+ conn = insertBtn->signal_clicked().connect(sigc::mem_fun(*this, &GlyphsPanel::insertText));
+ instanceConns.push_back(conn);
+#if GTK_CHECK_VERSION(2,18,0)
+ //gtkmm 2.18
+ insertBtn->set_can_default();
+#endif
+ insertBtn->set_sensitive(false);
+
+ box->pack_end(*Gtk::manage(insertBtn), Gtk::PACK_SHRINK);
+
+ table->attach( *Gtk::manage(box),
+ 0, 3, row, row + 1,
+ Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
+ row++;
+
+// -------------------------------
+
+
+ show_all_children();
+
+ restorePanelPrefs();
+
+ // Connect this up last
+ conn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &GlyphsPanel::setTargetDesktop) );
+ instanceConns.push_back(conn);
+ deskTrack.connect(GTK_WIDGET(gobj()));
+}
+
+GlyphsPanel::~GlyphsPanel()
+{
+ for (std::vector<sigc::connection>::iterator it = instanceConns.begin(); it != instanceConns.end(); ++it) {
+ it->disconnect();
+ }
+ instanceConns.clear();
+ for (std::vector<sigc::connection>::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) {
+ it->disconnect();
+ }
+ desktopConns.clear();
+}
+
+
+void GlyphsPanel::setDesktop(SPDesktop *desktop)
+{
+ Panel::setDesktop(desktop);
+ deskTrack.setBase(desktop);
+}
+
+void GlyphsPanel::setTargetDesktop(SPDesktop *desktop)
+{
+ if (targetDesktop != desktop) {
+ if (targetDesktop) {
+ for (std::vector<sigc::connection>::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) {
+ it->disconnect();
+ }
+ desktopConns.clear();
+ }
+
+ targetDesktop = desktop;
+
+ if (targetDesktop && targetDesktop->selection) {
+ sigc::connection conn = desktop->selection->connectChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, true)));
+ desktopConns.push_back(conn);
+
+ // Text selection within selected items has changed:
+ conn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, false)));
+ desktopConns.push_back(conn);
+
+ // Must check flags, so can't call performUpdate() directly.
+ conn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &GlyphsPanel::selectionModifiedCB)));
+ desktopConns.push_back(conn);
+
+ readSelection(true, true);
+ }
+ }
+}
+
+void GlyphsPanel::insertText()
+{
+ SPItem *textItem = 0;
+ for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
+ if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
+ textItem = SP_ITEM(item->data);
+ break;
+ }
+ }
+
+ if (textItem) {
+ Glib::ustring glyphs;
+ if (entry->get_text_length() > 0) {
+ glyphs = entry->get_text();
+ } else {
+ Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items();
+ if (!itemArray.empty()) {
+ Gtk::TreeModel::Path const & path = *itemArray.begin();
+ Gtk::ListStore::iterator row = store->get_iter(path);
+ gunichar ch = (*row)[getColumns()->code];
+ glyphs = ch;
+ }
+ }
+
+ if (!glyphs.empty()) {
+ Glib::ustring combined;
+ gchar *str = sp_te_get_string_multiline(textItem);
+ if (str) {
+ combined = str;
+ g_free(str);
+ str = 0;
+ }
+ combined += glyphs;
+ sp_te_set_repr_text_multiline(textItem, combined.c_str());
+ sp_document_done(targetDesktop->doc(), SP_VERB_CONTEXT_TEXT, _("Append text"));
+ }
+ }
+}
+
+void GlyphsPanel::glyphActivated(Gtk::TreeModel::Path const & path)
+{
+ Gtk::ListStore::iterator row = store->get_iter(path);
+ gunichar ch = (*row)[getColumns()->code];
+ Glib::ustring tmp;
+ tmp += ch;
+
+ int startPos = 0;
+ int endPos = 0;
+ if (entry->get_selection_bounds(startPos, endPos)) {
+ // there was something selected.
+ entry->delete_text(startPos, endPos);
+ }
+ startPos = entry->get_position();
+ entry->insert_text(tmp, -1, startPos);
+ entry->set_position(startPos);
+}
+
+void GlyphsPanel::glyphSelectionChanged()
+{
+ Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items();
+ if (itemArray.empty()) {
+ label->set_text(" ");
+ } else {
+ Gtk::TreeModel::Path const & path = *itemArray.begin();
+ Gtk::ListStore::iterator row = store->get_iter(path);
+ gunichar ch = (*row)[getColumns()->code];
+
+
+ Glib::ustring scriptName;
+#if GLIB_CHECK_VERSION(2,14,0)
+ GUnicodeScript script = g_unichar_get_script(ch);
+ std::map<GUnicodeScript, Glib::ustring> mappings = getScriptToName();
+ if (mappings.find(script) != mappings.end()) {
+ scriptName = mappings[script];
+ }
+#endif
+ gchar * tmp = g_strdup_printf("U+%04X %s", ch, scriptName.c_str());
+ label->set_text(tmp);
+ }
+ calcCanInsert();
+}
+
+void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*font*/, GlyphsPanel *self)
+{
+ if (self) {
+ self->rebuild();
+ }
+}
+
+void GlyphsPanel::selectionModifiedCB(guint flags)
+{
+ bool style = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG )) != 0 );
+
+ bool content = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG |
+ SP_TEXT_CONTENT_MODIFIED_FLAG )) != 0 );
+
+ readSelection(style, content);
+}
+
+void GlyphsPanel::calcCanInsert()
+{
+ int items = 0;
+ for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
+ if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
+ ++items;
+ }
+ }
+
+ bool enable = (items == 1);
+ if (enable) {
+ enable &= (!iconView->get_selected_items().empty()
+ || (entry->get_text_length() > 0));
+ }
+
+ if (enable != insertBtn->is_sensitive()) {
+ insertBtn->set_sensitive(enable);
+ }
+}
+
+void GlyphsPanel::readSelection( bool updateStyle, bool /*updateContent*/ )
+{
+ calcCanInsert();
+
+ if (targetDesktop && updateStyle) {
+ //SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT);
+
+ //int result_family = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ //int result_style = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ //int result_numbers = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+
+ //sp_style_unref(query);
+ }
+}
+
+
+void GlyphsPanel::rebuild()
+{
+ font_instance *font = fsel ? sp_font_selector_get_font(fsel) : 0;
+ if (font) {
+ //double sp_font_selector_get_size (SPFontSelector *fsel);
+
+#if GLIB_CHECK_VERSION(2,14,0)
+ GUnicodeScript script = G_UNICODE_SCRIPT_INVALID_CODE;
+ Glib::ustring scriptName = scriptCombo->get_active_text();
+ std::map<GUnicodeScript, Glib::ustring> items = getScriptToName();
+ for (std::map<GUnicodeScript, Glib::ustring>::iterator it = items.begin(); it != items.end(); ++it) {
+ if (scriptName == it->second) {
+ script = it->first;
+ break;
+ }
+ }
+#endif // GLIB_CHECK_VERSION(2,14,0)
+
+ // Disconnect the model while we update it. Simple work-around for 5x+ performance boost.
+ Glib::RefPtr<Gtk::ListStore> tmp = Gtk::ListStore::create(*getColumns());
+ iconView->set_model(tmp);
+
+ gunichar lower = 0x0001;
+ gunichar upper = 0xFFFD;
+ int active = rangeCombo->get_active_row_number();
+ if (active >= 0) {
+ lower = getRanges()[active].first.first;
+ upper = getRanges()[active].first.second;
+ }
+ std::vector<gunichar> present;
+ for (gunichar ch = lower; ch <= upper; ch++) {
+ int glyphId = font->MapUnicodeChar(ch);
+ if (glyphId > 0) {
+#if GLIB_CHECK_VERSION(2,14,0)
+ if ((script == G_UNICODE_SCRIPT_INVALID_CODE) || (script == g_unichar_get_script(ch))) {
+ present.push_back(ch);
+ }
+#else
+ present.push_back(ch);
+#endif
+ }
+ }
+
+ GlyphColumns *columns = getColumns();
+ store->clear();
+ for (std::vector<gunichar>::iterator it = present.begin(); it != present.end(); ++it)
+ {
+ Gtk::ListStore::iterator row = store->append();
+ Glib::ustring tmp;
+ tmp += *it;
+ (*row)[columns->code] = *it;
+ (*row)[columns->name] = tmp;
+ }
+
+ // Reconnect the model once it has been updated:
+ iconView->set_model(store);
+ }
+}
+
+
+} // namespace Dialogs
+} // namespace UI
+} // 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/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h
new file mode 100644
index 000000000..1a01aebca
--- /dev/null
+++ b/src/ui/dialog/glyphs.h
@@ -0,0 +1,107 @@
+/**
+ * Glyph selector dialog.
+ */
+
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2010 Jon A. Cruz
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef SEEN_DIALOGS_GLYPHS_H
+#define SEEN_DIALOGS_GLYPHS_H
+
+#include <gtkmm/treemodel.h>
+#include "ui/widget/panel.h"
+#include "ui/dialog/desktop-tracker.h"
+
+
+namespace Gtk {
+class ComboBoxText;
+class Entry;
+class IconView;
+class Label;
+class ListStore;
+}
+
+class SPFontSelector;
+class font_instance;
+
+
+namespace Inkscape {
+namespace UI {
+
+class PreviewHolder;
+
+namespace Dialog {
+
+class GlyphColumns;
+
+/**
+ * A panel that displays character glyphs.
+ */
+
+class GlyphsPanel : public Inkscape::UI::Widget::Panel
+{
+public:
+ GlyphsPanel(gchar const *prefsPath = "/dialogs/glyphs");
+ virtual ~GlyphsPanel();
+
+ static GlyphsPanel& getInstance();
+
+ virtual void setDesktop(SPDesktop *desktop);
+
+protected:
+
+private:
+ GlyphsPanel(GlyphsPanel const &); // no copy
+ GlyphsPanel &operator=(GlyphsPanel const &); // no assign
+
+ static GlyphColumns *getColumns();
+
+ static void fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self);
+
+ void rebuild();
+
+ void glyphActivated(Gtk::TreeModel::Path const & path);
+ void glyphSelectionChanged();
+ void setTargetDesktop(SPDesktop *desktop);
+ void selectionModifiedCB(guint flags);
+ void readSelection( bool updateStyle, bool updateContent );
+ void calcCanInsert();
+ void insertText();
+
+
+ Glib::RefPtr<Gtk::ListStore> store;
+ Gtk::IconView *iconView;
+ Gtk::Entry *entry;
+ Gtk::Label *label;
+ Gtk::Button *insertBtn;
+#if GLIB_CHECK_VERSION(2,14,0)
+ Gtk::ComboBoxText *scriptCombo;
+#endif //GLIB_CHECK_VERSION(2,14,0)
+ Gtk::ComboBoxText *rangeCombo;
+ SPFontSelector *fsel;
+ SPDesktop *targetDesktop;
+ DesktopTracker deskTrack;
+
+ std::vector<sigc::connection> instanceConns;
+ std::vector<sigc::connection> desktopConns;
+};
+
+
+} // namespace Dialogs
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_DIALOGS_GLYPHS_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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index 088f63031..a210fe163 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -45,14 +45,13 @@ namespace UI {
namespace Dialogs {
-IconPreviewPanel&
-IconPreviewPanel::getInstance()
+IconPreviewPanel &IconPreviewPanel::getInstance()
{
- static IconPreviewPanel &instance = *new IconPreviewPanel();
+ IconPreviewPanel *instance = new IconPreviewPanel();
- instance.refreshPreview();
+ instance->refreshPreview();
- return instance;
+ return *instance;
}
//#########################################################################
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 40efc8282..96f0a0f6e 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -56,6 +56,13 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
+using Inkscape::UI::Widget::DialogPage;
+using Inkscape::UI::Widget::PrefCheckButton;
+using Inkscape::UI::Widget::PrefRadioButton;
+using Inkscape::UI::Widget::PrefSpinButton;
+using Inkscape::UI::Widget::StyleSwatch;
+
+
InkscapePreferences::InkscapePreferences()
: UI::Widget::Panel ("", "/dialogs/preferences", SP_VERB_DIALOG_DISPLAY),
_max_dialog_width(0),
@@ -205,10 +212,10 @@ void InkscapePreferences::initPageScrolling()
_("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false);
_scroll_space.init ( _("Left mouse button pans when Space is pressed"), "/options/spacepans/value", false);
_page_scrolling.add_line( false, "", _scroll_space, "",
- _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator). When off, Space temporarily switches to Selector tool (default)."));
+ _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator); when off, Space temporarily switches to Selector tool (default)"));
_wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false);
_page_scrolling.add_line( false, "", _wheel_zoom, "",
- _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl."));
+ _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl"));
}
void InkscapePreferences::initPageSnapping()
@@ -284,7 +291,7 @@ void InkscapePreferences::AddGradientCheckbox(DialogPage &p, Glib::ustring const
void InkscapePreferences::AddConvertGuidesCheckbox(DialogPage &p, Glib::ustring const &prefs_path, bool def_value) {
PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
cb->init ( _("Conversion to guides uses edges instead of bounding box"), prefs_path + "/convertguides", def_value);
- p.add_line( false, "", *cb, "", _("Converting an object to guides places these along the object's true edges (imitating the object's shape), not along the bounding box."));
+ p.add_line( false, "", *cb, "", _("Converting an object to guides places these along the object's true edges (imitating the object's shape), not along the bounding box"));
}
void InkscapePreferences::AddDotSizeSpinbutton(DialogPage &p, Glib::ustring const &prefs_path, double def_value)
@@ -397,10 +404,10 @@ void InkscapePreferences::initPageTools()
_page_tools.add_group_header( _("Conversion to guides:"));
_t_cvg_keep_objects.init ( _("Keep objects after conversion to guides"), "/tools/cvg_keep_objects", false);
_page_tools.add_line( true, "", _t_cvg_keep_objects, "",
- _("When converting an object to guides, don't delete the object after the conversion."));
+ _("When converting an object to guides, don't delete the object after the conversion"));
_t_cvg_convert_whole_groups.init ( _("Treat groups as a single object"), "/tools/cvg_convert_whole_groups", false);
_page_tools.add_line( true, "", _t_cvg_convert_whole_groups, "",
- _("Treat groups as a single object during conversion to guides rather than converting each child separately."));
+ _("Treat groups as a single object during conversion to guides rather than converting each child separately"));
_pencil_average_all_sketches.init ( _("Average all sketches"), "/tools/freehand/pencil/average_all_sketches", false);
_calligrapy_use_abs_size.init ( _("Width is in absolute units"), "/tools/calligraphic/abs_width", false);
@@ -435,26 +442,26 @@ void InkscapePreferences::initPageTools()
AddGradientCheckbox(_page_node, "/tools/nodes", true);
_page_node.add_group_header( _("Path outline"));
_t_node_pathoutline_color.init(_("Path outline color"), "/tools/nodes/highlight_color", 0xff0000ff);
- _page_node.add_line( false, "", _t_node_pathoutline_color, "", _("Selects the color used for showing the path outline."), false);
+ _page_node.add_line( false, "", _t_node_pathoutline_color, "", _("Selects the color used for showing the path outline"), false);
_t_node_show_outline.init(_("Always show outline"), "/tools/nodes/show_outline", false);
_page_node.add_line( true, "", _t_node_show_outline, "", _("Show outlines for all paths, not only invisible paths"));
_t_node_live_outline.init(_("Update outline when dragging nodes"), "/tools/nodes/live_outline", false);
- _page_node.add_line( true, "", _t_node_live_outline, "", _("Update the outline when dragging or transforming nodes. If this is off, the outline will only update when completing a drag."));
+ _page_node.add_line( true, "", _t_node_live_outline, "", _("Update the outline when dragging or transforming nodes; if this is off, the outline will only update when completing a drag"));
_t_node_live_objects.init(_("Update paths when dragging nodes"), "/tools/nodes/live_objects", false);
- _page_node.add_line( true, "", _t_node_live_objects, "", _("Update paths when dragging or transforming nodes. If this is off, paths will only be updated when completing a drag."));
+ _page_node.add_line( true, "", _t_node_live_objects, "", _("Update paths when dragging or transforming nodes; if this is off, paths will only be updated when completing a drag"));
_t_node_show_path_direction.init(_("Show path direction on outlines"), "/tools/nodes/show_path_direction", false);
_page_node.add_line( true, "", _t_node_show_path_direction, "", _("Visualize the direction of selected paths by drawing small arrows in the middle of each outline segment"));
_t_node_pathflash_enabled.init ( _("Show temporary path outline"), "/tools/nodes/pathflash_enabled", false);
- _page_node.add_line( true, "", _t_node_pathflash_enabled, "", _("When hovering over a path, briefly flash its outline."));
+ _page_node.add_line( true, "", _t_node_pathflash_enabled, "", _("When hovering over a path, briefly flash its outline"));
_t_node_pathflash_selected.init ( _("Show temporary outline for selected paths"), "/tools/nodes/pathflash_selected", false);
_page_node.add_line( true, "", _t_node_pathflash_selected, "", _("Show temporary outline even when a path is selected for editing"));
_t_node_pathflash_timeout.init("/tools/nodes/pathflash_timeout", 0, 10000.0, 100.0, 100.0, 1000.0, true, false);
- _page_node.add_line( false, _("Flash time"), _t_node_pathflash_timeout, "ms", _("Specifies how long the path outline will be visible after a mouse-over (in milliseconds). Specify 0 to have the outline shown until mouse leaves the path."), false);
+ _page_node.add_line( false, _("Flash time"), _t_node_pathflash_timeout, "ms", _("Specifies how long the path outline will be visible after a mouse-over (in milliseconds); specify 0 to have the outline shown until mouse leaves the path"), false);
_page_node.add_group_header(_("Editing preferences"));
_t_node_single_node_transform_handles.init(_("Show transform handles for single nodes"), "/tools/nodes/single_node_transform_handles", false);
- _page_node.add_line( true, "", _t_node_single_node_transform_handles, "", _("Show transform handles even when only a single node is selected."));
+ _page_node.add_line( true, "", _t_node_single_node_transform_handles, "", _("Show transform handles even when only a single node is selected"));
_t_node_delete_preserves_shape.init(_("Deleting nodes preserves shape"), "/tools/nodes/delete_preserves_shape", true);
- _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape. Hold Ctrl to get the other behavior."));
+ _page_node.add_line( true, "", _t_node_delete_preserves_shape, "", _("Move handles next to deleted nodes to resemble original shape; hold Ctrl to get the other behavior"));
//Tweak
this->AddPage(_page_tweak, _("Tweak"), iter_tools, PREFS_PAGE_TOOLS_TWEAK);
@@ -508,7 +515,7 @@ void InkscapePreferences::initPageTools()
this->AddDotSizeSpinbutton(_page_pencil, "/tools/freehand/pencil", 3.0);
_page_pencil.add_group_header( _("Sketch mode"));
_page_pencil.add_line( true, "", _pencil_average_all_sketches, "",
- _("If on, the sketch result will be the normal average of all sketches made, instead of averaging the old result with the new sketch."));
+ _("If on, the sketch result will be the normal average of all sketches made, instead of averaging the old result with the new sketch"));
//Pen
this->AddPage(_page_pen, _("Pen"), iter_tools, PREFS_PAGE_TOOLS_PEN);
@@ -641,16 +648,16 @@ void InkscapePreferences::initPageClones()
_page_clones.add_group_header( _("When the original moves, its clones and linked offsets:"));
_page_clones.add_line( true, "", _clone_option_parallel, "",
- _("Clones are translated by the same vector as their original."));
+ _("Clones are translated by the same vector as their original"));
_page_clones.add_line( true, "", _clone_option_stay, "",
- _("Clones preserve their positions when their original is moved."));
+ _("Clones preserve their positions when their original is moved"));
_page_clones.add_line( true, "", _clone_option_transform, "",
- _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original."));
+ _("Each clone moves according to the value of its transform= attribute; for example, a rotated clone will move in a different direction than its original"));
_page_clones.add_group_header( _("When the original is deleted, its clones:"));
_page_clones.add_line( true, "", _clone_option_unlink, "",
- _("Orphaned clones are converted to regular objects."));
+ _("Orphaned clones are converted to regular objects"));
_page_clones.add_line( true, "", _clone_option_delete, "",
- _("Orphaned clones are deleted along with their original."));
+ _("Orphaned clones are deleted along with their original"));
_page_clones.add_group_header( _("When duplicating original+clones:"));
@@ -774,12 +781,12 @@ void InkscapePreferences::initPageFilters()
/* show infobox */
_show_filters_info_box.init( _("Show filter primitives infobox"), "/options/showfiltersinfobox/value", true);
_page_filters.add_line(true, "", _show_filters_info_box, "",
- _("Show icons and descriptions for the filter primitives available at the filter effects dialog."));
+ _("Show icons and descriptions for the filter primitives available at the filter effects dialog"));
/* threaded blur */ //related comments/widgets/functions should be renamed and option should be moved elsewhere when inkscape is fully multi-threaded
_filter_multi_threaded.init("/options/threading/numthreads", 1.0, 8.0, 1.0, 2.0, 4.0, true, false);
_page_filters.add_line( false, _("Number of Threads:"), _filter_multi_threaded, _("(requires restart)"),
- _("Configure number of processors/threads to use with rendering of gaussian blur."), false);
+ _("Configure number of processors/threads to use with rendering of gaussian blur"), false);
this->AddPage(_page_filters, _("Filters"), PREFS_PAGE_FILTERS);
}
@@ -820,13 +827,13 @@ void InkscapePreferences::initPageImportExport()
_("Default bitmap resolution (in dots per inch) in the Export dialog"), false);
_importexport_ocal_url.init("/options/ocalurl/str", true, g_strdup_printf("openclipart.org"));
_page_importexport.add_line( false, _("Open Clip Art Library Server Name:"), _importexport_ocal_url, "",
- _("The server name of the Open Clip Art Library webdav server. It's used by the Import and Export to OCAL function."), true);
+ _("The server name of the Open Clip Art Library webdav server; it's used by the Import and Export to OCAL function"), true);
_importexport_ocal_username.init("/options/ocalusername/str", true);
_page_importexport.add_line( false, _("Open Clip Art Library Username:"), _importexport_ocal_username, "",
- _("The username used to log into Open Clip Art Library."), true);
+ _("The username used to log into Open Clip Art Library"), true);
_importexport_ocal_password.init("/options/ocalpassword/str", false);
_page_importexport.add_line( false, _("Open Clip Art Library Password:"), _importexport_ocal_password, "",
- _("The password used to log into Open Clip Art Library."), true);
+ _("The password used to log into Open Clip Art Library"), true);
this->AddPage(_page_importexport, _("Import/Export"), PREFS_PAGE_IMPORTEXPORT);
}
@@ -905,42 +912,42 @@ void InkscapePreferences::initPageCMS()
_cms_from_display.init( _("Retrieve profile from display"), "/options/displayprofile/from_display", false);
_page_cms.add_line( false, "", _cms_from_display, "",
#ifdef GDK_WINDOWING_X11
- _("Retrieve profiles from those attached to displays via XICC."), false);
+ _("Retrieve profiles from those attached to displays via XICC"), false);
#else
- _("Retrieve profiles from those attached to displays."), false);
+ _("Retrieve profiles from those attached to displays"), false);
#endif // GDK_WINDOWING_X11
_cms_intent.init("/options/displayprofile/intent", intentLabels, intentValues, numIntents, 0);
_page_cms.add_line( false, _("Display rendering intent:"), _cms_intent, "",
- _("The rendering intent to use to calibrate display output."), false);
+ _("The rendering intent to use to calibrate display output"), false);
_page_cms.add_group_header( _("Proofing"));
_cms_softproof.init( _("Simulate output on screen"), "/options/softproof/enable", false);
_page_cms.add_line( false, "", _cms_softproof, "",
- _("Simulates output of target device."), false);
+ _("Simulates output of target device"), false);
_cms_gamutwarn.init( _("Mark out of gamut colors"), "/options/softproof/gamutwarn", false);
_page_cms.add_line( false, "", _cms_gamutwarn, "",
- _("Highlights colors that are out of gamut for the target device."), false);
+ _("Highlights colors that are out of gamut for the target device"), false);
Glib::ustring colorStr = prefs->getString("/options/softproof/gamutcolor");
Gdk::Color tmpColor( colorStr.empty() ? "#00ff00" : colorStr);
_cms_gamutcolor.set_color( tmpColor );
_page_cms.add_line( true, _("Out of gamut warning color:"), _cms_gamutcolor, "",
- _("Selects the color used for out of gamut warning."), false);
+ _("Selects the color used for out of gamut warning"), false);
_page_cms.add_line( false, _("Device profile:"), _cms_proof_profile, "",
- _("The ICC profile to use to simulate device output."), false);
+ _("The ICC profile to use to simulate device output"), false);
_cms_proof_intent.init("/options/softproof/intent", intentLabels, intentValues, numIntents, 0);
_page_cms.add_line( false, _("Device rendering intent:"), _cms_proof_intent, "",
- _("The rendering intent to use to calibrate display output."), false);
+ _("The rendering intent to use to calibrate display output"), false);
_cms_proof_blackpoint.init( _("Black point compensation"), "/options/softproof/bpc", false);
_page_cms.add_line( false, "", _cms_proof_blackpoint, "",
- _("Enables black point compensation."), false);
+ _("Enables black point compensation"), false);
_cms_proof_preserveblack.init( _("Preserve black"), "/options/softproof/preserveblack", false);
_page_cms.add_line( false, "", _cms_proof_preserveblack,
@@ -1015,7 +1022,7 @@ void InkscapePreferences::initPageGrids()
_page_grids.add_group_header( _("Major grid line emphasizing"));
_grids_no_emphasize_on_zoom.init( _("Don't emphasize gridlines when zoomed out"), "/options/grids/no_emphasize_when_zoomedout", false);
- _page_grids.add_line( false, "", _grids_no_emphasize_on_zoom, "", _("If set and zoomed out, the gridlines will be shown in normal color instead of major grid line color."), false);
+ _page_grids.add_line( false, "", _grids_no_emphasize_on_zoom, "", _("If set and zoomed out, the gridlines will be shown in normal color instead of major grid line color"), false);
_page_grids.add_group_header( _("Default grid settings"));
@@ -1092,7 +1099,7 @@ void InkscapePreferences::initPageSVGOutput()
_page_svgoutput.add_line( false, _("Numeric precision:"), _svgoutput_numericprecision, "", _("How many digits to write after the decimal dot"), false);
_svgoutput_minimumexponent.init("/options/svgoutput/minimumexponent", -32.0, -1, 1.0, 2.0, -8.0, true, false);
- _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero."), false);
+ _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero"), false);
this->AddPage(_page_svgoutput, _("SVG output"), PREFS_PAGE_SVGOUTPUT);
}
@@ -1124,21 +1131,21 @@ void InkscapePreferences::initPageUI()
int sizeValues[] = {0, 1, 2};
_misc_small_tools.init( "/toolbox/tools/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
- _page_ui.add_line( false, _("Toolbox icon size"), _misc_small_tools, "",
+ _page_ui.add_line( false, _("Toolbox icon size:"), _misc_small_tools, "",
_("Set the size for the tool icons (requires restart)"), false);
_misc_small_toolbar.init( "/toolbox/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
- _page_ui.add_line( false, _("Control bar icon size"), _misc_small_toolbar, "",
+ _page_ui.add_line( false, _("Control bar icon size:"), _misc_small_toolbar, "",
_("Set the size for the icons in tools' control bars to use (requires restart)"), false);
_misc_small_secondary.init( "/toolbox/secondary", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 1 );
- _page_ui.add_line( false, _("Secondary toolbar icon size"), _misc_small_secondary, "",
+ _page_ui.add_line( false, _("Secondary toolbar icon size:"), _misc_small_secondary, "",
_("Set the size for the icons in secondary toolbars to use (requires restart)"), false);
- _ui_colorsliders_top.init( _("Work-around color sliders not drawing."), "/options/workarounds/colorsontop", false);
+ _ui_colorsliders_top.init( _("Work-around color sliders not drawing"), "/options/workarounds/colorsontop", false);
_page_ui.add_line( false, "", _ui_colorsliders_top, "",
- _("When on, will attempt to work around bugs in certain GTK themes drawing color sliders."), true);
+ _("When on, will attempt to work around bugs in certain GTK themes drawing color sliders"), true);
_misc_recent.init("/options/maxrecentdocuments/value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false);
@@ -1157,9 +1164,9 @@ void InkscapePreferences::initPageUI()
_("Adjust the slider until the length of the ruler on your screen matches its real length. This information is used when zooming to 1:1, 1:2, etc., to display objects in their true sizes"), true);
- _ui_partialdynamic.init( _("Enable dynamic relayout for incomplete sections."), "/options/workarounds/dynamicnotdone", false);
+ _ui_partialdynamic.init( _("Enable dynamic relayout for incomplete sections"), "/options/workarounds/dynamicnotdone", false);
_page_ui.add_line( false, "", _ui_partialdynamic, "",
- _("When on, will allow dynamic layout of components that are not completely finished being refactored."), true);
+ _("When on, will allow dynamic layout of components that are not completely finished being refactored"), true);
this->AddPage(_page_ui, _("Interface"), PREFS_PAGE_UI);
@@ -1170,7 +1177,7 @@ void InkscapePreferences::initPageSave()
{
_save_use_current_dir.init( _("Use current directory for \"Save As ...\""), "/dialogs/save_as/use_current_dir", true);
_page_save.add_line( false, "", _save_use_current_dir, "",
- _("When this option is on, the \"Save as...\" dialog will always open in the directory where the currently open document is. When it's off, it will open in the directory where you last saved a file using that dialog."), true);
+ _("When this option is on, the \"Save as...\" dialog will always open in the directory where the currently open document is; when it's off, it will open in the directory where you last saved a file using that dialog"), true);
// Autosave options
@@ -1341,7 +1348,7 @@ void InkscapePreferences::initPageMisc()
_misc_latency_skew.init("/debug/latency/skew", 0.5, 2.0, 0.01, 0.10, 1.0, false, false);
_page_misc.add_line( false, _("Latency skew:"), _misc_latency_skew, _("(requires restart)"),
- _("Factor by which the event clock is skewed from the actual time (0.9766 on some systems)."), false);
+ _("Factor by which the event clock is skewed from the actual time (0.9766 on some systems)"), false);
_misc_namedicon_delay.init( _("Pre-render named icons"), "/options/iconrender/named_nodelay", false);
_page_misc.add_line( false, "", _misc_namedicon_delay, "",
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 0ba8c965d..5ee916e4c 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -82,8 +82,6 @@ enum {
PREFS_PAGE_MISC
};
-using namespace Inkscape::UI::Widget;
-
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -108,188 +106,272 @@ protected:
{ Gtk::TreeModelColumnRecord::add(_col_name); Gtk::TreeModelColumnRecord::add(_col_page); Gtk::TreeModelColumnRecord::add(_col_id); }
Gtk::TreeModelColumn<Glib::ustring> _col_name;
Gtk::TreeModelColumn<int> _col_id;
- Gtk::TreeModelColumn<DialogPage*> _col_page;
+ Gtk::TreeModelColumn<UI::Widget::DialogPage*> _col_page;
};
PageListModelColumns _page_list_columns;
Gtk::TreeModel::Path _path_tools;
Gtk::TreeModel::Path _path_shapes;
- DialogPage _page_mouse, _page_scrolling, _page_snapping, _page_steps, _page_tools, _page_windows,
- _page_clones, _page_mask, _page_transforms, _page_filters, _page_select,
- _page_importexport, _page_cms, _page_grids, _page_svgoutput, _page_misc,
- _page_ui, _page_save, _page_bitmaps, _page_spellcheck;
- DialogPage _page_selector, _page_node, _page_tweak, _page_spray, _page_zoom, _page_shapes, _page_pencil, _page_pen,
- _page_calligraphy, _page_text, _page_gradient, _page_connector, _page_dropper, _page_lpetool;
- DialogPage _page_rectangle, _page_3dbox, _page_ellipse, _page_star, _page_spiral, _page_paintbucket, _page_eraser;
-
- PrefSpinButton _mouse_sens, _mouse_thres;
- PrefCheckButton _mouse_use_ext_input;
- PrefCheckButton _mouse_switch_on_ext_input;
-
- PrefSpinButton _scroll_wheel, _scroll_arrow_px, _scroll_arrow_acc, _scroll_auto_speed, _scroll_auto_thres;
- PrefCheckButton _scroll_space;
- PrefCheckButton _wheel_zoom;
+ UI::Widget::DialogPage _page_mouse;
+ UI::Widget::DialogPage _page_scrolling;
+ UI::Widget::DialogPage _page_snapping;
+ UI::Widget::DialogPage _page_steps;
+ UI::Widget::DialogPage _page_tools;
+ UI::Widget::DialogPage _page_windows;
+ UI::Widget::DialogPage _page_clones;
+ UI::Widget::DialogPage _page_mask;
+ UI::Widget::DialogPage _page_transforms;
+ UI::Widget::DialogPage _page_filters;
+ UI::Widget::DialogPage _page_select;
+ UI::Widget::DialogPage _page_importexport;
+ UI::Widget::DialogPage _page_cms;
+ UI::Widget::DialogPage _page_grids;
+ UI::Widget::DialogPage _page_svgoutput;
+ UI::Widget::DialogPage _page_misc;
+ UI::Widget::DialogPage _page_ui;
+ UI::Widget::DialogPage _page_save;
+ UI::Widget::DialogPage _page_bitmaps;
+ UI::Widget::DialogPage _page_spellcheck;
+
+ UI::Widget::DialogPage _page_selector;
+ UI::Widget::DialogPage _page_node;
+ UI::Widget::DialogPage _page_tweak;
+ UI::Widget::DialogPage _page_spray;
+ UI::Widget::DialogPage _page_zoom;
+ UI::Widget::DialogPage _page_shapes;
+ UI::Widget::DialogPage _page_pencil;
+ UI::Widget::DialogPage _page_pen;
+ UI::Widget::DialogPage _page_calligraphy;
+ UI::Widget::DialogPage _page_text;
+ UI::Widget::DialogPage _page_gradient;
+ UI::Widget::DialogPage _page_connector;
+ UI::Widget::DialogPage _page_dropper;
+ UI::Widget::DialogPage _page_lpetool;
+
+ UI::Widget::DialogPage _page_rectangle;
+ UI::Widget::DialogPage _page_3dbox;
+ UI::Widget::DialogPage _page_ellipse;
+ UI::Widget::DialogPage _page_star;
+ UI::Widget::DialogPage _page_spiral;
+ UI::Widget::DialogPage _page_paintbucket;
+ UI::Widget::DialogPage _page_eraser;
+
+ UI::Widget::PrefSpinButton _mouse_sens;
+ UI::Widget::PrefSpinButton _mouse_thres;
+ UI::Widget::PrefCheckButton _mouse_use_ext_input;
+ UI::Widget::PrefCheckButton _mouse_switch_on_ext_input;
+
+ UI::Widget::PrefSpinButton _scroll_wheel;
+ UI::Widget::PrefSpinButton _scroll_arrow_px;
+ UI::Widget::PrefSpinButton _scroll_arrow_acc;
+ UI::Widget::PrefSpinButton _scroll_auto_speed;
+ UI::Widget::PrefSpinButton _scroll_auto_thres;
+ UI::Widget::PrefCheckButton _scroll_space;
+ UI::Widget::PrefCheckButton _wheel_zoom;
Gtk::HScale *_slider_snapping_delay;
- PrefCheckButton _snap_indicator, _snap_closest_only, _snap_mouse_pointer;
-
- PrefCombo _steps_rot_snap;
- PrefCheckButton _steps_compass;
- PrefSpinButton _steps_arrow, _steps_scale, _steps_inset, _steps_zoom;
-
- PrefRadioButton _t_sel_trans_obj, _t_sel_trans_outl, _t_sel_cue_none, _t_sel_cue_mark,
- _t_sel_cue_box, _t_bbox_visual, _t_bbox_geometric;
- PrefCheckButton _t_cvg_keep_objects, _t_cvg_convert_whole_groups;
- PrefCheckButton _t_node_show_outline;
- PrefCheckButton _t_node_live_outline;
- PrefCheckButton _t_node_live_objects;
- PrefCheckButton _t_node_pathflash_enabled;
- PrefCheckButton _t_node_pathflash_selected;
- PrefSpinButton _t_node_pathflash_timeout;
- PrefCheckButton _t_node_show_path_direction;
- PrefCheckButton _t_node_single_node_transform_handles;
- PrefCheckButton _t_node_delete_preserves_shape;
- PrefColorPicker _t_node_pathoutline_color;
-
- PrefRadioButton _win_dockable, _win_floating;
- PrefRadioButton _win_ontop_none, _win_ontop_normal, _win_ontop_agressive;
- PrefRadioButton _win_save_geom_off, _win_save_geom, _win_save_geom_prefs;
- PrefCheckButton _win_hide_task, _win_zoom_resize , _win_show_close;
- PrefSpinButton _win_trans_focus; /**< The dialog transparency setting for when the dialog is focused. */
- PrefSpinButton _win_trans_blur; /**< The dialog transparency setting for when the dialog is out of focus. */
- PrefSpinButton _win_trans_time; /**< How much time to go from one transparency setting to another */
-
- PrefCheckButton _pencil_average_all_sketches;
-
- PrefCheckButton _calligrapy_use_abs_size;
- PrefCheckButton _calligrapy_keep_selected;
-
- PrefCheckButton _connector_ignore_text;
-
- PrefRadioButton _clone_option_parallel, _clone_option_stay, _clone_option_transform,
- _clone_option_unlink, _clone_option_delete;
- PrefCheckButton _clone_relink_on_duplicate;
-
- PrefCheckButton _mask_mask_on_top;
- PrefCheckButton _mask_mask_remove;
- PrefRadioButton _mask_grouping_none, _mask_grouping_separate, _mask_grouping_all;
- PrefCheckButton _mask_ungrouping;
-
- PrefRadioButton _blur_quality_best, _blur_quality_better, _blur_quality_normal, _blur_quality_worse, _blur_quality_worst;
- PrefRadioButton _filter_quality_best, _filter_quality_better, _filter_quality_normal, _filter_quality_worse, _filter_quality_worst;
- PrefCheckButton _show_filters_info_box;
- PrefSpinButton _filter_multi_threaded;
-
- PrefCheckButton _trans_scale_stroke, _trans_scale_corner, _trans_gradient,_trans_pattern;
- PrefRadioButton _trans_optimized, _trans_preserved;
-
- PrefRadioButton _sel_all;
- PrefRadioButton _sel_current;
- PrefRadioButton _sel_recursive;
- PrefCheckButton _sel_hidden, _sel_locked;
- PrefCheckButton _sel_layer_deselects;
-
- PrefSpinButton _importexport_export, _misc_simpl;
- PrefSlider _snap_delay, _snap_weight;
- PrefSpinButton _misc_latency_skew;
- PrefCheckButton _misc_comment, _misc_forkvectors, _misc_scripts, _misc_namedicon_delay;
+ UI::Widget::PrefCheckButton _snap_indicator;
+ UI::Widget::PrefCheckButton _snap_closest_only;
+ UI::Widget::PrefCheckButton _snap_mouse_pointer;
+
+ UI::Widget::PrefCombo _steps_rot_snap;
+ UI::Widget::PrefCheckButton _steps_compass;
+ UI::Widget::PrefSpinButton _steps_arrow;
+ UI::Widget::PrefSpinButton _steps_scale;
+ UI::Widget::PrefSpinButton _steps_inset;
+ UI::Widget::PrefSpinButton _steps_zoom;
+
+ UI::Widget::PrefRadioButton _t_sel_trans_obj;
+ UI::Widget::PrefRadioButton _t_sel_trans_outl;
+ UI::Widget::PrefRadioButton _t_sel_cue_none;
+ UI::Widget::PrefRadioButton _t_sel_cue_mark;
+ UI::Widget::PrefRadioButton _t_sel_cue_box;
+ UI::Widget::PrefRadioButton _t_bbox_visual;
+ UI::Widget::PrefRadioButton _t_bbox_geometric;
+
+ UI::Widget::PrefCheckButton _t_cvg_keep_objects;
+ UI::Widget::PrefCheckButton _t_cvg_convert_whole_groups;
+ UI::Widget::PrefCheckButton _t_node_show_outline;
+ UI::Widget::PrefCheckButton _t_node_live_outline;
+ UI::Widget::PrefCheckButton _t_node_live_objects;
+ UI::Widget::PrefCheckButton _t_node_pathflash_enabled;
+ UI::Widget::PrefCheckButton _t_node_pathflash_selected;
+ UI::Widget::PrefSpinButton _t_node_pathflash_timeout;
+ UI::Widget::PrefCheckButton _t_node_show_path_direction;
+ UI::Widget::PrefCheckButton _t_node_single_node_transform_handles;
+ UI::Widget::PrefCheckButton _t_node_delete_preserves_shape;
+ UI::Widget::PrefColorPicker _t_node_pathoutline_color;
+
+ UI::Widget::PrefRadioButton _win_dockable;
+ UI::Widget::PrefRadioButton _win_floating;
+ UI::Widget::PrefRadioButton _win_ontop_none;
+ UI::Widget::PrefRadioButton _win_ontop_normal;
+ UI::Widget::PrefRadioButton _win_ontop_agressive;
+ UI::Widget::PrefRadioButton _win_save_geom_off;
+ UI::Widget::PrefRadioButton _win_save_geom;
+ UI::Widget::PrefRadioButton _win_save_geom_prefs;
+ UI::Widget::PrefCheckButton _win_hide_task;
+ UI::Widget::PrefCheckButton _win_zoom_resize;
+ UI::Widget::PrefCheckButton _win_show_close;
+ UI::Widget::PrefSpinButton _win_trans_focus; /**< The dialog transparency setting for when the dialog is focused. */
+ UI::Widget::PrefSpinButton _win_trans_blur; /**< The dialog transparency setting for when the dialog is out of focus. */
+ UI::Widget::PrefSpinButton _win_trans_time; /**< How much time to go from one transparency setting to another */
+
+ UI::Widget::PrefCheckButton _pencil_average_all_sketches;
+
+ UI::Widget::PrefCheckButton _calligrapy_use_abs_size;
+ UI::Widget::PrefCheckButton _calligrapy_keep_selected;
+
+ UI::Widget::PrefCheckButton _connector_ignore_text;
+
+ UI::Widget::PrefRadioButton _clone_option_parallel;
+ UI::Widget::PrefRadioButton _clone_option_stay;
+ UI::Widget::PrefRadioButton _clone_option_transform;
+ UI::Widget::PrefRadioButton _clone_option_unlink;
+ UI::Widget::PrefRadioButton _clone_option_delete;
+ UI::Widget::PrefCheckButton _clone_relink_on_duplicate;
+
+ UI::Widget::PrefCheckButton _mask_mask_on_top;
+ UI::Widget::PrefCheckButton _mask_mask_remove;
+ UI::Widget::PrefRadioButton _mask_grouping_none;
+ UI::Widget::PrefRadioButton _mask_grouping_separate;
+ UI::Widget::PrefRadioButton _mask_grouping_all;
+ UI::Widget::PrefCheckButton _mask_ungrouping;
+
+ UI::Widget::PrefRadioButton _blur_quality_best;
+ UI::Widget::PrefRadioButton _blur_quality_better;
+ UI::Widget::PrefRadioButton _blur_quality_normal;
+ UI::Widget::PrefRadioButton _blur_quality_worse;
+ UI::Widget::PrefRadioButton _blur_quality_worst;
+ UI::Widget::PrefRadioButton _filter_quality_best;
+ UI::Widget::PrefRadioButton _filter_quality_better;
+ UI::Widget::PrefRadioButton _filter_quality_normal;
+ UI::Widget::PrefRadioButton _filter_quality_worse;
+ UI::Widget::PrefRadioButton _filter_quality_worst;
+ UI::Widget::PrefCheckButton _show_filters_info_box;
+ UI::Widget::PrefSpinButton _filter_multi_threaded;
+
+ UI::Widget::PrefCheckButton _trans_scale_stroke;
+ UI::Widget::PrefCheckButton _trans_scale_corner;
+ UI::Widget::PrefCheckButton _trans_gradient;
+ UI::Widget::PrefCheckButton _trans_pattern;
+ UI::Widget::PrefRadioButton _trans_optimized;
+ UI::Widget::PrefRadioButton _trans_preserved;
+
+ UI::Widget::PrefRadioButton _sel_all;
+ UI::Widget::PrefRadioButton _sel_current;
+ UI::Widget::PrefRadioButton _sel_recursive;
+ UI::Widget::PrefCheckButton _sel_hidden;
+ UI::Widget::PrefCheckButton _sel_locked;
+ UI::Widget::PrefCheckButton _sel_layer_deselects;
+
+ UI::Widget::PrefSpinButton _importexport_export;
+ UI::Widget::PrefSpinButton _misc_simpl;
+ UI::Widget::PrefSlider _snap_delay;
+ UI::Widget::PrefSlider _snap_weight;
+ UI::Widget::PrefSpinButton _misc_latency_skew;
+ UI::Widget::PrefCheckButton _misc_comment;
+ UI::Widget::PrefCheckButton _misc_forkvectors;
+ UI::Widget::PrefCheckButton _misc_scripts;
+ UI::Widget::PrefCheckButton _misc_namedicon_delay;
Gtk::TextView _misc_info;
Gtk::ScrolledWindow _misc_info_scroll;
// UI page
- PrefCombo _ui_languages;
- PrefCombo _misc_small_toolbar;
- PrefCombo _misc_small_secondary;
- PrefCombo _misc_small_tools;
- PrefCheckButton _ui_colorsliders_top;
- PrefSpinButton _misc_recent;
- PrefCheckButton _ui_partialdynamic;
- ZoomCorrRulerSlider _ui_zoom_correction;
+ UI::Widget::PrefCombo _ui_languages;
+ UI::Widget::PrefCombo _misc_small_toolbar;
+ UI::Widget::PrefCombo _misc_small_secondary;
+ UI::Widget::PrefCombo _misc_small_tools;
+ UI::Widget::PrefCheckButton _ui_colorsliders_top;
+ UI::Widget::PrefSpinButton _misc_recent;
+ UI::Widget::PrefCheckButton _ui_partialdynamic;
+ UI::Widget::ZoomCorrRulerSlider _ui_zoom_correction;
//Spellcheck
- PrefCombo _spell_language;
- PrefCombo _spell_language2;
- PrefCombo _spell_language3;
- PrefCheckButton _spell_ignorenumbers;
- PrefCheckButton _spell_ignoreallcaps;
-
- PrefCombo _misc_overs_bitmap;
- PrefCombo _misc_bitmap_editor;
- PrefCheckButton _misc_bitmap_autoreload;
- PrefSpinButton _bitmap_copy_res;
-
- PrefCheckButton _save_use_current_dir;
- PrefCheckButton _save_autosave_enable;
- PrefSpinButton _save_autosave_interval;
- PrefEntry _save_autosave_path;
- PrefSpinButton _save_autosave_max;
+ UI::Widget::PrefCombo _spell_language;
+ UI::Widget::PrefCombo _spell_language2;
+ UI::Widget::PrefCombo _spell_language3;
+ UI::Widget::PrefCheckButton _spell_ignorenumbers;
+ UI::Widget::PrefCheckButton _spell_ignoreallcaps;
+
+ UI::Widget::PrefCombo _misc_overs_bitmap;
+ UI::Widget::PrefCombo _misc_bitmap_editor;
+ UI::Widget::PrefCheckButton _misc_bitmap_autoreload;
+ UI::Widget::PrefSpinButton _bitmap_copy_res;
+
+ UI::Widget::PrefCheckButton _save_use_current_dir;
+ UI::Widget::PrefCheckButton _save_autosave_enable;
+ UI::Widget::PrefSpinButton _save_autosave_interval;
+ UI::Widget::PrefEntry _save_autosave_path;
+ UI::Widget::PrefSpinButton _save_autosave_max;
Gtk::ComboBoxText _cms_display_profile;
- PrefCheckButton _cms_from_display;
- PrefCombo _cms_intent;
+ UI::Widget::PrefCheckButton _cms_from_display;
+ UI::Widget::PrefCombo _cms_intent;
- PrefCheckButton _cms_softproof;
- PrefCheckButton _cms_gamutwarn;
+ UI::Widget::PrefCheckButton _cms_softproof;
+ UI::Widget::PrefCheckButton _cms_gamutwarn;
Gtk::ColorButton _cms_gamutcolor;
Gtk::ComboBoxText _cms_proof_profile;
- PrefCombo _cms_proof_intent;
- PrefCheckButton _cms_proof_blackpoint;
- PrefCheckButton _cms_proof_preserveblack;
+ UI::Widget::PrefCombo _cms_proof_intent;
+ UI::Widget::PrefCheckButton _cms_proof_blackpoint;
+ UI::Widget::PrefCheckButton _cms_proof_preserveblack;
Gtk::Notebook _grids_notebook;
- PrefCheckButton _grids_no_emphasize_on_zoom;
- DialogPage _grids_xy, _grids_axonom;
+ UI::Widget::PrefCheckButton _grids_no_emphasize_on_zoom;
+ UI::Widget::DialogPage _grids_xy;
+ UI::Widget::DialogPage _grids_axonom;
// CanvasXYGrid properties:
- PrefUnit _grids_xy_units;
- PrefSpinButton _grids_xy_origin_x;
- PrefSpinButton _grids_xy_origin_y;
- PrefSpinButton _grids_xy_spacing_x;
- PrefSpinButton _grids_xy_spacing_y;
- PrefColorPicker _grids_xy_color;
- PrefColorPicker _grids_xy_empcolor;
- PrefSpinButton _grids_xy_empspacing;
- PrefCheckButton _grids_xy_dotted;
+ UI::Widget::PrefUnit _grids_xy_units;
+ UI::Widget::PrefSpinButton _grids_xy_origin_x;
+ UI::Widget::PrefSpinButton _grids_xy_origin_y;
+ UI::Widget::PrefSpinButton _grids_xy_spacing_x;
+ UI::Widget::PrefSpinButton _grids_xy_spacing_y;
+ UI::Widget::PrefColorPicker _grids_xy_color;
+ UI::Widget::PrefColorPicker _grids_xy_empcolor;
+ UI::Widget::PrefSpinButton _grids_xy_empspacing;
+ UI::Widget::PrefCheckButton _grids_xy_dotted;
// CanvasAxonomGrid properties:
- PrefUnit _grids_axonom_units;
- PrefSpinButton _grids_axonom_origin_x;
- PrefSpinButton _grids_axonom_origin_y;
- PrefSpinButton _grids_axonom_spacing_y;
- PrefSpinButton _grids_axonom_angle_x;
- PrefSpinButton _grids_axonom_angle_z;
- PrefColorPicker _grids_axonom_color;
- PrefColorPicker _grids_axonom_empcolor;
- PrefSpinButton _grids_axonom_empspacing;
+ UI::Widget::PrefUnit _grids_axonom_units;
+ UI::Widget::PrefSpinButton _grids_axonom_origin_x;
+ UI::Widget::PrefSpinButton _grids_axonom_origin_y;
+ UI::Widget::PrefSpinButton _grids_axonom_spacing_y;
+ UI::Widget::PrefSpinButton _grids_axonom_angle_x;
+ UI::Widget::PrefSpinButton _grids_axonom_angle_z;
+ UI::Widget::PrefColorPicker _grids_axonom_color;
+ UI::Widget::PrefColorPicker _grids_axonom_empcolor;
+ UI::Widget::PrefSpinButton _grids_axonom_empspacing;
// SVG Output page:
- PrefCheckButton _svgoutput_usenamedcolors;
- PrefSpinButton _svgoutput_numericprecision;
- PrefSpinButton _svgoutput_minimumexponent;
- PrefCheckButton _svgoutput_inlineattrs;
- PrefSpinButton _svgoutput_indent;
- PrefCheckButton _svgoutput_allowrelativecoordinates;
- PrefCheckButton _svgoutput_forcerepeatcommands;
-
- PrefEntryButtonHBox _importexport_ocal_url;
- PrefEntry _importexport_ocal_username;
- PrefEntry _importexport_ocal_password;
+ UI::Widget::PrefCheckButton _svgoutput_usenamedcolors;
+ UI::Widget::PrefSpinButton _svgoutput_numericprecision;
+ UI::Widget::PrefSpinButton _svgoutput_minimumexponent;
+ UI::Widget::PrefCheckButton _svgoutput_inlineattrs;
+ UI::Widget::PrefSpinButton _svgoutput_indent;
+ UI::Widget::PrefCheckButton _svgoutput_allowrelativecoordinates;
+ UI::Widget::PrefCheckButton _svgoutput_forcerepeatcommands;
+
+ UI::Widget::PrefEntryButtonHBox _importexport_ocal_url;
+ UI::Widget::PrefEntry _importexport_ocal_username;
+ UI::Widget::PrefEntry _importexport_ocal_password;
int _max_dialog_width;
int _max_dialog_height;
int _sb_width;
- DialogPage* _current_page;
+ UI::Widget::DialogPage* _current_page;
- Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title, int id);
- Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent, int id);
+ Gtk::TreeModel::iterator AddPage(UI::Widget::DialogPage& p, Glib::ustring title, int id);
+ Gtk::TreeModel::iterator AddPage(UI::Widget::DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent, int id);
bool SetMaxDialogSize(const Gtk::TreeModel::iterator& iter);
bool PresentPage(const Gtk::TreeModel::iterator& iter);
- static void AddSelcueCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
- static void AddGradientCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
- static void AddConvertGuidesCheckbox(DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
- static void AddDotSizeSpinbutton(DialogPage& p, Glib::ustring const &prefs_path, double def_value);
- static void AddNewObjectsStyle(DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL);
+ static void AddSelcueCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
+ static void AddGradientCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
+ static void AddConvertGuidesCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
+ static void AddDotSizeSpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value);
+ static void AddNewObjectsStyle(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL);
void on_pagelist_selection_changed();
void on_reset_open_recent_clicked();
diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp
index ae8594e50..92a54affb 100644
--- a/src/ui/dialog/input.cpp
+++ b/src/ui/dialog/input.cpp
@@ -12,11 +12,15 @@
#include <set>
#include <glib/gprintf.h>
#include <glibmm/i18n.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/cellrenderercombo.h>
+#include <gtkmm/checkbutton.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/enums.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/frame.h>
#include <gtkmm/image.h>
+#include <gtkmm/liststore.h>
#include <gtkmm/menubar.h>
#include <gtkmm/notebook.h>
#include <gtkmm/paned.h>
@@ -28,8 +32,9 @@
#include <gtkmm/treestore.h>
#include <gtkmm/treeview.h>
-#include "ui/widget/panel.h"
#include "device-manager.h"
+#include "preferences.h"
+#include "ui/widget/panel.h"
#include "input.h"
@@ -323,38 +328,87 @@ namespace Dialog {
-class MyModelColumns : public Gtk::TreeModel::ColumnRecord
+class DeviceModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
- Gtk::TreeModelColumn<Glib::ustring> filename;
Gtk::TreeModelColumn<Glib::ustring> description;
Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > thumbnail;
- Gtk::TreeModelColumn<InputDevice const *> device;
+ Gtk::TreeModelColumn<Glib::RefPtr<InputDevice const> > device;
+ Gtk::TreeModelColumn<Gdk::InputMode> mode;
- MyModelColumns() { add(filename); add(description); add(thumbnail); add(device); }
+ DeviceModelColumns() { add(description); add(thumbnail); add(device); add(mode); }
};
+static std::map<Gdk::InputMode, Glib::ustring> &getModeToString()
+{
+ static std::map<Gdk::InputMode, Glib::ustring> mapping;
+ if (mapping.empty()) {
+ mapping[Gdk::MODE_DISABLED] = _("Disabled");
+ mapping[Gdk::MODE_SCREEN] = _("Screen");
+ mapping[Gdk::MODE_WINDOW] = _("Window");
+ }
+
+ return mapping;
+}
+
+static std::map<Glib::ustring, Gdk::InputMode> &getStringToMode()
+{
+ static std::map<Glib::ustring, Gdk::InputMode> mapping;
+ if (mapping.empty()) {
+ mapping[_("Disabled")] = Gdk::MODE_DISABLED;
+ mapping[_("Screen")] = Gdk::MODE_SCREEN;
+ mapping[_("Window")] = Gdk::MODE_WINDOW;
+ }
+
+ return mapping;
+}
+
+
+
class InputDialogImpl : public InputDialog {
public:
InputDialogImpl();
virtual ~InputDialogImpl() {}
private:
- Glib::RefPtr<Gdk::Pixbuf> corePix;
- Glib::RefPtr<Gdk::Pixbuf> penPix;
- Glib::RefPtr<Gdk::Pixbuf> mousePix;
- Glib::RefPtr<Gdk::Pixbuf> tipPix;
- Glib::RefPtr<Gdk::Pixbuf> tabletPix;
- Glib::RefPtr<Gdk::Pixbuf> eraserPix;
- Glib::RefPtr<Gdk::Pixbuf> sidebuttonsPix;
-
- Glib::RefPtr<Gdk::Pixbuf> buttonsNonePix;
- Glib::RefPtr<Gdk::Pixbuf> buttonsOnPix;
- Glib::RefPtr<Gdk::Pixbuf> buttonsOffPix;
-
- Glib::RefPtr<Gdk::Pixbuf> axisNonePix;
- Glib::RefPtr<Gdk::Pixbuf> axisOnPix;
- Glib::RefPtr<Gdk::Pixbuf> axisOffPix;
+ class ConfPanel : public Gtk::VBox
+ {
+ public:
+ ConfPanel();
+ ~ConfPanel();
+
+ class Blink : public Preferences::Observer
+ {
+ public:
+ Blink(ConfPanel &parent);
+ virtual ~Blink();
+ virtual void notify(Preferences::Entry const &new_val);
+
+ ConfPanel &parent;
+ };
+
+ static void commitCellModeChange(Glib::ustring const &path, Glib::ustring const &newText, Glib::RefPtr<Gtk::TreeStore> store);
+ static void setModeCellString(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter);
+
+ void saveSettings();
+ void useExtToggled();
+
+ Glib::RefPtr<Gtk::TreeStore> store;
+ Gtk::TreeIter tabletIter;
+ Gtk::TreeView tree;
+ Gtk::ScrolledWindow treeScroller;
+ Blink watcher;
+ Gtk::CheckButton useExt;
+ Gtk::Button save;
+ };
+
+ static DeviceModelColumns &getCols();
+
+ enum PixId {PIX_CORE, PIX_PEN, PIX_MOUSE, PIX_TIP, PIX_TABLET, PIX_ERASER, PIX_SIDEBUTTONS,
+ PIX_BUTTONS_NONE, PIX_BUTTONS_ON, PIX_BUTTONS_OFF,
+ PIX_AXIS_NONE, PIX_AXIS_ON, PIX_AXIS_OFF};
+
+ static Glib::RefPtr<Gdk::Pixbuf> getPix(PixId id);
std::map<Glib::ustring, std::set<guint> > buttonMap;
std::map<Glib::ustring, std::map<guint, std::pair<guint, gdouble> > > axesMap;
@@ -362,7 +416,6 @@ private:
GdkInputSource lastSourceSeen;
Glib::ustring lastDevnameSeen;
- MyModelColumns cols;
Glib::RefPtr<Gtk::TreeStore> store;
Gtk::TreeIter tabletIter;
Gtk::TreeView tree;
@@ -383,7 +436,6 @@ private:
Gtk::Label keyVal;
Gtk::Entry keyEntry;
Gtk::Table devDetails;
- Gtk::HPaned confSplitter;
Gtk::Notebook topHolder;
Gtk::Image testThumb;
Gtk::Image testButtons[24];
@@ -391,6 +443,9 @@ private:
Gtk::Table imageTable;
Gtk::EventBox testDetector;
+ ConfPanel cfgPanel;
+
+ static void setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIter &tablet );
void setupValueAndCombo( gint reported, gint actual, Gtk::Label& label, Gtk::ComboBoxText& combo );
void updateTestButtons( Glib::ustring const& key, gint hotButton );
void updateTestAxes( Glib::ustring const& key, GdkDevice* dev );
@@ -399,18 +454,54 @@ private:
bool eventSnoop(GdkEvent* event);
void linkComboChanged();
void resyncToSelection();
- void handleDeviceChange(const Glib::RefPtr<InputDevice>& device);
- void updateDeviceAxes(const Glib::RefPtr<InputDevice>& device);
- void updateDeviceButtons(const Glib::RefPtr<InputDevice>& device);
- void updateDeviceLinks(const Glib::RefPtr<InputDevice>& device);
-
- bool findDevice(const Gtk::TreeModel::iterator& iter,
- Glib::ustring id,
- Gtk::TreeModel::iterator* result);
- bool findDeviceByLink(const Gtk::TreeModel::iterator& iter,
- Glib::ustring link,
- Gtk::TreeModel::iterator* result);
-};
+ void handleDeviceChange(Glib::RefPtr<InputDevice const> device);
+ void updateDeviceAxes(Glib::RefPtr<InputDevice const> device);
+ void updateDeviceButtons(Glib::RefPtr<InputDevice const> device);
+ static void updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Gtk::TreeIter tabletIter, Glib::RefPtr<Gtk::TreeView> tree);
+
+ static bool findDevice(const Gtk::TreeModel::iterator& iter,
+ Glib::ustring id,
+ Gtk::TreeModel::iterator* result);
+ static bool findDeviceByLink(const Gtk::TreeModel::iterator& iter,
+ Glib::ustring link,
+ Gtk::TreeModel::iterator* result);
+
+}; // class InputDialogImpl
+
+
+DeviceModelColumns &InputDialogImpl::getCols()
+{
+ static DeviceModelColumns cols;
+ return cols;
+}
+
+Glib::RefPtr<Gdk::Pixbuf> InputDialogImpl::getPix(PixId id)
+{
+ static std::map<PixId, Glib::RefPtr<Gdk::Pixbuf> > mappings;
+
+ mappings[PIX_CORE] = Gdk::Pixbuf::create_from_xpm_data(core_xpm);
+ mappings[PIX_PEN] = Gdk::Pixbuf::create_from_xpm_data(pen);
+ mappings[PIX_MOUSE] = Gdk::Pixbuf::create_from_xpm_data(mouse);
+ mappings[PIX_TIP] = Gdk::Pixbuf::create_from_xpm_data(tip);
+ mappings[PIX_TABLET] = Gdk::Pixbuf::create_from_xpm_data(tablet);
+ mappings[PIX_ERASER] = Gdk::Pixbuf::create_from_xpm_data(eraser);
+ mappings[PIX_SIDEBUTTONS] = Gdk::Pixbuf::create_from_xpm_data(sidebuttons);
+
+ mappings[PIX_BUTTONS_NONE] = Gdk::Pixbuf::create_from_xpm_data(button_none);
+ mappings[PIX_BUTTONS_ON] = Gdk::Pixbuf::create_from_xpm_data(button_on);
+ mappings[PIX_BUTTONS_OFF] = Gdk::Pixbuf::create_from_xpm_data(button_off);
+
+ mappings[PIX_AXIS_NONE] = Gdk::Pixbuf::create_from_xpm_data(axis_none_xpm);
+ mappings[PIX_AXIS_ON] = Gdk::Pixbuf::create_from_xpm_data(axis_on_xpm);
+ mappings[PIX_AXIS_OFF] = Gdk::Pixbuf::create_from_xpm_data(axis_off_xpm);
+
+ Glib::RefPtr<Gdk::Pixbuf> pix;
+ if (mappings.find(id) != mappings.end()) {
+ pix = mappings[id];
+ }
+
+ return pix;
+}
// Now that we've defined the *Impl class, we can do the method to aquire one.
@@ -424,38 +515,23 @@ InputDialog &InputDialog::getInstance()
InputDialogImpl::InputDialogImpl() :
InputDialog(),
- corePix(Gdk::Pixbuf::create_from_xpm_data(core_xpm)),
- penPix(Gdk::Pixbuf::create_from_xpm_data(pen)),
- mousePix(Gdk::Pixbuf::create_from_xpm_data(mouse)),
- tipPix(Gdk::Pixbuf::create_from_xpm_data(tip)),
- tabletPix(Gdk::Pixbuf::create_from_xpm_data(tablet)),
- eraserPix(Gdk::Pixbuf::create_from_xpm_data(eraser)),
- sidebuttonsPix(Gdk::Pixbuf::create_from_xpm_data(sidebuttons)),
-
- buttonsNonePix(Gdk::Pixbuf::create_from_xpm_data(button_none)),
- buttonsOnPix(Gdk::Pixbuf::create_from_xpm_data(button_on)),
- buttonsOffPix(Gdk::Pixbuf::create_from_xpm_data(button_off)),
-
- axisNonePix(Gdk::Pixbuf::create_from_xpm_data(axis_none_xpm)),
- axisOnPix(Gdk::Pixbuf::create_from_xpm_data(axis_on_xpm)),
- axisOffPix(Gdk::Pixbuf::create_from_xpm_data(axis_off_xpm)),
-
lastSourceSeen((GdkInputSource)-1),
lastDevnameSeen(""),
- cols(),
- store(Gtk::TreeStore::create(cols)),
+ store(Gtk::TreeStore::create(getCols())),
+ tabletIter(),
tree(store),
frame2(),
- testFrame("Test Area"),
+ testFrame(_("Test Area")),
treeScroller(),
detailScroller(),
splitter(),
split2(),
linkCombo(),
devDetails(12, 2),
- confSplitter(),
topHolder(),
- imageTable(8, 7)
+ imageTable(8, 7),
+ testDetector(),
+ cfgPanel()
{
Gtk::Box *contents = _getContents();
@@ -469,14 +545,14 @@ InputDialogImpl::InputDialogImpl() :
testDetector.add(imageTable);
testFrame.add(testDetector);
- testThumb.set(tabletPix);
+ testThumb.set(getPix(PIX_TABLET));
testThumb.set_padding(24, 24);
imageTable.attach(testThumb, 0, 8, 0, 1, ::Gtk::EXPAND, ::Gtk::EXPAND);
{
guint col = 0;
guint row = 1;
for ( guint num = 0; num < G_N_ELEMENTS(testButtons); num++ ) {
- testButtons[num].set(buttonsNonePix);
+ testButtons[num].set(getPix(PIX_BUTTONS_NONE));
imageTable.attach(testButtons[num], col, col + 1, row, row + 1, ::Gtk::FILL, ::Gtk::FILL);
col++;
if (col > 7) {
@@ -487,7 +563,7 @@ InputDialogImpl::InputDialogImpl() :
col = 0;
for ( guint num = 0; num < G_N_ELEMENTS(testAxes); num++ ) {
- testAxes[num].set(axisNonePix);
+ testAxes[num].set(getPix(PIX_AXIS_NONE));
imageTable.attach(testAxes[num], col * 2, (col + 1) * 2, row, row + 1, ::Gtk::FILL, ::Gtk::FILL);
col++;
if (col > 3) {
@@ -498,18 +574,16 @@ InputDialogImpl::InputDialogImpl() :
}
- topHolder.append_page(confSplitter, "Configuration");
- topHolder.append_page(splitter, "Hardware");
-// confSplitter.show_all();
-// splitter.show_all();
+ topHolder.append_page(cfgPanel, _("Configuration"));
+ topHolder.append_page(splitter, _("Hardware"));
topHolder.show_all();
- topHolder.set_current_page(1);
+ topHolder.set_current_page(0);
contents->pack_start(topHolder);
int rowNum = 0;
- Gtk::Label* lbl = Gtk::manage(new Gtk::Label("Name:"));
+ Gtk::Label* lbl = Gtk::manage(new Gtk::Label(_("Name:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -519,13 +593,13 @@ InputDialogImpl::InputDialogImpl() :
rowNum++;
- lbl = Gtk::manage(new Gtk::Label("Link:"));
+ lbl = Gtk::manage(new Gtk::Label(_("Link:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
- linkCombo.append_text("None");
- linkCombo.set_active_text("None");
+ linkCombo.append_text(_("None"));
+ linkCombo.set_active_text(_("None"));
linkCombo.set_sensitive(false);
linkConnection = linkCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::linkComboChanged));
@@ -534,7 +608,7 @@ InputDialogImpl::InputDialogImpl() :
::Gtk::SHRINK);
rowNum++;
- lbl = Gtk::manage(new Gtk::Label("Axes count:"));
+ lbl = Gtk::manage(new Gtk::Label(_("Axes count:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -545,7 +619,7 @@ InputDialogImpl::InputDialogImpl() :
rowNum++;
/*
- lbl = Gtk::manage(new Gtk::Label("Actual axes count:"));
+ lbl = Gtk::manage(new Gtk::Label(_("Actual axes count:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -557,7 +631,7 @@ InputDialogImpl::InputDialogImpl() :
*/
for ( guint barNum = 0; barNum < static_cast<guint>(G_N_ELEMENTS(axesValues)); barNum++ ) {
- lbl = Gtk::manage(new Gtk::Label("axis:"));
+ lbl = Gtk::manage(new Gtk::Label(_("axis:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -569,7 +643,7 @@ InputDialogImpl::InputDialogImpl() :
rowNum++;
}
- lbl = Gtk::manage(new Gtk::Label("Button count:"));
+ lbl = Gtk::manage(new Gtk::Label(_("Button count:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -580,7 +654,7 @@ InputDialogImpl::InputDialogImpl() :
rowNum++;
/*
- lbl = Gtk::manage(new Gtk::Label("Actual button count:"));
+ lbl = Gtk::manage(new Gtk::Label(_("Actual button count:")));
devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
::Gtk::FILL,
::Gtk::SHRINK);
@@ -625,58 +699,67 @@ InputDialogImpl::InputDialogImpl() :
- Gtk::TreeModel::Row row;
- Gtk::TreeModel::Row childrow;
- Gtk::TreeModel::Row deviceRow;
-
-
//Add the TreeView's view columns:
- tree.append_column("I", cols.thumbnail);
- tree.append_column("Bar", cols.description);
+ tree.append_column("I", getCols().thumbnail);
+ tree.append_column("Bar", getCols().description);
tree.set_enable_tree_lines();
tree.set_headers_visible(false);
tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection));
+ setupTree( store, tabletIter );
- std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
+ Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange));
+ Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes));
+ Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons));
+ Glib::RefPtr<Gtk::TreeView> treePtr(&tree);
+ Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr));
+
+ tree.expand_all();
+ show_all_children();
+}
+
+void InputDialogImpl::setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIter &tablet )
+{
+ std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
if ( !devList.empty() ) {
- row = *(store->append());
- row[cols.description] = "Hardware";
+ Gtk::TreeModel::Row row = *(store->append());
+ row[getCols().description] = _("Hardware");
- tabletIter = store->append(row.children());
- childrow = *tabletIter;
- childrow[cols.description] = "Tablet";
- childrow[cols.thumbnail] = tabletPix;
+ tablet = store->append(row.children());
+ Gtk::TreeModel::Row childrow = *tablet;
+ childrow[getCols().description] = _("Tablet");
+ childrow[getCols().thumbnail] = getPix(PIX_TABLET);
- for ( std::list<InputDevice const *>::iterator it = devList.begin(); it != devList.end(); ++it ) {
- InputDevice const* dev = *it;
+ for ( std::list<Glib::RefPtr<InputDevice const> >::iterator it = devList.begin(); it != devList.end(); ++it ) {
+ Glib::RefPtr<InputDevice const> dev = *it;
if ( dev ) {
// g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->getName().c_str(), dev->getSource(), dev->getMode(),
// dev->hasCursor() ? "Yes":"no", dev->getNumAxes(), dev->getNumKeys());
// if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
if ( dev ) {
- deviceRow = *(store->append(childrow.children()));
- deviceRow[cols.description] = dev->getName();
- deviceRow[cols.device] = dev;
+ Gtk::TreeModel::Row deviceRow = *(store->append(childrow.children()));
+ deviceRow[getCols().description] = dev->getName();
+ deviceRow[getCols().device] = dev;
+ deviceRow[getCols().mode] = dev->getMode();
switch ( dev->getSource() ) {
case GDK_SOURCE_MOUSE:
- deviceRow[cols.thumbnail] = corePix;
+ deviceRow[getCols().thumbnail] = getPix(PIX_CORE);
break;
case GDK_SOURCE_PEN:
- if (deviceRow[cols.description] == "pad") {
- deviceRow[cols.thumbnail] = sidebuttonsPix;
+ if (deviceRow[getCols().description] == _("pad")) {
+ deviceRow[getCols().thumbnail] = getPix(PIX_SIDEBUTTONS);
} else {
- deviceRow[cols.thumbnail] = tipPix;
+ deviceRow[getCols().thumbnail] = getPix(PIX_TIP);
}
break;
case GDK_SOURCE_CURSOR:
- deviceRow[cols.thumbnail] = mousePix;
+ deviceRow[getCols().thumbnail] = getPix(PIX_MOUSE);
break;
case GDK_SOURCE_ERASER:
- deviceRow[cols.thumbnail] = eraserPix;
+ deviceRow[getCols().thumbnail] = getPix(PIX_ERASER);
break;
default:
; // nothing
@@ -689,21 +772,169 @@ InputDialogImpl::InputDialogImpl() :
} else {
g_warning("No devices found");
}
- Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange));
- Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes));
- Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons));
- Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceLinks));
+}
+
+
+InputDialogImpl::ConfPanel::ConfPanel() :
+ Gtk::VBox(),
+ store(Gtk::TreeStore::create(getCols())),
+ tabletIter(),
+ tree(store),
+ treeScroller(),
+ watcher(*this),
+ useExt(_("Use pressure-sensitive tablet (requires restart)")),
+ save(_("Save"))
+{
+ pack_start(treeScroller);
+
+ treeScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ treeScroller.add(tree);
+
+ class Foo : public Gtk::TreeModel::ColumnRecord {
+ public :
+ Gtk::TreeModelColumn<Glib::ustring> one;
+ Foo() {add(one);}
+ };
+ static Foo foo;
+ Glib::RefPtr<Gtk::ListStore> poppers = Gtk::ListStore::create(foo);
+ poppers->reference();
+
+ Gtk::TreeModel::Row row = *(poppers->append());
+ row[foo.one] = getModeToString()[Gdk::MODE_DISABLED];
+ row = *(poppers->append());
+ row[foo.one] = getModeToString()[Gdk::MODE_SCREEN];
+ row = *(poppers->append());
+ row[foo.one] = getModeToString()[Gdk::MODE_WINDOW];
+
+ Gtk::CellRendererCombo *rendr = new Gtk::CellRendererCombo();
+ rendr->property_model().set_value(poppers);
+ rendr->property_text_column().set_value(0);
+ rendr->property_has_entry() = false;
+
+ //Add the TreeView's view columns:
+ tree.append_column("I", getCols().thumbnail);
+ tree.append_column("Bar", getCols().description);
+ Gtk::TreeViewColumn *col = new Gtk::TreeViewColumn("X", *rendr);
+ if (col) {
+ tree.append_column(*col);
+ col->set_cell_data_func(*rendr, sigc::ptr_fun(setModeCellString));
+ rendr->signal_edited().connect(sigc::bind(sigc::ptr_fun(commitCellModeChange), store));
+ rendr->property_editable() = true;
+ }
+
+ tree.set_enable_tree_lines();
+ tree.set_headers_visible(false);
+
+ setupTree( store, tabletIter );
+
+ Glib::RefPtr<Gtk::TreeView> treePtr(&tree);
+ Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr));
tree.expand_all();
- show_all_children();
+
+ useExt.set_active(Preferences::get()->getBool("/options/useextinput/value"));
+ useExt.signal_toggled().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::useExtToggled));
+ pack_start(useExt, Gtk::PACK_SHRINK);
+
+ save.signal_clicked().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::saveSettings));
+ Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_RIGHT, Gtk::ALIGN_TOP, 0, 0);
+ align->add(save);
+ pack_start(*Gtk::manage(align), Gtk::PACK_SHRINK);
+}
+
+InputDialogImpl::ConfPanel::~ConfPanel()
+{
+}
+
+void InputDialogImpl::ConfPanel::setModeCellString(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter)
+{
+ if (iter) {
+ Gtk::CellRendererCombo *combo = dynamic_cast<Gtk::CellRendererCombo *>(rndr);
+ if (combo) {
+ Glib::RefPtr<InputDevice const> dev = (*iter)[getCols().device];
+ Gdk::InputMode mode = (*iter)[getCols().mode];
+ if (dev && (getModeToString().find(mode) != getModeToString().end())) {
+ combo->property_text() = getModeToString()[mode];
+ } else {
+ combo->property_text() = "";
+ }
+ }
+ }
}
-void InputDialogImpl::handleDeviceChange(const Glib::RefPtr<InputDevice>& /*device*/)
+void InputDialogImpl::ConfPanel::commitCellModeChange(Glib::ustring const &path, Glib::ustring const &newText, Glib::RefPtr<Gtk::TreeStore> store)
+{
+ Gtk::TreeIter iter = store->get_iter(path);
+ if (iter) {
+ Glib::RefPtr<InputDevice const> dev = (*iter)[getCols().device];
+ if (dev && (getStringToMode().find(newText) != getStringToMode().end())) {
+ Gdk::InputMode mode = getStringToMode()[newText];
+ Inkscape::DeviceManager::getManager().setMode( dev->getId(), mode );
+ }
+ }
+}
+
+void InputDialogImpl::ConfPanel::saveSettings()
+{
+ Inkscape::DeviceManager::getManager().saveConfig();
+}
+
+void InputDialogImpl::ConfPanel::useExtToggled()
+{
+ bool active = useExt.get_active();
+ if (active != Preferences::get()->getBool("/options/useextinput/value")) {
+ Preferences::get()->setBool("/options/useextinput/value", active);
+ if (active) {
+ // As a work-around for a common problem, enable tablet toggles on the calligraphic tool.
+ // Covered in Launchpad bug #196195.
+ Preferences::get()->setBool("/tools/tweak/usepressure", true);
+ Preferences::get()->setBool("/tools/calligraphic/usepressure", true);
+ Preferences::get()->setBool("/tools/calligraphic/usetilt", true);
+ }
+ }
+}
+
+InputDialogImpl::ConfPanel::Blink::Blink(ConfPanel &parent) :
+ Preferences::Observer("/options/useextinput/value"),
+ parent(parent)
+{
+ Preferences::get()->addObserver(*this);
+}
+
+InputDialogImpl::ConfPanel::Blink::~Blink()
+{
+ Preferences::get()->removeObserver(*this);
+}
+
+void InputDialogImpl::ConfPanel::Blink::notify(Preferences::Entry const &new_val)
+{
+ parent.useExt.set_active(new_val.getBool());
+}
+
+void InputDialogImpl::handleDeviceChange(Glib::RefPtr<InputDevice const> device)
{
// g_message("OUCH!!!! for %p hits %s", &device, device->getId().c_str());
+ std::vector<Glib::RefPtr<Gtk::TreeStore> > stores;
+ stores.push_back(store);
+ stores.push_back(cfgPanel.store);
+
+ for (std::vector<Glib::RefPtr<Gtk::TreeStore> >::iterator it = stores.begin(); it != stores.end(); ++it) {
+ Gtk::TreeModel::iterator deviceIter;
+ (*it)->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>(
+ sigc::ptr_fun(&InputDialogImpl::findDevice),
+ device->getId(),
+ &deviceIter) );
+ if ( deviceIter ) {
+ Gdk::InputMode mode = device->getMode();
+ Gtk::TreeModel::Row row = *deviceIter;
+ if (row[getCols().mode] != mode) {
+ row[getCols().mode] = mode;
+ }
+ }
+ }
}
-void InputDialogImpl::updateDeviceAxes(const Glib::RefPtr<InputDevice>& device)
+void InputDialogImpl::updateDeviceAxes(Glib::RefPtr<InputDevice const> device)
{
gint live = device->getLiveAxes();
@@ -720,7 +951,7 @@ void InputDialogImpl::updateDeviceAxes(const Glib::RefPtr<InputDevice>& device)
updateTestAxes( device->getId(), 0 );
}
-void InputDialogImpl::updateDeviceButtons(const Glib::RefPtr<InputDevice>& device)
+void InputDialogImpl::updateDeviceButtons(Glib::RefPtr<InputDevice const> device)
{
gint live = device->getLiveButtons();
std::set<guint> existing = buttonMap[device->getId()];
@@ -741,7 +972,7 @@ bool InputDialogImpl::findDevice(const Gtk::TreeModel::iterator& iter,
Gtk::TreeModel::iterator* result)
{
bool stop = false;
- const InputDevice* dev = (*iter)[cols.device];
+ Glib::RefPtr<InputDevice const> dev = (*iter)[getCols().device];
if ( dev && (dev->getId() == id) ) {
if ( result ) {
*result = iter;
@@ -756,7 +987,7 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter,
Gtk::TreeModel::iterator* result)
{
bool stop = false;
- const InputDevice* dev = (*iter)[cols.device];
+ Glib::RefPtr<InputDevice const> dev = (*iter)[getCols().device];
if ( dev && (dev->getLink() == link) ) {
if ( result ) {
*result = iter;
@@ -766,12 +997,14 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter,
return stop;
}
-void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
+void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Gtk::TreeIter tabletIter, Glib::RefPtr<Gtk::TreeView> tree)
{
+ Glib::RefPtr<Gtk::TreeStore> store = Glib::RefPtr<Gtk::TreeStore>::cast_dynamic(tree->get_model());
+
// g_message("Links!!!! for %p hits [%s] with link of [%s]", &device, device->getId().c_str(), device->getLink().c_str());
Gtk::TreeModel::iterator deviceIter;
store->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>(
- sigc::mem_fun(*this, &InputDialogImpl::findDevice),
+ sigc::ptr_fun(&InputDialogImpl::findDevice),
device->getId(),
&deviceIter) );
@@ -783,15 +1016,16 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
// g_message("Item %s is unlinked", device->getId().c_str());
if ( deviceIter->parent() != tabletIter ) {
// Not the child of the tablet. move on up
-
- InputDevice const *dev = (*deviceIter)[cols.device];
- Glib::ustring descr = (*deviceIter)[cols.description];
- Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[cols.thumbnail];
+
+ Glib::RefPtr<InputDevice const> dev = (*deviceIter)[getCols().device];
+ Glib::ustring descr = (*deviceIter)[getCols().description];
+ Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[getCols().thumbnail];
Gtk::TreeModel::Row deviceRow = *store->append(tabletIter->children());
- deviceRow[cols.description] = descr;
- deviceRow[cols.thumbnail] = thumb;
- deviceRow[cols.device] = dev;
+ deviceRow[getCols().description] = descr;
+ deviceRow[getCols().thumbnail] = thumb;
+ deviceRow[getCols().device] = dev;
+ deviceRow[getCols().mode] = dev->getMode();
Gtk::TreeModel::iterator oldParent = deviceIter->parent();
store->erase(deviceIter);
@@ -805,33 +1039,35 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
// Simple case. Not already linked
Gtk::TreeIter newGroup = store->append(tabletIter->children());
- (*newGroup)[cols.description] = "Pen";
- (*newGroup)[cols.thumbnail] = penPix;
+ (*newGroup)[getCols().description] = _("Pen");
+ (*newGroup)[getCols().thumbnail] = getPix(PIX_PEN);
- InputDevice const *dev = (*deviceIter)[cols.device];
- Glib::ustring descr = (*deviceIter)[cols.description];
- Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[cols.thumbnail];
+ Glib::RefPtr<InputDevice const> dev = (*deviceIter)[getCols().device];
+ Glib::ustring descr = (*deviceIter)[getCols().description];
+ Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[getCols().thumbnail];
Gtk::TreeModel::Row deviceRow = *store->append(newGroup->children());
- deviceRow[cols.description] = descr;
- deviceRow[cols.thumbnail] = thumb;
- deviceRow[cols.device] = dev;
+ deviceRow[getCols().description] = descr;
+ deviceRow[getCols().thumbnail] = thumb;
+ deviceRow[getCols().device] = dev;
+ deviceRow[getCols().mode] = dev->getMode();
+
-
Gtk::TreeModel::iterator linkIter;
store->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>(
- sigc::mem_fun(*this, &InputDialogImpl::findDeviceByLink),
+ sigc::ptr_fun(&InputDialogImpl::findDeviceByLink),
device->getId(),
&linkIter) );
if ( linkIter ) {
- dev = (*linkIter)[cols.device];
- descr = (*linkIter)[cols.description];
- thumb = (*linkIter)[cols.thumbnail];
+ dev = (*linkIter)[getCols().device];
+ descr = (*linkIter)[getCols().description];
+ thumb = (*linkIter)[getCols().thumbnail];
deviceRow = *store->append(newGroup->children());
- deviceRow[cols.description] = descr;
- deviceRow[cols.thumbnail] = thumb;
- deviceRow[cols.device] = dev;
+ deviceRow[getCols().description] = descr;
+ deviceRow[getCols().thumbnail] = thumb;
+ deviceRow[getCols().device] = dev;
+ deviceRow[getCols().mode] = dev->getMode();
Gtk::TreeModel::iterator oldParent = linkIter->parent();
store->erase(linkIter);
if ( oldParent->children().empty() ) {
@@ -844,7 +1080,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
if ( oldParent->children().empty() ) {
store->erase(oldParent);
}
- tree.expand_row(Gtk::TreePath(newGroup), true);
+ tree->expand_row(Gtk::TreePath(newGroup), true);
}
}
}
@@ -855,16 +1091,16 @@ void InputDialogImpl::linkComboChanged() {
Gtk::TreeModel::iterator iter = treeSel->get_selected();
if (iter) {
Gtk::TreeModel::Row row = *iter;
- Glib::ustring val = row[cols.description];
- InputDevice const * dev = row[cols.device];
+ Glib::ustring val = row[getCols().description];
+ Glib::RefPtr<InputDevice const> dev = row[getCols().device];
if ( dev ) {
if ( linkCombo.get_active_row_number() == 0 ) {
// It is the "None" entry
DeviceManager::getManager().setLinkedTo(dev->getId(), "");
} else {
Glib::ustring linkName = linkCombo.get_active_text();
- std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
- for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+ std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
+ for ( std::list<Glib::RefPtr<InputDevice const> >::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
if ( linkName == (*it)->getName() ) {
DeviceManager::getManager().setLinkedTo(dev->getId(), (*it)->getId());
break;
@@ -881,19 +1117,19 @@ void InputDialogImpl::resyncToSelection() {
Gtk::TreeModel::iterator iter = treeSel->get_selected();
if (iter) {
Gtk::TreeModel::Row row = *iter;
- Glib::ustring val = row[cols.description];
- InputDevice const * dev = row[cols.device];
+ Glib::ustring val = row[getCols().description];
+ Glib::RefPtr<InputDevice const> dev = row[getCols().device];
if ( dev ) {
devDetails.set_sensitive(true);
linkConnection.block();
linkCombo.clear_items();
- linkCombo.append_text("None");
+ linkCombo.append_text(_("None"));
linkCombo.set_active(0);
if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
Glib::ustring linked = dev->getLink();
- std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
- for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+ std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
+ for ( std::list<Glib::RefPtr<InputDevice const> >::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) {
linkCombo.append_text((*it)->getName().c_str());
if ( (linked.length() > 0) && (linked == (*it)->getId()) ) {
@@ -908,7 +1144,7 @@ void InputDialogImpl::resyncToSelection() {
linkConnection.unblock();
clear = false;
- devName.set_label(row[cols.description]);
+ devName.set_label(row[getCols().description]);
setupValueAndCombo( dev->getNumAxes(), dev->getNumAxes(), devAxesCount, axesCombo);
setupValueAndCombo( dev->getNumKeys(), dev->getNumKeys(), devKeyCount, buttonCombo);
}
@@ -945,12 +1181,12 @@ void InputDialogImpl::updateTestButtons( Glib::ustring const& key, gint hotButto
for ( gint i = 0; i < static_cast<gint>(G_N_ELEMENTS(testButtons)); i++ ) {
if ( buttonMap[key].find(i) != buttonMap[key].end() ) {
if ( i == hotButton ) {
- testButtons[i].set(buttonsOnPix);
+ testButtons[i].set(getPix(PIX_BUTTONS_ON));
} else {
- testButtons[i].set(buttonsOffPix);
+ testButtons[i].set(getPix(PIX_BUTTONS_OFF));
}
} else {
- testButtons[i].set(buttonsNonePix);
+ testButtons[i].set(getPix(PIX_BUTTONS_NONE));
}
}
}
@@ -963,8 +1199,8 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev )
Gtk::TreeModel::iterator iter = treeSel->get_selected();
if (iter) {
Gtk::TreeModel::Row row = *iter;
- Glib::ustring val = row[cols.description];
- InputDevice const * idev = row[cols.device];
+ Glib::ustring val = row[getCols().description];
+ Glib::RefPtr<InputDevice const> idev = row[getCols().device];
if ( !idev || (idev->getId() != key) ) {
dev = 0;
}
@@ -977,13 +1213,13 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev )
switch ( axesMap[key][i].first ) {
case 0:
case 1:
- testAxes[i].set(axisNonePix);
+ testAxes[i].set(getPix(PIX_AXIS_NONE));
if ( dev && (i < static_cast<gint>(G_N_ELEMENTS(axesValues)) ) ) {
axesValues[i].set_sensitive(false);
}
break;
case 2:
- testAxes[i].set(axisOffPix);
+ testAxes[i].set(getPix(PIX_AXIS_OFF));
axesValues[i].set_sensitive(true);
if ( dev && (i < static_cast<gint>(G_N_ELEMENTS(axesValues)) ) ) {
if ( (dev->axes[i].max - dev->axes[i].min) > epsilon ) {
@@ -996,7 +1232,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev )
}
break;
case 3:
- testAxes[i].set(axisOnPix);
+ testAxes[i].set(getPix(PIX_AXIS_ON));
axesValues[i].set_sensitive(true);
if ( dev && (i < static_cast<gint>(G_N_ELEMENTS(axesValues)) ) ) {
if ( (dev->axes[i].max - dev->axes[i].min) > epsilon ) {
@@ -1010,7 +1246,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev )
}
} else {
- testAxes[i].set(axisNonePix);
+ testAxes[i].set(getPix(PIX_AXIS_NONE));
}
}
if ( !dev ) {
@@ -1180,30 +1416,30 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event)
switch (source) {
case GDK_SOURCE_MOUSE:
{
- testThumb.set(corePix);
+ testThumb.set(getPix(PIX_CORE));
}
break;
case GDK_SOURCE_CURSOR:
{
// g_message("flip to cursor");
- testThumb.set(mousePix);
+ testThumb.set(getPix(PIX_MOUSE));
}
break;
case GDK_SOURCE_PEN:
{
- if (devName == "pad") {
+ if (devName == _("pad")) {
// g_message("flip to pad");
- testThumb.set(sidebuttonsPix);
+ testThumb.set(getPix(PIX_SIDEBUTTONS));
} else {
// g_message("flip to pen");
- testThumb.set(tipPix);
+ testThumb.set(getPix(PIX_TIP));
}
}
break;
case GDK_SOURCE_ERASER:
{
// g_message("flip to eraser");
- testThumb.set(eraserPix);
+ testThumb.set(getPix(PIX_ERASER));
}
break;
// default:
diff --git a/src/ui/dialog/input.h b/src/ui/dialog/input.h
index 38666f52c..186612af0 100644
--- a/src/ui/dialog/input.h
+++ b/src/ui/dialog/input.h
@@ -25,7 +25,7 @@ class InputDialog : public UI::Widget::Panel
public:
static InputDialog &getInstance();
- InputDialog() : UI::Widget::Panel("", "/dialogs/inputdevices2", SP_VERB_DIALOG_INPUT2) {}
+ InputDialog() : UI::Widget::Panel("", "/dialogs/inputdevices", SP_VERB_DIALOG_INPUT) {}
virtual ~InputDialog() {}
};
diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h
index 7dbb6dd4a..dc01c6a29 100644
--- a/src/ui/dialog/panel-dialog.h
+++ b/src/ui/dialog/panel-dialog.h
@@ -30,14 +30,14 @@ namespace Dialog {
class PanelDialogBase {
public:
- PanelDialogBase(Panel &panel, char const */*prefs_path*/, int const /*verb_num*/,
+ PanelDialogBase(UI::Widget::Panel &panel, char const */*prefs_path*/, int const /*verb_num*/,
Glib::ustring const &/*apply_label*/) :
_panel (panel) { }
virtual void present() = 0;
virtual ~PanelDialogBase() {}
- virtual Panel &getPanel() { return _panel; }
+ virtual UI::Widget::Panel &getPanel() { return _panel; }
protected:
static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) {
@@ -54,7 +54,7 @@ protected:
inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *);
inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *);
- Panel &_panel;
+ UI::Widget::Panel &_panel;
sigc::connection _document_replaced_connection;
};
@@ -62,7 +62,7 @@ template <typename Behavior>
class PanelDialog : public PanelDialogBase, public Inkscape::UI::Dialog::Dialog {
public:
- PanelDialog(Panel &contents, char const *prefs_path, int const verb_num,
+ PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num,
Glib::ustring const &apply_label);
virtual ~PanelDialog() {}
@@ -86,7 +86,7 @@ class PanelDialog<Behavior::FloatingBehavior> :
public PanelDialogBase, public Inkscape::UI::Dialog::Dialog {
public:
- inline PanelDialog(Panel &contents, char const *prefs_path, int const verb_num,
+ inline PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num,
Glib::ustring const &apply_label);
virtual ~PanelDialog() {}
@@ -128,7 +128,7 @@ PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application
template <typename B>
-PanelDialog<B>::PanelDialog(Panel &panel, char const *prefs_path, int const verb_num,
+PanelDialog<B>::PanelDialog(Widget::Panel &panel, char const *prefs_path, int const verb_num,
Glib::ustring const &apply_label) :
PanelDialogBase(panel, prefs_path, verb_num, apply_label),
Dialog(&B::create, prefs_path, verb_num, apply_label)
@@ -163,7 +163,7 @@ template <typename B> template <typename P>
PanelDialog<B> *
PanelDialog<B>::create()
{
- Panel &panel = P::getInstance();
+ UI::Widget::Panel &panel = P::getInstance();
return new PanelDialog<B>(panel, panel.getPrefsPath(), panel.getVerb(), panel.getApplyLabel());
}
@@ -171,17 +171,17 @@ template <typename B>
void
PanelDialog<B>::present()
{
- _panel.present();
+ _panel.present();
}
template <typename B>
void
PanelDialog<B>::_presentDialog()
{
- Dialog::present();
+ Dialog::present();
}
-PanelDialog<Behavior::FloatingBehavior>::PanelDialog(Panel &panel, char const *prefs_path,
+PanelDialog<Behavior::FloatingBehavior>::PanelDialog(UI::Widget::Panel &panel, char const *prefs_path,
int const verb_num, Glib::ustring const &apply_label) :
PanelDialogBase(panel, prefs_path, verb_num, apply_label),
Dialog(&Behavior::FloatingBehavior::create, prefs_path, verb_num, apply_label)
@@ -213,7 +213,7 @@ PanelDialog<Behavior::FloatingBehavior>::PanelDialog(Panel &panel, char const *p
void
PanelDialog<Behavior::FloatingBehavior>::present()
-{
+{
Dialog::present();
_panel.present();
}
@@ -226,7 +226,7 @@ template <typename P>
PanelDialog<Behavior::FloatingBehavior> *
PanelDialog<Behavior::FloatingBehavior>::create()
{
- Panel &panel = P::getInstance();
+ UI::Widget::Panel &panel = P::getInstance();
PanelDialog<Behavior::FloatingBehavior> *instance =
new PanelDialog<Behavior::FloatingBehavior>(panel, panel.getPrefsPath(),
panel.getVerb(), panel.getApplyLabel());
diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp
index e0191c589..6be346582 100644
--- a/src/ui/dialog/tile.cpp
+++ b/src/ui/dialog/tile.cpp
@@ -31,6 +31,7 @@
#include "sp-item.h"
#include "widgets/icon.h"
#include "tile.h"
+#include "desktop.h"
/*
* Sort items by their x co-ordinates, taking account of y (keeps rows intact)
@@ -161,7 +162,7 @@ void TileDialog::Grid_Arrange ()
sp_document_ensure_up_to_date(sp_desktop_document(desktop));
Inkscape::Selection *selection = sp_desktop_selection (desktop);
- const GSList *items = selection->itemList();
+ const GSList *items = selection ? selection->itemList() : 0;
cnt=0;
for (; items != NULL; items = items->next) {
SPItem *item = SP_ITEM(items->data);
@@ -193,6 +194,7 @@ void TileDialog::Grid_Arrange ()
// require the sorting done before we can calculate row heights etc.
+ g_return_if_fail(selection);
const GSList *items2 = selection->itemList();
GSList *rev = g_slist_copy((GSList *) items2);
GSList *sorted = NULL;
@@ -373,7 +375,8 @@ void TileDialog::on_row_spinbutton_changed()
updating = true;
SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail( selection );
GSList const *items = selection->itemList();
int selcount = g_slist_length((GSList *)items);
@@ -398,7 +401,8 @@ void TileDialog::on_col_spinbutton_changed()
// in turn, prevent listener from responding
updating = true;
SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail(selection);
GSList const *items = selection->itemList();
int selcount = g_slist_length((GSList *)items);
@@ -560,32 +564,33 @@ void TileDialog::updateSelection()
// in turn, prevent listener from responding
updating = true;
SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
- const GSList *items = selection->itemList();
- int selcount = g_slist_length((GSList *)items);
-
- if (NoOfColsSpinner.get_value()>1 && NoOfRowsSpinner.get_value()>1){
- // Update the number of rows assuming number of columns wanted remains same.
- double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value());
- NoOfRowsSpinner.set_value(NoOfRows);
-
- // if the selection has less than the number set for one row, reduce it appropriately
- if (selcount<NoOfColsSpinner.get_value()) {
- double NoOfCols = ceil(selcount / NoOfRowsSpinner.get_value());
- NoOfColsSpinner.set_value(NoOfCols);
- prefs->setInt("/dialogs/gridtiler/NoOfCols", NoOfCols);
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ GSList const *items = selection ? selection->itemList() : 0;
+
+ if (items) {
+ int selcount = g_slist_length((GSList *)items);
+
+ if (NoOfColsSpinner.get_value() > 1 && NoOfRowsSpinner.get_value() > 1){
+ // Update the number of rows assuming number of columns wanted remains same.
+ double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value());
+ NoOfRowsSpinner.set_value(NoOfRows);
+
+ // if the selection has less than the number set for one row, reduce it appropriately
+ if (selcount < NoOfColsSpinner.get_value()) {
+ double NoOfCols = ceil(selcount / NoOfRowsSpinner.get_value());
+ NoOfColsSpinner.set_value(NoOfCols);
+ prefs->setInt("/dialogs/gridtiler/NoOfCols", NoOfCols);
+ }
+ } else {
+ double PerRow = ceil(sqrt(selcount));
+ double PerCol = ceil(sqrt(selcount));
+ NoOfRowsSpinner.set_value(PerRow);
+ NoOfColsSpinner.set_value(PerCol);
+ prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast<int>(PerCol));
}
- } else {
- double PerRow = ceil(sqrt(selcount));
- double PerCol = ceil(sqrt(selcount));
- NoOfRowsSpinner.set_value(PerRow);
- NoOfColsSpinner.set_value(PerCol);
- prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast<int>(PerCol));
-
}
- updating=false;
-
+ updating = false;
}
@@ -632,7 +637,8 @@ TileDialog::TileDialog()
SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail( selection );
int selcount = 1;
if (!selection->isEmpty()) {
GSList const *items = selection->itemList();
diff --git a/src/ui/dialog/tile.h b/src/ui/dialog/tile.h
index 075b2b33f..9ade64935 100644
--- a/src/ui/dialog/tile.h
+++ b/src/ui/dialog/tile.h
@@ -66,10 +66,7 @@ public:
void VertAlign_changed();
void HorizAlign_changed();
- static TileDialog& getInstance() {
- static TileDialog instance;
- return instance;
- }
+ static TileDialog& getInstance() { return *new TileDialog(); }
private:
TileDialog(TileDialog const &d); // no copy
diff --git a/src/ui/dialog/transformation.h b/src/ui/dialog/transformation.h
index 9d05713ad..0607871fd 100644
--- a/src/ui/dialog/transformation.h
+++ b/src/ui/dialog/transformation.h
@@ -26,8 +26,6 @@
#include "ui/widget/button.h"
-using namespace Inkscape::UI::Widget;
-
namespace Inkscape {
@@ -105,36 +103,36 @@ protected:
Gtk::Notebook _notebook;
- NotebookPage _page_move;
- NotebookPage _page_scale;
- NotebookPage _page_rotate;
- NotebookPage _page_skew;
- NotebookPage _page_transform;
-
- UnitMenu _units_move;
- UnitMenu _units_scale;
- UnitMenu _units_rotate;
- UnitMenu _units_skew;
-
- ScalarUnit _scalar_move_horizontal;
- ScalarUnit _scalar_move_vertical;
- ScalarUnit _scalar_scale_horizontal;
- ScalarUnit _scalar_scale_vertical;
- ScalarUnit _scalar_rotate;
- ScalarUnit _scalar_skew_horizontal;
- ScalarUnit _scalar_skew_vertical;
-
- Scalar _scalar_transform_a;
- Scalar _scalar_transform_b;
- Scalar _scalar_transform_c;
- Scalar _scalar_transform_d;
- Scalar _scalar_transform_e;
- Scalar _scalar_transform_f;
-
- CheckButton _check_move_relative;
- CheckButton _check_scale_proportional;
- CheckButton _check_apply_separately;
- CheckButton _check_replace_matrix;
+ UI::Widget::NotebookPage _page_move;
+ UI::Widget::NotebookPage _page_scale;
+ UI::Widget::NotebookPage _page_rotate;
+ UI::Widget::NotebookPage _page_skew;
+ UI::Widget::NotebookPage _page_transform;
+
+ UI::Widget::UnitMenu _units_move;
+ UI::Widget::UnitMenu _units_scale;
+ UI::Widget::UnitMenu _units_rotate;
+ UI::Widget::UnitMenu _units_skew;
+
+ UI::Widget::ScalarUnit _scalar_move_horizontal;
+ UI::Widget::ScalarUnit _scalar_move_vertical;
+ UI::Widget::ScalarUnit _scalar_scale_horizontal;
+ UI::Widget::ScalarUnit _scalar_scale_vertical;
+ UI::Widget::ScalarUnit _scalar_rotate;
+ UI::Widget::ScalarUnit _scalar_skew_horizontal;
+ UI::Widget::ScalarUnit _scalar_skew_vertical;
+
+ UI::Widget::Scalar _scalar_transform_a;
+ UI::Widget::Scalar _scalar_transform_b;
+ UI::Widget::Scalar _scalar_transform_c;
+ UI::Widget::Scalar _scalar_transform_d;
+ UI::Widget::Scalar _scalar_transform_e;
+ UI::Widget::Scalar _scalar_transform_f;
+
+ UI::Widget::CheckButton _check_move_relative;
+ UI::Widget::CheckButton _check_scale_proportional;
+ UI::Widget::CheckButton _check_apply_separately;
+ UI::Widget::CheckButton _check_replace_matrix;
/**
* Layout the GUI components, and prepare for use
diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp
index 443e7f258..b5f420597 100644
--- a/src/ui/tool/node-tool.cpp
+++ b/src/ui/tool/node-tool.cpp
@@ -316,7 +316,8 @@ void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value)
Glib::ustring entry_name = value->getEntryName();
if (entry_name == "show_handles") {
- nt->_multipath->showHandles(value->getBool(true));
+ nt->show_handles = value->getBool(true);
+ nt->_multipath->showHandles(nt->show_handles);
} else if (entry_name == "show_outline") {
nt->show_outline = value->getBool();
nt->_multipath->showOutline(nt->show_outline);
@@ -491,6 +492,7 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event)
ink_node_tool_update_tip(nt, event);
return TRUE;
case GDK_a:
+ case GDK_A:
if (held_control(event->key) && held_alt(event->key)) {
nt->_selected_nodes->selectAll();
// Ctrl+A is handled in selection-chemistry.cpp via verb
@@ -498,6 +500,14 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event)
return TRUE;
}
break;
+ case GDK_h:
+ case GDK_H:
+ if (held_only_control(event->key)) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/tools/nodes/show_handles", !nt->show_handles);
+ return TRUE;
+ }
+ break;
default:
break;
}
diff --git a/src/ui/tool/node-tool.h b/src/ui/tool/node-tool.h
index baac642ac..641d064c1 100644
--- a/src/ui/tool/node-tool.h
+++ b/src/ui/tool/node-tool.h
@@ -58,6 +58,7 @@ struct InkNodeTool : public SPEventContext
SPItem *_last_over;
unsigned cursor_drag : 1;
+ unsigned show_handles : 1;
unsigned show_outline : 1;
unsigned live_outline : 1;
unsigned live_objects : 1;
diff --git a/src/ui/widget/imageicon.cpp b/src/ui/widget/imageicon.cpp
index 6a817e30d..71ba4428c 100644
--- a/src/ui/widget/imageicon.cpp
+++ b/src/ui/widget/imageicon.cpp
@@ -295,7 +295,7 @@ void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage)
" <text"
" xml:space='preserve'"
" id='text1644'"
- " style='font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans'"
+ " style='font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Sans'"
" y='59.288345'"
" x='12.760736'><tspan"
" id='tspan1646'"
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
index 93a950d1a..4b806afb5 100644
--- a/src/ui/widget/panel.cpp
+++ b/src/ui/widget/panel.cpp
@@ -133,9 +133,9 @@ void Panel::_init()
{
//TRANSLATORS: only translate "string" in "context|string".
// For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
- Glib::ustring heightItemLabel(Q_("swatches|Size"));
+ Glib::ustring heightItemLabel(Q_("swatches|Size"));
- //TRANSLATORS: Indicates size of colour swatches
+ //TRANSLATORS: Indicates size of colour swatches
const gchar *heightLabels[] = {
N_("tiny"),
N_("small"),
@@ -157,7 +157,7 @@ void Panel::_init()
Gtk::RadioMenuItem* _item = manage(new Gtk::RadioMenuItem(heightGroup, _label));
sizeMenu->append(*_item);
if (i == panel_size) {
- _item->set_active(true);
+ _item->set_active(true);
}
_item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i));
}
@@ -198,11 +198,11 @@ void Panel::_init()
}
}
for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) {
- Glib::ustring _label(Q_(widthLabels[i]));
+ Glib::ustring _label(Q_(widthLabels[i]));
Gtk::RadioMenuItem *_item = manage(new Gtk::RadioMenuItem(widthGroup, _label));
type_menu->append(*_item);
if ( i <= hot_index ) {
- _item->set_active(true);
+ _item->set_active(true);
}
_item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SHAPE, values[i]));
}
@@ -212,7 +212,7 @@ void Panel::_init()
//TRANSLATORS: only translate "string" in "context|string".
// For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
// "Wrap" indicates how colour swatches are displayed
- Glib::ustring wrap_label(Q_("swatches|Wrap"));
+ Glib::ustring wrap_label(Q_("swatches|Wrap"));
Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label));
check->set_active(panel_wrap);
_menu->append(*check);
diff --git a/src/verbs.cpp b/src/verbs.cpp
index dc1116953..24c17aad8 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -40,7 +40,6 @@
#include "desktop-handles.h"
#include "dialogs/clonetiler.h"
#include "dialogs/find.h"
-#include "dialogs/input.h"
#include "dialogs/item-properties.h"
#include "dialogs/spellcheck.h"
#include "dialogs/text-edit.h"
@@ -73,6 +72,7 @@
#include "ui/dialog/dialog-manager.h"
#include "ui/dialog/document-properties.h"
#include "ui/dialog/extensions.h"
+#include "ui/dialog/glyphs.h"
#include "ui/dialog/icon-preview.h"
#include "ui/dialog/inkscape-preferences.h"
#include "ui/dialog/layer-properties.h"
@@ -1731,6 +1731,9 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/)
case SP_VERB_DIALOG_FILL_STROKE:
dt->_dlg_mgr->showDialog("FillAndStroke");
break;
+ case SP_VERB_DIALOG_GLYPHS:
+ dt->_dlg_mgr->showDialog("Glyphs");
+ break;
case SP_VERB_DIALOG_SWATCHES:
dt->_dlg_mgr->showDialog("Swatches");
break;
@@ -1787,9 +1790,6 @@ DialogVerb::perform(SPAction *action, void *data, void */*pdata*/)
}
#endif*/
case SP_VERB_DIALOG_INPUT:
- sp_input_dialog();
- break;
- case SP_VERB_DIALOG_INPUT2:
dt->_dlg_mgr->showDialog("InputDevices");
break;
case SP_VERB_DIALOG_EXTENSIONEDITOR:
@@ -2597,6 +2597,8 @@ Verb *Verb::_base_verbs[] = {
N_("Edit document metadata (to be saved with the document)"), INKSCAPE_ICON_DOCUMENT_METADATA ),
new DialogVerb(SP_VERB_DIALOG_FILL_STROKE, "DialogFillStroke", N_("_Fill and Stroke..."),
N_("Edit objects' colors, gradients, stroke width, arrowheads, dash patterns..."), INKSCAPE_ICON_DIALOG_FILL_AND_STROKE),
+ new DialogVerb(SP_VERB_DIALOG_GLYPHS, "DialogGlyphs", N_("Glyphs..."),
+ N_("Select characters from a glyphs palette"), GTK_STOCK_SELECT_FONT),
// TRANSLATORS: "Swatches" means: color samples
new DialogVerb(SP_VERB_DIALOG_SWATCHES, "DialogSwatches", N_("S_watches..."),
N_("Select colors from a swatches palette"), GTK_STOCK_SELECT_COLOR),
@@ -2634,8 +2636,6 @@ Verb *Verb::_base_verbs[] = {
#endif*/
new DialogVerb(SP_VERB_DIALOG_INPUT, "DialogInput", N_("_Input Devices..."),
N_("Configure extended input devices, such as a graphics tablet"), INKSCAPE_ICON_DIALOG_INPUT_DEVICES),
- new DialogVerb(SP_VERB_DIALOG_INPUT2, "DialogInput2", N_("_Input Devices (new)..."),
- N_("Configure extended input devices, such as a graphics tablet"), INKSCAPE_ICON_DIALOG_INPUT_DEVICES),
new DialogVerb(SP_VERB_DIALOG_EXTENSIONEDITOR, "org.inkscape.dialogs.extensioneditor", N_("_Extensions..."),
N_("Query information about extensions"), NULL),
new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."),
diff --git a/src/verbs.h b/src/verbs.h
index 7cc580f26..36bb9f9d9 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -227,6 +227,7 @@ enum {
SP_VERB_DIALOG_NAMEDVIEW,
SP_VERB_DIALOG_METADATA,
SP_VERB_DIALOG_FILL_STROKE,
+ SP_VERB_DIALOG_GLYPHS,
SP_VERB_DIALOG_SWATCHES,
SP_VERB_DIALOG_TRANSFORM,
SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
@@ -246,7 +247,6 @@ enum {
SP_VERB_XMPP_CLIENT,
#endif*/
SP_VERB_DIALOG_INPUT,
- SP_VERB_DIALOG_INPUT2,
SP_VERB_DIALOG_EXTENSIONEDITOR,
SP_VERB_DIALOG_LAYERS,
SP_VERB_DIALOG_LIVE_PATH_EFFECT,
diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert
index 5d327d8a3..313e27528 100644
--- a/src/widgets/Makefile_insert
+++ b/src/widgets/Makefile_insert
@@ -13,6 +13,7 @@ ink_common_sources += \
widgets/ege-paint-def.h \
widgets/fill-style.cpp \
widgets/fill-style.h \
+ widgets/fill-n-stroke-factory.h \
widgets/font-selector.cpp \
widgets/font-selector.h \
widgets/gradient-image.cpp \
diff --git a/src/widgets/fill-n-stroke-factory.h b/src/widgets/fill-n-stroke-factory.h
new file mode 100644
index 000000000..74339a07f
--- /dev/null
+++ b/src/widgets/fill-n-stroke-factory.h
@@ -0,0 +1,36 @@
+#ifndef SEEN_FILL_N_STROKE_FACTORY_H
+#define SEEN_FILL_N_STROKE_FACTORY_H
+/* Authors:
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2010 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "fill-or-stroke.h"
+
+namespace Gtk {
+class Widget;
+}
+
+namespace Inkscape {
+namespace Widgets {
+
+Gtk::Widget *createStyleWidget( FillOrStroke kind );
+
+} // namespace Widgets
+} // namespace Inkscape
+
+#endif // !SEEN_FILL_N_STROKE_FACTORY_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:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp
index 3f2018b91..15d8b6cc2 100644
--- a/src/widgets/fill-style.cpp
+++ b/src/widgets/fill-style.cpp
@@ -5,9 +5,11 @@
* Lauris Kaplinski <lauris@kaplinski.com>
* Frank Felfe <innerspace@iname.com>
* bulia byak <buliabyak@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 1999-2005 authors
* Copyright (C) 2001-2002 Ximian, Inc.
+ * Copyright (C) 2010 Jon A. Cruz
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -19,7 +21,11 @@
#endif
#include <glibmm/i18n.h>
+#include <gtkmm/box.h>
+#include <gtk/gtkvbox.h>
+#include "desktop.h"
+#include "selection.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "display/sp-canvas.h"
@@ -32,162 +38,201 @@
#include "sp-radial-gradient.h"
#include "style.h"
#include "widgets/paint-selector.h"
-#include "widgets/sp-widget.h"
#include "xml/repr.h"
-#include "widgets/fill-style.h"
+#include "fill-style.h"
+#include "fill-n-stroke-factory.h"
// These can be deleted once we sort out the libart dependence.
#define ART_WIND_RULE_NONZERO 0
-static void sp_fill_style_widget_construct ( SPWidget *spw,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_modify_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- guint flags,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
+/* Fill */
-static void sp_fill_style_widget_change_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- SPPaintSelector *psel );
-static void sp_fill_style_widget_update (SPWidget *spw);
+Gtk::Widget *sp_fill_style_widget_new(void)
+{
+ return Inkscape::Widgets::createStyleWidget( FILL );
+}
-static void sp_fill_style_widget_paint_mode_changed( SPPaintSelector *psel,
- SPPaintSelector::Mode mode,
- SPWidget *spw );
-static void sp_fill_style_widget_fillrule_changed( SPPaintSelector *psel,
- SPPaintSelector::FillRule mode,
- SPWidget *spw );
-static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw );
-static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw );
+namespace Inkscape {
-GtkWidget *
-sp_fill_style_widget_new (void)
+class FillNStroke : public Gtk::VBox
{
- GtkWidget *spw = sp_widget_new_global (INKSCAPE);
-
- GtkWidget *vb = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vb);
- gtk_container_add (GTK_CONTAINER (spw), vb);
+public:
+ FillNStroke( FillOrStroke kind );
+ ~FillNStroke();
- GtkWidget *psel = sp_paint_selector_new (true); // with fillrule selector
- gtk_widget_show (psel);
- gtk_box_pack_start (GTK_BOX (vb), psel, TRUE, TRUE, 0);
- g_object_set_data (G_OBJECT (spw), "paint-selector", psel);
+ void setFillrule( SPPaintSelector::FillRule mode );
- g_signal_connect ( G_OBJECT (psel), "mode_changed",
- G_CALLBACK (sp_fill_style_widget_paint_mode_changed),
- spw );
+ void setDesktop(SPDesktop *desktop);
- g_signal_connect ( G_OBJECT (psel), "dragged",
- G_CALLBACK (sp_fill_style_widget_paint_dragged),
- spw );
+private:
+ static void paintModeChangeCB(SPPaintSelector *psel, SPPaintSelector::Mode mode, FillNStroke *self);
+ static void paintChangedCB(SPPaintSelector *psel, FillNStroke *self);
+ static void paintDraggedCB(SPPaintSelector *psel, FillNStroke *self);
+ static gboolean dragDelayCB(gpointer data);
- g_signal_connect ( G_OBJECT (psel), "changed",
- G_CALLBACK (sp_fill_style_widget_paint_changed),
- spw );
+ static void fillruleChangedCB( SPPaintSelector *psel, SPPaintSelector::FillRule mode, FillNStroke *self );
- g_signal_connect ( G_OBJECT (psel), "fillrule_changed",
- G_CALLBACK (sp_fill_style_widget_fillrule_changed),
- spw );
+ void selectionModifiedCB(guint flags);
+ void dragFromPaint();
+ void updateFromPaint();
- g_signal_connect ( G_OBJECT (spw), "construct",
- G_CALLBACK (sp_fill_style_widget_construct), psel);
+ void performUpdate();
-//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates
-//those anyway; then eliminate spw
- g_signal_connect ( G_OBJECT (spw), "modify_selection",
- G_CALLBACK (sp_fill_style_widget_modify_selection), psel);
+ FillOrStroke kind;
+ SPDesktop *desktop;
+ SPPaintSelector *psel;
+ guint32 lastDrag;
+ guint dragId;
+ bool update;
+ sigc::connection selectChangedConn;
+ sigc::connection subselChangedConn;
+ sigc::connection selectModifiedConn;
+};
- g_signal_connect ( G_OBJECT (spw), "change_selection",
- G_CALLBACK (sp_fill_style_widget_change_selection), psel);
+} // namespace Inkscape
- g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_fill_style_widget_change_subselection), spw);
+void sp_fill_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop)
+{
+ Inkscape::FillNStroke *fs = dynamic_cast<Inkscape::FillNStroke*>(widget);
+ if (fs) {
+ fs->setDesktop(desktop);
+ }
+}
- sp_fill_style_widget_update (SP_WIDGET (spw));
+namespace Inkscape {
- return spw;
+/**
+ * Create the fill or stroke style widget, and hook up all the signals.
+ */
+Gtk::Widget *Inkscape::Widgets::createStyleWidget( FillOrStroke kind )
+{
+ FillNStroke *filler = new FillNStroke(kind);
-} // end of sp_fill_style_widget_new()
+ return filler;
+}
+FillNStroke::FillNStroke( FillOrStroke kind ) :
+ Gtk::VBox(),
+ kind(kind),
+ desktop(0),
+ psel(0),
+ lastDrag(0),
+ dragId(0),
+ update(false),
+ selectChangedConn(),
+ subselChangedConn(),
+ selectModifiedConn()
+{
+ // Add and connect up the paint selector widget:
+ psel = sp_paint_selector_new(kind);
+ gtk_widget_show(GTK_WIDGET(psel));
+ gtk_container_add(GTK_CONTAINER(gobj()), GTK_WIDGET(psel));
+ g_signal_connect( G_OBJECT(psel), "mode_changed",
+ G_CALLBACK(paintModeChangeCB),
+ this );
+
+ g_signal_connect( G_OBJECT(psel), "dragged",
+ G_CALLBACK(paintDraggedCB),
+ this );
+
+ g_signal_connect( G_OBJECT(psel), "changed",
+ G_CALLBACK(paintChangedCB),
+ this );
+ if (kind == FILL) {
+ g_signal_connect( G_OBJECT(psel), "fillrule_changed",
+ G_CALLBACK(fillruleChangedCB),
+ this );
+ }
+ performUpdate();
+}
-static void
-sp_fill_style_widget_construct( SPWidget *spw, SPPaintSelector */*psel*/ )
+FillNStroke::~FillNStroke()
{
-#ifdef SP_FS_VERBOSE
- g_print ( "Fill style widget constructed: inkscape %p\n",
- spw->inkscape );
-#endif
- if (spw->inkscape) {
- sp_fill_style_widget_update (spw);
+ if (dragId) {
+ g_source_remove(dragId);
+ dragId = 0;
}
+ psel = 0;
+ selectModifiedConn.disconnect();
+ subselChangedConn.disconnect();
+ selectChangedConn.disconnect();
+}
-} // end of sp_fill_style_widget_construct()
-
-static void
-sp_fill_style_widget_modify_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- guint flags,
- SPPaintSelector */*psel*/ )
+/**
+ * On signal modified, invokes an update of the fill or stroke style paint object.
+ */
+void FillNStroke::selectionModifiedCB( guint flags )
{
if (flags & ( SP_OBJECT_MODIFIED_FLAG |
- SP_OBJECT_PARENT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG) )
- {
+ SP_OBJECT_PARENT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
#ifdef SP_FS_VERBOSE
- g_message("sp_fill_style_widget_modify_selection()");
+ g_message("selectionModifiedCB(%d) on %p", flags, this);
#endif
- sp_fill_style_widget_update (spw);
+ performUpdate();
}
}
-static void
-sp_fill_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget *spw )
+void FillNStroke::setDesktop(SPDesktop *desktop)
{
- sp_fill_style_widget_update (spw);
-}
+ if (this->desktop != desktop) {
+ if (dragId) {
+ g_source_remove(dragId);
+ dragId = 0;
+ }
+ if (this->desktop) {
+ selectModifiedConn.disconnect();
+ subselChangedConn.disconnect();
+ selectChangedConn.disconnect();
+ }
+ this->desktop = desktop;
+ if (desktop && desktop->selection) {
+ selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate)));
+ subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &FillNStroke::performUpdate)));
-static void
-sp_fill_style_widget_change_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- SPPaintSelector */*psel*/ )
-{
- sp_fill_style_widget_update (spw);
+ // Must check flags, so can't call performUpdate() directly.
+ selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &FillNStroke::selectionModifiedCB)));
+ }
+ performUpdate();
+ }
}
/**
-* \param sel Selection to use, or NULL.
-*/
-static void
-sp_fill_style_widget_update (SPWidget *spw)
+ * Gets the active fill or stroke style property, then sets the appropriate
+ * color, alpha, gradient, pattern, etc. for the paint-selector.
+ *
+ * @param sel Selection to use, or NULL.
+ */
+void FillNStroke::performUpdate()
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
+ if ( update || !desktop ) {
return;
+ }
- if (g_object_get_data (G_OBJECT (spw), "local")) {
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (FALSE)); // local change; do nothing, but reset the flag
+ if ( dragId ) {
+ // local change; do nothing, but reset the flag
+ g_source_remove(dragId);
+ dragId = 0;
return;
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPPaintSelector *psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector"));
+ update = true;
// create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ SPStyle *query = sp_style_new(desktop->doc());
+
// query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection
- int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FILL);
+ int result = sp_desktop_query_style(desktop, query, (kind == FILL) ? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE);
+
+ SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
+ SPIScale24 &targOpacity = (kind == FILL) ? query->fill_opacity : query->stroke_opacity;
switch (result) {
case QUERY_STYLE_NOTHING:
@@ -201,37 +246,39 @@ sp_fill_style_widget_update (SPWidget *spw)
case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
case QUERY_STYLE_MULTIPLE_SAME:
{
- SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, true);
+ SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, kind);
psel->setMode(pselmode);
- psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO?
- SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD);
+ if (kind == FILL) {
+ psel->setFillrule(query->fill_rule.computed == ART_WIND_RULE_NONZERO?
+ SPPaintSelector::FILLRULE_NONZERO : SPPaintSelector::FILLRULE_EVENODD);
+ }
- if (query->fill.set && query->fill.isColor()) {
- psel->setColorAlpha(query->fill.value.color, SP_SCALE24_TO_FLOAT(query->fill_opacity.value));
- } else if (query->fill.set && query->fill.isPaintserver()) {
+ if (targPaint.set && targPaint.isColor()) {
+ psel->setColorAlpha(targPaint.value.color, SP_SCALE24_TO_FLOAT(targOpacity.value));
+ } else if (targPaint.set && targPaint.isPaintserver()) {
- SPPaintServer *server = query->getFillPaintServer();
+ SPPaintServer *server = (kind == FILL) ? query->getFillPaintServer() : query->getStrokePaintServer();
if (server && SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
psel->setSwatch( vector );
- } else if (SP_IS_LINEARGRADIENT (server)) {
+ } else if (SP_IS_LINEARGRADIENT(server)) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
psel->setGradientLinear( vector );
- SPLinearGradient *lg = SP_LINEARGRADIENT (server);
+ SPLinearGradient *lg = SP_LINEARGRADIENT(server);
psel->setGradientProperties( SP_GRADIENT_UNITS(lg),
SP_GRADIENT_SPREAD(lg) );
- } else if (SP_IS_RADIALGRADIENT (server)) {
+ } 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) );
- } else if (SP_IS_PATTERN (server)) {
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
+ SPRadialGradient *rg = SP_RADIALGRADIENT(server);
+ psel->setGradientProperties( SP_GRADIENT_UNITS(rg),
+ SP_GRADIENT_SPREAD(rg) );
+ } else if (SP_IS_PATTERN(server)) {
+ SPPattern *pat = pattern_getroot(SP_PATTERN(server));
psel->updatePatternList( pat );
}
}
@@ -247,101 +294,142 @@ sp_fill_style_widget_update (SPWidget *spw)
sp_style_unref(query);
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-
+ update = false;
}
-
-static void
-sp_fill_style_widget_paint_mode_changed( SPPaintSelector *psel,
- SPPaintSelector::Mode /*mode*/,
- SPWidget *spw )
+/**
+ * When the mode is changed, invoke a regular changed handler.
+ */
+void FillNStroke::paintModeChangeCB( SPPaintSelector * /*psel*/,
+ SPPaintSelector::Mode /*mode*/,
+ FillNStroke *self )
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
-
#ifdef SP_FS_VERBOSE
- g_message("sp_fill_style_widget_paint_mode_changed(psel:%p, mode, spw:%p)", psel, spw);
+ g_message("paintModeChangeCB(psel, mode, self:%p)", self);
#endif
+ if (self && !self->update) {
+ self->updateFromPaint();
+ }
+}
- /* TODO: Does this work? */
- /* TODO: Not really, here we have to get old color back from object */
- /* Instead of relying on paint widget having meaningful colors set */
- sp_fill_style_widget_paint_changed (psel, spw);
+void FillNStroke::fillruleChangedCB( SPPaintSelector * /*psel*/,
+ SPPaintSelector::FillRule mode,
+ FillNStroke *self )
+{
+ if (self) {
+ self->setFillrule(mode);
+ }
}
-static void sp_fill_style_widget_fillrule_changed( SPPaintSelector */*psel*/,
- SPPaintSelector::FillRule mode,
- SPWidget *spw )
+void FillNStroke::setFillrule( SPPaintSelector::FillRule mode )
{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
+ if (!update && desktop) {
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-rule", (mode == SPPaintSelector::FILLRULE_EVENODD) ? "evenodd":"nonzero");
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style(desktop, css);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property(css, "fill-rule", mode == SPPaintSelector::FILLRULE_EVENODD? "evenodd":"nonzero");
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_desktop_set_style (desktop, css);
+ sp_document_done(desktop->doc(), SP_VERB_DIALOG_FILL_STROKE,
+ _("Change fill rule"));
+ }
+}
+
+static gchar const *undo_F_label_1 = "fill:flatcolor:1";
+static gchar const *undo_F_label_2 = "fill:flatcolor:2";
+
+static gchar const *undo_S_label_1 = "stroke:flatcolor:1";
+static gchar const *undo_S_label_2 = "stroke:flatcolor:2";
- sp_repr_css_attr_unref (css);
+static gchar const *undo_F_label = undo_F_label_1;
+static gchar const *undo_S_label = undo_S_label_1;
- sp_document_done (SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE,
- _("Change fill rule"));
+
+void FillNStroke::paintDraggedCB(SPPaintSelector * /*psel*/, FillNStroke *self)
+{
+#ifdef SP_FS_VERBOSE
+ g_message("paintDraggedCB(psel, spw:%p)", self);
+#endif
+ if (self && !self->update) {
+ self->dragFromPaint();
+ }
}
-static gchar const *undo_label_1 = "fill:flatcolor:1";
-static gchar const *undo_label_2 = "fill:flatcolor:2";
-static gchar const *undo_label = undo_label_1;
+
+gboolean FillNStroke::dragDelayCB(gpointer data)
+{
+ gboolean keepGoing = TRUE;
+ if (data) {
+ FillNStroke *self = reinterpret_cast<FillNStroke*>(data);
+ if (!self->update) {
+ if (self->dragId) {
+ g_source_remove(self->dragId);
+ self->dragId = 0;
+
+ self->dragFromPaint();
+ self->performUpdate();
+ }
+ keepGoing = FALSE;
+ }
+ } else {
+ keepGoing = FALSE;
+ }
+ return keepGoing;
+}
/**
-This is called repeatedly while you are dragging a color slider, only for flat color
-modes. Previously it set the color in style but did not update the repr for efficiency, however
-this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
-lumps all its changes for undo.
+ * This is called repeatedly while you are dragging a color slider, only for flat color
+ * modes. Previously it set the color in style but did not update the repr for efficiency, however
+ * this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
+ * lumps all its changes for undo.
*/
-static void
-sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw)
+void FillNStroke::dragFromPaint()
{
- if (!spw->inkscape) {
+ if (!desktop || update) {
return;
}
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
+ guint32 when = gtk_get_current_event_time();
+
+ // Don't attempt too many updates per second.
+ // Assume a base 15.625ms resolution on the timer.
+ if (!dragId && lastDrag && when && ((when - lastDrag) < 32)) {
+ // local change, do not update from selection
+ dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 33, dragDelayCB, this, 0);
}
- if (g_object_get_data (G_OBJECT (spw), "local")) {
+ if (dragId) {
// previous local flag not cleared yet;
// this means dragged events come too fast, so we better skip this one to speed up display
// (it's safe to do this in any case)
return;
}
+ lastDrag = when;
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+ update = true;
switch (psel->mode) {
-
case SPPaintSelector::MODE_COLOR_RGB:
case SPPaintSelector::MODE_COLOR_CMYK:
{
- psel->setFlatColor( SP_ACTIVE_DESKTOP, "fill", "fill-opacity" );
- sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (TRUE)); // local change, do not update from selection
+ // local change, do not update from selection
+ dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 100, dragDelayCB, this, 0);
+ psel->setFlatColor( desktop, (kind == FILL) ? "fill" : "stroke", (kind == FILL) ? "fill-opacity" : "stroke-opacity" );
+ sp_document_maybe_done(desktop->doc(), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set fill color") : _("Set stroke color"));
break;
}
default:
- g_warning ( "file %s: line %d: Paint %d should not emit 'dragged'",
- __FILE__, __LINE__, psel->mode );
+ g_warning( "file %s: line %d: Paint %d should not emit 'dragged'",
+ __FILE__, __LINE__, psel->mode );
break;
-
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+ update = false;
}
-
/**
This is called (at least) when:
1 paint selector mode is switched (e.g. flat color -> gradient)
@@ -349,33 +437,33 @@ This is called (at least) when:
3 you changed a gradient selector parameter (e.g. spread)
Must update repr.
*/
-static void
-sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
- SPWidget *spw )
+void FillNStroke::paintChangedCB( SPPaintSelector * /*psel*/, FillNStroke *self )
{
#ifdef SP_FS_VERBOSE
- g_message("sp_fill_style_widget_paint_changed(psel:%p, spw:%p)", psel, spw);
+ g_message("paintChangedCB(psel, spw:%p)", self);
#endif
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
+ if (self && !self->update) {
+ self->updateFromPaint();
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+}
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+void FillNStroke::updateFromPaint()
+{
if (!desktop) {
return;
}
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ update = true;
+
+ SPDocument *document = sp_desktop_document(desktop);
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
GSList const *items = selection->itemList();
switch (psel->mode) {
-
case SPPaintSelector::MODE_EMPTY:
// This should not happen.
- g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
- __FILE__, __LINE__, psel->mode);
+ g_warning( "file %s: line %d: Paint %d should not emit 'changed'",
+ __FILE__, __LINE__, psel->mode);
break;
case SPPaintSelector::MODE_MULTIPLE:
// This happens when you switch multiple objects with different gradients to flat color;
@@ -384,35 +472,46 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
case SPPaintSelector::MODE_NONE:
{
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "fill", "none");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none");
- sp_desktop_set_style (desktop, css);
+ sp_desktop_set_style(desktop, css);
- sp_repr_css_attr_unref (css);
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Remove fill"));
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Remove fill") : _("Remove stroke"));
break;
}
case SPPaintSelector::MODE_COLOR_RGB:
case SPPaintSelector::MODE_COLOR_CMYK:
{
- // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
- sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
+ if (kind == FILL) {
+ // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
+ sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
+ }
+
+ psel->setFlatColor( desktop,
+ (kind == FILL) ? "fill" : "stroke",
+ (kind == FILL) ? "fill-opacity" : "stroke-opacity" );
+ sp_document_maybe_done(sp_desktop_document(desktop), (kind == FILL) ? undo_F_label : undo_S_label, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set fill color") : _("Set stroke color"));
- psel->setFlatColor( desktop, "fill", "fill-opacity" );
- sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- // resume interruptibility
- sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
+ if (kind == FILL) {
+ // resume interruptibility
+ sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
+ }
// on release, toggle undo_label so that the next drag will not be lumped with this one
- if (undo_label == undo_label_1)
- undo_label = undo_label_2;
- else
- undo_label = undo_label_1;
+ if (undo_F_label == undo_F_label_1) {
+ undo_F_label = undo_F_label_2;
+ undo_S_label = undo_S_label_2;
+ } else {
+ undo_F_label = undo_F_label_1;
+ undo_S_label = undo_S_label_1;
+ }
break;
}
@@ -425,22 +524,26 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
? SP_GRADIENT_TYPE_LINEAR
: SP_GRADIENT_TYPE_RADIAL );
- // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ SPCSSAttr *css = 0;
+ if (kind == FILL) {
+ // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
+ css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ }
SPGradient *vector = psel->getGradientVector();
if (!vector) {
/* No vector in paint selector should mean that we just changed mode */
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result = objects_query_fillstroke ((GSList *) items, query, true);
+ SPStyle *query = sp_style_new(desktop->doc());
+ int result = objects_query_fillstroke(const_cast<GSList *>(items), query, kind == FILL);
+ SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
guint32 common_rgb = 0;
if (result == QUERY_STYLE_MULTIPLE_SAME) {
- if (!query->fill.isColor()) {
- common_rgb = sp_desktop_get_color(desktop, true);
+ if (!targPaint.isColor()) {
+ common_rgb = sp_desktop_get_color(desktop, kind == FILL);
} else {
- common_rgb = query->fill.value.color.toRGBA32( 0xff );
+ common_rgb = targPaint.value.color.toRGBA32( 0xff );
}
vector = sp_document_default_gradient_vector(document, common_rgb);
}
@@ -448,33 +551,40 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
for (GSList const *i = items; i != NULL; i = i->next) {
//FIXME: see above
- sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+ if (kind == FILL) {
+ sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+ }
if (!vector) {
sp_item_set_gradient(SP_ITEM(i->data),
- sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), true),
- gradient_type, true);
+ sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), kind == FILL),
+ gradient_type, kind == FILL);
} else {
- sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
+ sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL);
}
}
} else {
- /* We have changed from another gradient type, or modified spread/units within
- * this gradient type. */
- vector = sp_gradient_ensure_vector_normalized (vector);
+ // We have changed from another gradient type, or modified spread/units within
+ // this gradient type.
+ vector = sp_gradient_ensure_vector_normalized(vector);
for (GSList const *i = items; i != NULL; i = i->next) {
//FIXME: see above
- sp_repr_css_change_recursive (SP_OBJECT_REPR (i->data), css, "style");
+ if (kind == FILL) {
+ sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+ }
- SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
+ SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, kind == FILL);
psel->pushAttrsToGradient( gr );
}
}
- sp_repr_css_attr_unref (css);
+ if (css) {
+ sp_repr_css_attr_unref(css);
+ css = 0;
+ }
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set gradient on fill"));
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke"));
}
break;
@@ -491,65 +601,92 @@ sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
} else {
Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
- sp_repr_css_set_property (css, "fill", urltext);
+ 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);
// HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ if (kind == FILL) {
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+ }
// cannot just call sp_desktop_set_style, because we don't want to touch those
// 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) {
- SPObject *selobj = SP_OBJECT (i->data);
-
- SPStyle *style = SP_OBJECT_STYLE (selobj);
- if (style && style->fill.isPaintserver()) {
- SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (selobj);
- if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
+ Inkscape::XML::Node *selrepr = SP_OBJECT_REPR(i->data);
+ if ( (kind == STROKE) && !selrepr) {
+ continue;
+ }
+ SPObject *selobj = SP_OBJECT(i->data);
+
+ SPStyle *style = SP_OBJECT_STYLE(selobj);
+ 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);
+ 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;
- }
+ continue;
+ }
- sp_desktop_apply_css_recursive (selobj, css, true);
- }
+ if (kind == FILL) {
+ sp_desktop_apply_css_recursive(selobj, css, true);
+ } else {
+ sp_repr_css_change_recursive(selrepr, css, "style");
+ }
+ }
- sp_repr_css_attr_unref (css);
- g_free (urltext);
+ sp_repr_css_attr_unref(css);
+ css = 0;
+ g_free(urltext);
} // end if
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set pattern on fill"));
-
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Set pattern on fill") :
+ _("Set pattern on stroke"));
} // end if
break;
case SPPaintSelector::MODE_UNSET:
if (items) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_unset_property (css, "fill");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ if (kind == FILL) {
+ sp_repr_css_unset_property(css, "fill");
+ } else {
+ sp_repr_css_unset_property(css, "stroke");
+ sp_repr_css_unset_property(css, "stroke-opacity");
+ sp_repr_css_unset_property(css, "stroke-width");
+ sp_repr_css_unset_property(css, "stroke-miterlimit");
+ sp_repr_css_unset_property(css, "stroke-linejoin");
+ sp_repr_css_unset_property(css, "stroke-linecap");
+ sp_repr_css_unset_property(css, "stroke-dashoffset");
+ sp_repr_css_unset_property(css, "stroke-dasharray");
+ }
- sp_desktop_set_style (desktop, css);
- sp_repr_css_attr_unref (css);
+ sp_desktop_set_style(desktop, css);
+ sp_repr_css_attr_unref(css);
+ css = 0;
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Unset fill"));
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ (kind == FILL) ? _("Unset fill") : _("Unset stroke"));
}
break;
default:
- g_warning ( "file %s: line %d: Paint selector should not be in "
- "mode %d",
- __FILE__, __LINE__, psel->mode );
+ g_warning( "file %s: line %d: Paint selector should not be in "
+ "mode %d",
+ __FILE__, __LINE__,
+ psel->mode );
break;
}
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+ update = false;
}
+} // namespace Inkscape
/*
Local Variables:
diff --git a/src/widgets/fill-style.h b/src/widgets/fill-style.h
index 3924412ec..ef19d7788 100644
--- a/src/widgets/fill-style.h
+++ b/src/widgets/fill-style.h
@@ -3,7 +3,9 @@
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon A. Cruz <jon@joncruz.org>
*
+ * Copyright (C) 2010 Jon A. Cruz
* Copyright (C) 2002 Lauris Kaplinski
*
* Released under GNU GPL, read the file 'COPYING' for more information
@@ -12,14 +14,17 @@
#ifndef SEEN_DIALOGS_SP_FILL_STYLE_H
#define SEEN_DIALOGS_SP_FILL_STYLE_H
-#include <glib.h>
-#include <gtk/gtkwidget.h>
-#include "forward.h"
+namespace Gtk {
+class Widget;
+}
+class SPDesktop;
-GtkWidget *sp_fill_style_widget_new (void);
+Gtk::Widget *sp_fill_style_widget_new(void);
-#endif
+void sp_fill_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop);
+
+#endif // SEEN_DIALOGS_SP_FILL_STYLE_H
/*
Local Variables:
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index 288764177..d3092669a 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -352,8 +352,7 @@ sp_paint_selector_show_fillrule(SPPaintSelector *psel, bool is_fill)
}
-GtkWidget *
-sp_paint_selector_new(bool is_fill)
+SPPaintSelector *sp_paint_selector_new(FillOrStroke kind)
{
SPPaintSelector *psel = static_cast<SPPaintSelector*>(gtk_type_new(SP_TYPE_PAINT_SELECTOR));
@@ -362,9 +361,9 @@ sp_paint_selector_new(bool is_fill)
// This silliness is here because I don't know how to pass a parameter to the
// GtkObject "constructor" (sp_paint_selector_init). Remove it when paint_selector
// becomes a normal class.
- sp_paint_selector_show_fillrule(psel, is_fill);
+ sp_paint_selector_show_fillrule(psel, kind == FILL);
- return GTK_WIDGET(psel);
+ return psel;
}
void SPPaintSelector::setMode(Mode mode)
@@ -1137,18 +1136,18 @@ void SPPaintSelector::setFlatColor( SPDesktop *desktop, gchar const *color_prope
sp_repr_css_attr_unref(css);
}
-SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, bool isfill)
+SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, FillOrStroke kind)
{
Mode mode = MODE_UNSET;
- SPIPaint const & target = isfill ? style.fill : style.stroke;
+ SPIPaint const & target = (kind == FILL) ? style.fill : style.stroke;
if ( !target.set ) {
mode = MODE_UNSET;
} else if ( target.isPaintserver() ) {
- SPPaintServer const *server = isfill ? style.getFillPaintServer() : style.getStrokePaintServer();
+ SPPaintServer const *server = (kind == FILL) ? style.getFillPaintServer() : style.getStrokePaintServer();
#ifdef SP_PS_VERBOSE
- g_message("SPPaintSelector::getModeForStyle(%p, %d)", &style, isfill);
+ g_message("SPPaintSelector::getModeForStyle(%p, %d)", &style, kind);
g_message("==== server:%p %s grad:%s swatch:%s", server, server->getId(), (SP_IS_GRADIENT(server)?"Y":"n"), (SP_IS_GRADIENT(server) && SP_GRADIENT(server)->getVector()->isSwatch()?"Y":"n"));
#endif // SP_PS_VERBOSE
diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h
index a3c4cb973..84209d1da 100644
--- a/src/widgets/paint-selector.h
+++ b/src/widgets/paint-selector.h
@@ -14,6 +14,8 @@
*/
#include <glib.h>
+
+#include "fill-or-stroke.h"
#include "sp-gradient-spread.h"
#include "sp-gradient-units.h"
@@ -75,7 +77,7 @@ struct SPPaintSelector {
SPColor color;
float alpha;
- static Mode getModeForStyle(SPStyle const & style, bool isfill);
+ static Mode getModeForStyle(SPStyle const & style, FillOrStroke kind);
void setMode( Mode mode );
void setFillrule( FillRule fillrule );
@@ -114,7 +116,7 @@ struct SPPaintSelectorClass {
GtkType sp_paint_selector_get_type (void);
-GtkWidget *sp_paint_selector_new (bool is_fill);
+SPPaintSelector *sp_paint_selector_new(FillOrStroke kind);
diff --git a/src/widgets/sp-color-icc-selector.cpp b/src/widgets/sp-color-icc-selector.cpp
index 3b4b6b711..6bd1957a8 100644
--- a/src/widgets/sp-color-icc-selector.cpp
+++ b/src/widgets/sp-color-icc-selector.cpp
@@ -17,7 +17,7 @@
#include "inkscape.h"
#include "profile-manager.h"
-#define DEBUG_LCMS
+#define noDEBUG_LCMS
#if ENABLE_LCMS
#include "color-profile-fns.h"
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index ddd1c92d3..f020b0c3a 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -25,6 +25,7 @@
#include "desktop-handles.h"
#include "desktop-style.h"
#include "dialogs/dialog-events.h"
+#include "display/canvas-bpath.h" // for SP_STROKE_LINEJOIN_*
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "document-private.h"
@@ -54,23 +55,9 @@
#include "widgets/spw-utilities.h"
#include "xml/repr.h"
-#include "widgets/stroke-style.h"
-
-
-/* Paint */
-
-static void sp_stroke_style_paint_selection_modified (SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel);
-static void sp_stroke_style_paint_selection_changed (SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel);
-static void sp_stroke_style_paint_update(SPWidget *spw);
-
-static void sp_stroke_style_paint_mode_changed(SPPaintSelector *psel, SPPaintSelector::Mode mode, SPWidget *spw);
-static void sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw);
-static void sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw);
-
-static void sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
-static void sp_stroke_style_widget_transientize_callback(Inkscape::Application *inkscape,
- SPDesktop *desktop,
- SPWidget *spw );
+#include "stroke-style.h"
+#include "fill-style.h" // to get sp_fill_style_widget_set_desktop
+#include "fill-n-stroke-factory.h"
/** Marker selection option menus */
static Gtk::OptionMenu * marker_start_menu = NULL;
@@ -86,401 +73,17 @@ static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const
static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
-/**
- * Create the stroke style widget, and hook up all the signals.
- */
-GtkWidget *
-sp_stroke_style_paint_widget_new(void)
+Gtk::Widget *sp_stroke_style_paint_widget_new(void)
{
- GtkWidget *spw, *psel;
-
- spw = sp_widget_new_global(INKSCAPE);
-
- psel = sp_paint_selector_new(false); // without fillrule selector
- gtk_widget_show(psel);
- gtk_container_add(GTK_CONTAINER(spw), psel);
- gtk_object_set_data(GTK_OBJECT(spw), "paint-selector", psel);
-
- gtk_signal_connect(GTK_OBJECT(spw), "modify_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_modified),
- psel);
- gtk_signal_connect(GTK_OBJECT(spw), "change_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_changed),
- psel);
-
- g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_stroke_style_widget_change_subselection), spw);
-
- g_signal_connect (G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK (sp_stroke_style_widget_transientize_callback), spw );
-
- gtk_signal_connect(GTK_OBJECT(psel), "mode_changed",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_mode_changed),
- spw);
- gtk_signal_connect(GTK_OBJECT(psel), "dragged",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_dragged),
- spw);
- gtk_signal_connect(GTK_OBJECT(psel), "changed",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_changed),
- spw);
-
- sp_stroke_style_paint_update (SP_WIDGET(spw));
- return spw;
+ return Inkscape::Widgets::createStyleWidget( STROKE );
}
-/**
- * On signal modified, invokes an update of the stroke style paint object.
- */
-static void
-sp_stroke_style_paint_selection_modified( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- guint flags,
- SPPaintSelector */*psel*/ )
+void sp_stroke_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop)
{
- if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
- sp_stroke_style_paint_update(spw);
- }
+ sp_fill_style_widget_set_desktop(widget, desktop);
}
-/**
- * On signal selection changed, invokes an update of the stroke style paint object.
- */
-static void
-sp_stroke_style_paint_selection_changed( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- SPPaintSelector */*psel*/ )
-{
- sp_stroke_style_paint_update (spw);
-}
-
-
-/**
- * On signal change subselection, invoke an update of the stroke style widget.
- */
-static void
-sp_stroke_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget *spw )
-{
- sp_stroke_style_paint_update (spw);
-}
-
-/**
- * Gets the active stroke style property, then sets the appropriate color, alpha, gradient,
- * pattern, etc. for the paint-selector.
- */
-static void
-sp_stroke_style_paint_update (SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE));
-
- SPPaintSelector *psel = SP_PAINT_SELECTOR(gtk_object_get_data(GTK_OBJECT(spw), "paint-selector"));
-
- // create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- // query into it
- int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE);
-
- switch (result) {
- case QUERY_STYLE_NOTHING:
- {
- /* No paint at all */
- psel->setMode(SPPaintSelector::MODE_EMPTY);
- break;
- }
-
- case QUERY_STYLE_SINGLE:
- case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
- case QUERY_STYLE_MULTIPLE_SAME:
- {
- SPPaintSelector::Mode pselmode = SPPaintSelector::getModeForStyle(*query, false);
- psel->setMode(pselmode);
-
- if (query->stroke.set && query->stroke.isPaintserver()) {
-
- SPPaintServer *server = SP_STYLE_STROKE_SERVER (query);
-
- if (server && server->isSwatch()) {
- SPGradient *vector = SP_GRADIENT(server)->getVector();
- psel->setSwatch( vector );
- } else if (SP_IS_LINEARGRADIENT (server)) {
- SPGradient *vector = SP_GRADIENT(server)->getVector();
- psel->setGradientLinear( vector );
-
- SPLinearGradient *lg = SP_LINEARGRADIENT (server);
- psel->setGradientProperties( SP_GRADIENT_UNITS(lg),
- SP_GRADIENT_SPREAD(lg) );
- } 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) );
- } else if (SP_IS_PATTERN (server)) {
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
- psel->updatePatternList( pat );
- }
- } else if (query->stroke.set && query->stroke.isColor()) {
- psel->setColorAlpha(query->stroke.value.color, SP_SCALE24_TO_FLOAT(query->stroke_opacity.value));
- }
- break;
- }
-
- case QUERY_STYLE_MULTIPLE_DIFFERENT:
- {
- psel->setMode(SPPaintSelector::MODE_MULTIPLE);
- break;
- }
- }
-
- sp_style_unref(query);
-
- gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE));
-}
-
-/**
- * When the mode is changed, invoke a regular changed handler.
- */
-static void
-sp_stroke_style_paint_mode_changed( SPPaintSelector *psel,
- SPPaintSelector::Mode /*mode*/,
- SPWidget *spw )
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- /* TODO: Does this work?
- * Not really, here we have to get old color back from object
- * Instead of relying on paint widget having meaningful colors set
- */
- sp_stroke_style_paint_changed(psel, spw);
-}
-
-static gchar const *const undo_label_1 = "stroke:flatcolor:1";
-static gchar const *const undo_label_2 = "stroke:flatcolor:2";
-static gchar const *undo_label = undo_label_1;
-
-/**
- * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK
- * color mode, then set the stroke opacity to psel's flat color.
- */
-static void
-sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- switch (psel->mode) {
- case SPPaintSelector::MODE_COLOR_RGB:
- case SPPaintSelector::MODE_COLOR_CMYK:
- {
- psel->setFlatColor( SP_ACTIVE_DESKTOP, "stroke", "stroke-opacity" );
- sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke color"));
- break;
- }
-
- default:
- g_warning( "file %s: line %d: Paint %d should not emit 'dragged'",
- __FILE__, __LINE__, psel->mode);
- break;
- }
-}
-
-/**
- * When the stroke style's paint settings change, this handler updates the
- * repr's stroke css style and applies the style to relevant drawing items.
- */
-static void
-sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- GSList const *items = selection->itemList();
-
- switch (psel->mode) {
- case SPPaintSelector::MODE_EMPTY:
- // This should not happen.
- g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
- __FILE__, __LINE__, psel->mode);
- break;
- case SPPaintSelector::MODE_MULTIPLE:
- // This happens when you switch multiple objects with different gradients to flat color;
- // nothing to do here.
- break;
-
- case SPPaintSelector::MODE_NONE:
- {
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "stroke", "none");
-
- sp_desktop_set_style (desktop, css);
-
- sp_repr_css_attr_unref(css);
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Remove stroke"));
- break;
- }
-
- case SPPaintSelector::MODE_COLOR_RGB:
- case SPPaintSelector::MODE_COLOR_CMYK:
- {
- psel->setFlatColor(desktop, "stroke", "stroke-opacity");
- sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke color"));
-
- // on release, toggle undo_label so that the next drag will not be lumped with this one
- if (undo_label == undo_label_1)
- undo_label = undo_label_2;
- else
- undo_label = undo_label_1;
-
- break;
- }
-
- case SPPaintSelector::MODE_GRADIENT_LINEAR:
- case SPPaintSelector::MODE_GRADIENT_RADIAL:
- if (items) {
- SPGradientType const gradient_type = ( psel->mode == SPPaintSelector::MODE_GRADIENT_LINEAR
- ? SP_GRADIENT_TYPE_LINEAR
- : SP_GRADIENT_TYPE_RADIAL );
- SPGradient *vector = psel->getGradientVector();
- if (!vector) {
- /* No vector in paint selector should mean that we just changed mode */
-
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result = objects_query_fillstroke ((GSList *) items, query, false);
- guint32 common_rgb = 0;
- if (result == QUERY_STYLE_MULTIPLE_SAME) {
- if (!query->fill.isColor()) {
- common_rgb = sp_desktop_get_color(desktop, false);
- } else {
- common_rgb = query->stroke.value.color.toRGBA32( 0xff );
- }
- vector = sp_document_default_gradient_vector(document, common_rgb);
- }
- sp_style_unref(query);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- if (!vector) {
- sp_item_set_gradient(SP_ITEM(i->data),
- sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), false),
- gradient_type, false);
- } else {
- sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
- }
- }
- } else {
- vector = sp_gradient_ensure_vector_normalized(vector);
- for (GSList const *i = items; i != NULL; i = i->next) {
- SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
- psel->pushAttrsToGradient( gr );
- }
- }
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set gradient on stroke"));
- }
- break;
-
- case SPPaintSelector::MODE_PATTERN:
-
- if (items) {
-
- SPPattern *pattern = psel->getPattern();
- if (!pattern) {
-
- /* No Pattern in paint selector should mean that we just
- * changed mode - dont do jack.
- */
-
- } else {
- Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
- sp_repr_css_set_property (css, "stroke", urltext);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- Inkscape::XML::Node *selrepr = SP_OBJECT_REPR (i->data);
- SPObject *selobj = SP_OBJECT (i->data);
- if (!selrepr)
- continue;
-
- SPStyle *style = SP_OBJECT_STYLE (selobj);
- if (style && style->stroke.isPaintserver()) {
- SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (selobj);
- 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;
- }
-
- sp_repr_css_change_recursive (selrepr, css, "style");
- }
-
- sp_repr_css_attr_unref (css);
- g_free (urltext);
-
- } // end if
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set pattern on stroke"));
- } // end if
-
- break;
-
- case SPPaintSelector::MODE_SWATCH:
- // TODO
- break;
-
- case SPPaintSelector::MODE_UNSET:
- if (items) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_unset_property (css, "stroke");
- sp_repr_css_unset_property (css, "stroke-opacity");
- sp_repr_css_unset_property (css, "stroke-width");
- sp_repr_css_unset_property (css, "stroke-miterlimit");
- sp_repr_css_unset_property (css, "stroke-linejoin");
- sp_repr_css_unset_property (css, "stroke-linecap");
- sp_repr_css_unset_property (css, "stroke-dashoffset");
- sp_repr_css_unset_property (css, "stroke-dasharray");
-
- sp_desktop_set_style (desktop, css);
- sp_repr_css_attr_unref (css);
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Unset stroke"));
- }
- break;
-
- default:
- g_warning( "file %s: line %d: Paint selector should not be in "
- "mode %d",
- __FILE__, __LINE__,
- psel->mode );
- break;
- }
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-}
-
-
-
-
/* Line */
@@ -537,25 +140,15 @@ sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon,
}
-static void
-sp_stroke_style_widget_transientize_callback(Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget */*spw*/ )
-{
-// TODO: Either of these will cause crashes sometimes
-// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
-// ink_markers_menu_update(spw);
-}
-
/**
- * Creates a copy of the marker named mname, determines its visible and renderable
+ * Create sa copy of the marker named mname, determines its visible and renderable
* area in menu_id's bounding box, and then renders it. This allows us to fill in
* preview images of each marker in the marker menu.
*/
static Gtk::Image *
sp_marker_prev_new(unsigned psize, gchar const *mname,
SPDocument *source, SPDocument *sandbox,
- gchar const *menu_id, NRArena const */*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
+ gchar const *menu_id, NRArena const * /*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
{
// Retrieve the marker named 'mname' from the source SVG document
SPObject const *marker = source->getObjectById(mname);
@@ -699,7 +292,7 @@ sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPD
*
*/
static void
-sp_marker_list_from_doc (Gtk::Menu *m, SPDocument */*current_doc*/, SPDocument *source, SPDocument */*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
+sp_marker_list_from_doc (Gtk::Menu *m, SPDocument * /*current_doc*/, SPDocument *source, SPDocument * /*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
{
GSList *ml = ink_marker_list_get(source);
GSList *clean_ml = NULL;
@@ -808,7 +401,7 @@ ink_marker_menu_create_menu(Gtk::Menu *m, gchar const *menu_id, SPDocument *doc,
* Creates a menu widget to display markers from markers.svg
*/
static Gtk::OptionMenu *
-ink_marker_menu(Gtk::Widget */*tbl*/, gchar const *menu_id, SPDocument *sandbox)
+ink_marker_menu(Gtk::Widget * /*tbl*/, gchar const *menu_id, SPDocument *sandbox)
{
SPDesktop *desktop = inkscape_active_desktop();
SPDocument *doc = sp_desktop_document(desktop);
@@ -903,6 +496,7 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh
}
sp_repr_css_attr_unref(css);
+ css = 0;
sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
_("Set markers"));
@@ -1269,12 +863,12 @@ sp_stroke_style_line_widget_new(void)
// FIXME: we cheat and still use gtk+ signals
- gtk_signal_connect(GTK_OBJECT(spw_old), "modify_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_modified),
- spw);
- gtk_signal_connect(GTK_OBJECT(spw_old), "change_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_changed),
- spw);
+ g_signal_connect(G_OBJECT(spw_old), "modify_selection",
+ G_CALLBACK(sp_stroke_style_line_selection_modified),
+ spw);
+ g_signal_connect(G_OBJECT(spw_old), "change_selection",
+ G_CALLBACK(sp_stroke_style_line_selection_changed),
+ spw);
sp_stroke_style_line_update(spw, desktop ? sp_desktop_selection(desktop) : NULL);
@@ -1393,6 +987,8 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
spw->set_data("update", GINT_TO_POINTER(TRUE));
+ FillOrStroke kind = GPOINTER_TO_INT(spw->get_data("kind")) ? FILL : STROKE;
+
Gtk::Table *sset = static_cast<Gtk::Table *>(spw->get_data("stroke"));
Gtk::Adjustment *width = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
Gtk::Adjustment *ml = static_cast<Gtk::Adjustment *>(spw->get_data("miterlimit"));
@@ -1406,10 +1002,11 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT);
int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP);
int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN);
+ SPIPaint &targPaint = (kind == FILL) ? query->fill : query->stroke;
if (!sel || sel->isEmpty()) {
// Nothing selected, grey-out all controls in the stroke-style dialog
- sset->set_sensitive(false);
+ sset->set_sensitive(false);
spw->set_data("update", GINT_TO_POINTER(FALSE));
@@ -1439,7 +1036,7 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
// if none of the selected objects has a stroke, than quite some controls should be disabled
// The markers might still be shown though, so these will not be disabled
- bool enabled = (result_sw != QUERY_STYLE_NOTHING) && !query->stroke.isNoneSet();
+ bool enabled = (result_sw != QUERY_STYLE_NOTHING) && !targPaint.isNoneSet();
/* No objects stroked, set insensitive */
Gtk::RadioButton *tb = NULL;
tb = static_cast<Gtk::RadioButton *>(spw->get_data("miter join"));
@@ -1454,11 +1051,11 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
sb->set_sensitive(enabled);
tb = static_cast<Gtk::RadioButton *>(spw->get_data("cap butt"));
- tb->set_sensitive(enabled);
- tb = static_cast<Gtk::RadioButton *>(spw->get_data("cap round"));
- tb->set_sensitive(enabled);
- tb = static_cast<Gtk::RadioButton *>(spw->get_data("cap square"));
- tb->set_sensitive(enabled);
+ tb->set_sensitive(enabled);
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data("cap round"));
+ tb->set_sensitive(enabled);
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data("cap square"));
+ tb->set_sensitive(enabled);
dsel->set_sensitive(enabled);
}
@@ -1604,6 +1201,7 @@ sp_stroke_style_scale_line(Gtk::Container *spw)
sp_desktop_set_style (desktop, css, false);
sp_repr_css_attr_unref(css);
+ css = 0;
sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
_("Set stroke style"));
@@ -1700,6 +1298,7 @@ sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw)
}
sp_repr_css_attr_unref(css);
+ css = 0;
sp_document_done(sp_desktop_document(desktop), SP_VERB_DIALOG_FILL_STROKE,
_("Set stroke style"));
diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h
index b947209e3..72dc5449a 100644
--- a/src/widgets/stroke-style.h
+++ b/src/widgets/stroke-style.h
@@ -3,25 +3,28 @@
*/
/* Author:
* Lauris Kaplinski <lauris@ximian.com>
+ * Jon A. Cruz <jon@joncruz.org>
*
+ * Copyright (C) 2010 Jon A. Cruz
* Copyright (C) 2001 Ximian, Inc.
+ *
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifndef SEEN_DIALOGS_STROKE_STYLE_H
#define SEEN_DIALOGS_STROKE_STYLE_H
-#include <glib.h>
-
-#include <gtk/gtkwidget.h>
+namespace Gtk {
+class Widget;
+class Container;
+}
-#include "forward.h"
-#include "display/canvas-bpath.h"
+Gtk::Widget *sp_stroke_style_paint_widget_new(void);
+Gtk::Container *sp_stroke_style_line_widget_new(void);
-GtkWidget *sp_stroke_style_paint_widget_new (void);
-Gtk::Container *sp_stroke_style_line_widget_new (void);
+void sp_stroke_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop);
-#endif
+#endif // SEEN_DIALOGS_STROKE_STYLE_H
/*
Local Variables:
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 4b0d84d90..826fabb06 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -12,10 +12,11 @@
* Josh Andler <scislac@scislac.com>
* Jon A. Cruz <jon@joncruz.org>
* Maximilian Albert <maximilian.albert@gmail.com>
+ * Tavmjong Bah <tavmjong@free.fr>
*
* Copyright (C) 2004 David Turner
* Copyright (C) 2003 MenTaLguY
- * Copyright (C) 1999-2008 authors
+ * Copyright (C) 1999-2010 authors
* Copyright (C) 2001-2002 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
@@ -56,6 +57,7 @@
#include "../helper/unit-tracker.h"
#include "icon.h"
#include "../ink-action.h"
+#include "../ink-comboboxentry-action.h"
#include "../inkscape.h"
#include "../interface.h"
#include "../libnrtype/font-instance.h"
@@ -105,6 +107,7 @@
#include "toolbox.h"
#define ENABLE_TASK_SUPPORT 1
+//#define DEBUG_TEXT
using Inkscape::UnitTracker;
using Inkscape::UI::UXManager;
@@ -139,11 +142,9 @@ static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
static void sp_connector_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
+static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
-namespace { GtkWidget *sp_text_toolbox_new (SPDesktop *desktop); }
-
-
#if ENABLE_TASK_SUPPORT
static void fireTaskChange( EgeSelectOneAction *act, SPDesktop *dt )
{
@@ -235,7 +236,7 @@ static struct {
SP_VERB_CONTEXT_ERASER_PREFS, "/tools/eraser", _("TBD")},
{ "SPLPEToolContext", "lpetool_toolbox", 0, sp_lpetool_toolbox_prep, "LPEToolToolbar",
SP_VERB_CONTEXT_LPETOOL_PREFS, "/tools/lpetool", _("TBD")},
- { "SPTextContext", "text_toolbox", sp_text_toolbox_new, 0, 0,
+ { "SPTextContext", "text_toolbox", 0, sp_text_toolbox_prep, "TextToolbar",
SP_VERB_INVALID, 0, 0},
{ "SPDropperContext", "dropper_toolbox", 0, sp_dropper_toolbox_prep, "DropperToolbar",
SP_VERB_INVALID, 0, 0},
@@ -478,6 +479,21 @@ static gchar const * ui_descr =
" <toolitem action='EraserModeAction' />"
" </toolbar>"
+ " <toolbar name='TextToolbar'>"
+ " <toolitem action='TextFontFamilyAction' />"
+ " <toolitem action='TextFontSizeAction' />"
+ " <toolitem action='TextBoldAction' />"
+ " <toolitem action='TextItalicAction' />"
+ " <separator />"
+ " <toolitem action='TextAlignAction' />"
+ " <separator />"
+ " <toolitem action='TextLineHeightAction' />"
+ " <toolitem action='TextLetterSpacingAction' />"
+ " <toolitem action='TextWordSpacingAction' />"
+ " <separator />"
+ " <toolitem action='TextOrientationAction' />"
+ " </toolbar>"
+
" <toolbar name='LPEToolToolbar'>"
" <toolitem action='LPEToolModeAction' />"
" <separator />"
@@ -518,20 +534,20 @@ static gchar const * ui_descr =
static Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop );
-void setup_snap_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
+static void setup_snap_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
-static void setup_tool_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
-static void update_tool_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
+static void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
+static void update_tool_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
-static void setup_aux_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
-static void update_aux_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
+static void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
+static void update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
-static void setup_commands_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
-static void update_commands_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
+static void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
+static void update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
-GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick( GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
- Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
- Inkscape::UI::View::View *view, GtkTooltips *tt);
+static GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick( GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
+ Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
+ Inkscape::UI::View::View *view, GtkTooltips *tt);
class VerbAction : public Gtk::Action {
public:
@@ -665,14 +681,14 @@ void VerbAction::on_activate()
*dropper_opacity_entry ; */
// should be made a private member once this is converted to class
-static void delete_connection(GObject */*obj*/, sigc::connection *connection) {
+static void delete_connection(GObject * /*obj*/, sigc::connection *connection)
+{
connection->disconnect();
delete connection;
}
-static void purge_repr_listener( GObject* obj, GObject* tbl )
+static void purge_repr_listener( GObject* /*obj*/, GObject* tbl )
{
- (void)obj;
Inkscape::XML::Node* oldrepr = reinterpret_cast<Inkscape::XML::Node *>( g_object_get_data( tbl, "repr" ) );
if (oldrepr) { // remove old listener
sp_repr_remove_listener_by_data(oldrepr, tbl);
@@ -682,19 +698,128 @@ static void purge_repr_listener( GObject* obj, GObject* tbl )
}
}
-GtkWidget *
-sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
- Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
- Inkscape::UI::View::View *view, GtkTooltips *tt)
+// ------------------------------------------------------
+
+/**
+ * A simple mediator class that keeps UI controls matched to the preference values they set.
+ */
+class PrefPusher : public Inkscape::Preferences::Observer
+{
+public:
+ /**
+ * Constructor for a boolean value that syncs to the supplied path.
+ * Initializes the widget to the current preference stored state and registers callbacks
+ * for widget changes and preference changes.
+ *
+ * @param act the widget to synchronize preference with.
+ * @param path the path to the preference the widget is synchronized with.
+ * @param callback function to invoke when changes are pushed.
+ * @param cbData data to be passed on to the callback function.
+ */
+ PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*) = 0, GObject *cbData = 0 );
+
+ /**
+ * Destructor that unregisters the preference callback.
+ */
+ virtual ~PrefPusher();
+
+ /**
+ * Callback method invoked when the preference setting changes.
+ */
+ virtual void notify(Inkscape::Preferences::Entry const &new_val);
+
+private:
+ /**
+ * Callback hook invoked when the widget changes.
+ *
+ * @param act the toggle action widget that was changed.
+ * @param self the PrefPusher instance the callback was registered to.
+ */
+ static void toggleCB( GtkToggleAction *act, PrefPusher *self );
+
+ /**
+ * Method to handle the widget change.
+ */
+ void handleToggled();
+
+ GtkToggleAction *act;
+ void (*callback)(GObject*);
+ GObject *cbData;
+ bool freeze;
+};
+
+PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*), GObject *cbData ) :
+ Observer(path),
+ act(act),
+ callback(callback),
+ cbData(cbData),
+ freeze(false)
+{
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggleCB), this);
+ freeze = true;
+ gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path) );
+ freeze = false;
+
+ Inkscape::Preferences::get()->addObserver(*this);
+}
+
+PrefPusher::~PrefPusher()
+{
+ Inkscape::Preferences::get()->removeObserver(*this);
+}
+
+void PrefPusher::toggleCB( GtkToggleAction * /*act*/, PrefPusher *self )
+{
+ if (self) {
+ self->handleToggled();
+ }
+}
+
+void PrefPusher::handleToggled()
+{
+ if (!freeze) {
+ freeze = true;
+ Inkscape::Preferences::get()->setBool(observed_path, gtk_toggle_action_get_active( act ));
+ if (callback) {
+ (*callback)(cbData);
+ }
+ freeze = false;
+ }
+}
+
+void PrefPusher::notify(Inkscape::Preferences::Entry const &newVal)
+{
+ bool newBool = newVal.getBool();
+ bool oldBool = gtk_toggle_action_get_active(act);
+
+ if (!freeze && (newBool != oldBool)) {
+ gtk_toggle_action_set_active( act, newBool );
+ }
+}
+
+static void delete_prefspusher(GtkObject * /*obj*/, PrefPusher *watcher )
+{
+ delete watcher;
+}
+
+// ------------------------------------------------------
+
+
+GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
+ Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
+ Inkscape::UI::View::View *view, GtkTooltips *tt)
{
SPAction *action = verb->get_action(view);
- if (!action) return NULL;
+ if (!action) {
+ return NULL;
+ }
SPAction *doubleclick_action;
- if (doubleclick_verb)
+ if (doubleclick_verb) {
doubleclick_action = doubleclick_verb->get_action(view);
- else
+ } else {
doubleclick_action = NULL;
+ }
/* fixme: Handle sensitive/unsensitive */
/* fixme: Implement sp_button_new_from_action */
@@ -729,7 +854,7 @@ static void trigger_sp_action( GtkAction* /*act*/, gpointer user_data )
}
}
-static void sp_action_action_set_sensitive (SPAction */*action*/, unsigned int sensitive, void *data)
+static void sp_action_action_set_sensitive(SPAction * /*action*/, unsigned int sensitive, void *data)
{
if ( data ) {
GtkAction* act = GTK_ACTION(data);
@@ -763,7 +888,7 @@ static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::Vi
return act;
}
-Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
+static Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
{
Inkscape::UI::View::View *view = desktop;
gint verbsToUse[] = {
@@ -887,14 +1012,14 @@ Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
}
-void handlebox_detached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
+static void handlebox_detached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
{
gtk_widget_set_size_request( widget,
widget->allocation.width,
widget->allocation.height );
}
-void handlebox_attached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
+static void handlebox_attached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
{
gtk_widget_set_size_request( widget, -1, -1 );
}
@@ -1023,14 +1148,17 @@ static EgeAdjustmentAction * create_adjustment_action( gchar const *name,
* Will go away during tool refactoring. */
static InkNodeTool *get_node_tool()
{
- if (!SP_ACTIVE_DESKTOP) return NULL;
- SPEventContext *ec = SP_ACTIVE_DESKTOP->event_context;
- if (!INK_IS_NODE_TOOL(ec)) return NULL;
- return static_cast<InkNodeTool*>(ec);
+ InkNodeTool *tool = 0;
+ if (SP_ACTIVE_DESKTOP ) {
+ SPEventContext *ec = SP_ACTIVE_DESKTOP->event_context;
+ if (INK_IS_NODE_TOOL(ec)) {
+ tool = static_cast<InkNodeTool*>(ec);
+ }
+ }
+ return tool;
}
-void
-sp_node_path_edit_add(void)
+static void sp_node_path_edit_add(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1038,8 +1166,7 @@ sp_node_path_edit_add(void)
}
}
-void
-sp_node_path_edit_delete(void)
+static void sp_node_path_edit_delete(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1048,8 +1175,7 @@ sp_node_path_edit_delete(void)
}
}
-void
-sp_node_path_edit_delete_segment(void)
+static void sp_node_path_edit_delete_segment(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1057,8 +1183,7 @@ sp_node_path_edit_delete_segment(void)
}
}
-void
-sp_node_path_edit_break(void)
+static void sp_node_path_edit_break(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1066,8 +1191,7 @@ sp_node_path_edit_break(void)
}
}
-void
-sp_node_path_edit_join(void)
+static void sp_node_path_edit_join(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1075,8 +1199,7 @@ sp_node_path_edit_join(void)
}
}
-void
-sp_node_path_edit_join_segment(void)
+static void sp_node_path_edit_join_segment(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1084,8 +1207,7 @@ sp_node_path_edit_join_segment(void)
}
}
-void
-sp_node_path_edit_toline(void)
+static void sp_node_path_edit_toline(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1093,8 +1215,7 @@ sp_node_path_edit_toline(void)
}
}
-void
-sp_node_path_edit_tocurve(void)
+static void sp_node_path_edit_tocurve(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1102,8 +1223,7 @@ sp_node_path_edit_tocurve(void)
}
}
-void
-sp_node_path_edit_cusp(void)
+static void sp_node_path_edit_cusp(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1111,8 +1231,7 @@ sp_node_path_edit_cusp(void)
}
}
-void
-sp_node_path_edit_smooth(void)
+static void sp_node_path_edit_smooth(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1120,8 +1239,7 @@ sp_node_path_edit_smooth(void)
}
}
-void
-sp_node_path_edit_symmetrical(void)
+static void sp_node_path_edit_symmetrical(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1129,8 +1247,7 @@ sp_node_path_edit_symmetrical(void)
}
}
-void
-sp_node_path_edit_auto(void)
+static void sp_node_path_edit_auto(void)
{
InkNodeTool *nt = get_node_tool();
if (nt) {
@@ -1138,43 +1255,12 @@ sp_node_path_edit_auto(void)
}
}
-static void toggle_show_transform_handles (GtkToggleAction *act, gpointer /*data*/) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool show = gtk_toggle_action_get_active( act );
- prefs->setBool("/tools/nodes/show_transform_handles", show);
-}
-
-static void toggle_show_handles (GtkToggleAction *act, gpointer /*data*/) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool show = gtk_toggle_action_get_active( act );
- prefs->setBool("/tools/nodes/show_handles", show);
-}
-
-static void toggle_show_helperpath (GtkToggleAction *act, gpointer /*data*/) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool show = gtk_toggle_action_get_active( act );
- prefs->setBool("/tools/nodes/show_outline", show);
-}
-
-void sp_node_path_edit_nextLPEparam (GtkAction */*act*/, gpointer data) {
+static void sp_node_path_edit_nextLPEparam(GtkAction * /*act*/, gpointer data) {
sp_selection_next_patheffect_param( reinterpret_cast<SPDesktop*>(data) );
}
-void toggle_edit_clip (GtkToggleAction *act, gpointer /*data*/) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool edit = gtk_toggle_action_get_active( act );
- prefs->setBool("/tools/nodes/edit_clipping_paths", edit);
-}
-
-void toggle_edit_mask (GtkToggleAction *act, gpointer /*data*/) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool edit = gtk_toggle_action_get_active( act );
- prefs->setBool("/tools/nodes/edit_masks", edit);
-}
-
/* is called when the node selection is modified */
-static void
-sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
+static void sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
{
GtkAction* xact = GTK_ACTION( g_object_get_data( tbl, "nodes_x_action" ) );
GtkAction* yact = GTK_ACTION( g_object_get_data( tbl, "nodes_y_action" ) );
@@ -1204,17 +1290,18 @@ sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
Geom::Coord oldy = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
Geom::Point mid = nt->_selected_nodes->pointwiseBounds()->midpoint();
- if (oldx != mid[Geom::X])
+ if (oldx != mid[Geom::X]) {
gtk_adjustment_set_value(xadj, sp_pixels_get_units(mid[Geom::X], *unit));
- if (oldy != mid[Geom::Y])
+ }
+ if (oldy != mid[Geom::Y]) {
gtk_adjustment_set_value(yadj, sp_pixels_get_units(mid[Geom::Y], *unit));
+ }
}
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-static void
-sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d)
+static void sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d)
{
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1247,20 +1334,17 @@ sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d)
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-static void
-sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_node_path_value_changed(adj, tbl, Geom::X);
}
-static void
-sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_node_path_value_changed(adj, tbl, Geom::Y);
}
-void
-sp_node_toolbox_sel_changed (Inkscape::Selection *selection, GObject *tbl)
+static void sp_node_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
{
{
GtkAction* w = GTK_ACTION( g_object_get_data( tbl, "nodes_lpeedit" ) );
@@ -1277,8 +1361,7 @@ sp_node_toolbox_sel_changed (Inkscape::Selection *selection, GObject *tbl)
}
}
-void
-sp_node_toolbox_sel_modified (Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
+static void sp_node_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
{
sp_node_toolbox_sel_changed (selection, tbl);
}
@@ -1291,7 +1374,6 @@ sp_node_toolbox_sel_modified (Inkscape::Selection *selection, guint /*flags*/, G
static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
g_object_set_data( holder, "tracker", tracker );
@@ -1429,8 +1511,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
"node-transform",
secondarySize );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_transform_handles), desktop );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_transform_handles", false) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_transform_handles");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
{
@@ -1440,8 +1522,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
INKSCAPE_ICON_SHOW_NODE_HANDLES,
secondarySize );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_handles), desktop );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_handles", true) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_handles");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
{
@@ -1451,8 +1533,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
INKSCAPE_ICON_SHOW_PATH_OUTLINE,
secondarySize );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_helperpath), desktop );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/nodes/show_outline", false) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_outline");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
{
@@ -1473,8 +1555,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
INKSCAPE_ICON_PATH_CLIP_EDIT,
secondarySize );
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
- g_signal_connect_after( G_OBJECT(inky), "toggled", G_CALLBACK(toggle_edit_clip), desktop );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(inky), prefs->getBool("/tools/nodes/edit_clipping_paths") );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_clipping_paths");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
{
@@ -1484,8 +1566,8 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
INKSCAPE_ICON_PATH_MASK_EDIT,
secondarySize );
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
- g_signal_connect_after( G_OBJECT(inky), "toggled", G_CALLBACK(toggle_edit_mask), desktop );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(inky), prefs->getBool("/tools/nodes/edit_masks") );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_masks");
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
}
/* X coord of selected node(s) */
@@ -1561,7 +1643,7 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
//## Zoom Toolbox ##
//########################
-static void sp_zoom_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* /*mainActions*/, GObject* /*holder*/)
+static void sp_zoom_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* /*mainActions*/, GObject* /*holder*/)
{
// no custom GtkAction setup needed
} // end of sp_zoom_toolbox_prep()
@@ -1766,8 +1848,7 @@ void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientati
}
}
-static void
-setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
+void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
{
gchar const * descr =
"<ui>"
@@ -1800,8 +1881,7 @@ setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
"/toolbox/tools/small");
}
-static void
-update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget */*toolbox*/ )
+void update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget * /*toolbox*/ )
{
gchar const *const tname = ( eventcontext
? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
@@ -1820,8 +1900,7 @@ update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget
}
}
-static void
-setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
+void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
@@ -1905,8 +1984,7 @@ setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
g_object_unref( G_OBJECT(grouper) );
}
-static void
-update_aux_toolbox(SPDesktop */*desktop*/, SPEventContext *eventcontext, GtkWidget *toolbox)
+void update_aux_toolbox(SPDesktop * /*desktop*/, SPEventContext *eventcontext, GtkWidget *toolbox)
{
gchar const *tname = ( eventcontext
? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
@@ -1922,8 +2000,7 @@ update_aux_toolbox(SPDesktop */*desktop*/, SPEventContext *eventcontext, GtkWidg
}
}
-static void
-setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
+void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
{
gchar const * descr =
"<ui>"
@@ -1974,13 +2051,12 @@ setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
"/toolbox/small" );
}
-static void
-update_commands_toolbox(SPDesktop */*desktop*/, SPEventContext */*eventcontext*/, GtkWidget */*toolbox*/)
+void update_commands_toolbox(SPDesktop * /*desktop*/, SPEventContext * /*eventcontext*/, GtkWidget * /*toolbox*/)
{
}
-void toggle_snap_callback (GtkToggleAction *act, gpointer data) { //data points to the toolbox
-
+static void toggle_snap_callback(GtkToggleAction *act, gpointer data) //data points to the toolbox
+{
if (g_object_get_data(G_OBJECT(data), "freeze" )) {
return;
}
@@ -2316,7 +2392,7 @@ Glib::ustring ToolboxFactory::getToolboxName(GtkWidget* toolbox)
return name;
}
-void ToolboxFactory::updateSnapToolbox(SPDesktop *desktop, SPEventContext */*eventcontext*/, GtkWidget *toolbox)
+void ToolboxFactory::updateSnapToolbox(SPDesktop *desktop, SPEventContext * /*eventcontext*/, GtkWidget *toolbox)
{
g_assert(desktop != NULL);
g_assert(toolbox != NULL);
@@ -2474,8 +2550,10 @@ static void sp_stb_magnitude_value_changed( GtkAdjustment *adj, GObject *dataKlu
modmade = true;
}
}
- if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
- _("Star: Change number of corners"));
+ if (modmade) {
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
+ _("Star: Change number of corners"));
+ }
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
}
@@ -2519,8 +2597,10 @@ static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GObject *dataKl
}
}
- if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
- _("Star: Change spoke ratio"));
+ if (modmade) {
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
+ _("Star: Change spoke ratio"));
+ }
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
}
@@ -2598,8 +2678,10 @@ static void sp_stb_rounded_value_changed( GtkAdjustment *adj, GObject *dataKludg
modmade = true;
}
}
- if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
- _("Star: Change rounding"));
+ if (modmade) {
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
+ _("Star: Change rounding"));
+ }
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
}
@@ -2633,15 +2715,17 @@ static void sp_stb_randomized_value_changed( GtkAdjustment *adj, GObject *dataKl
modmade = true;
}
}
- if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
- _("Star: Change randomization"));
+ if (modmade) {
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
+ _("Star: Change randomization"));
+ }
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
}
static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
- gchar const */*old_value*/, gchar const */*new_value*/,
+ gchar const * /*old_value*/, gchar const * /*new_value*/,
bool /*is_interactive*/, gpointer data)
{
GtkWidget *tbl = GTK_WIDGET(data);
@@ -2746,7 +2830,7 @@ sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
}
-static void sp_stb_defaults( GtkWidget */*widget*/, GObject *dataKludge )
+static void sp_stb_defaults( GtkWidget * /*widget*/, GObject *dataKludge )
{
// FIXME: in this and all other _default functions, set some flag telling the value_changed
// callbacks to lump all the changes for all selected objects in one undo step
@@ -2784,11 +2868,13 @@ static void sp_stb_defaults( GtkWidget */*widget*/, GObject *dataKludge )
}
-void
-sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
+// public:
+void sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
{
GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
- if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
+ if (wide) {
+ gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
+ }
GtkWidget *l = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(l), title);
gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
@@ -2961,9 +3047,8 @@ static void sp_rtb_sensitivize( GObject *tbl )
}
-static void
-sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name,
- void (*setter)(SPRect *, gdouble))
+static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name,
+ void (*setter)(SPRect *, gdouble))
{
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
@@ -3006,34 +3091,29 @@ sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name,
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-static void
-sp_rtb_rx_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_rtb_rx_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
}
-static void
-sp_rtb_ry_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_rtb_ry_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
}
-static void
-sp_rtb_width_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_rtb_width_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
}
-static void
-sp_rtb_height_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_rtb_height_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
}
-static void
-sp_rtb_defaults( GtkWidget */*widget*/, GObject *obj)
+static void sp_rtb_defaults( GtkWidget * /*widget*/, GObject *obj)
{
GtkAdjustment *adj = 0;
@@ -3049,8 +3129,8 @@ sp_rtb_defaults( GtkWidget */*widget*/, GObject *obj)
sp_rtb_sensitivize( obj );
}
-static void rect_tb_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const */*name*/,
- gchar const */*old_value*/, gchar const */*new_value*/,
+static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*name*/,
+ gchar const * /*old_value*/, gchar const * /*new_value*/,
bool /*is_interactive*/, gpointer data)
{
GObject *tbl = G_OBJECT(data);
@@ -3110,8 +3190,7 @@ static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
/**
* \param selection should not be NULL.
*/
-static void
-sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
+static void sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
{
int n_selected = 0;
Inkscape::XML::Node *repr = NULL;
@@ -3294,9 +3373,12 @@ static double box3d_normalize_angle (double a) {
return angle;
}
-static void
-box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis,
- GtkAdjustment *adj, GtkAction *act, GtkToggleAction *tact) {
+static void box3d_set_button_and_adjustment(Persp3D *persp,
+ Proj::Axis axis,
+ GtkAdjustment *adj,
+ GtkAction *act,
+ GtkToggleAction *tact)
+{
// TODO: Take all selected perspectives into account but don't touch the state button if not all of them
// have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states
// are reset).
@@ -3316,8 +3398,8 @@ box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis,
}
}
-static void
-box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) {
+static void box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data)
+{
if (!persp_repr) {
g_print ("No perspective given to box3d_resync_toolbar().\n");
return;
@@ -3355,9 +3437,12 @@ box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) {
}
}
-static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/,
- gchar const */*old_value*/, gchar const */*new_value*/,
- bool /*is_interactive*/, gpointer data)
+static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr,
+ gchar const * /*name*/,
+ gchar const * /*old_value*/,
+ gchar const * /*new_value*/,
+ bool /*is_interactive*/,
+ gpointer data)
{
GtkWidget *tbl = GTK_WIDGET(data);
@@ -3395,8 +3480,7 @@ static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events =
*/
// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each
// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?)
-static void
-box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
+static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
{
// Here the following should be done: If all selected boxes have finite VPs in a certain direction,
// disable the angle entry fields for this direction (otherwise entering a value in them should only
@@ -3428,8 +3512,7 @@ box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
}
}
-static void
-box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis)
+static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis)
{
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
SPDocument *document = sp_desktop_document(desktop);
@@ -3459,26 +3542,23 @@ box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis ax
}
-static void
-box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge)
+static void box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge)
{
box3d_angle_value_changed(adj, dataKludge, Proj::X);
}
-static void
-box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge)
+static void box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge)
{
box3d_angle_value_changed(adj, dataKludge, Proj::Y);
}
-static void
-box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge)
+static void box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge)
{
box3d_angle_value_changed(adj, dataKludge, Proj::Z);
}
-static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction */*box3d_angle*/, Proj::Axis axis )
+static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction * /*box3d_angle*/, Proj::Axis axis )
{
// TODO: Take all selected perspectives into account
std::list<Persp3D *> sel_persps = sp_desktop_selection(inkscape_active_desktop())->perspList();
@@ -3647,8 +3727,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
//## Spiral ##
//########################
-static void
-sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &value_name)
+static void sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &value_name)
{
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
@@ -3690,26 +3769,22 @@ sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &v
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-static void
-sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_spl_tb_value_changed(adj, tbl, "revolution");
}
-static void
-sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_spl_tb_value_changed(adj, tbl, "expansion");
}
-static void
-sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GObject *tbl)
{
sp_spl_tb_value_changed(adj, tbl, "t0");
}
-static void
-sp_spl_tb_defaults(GtkWidget */*widget*/, GtkObject *obj)
+static void sp_spl_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj)
{
GtkWidget *tbl = GTK_WIDGET(obj);
@@ -3736,9 +3811,12 @@ sp_spl_tb_defaults(GtkWidget */*widget*/, GtkObject *obj)
}
-static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/,
- gchar const */*old_value*/, gchar const */*new_value*/,
- bool /*is_interactive*/, gpointer data)
+static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr,
+ gchar const * /*name*/,
+ gchar const * /*old_value*/,
+ gchar const * /*new_value*/,
+ bool /*is_interactive*/,
+ gpointer data)
{
GtkWidget *tbl = GTK_WIDGET(data);
@@ -3772,8 +3850,7 @@ static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
NULL /* order_changed */
};
-static void
-sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
+static void sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
{
int n_selected = 0;
Inkscape::XML::Node *repr = NULL;
@@ -3889,8 +3966,7 @@ static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
//########################
/* This is used in generic functions below to share large portions of code between pen and pencil tool */
-static Glib::ustring const
-freehand_tool_name(GObject *dataKludge)
+static Glib::ustring const freehand_tool_name(GObject *dataKludge)
{
SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop");
return ( tools_isactive(desktop, TOOLS_FREEHAND_PEN)
@@ -3985,7 +4061,7 @@ static void freehand_change_shape(EgeSelectOneAction* act, GObject *dataKludge)
/**
* \brief Generate the list of freehand advanced shape option entries.
*/
-GList * freehand_shape_dropdown_items_list() {
+static GList * freehand_shape_dropdown_items_list() {
GList *glist = NULL;
glist = g_list_append (glist, _("None"));
@@ -3997,8 +4073,8 @@ GList * freehand_shape_dropdown_items_list() {
return glist;
}
-static void
-freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil) {
+static void freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil)
+{
/*advanced shape options */
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -4027,15 +4103,14 @@ freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder
}
}
-static void sp_pen_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* mainActions, GObject* holder)
+static void sp_pen_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder)
{
sp_add_freehand_mode_toggle(mainActions, holder, false);
freehand_add_advanced_shape_options(mainActions, holder, false);
}
-static void
-sp_pencil_tb_defaults(GtkWidget */*widget*/, GtkObject *obj)
+static void sp_pencil_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj)
{
GtkWidget *tbl = GTK_WIDGET(obj);
@@ -4051,8 +4126,7 @@ sp_pencil_tb_defaults(GtkWidget */*widget*/, GtkObject *obj)
spinbutton_defocus(GTK_OBJECT(tbl));
}
-static void
-sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
+static void sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
{
// quit if run by the attr_changed listener
if (g_object_get_data( tbl, "freeze" )) {
@@ -4143,13 +4217,13 @@ static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
//## Tweak ##
//########################
-static void sp_tweak_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_tweak_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/tweak/width", adj->value * 0.01 );
}
-static void sp_tweak_force_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_tweak_force_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/tweak/force", adj->value * 0.01 );
@@ -4167,48 +4241,39 @@ static void sp_tweak_mode_changed( EgeSelectOneAction *act, GObject *tbl )
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt("/tools/tweak/mode", mode);
- GtkAction *doh = GTK_ACTION(g_object_get_data( tbl, "tweak_doh"));
- GtkAction *dos = GTK_ACTION(g_object_get_data( tbl, "tweak_dos"));
- GtkAction *dol = GTK_ACTION(g_object_get_data( tbl, "tweak_dol"));
- GtkAction *doo = GTK_ACTION(g_object_get_data( tbl, "tweak_doo"));
+ static gchar const* names[] = {"tweak_doh", "tweak_dos", "tweak_dol", "tweak_doo", "tweak_channels_label"};
+ bool flag = ((mode == TWEAK_MODE_COLORPAINT) || (mode == TWEAK_MODE_COLORJITTER));
+ for (size_t i = 0; i < G_N_ELEMENTS(names); ++i) {
+ GtkAction *act = GTK_ACTION(g_object_get_data( tbl, names[i] ));
+ if (act) {
+ gtk_action_set_sensitive(act, flag);
+ }
+ }
GtkAction *fid = GTK_ACTION(g_object_get_data( tbl, "tweak_fidelity"));
- GtkAction *dolabel = GTK_ACTION(g_object_get_data( tbl, "tweak_channels_label"));
- if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) {
- if (doh) gtk_action_set_sensitive (doh, TRUE);
- if (dos) gtk_action_set_sensitive (dos, TRUE);
- if (dol) gtk_action_set_sensitive (dol, TRUE);
- if (doo) gtk_action_set_sensitive (doo, TRUE);
- if (dolabel) gtk_action_set_sensitive (dolabel, TRUE);
- if (fid) gtk_action_set_sensitive (fid, FALSE);
- } else {
- if (doh) gtk_action_set_sensitive (doh, FALSE);
- if (dos) gtk_action_set_sensitive (dos, FALSE);
- if (dol) gtk_action_set_sensitive (dol, FALSE);
- if (doo) gtk_action_set_sensitive (doo, FALSE);
- if (dolabel) gtk_action_set_sensitive (dolabel, FALSE);
- if (fid) gtk_action_set_sensitive (fid, TRUE);
+ if (fid) {
+ gtk_action_set_sensitive(fid, !flag);
}
}
-static void sp_tweak_fidelity_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_tweak_fidelity_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/tweak/fidelity", adj->value * 0.01 );
}
-static void tweak_toggle_doh (GtkToggleAction *act, gpointer /*data*/) {
+static void tweak_toggle_doh(GtkToggleAction *act, gpointer /*data*/) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/tweak/doh", gtk_toggle_action_get_active(act));
}
-static void tweak_toggle_dos (GtkToggleAction *act, gpointer /*data*/) {
+static void tweak_toggle_dos(GtkToggleAction *act, gpointer /*data*/) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/tweak/dos", gtk_toggle_action_get_active(act));
}
-static void tweak_toggle_dol (GtkToggleAction *act, gpointer /*data*/) {
+static void tweak_toggle_dol(GtkToggleAction *act, gpointer /*data*/) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/tweak/dol", gtk_toggle_action_get_active(act));
}
-static void tweak_toggle_doo (GtkToggleAction *act, gpointer /*data*/) {
+static void tweak_toggle_doo(GtkToggleAction *act, gpointer /*data*/) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/tweak/doo", gtk_toggle_action_get_active(act));
}
@@ -4373,8 +4438,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
EgeOutputAction* act = ege_output_action_new( "TweakChannelsLabel", _("Channels:"), "", 0 );
ege_output_action_set_use_markup( act, TRUE );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER)
+ if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
+ }
g_object_set_data( holder, "tweak_channels_label", act);
}
@@ -4389,8 +4455,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doh), desktop );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doh", true) );
- if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER)
+ if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
+ }
g_object_set_data( holder, "tweak_doh", act);
}
{
@@ -4404,8 +4471,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dos), desktop );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dos", true) );
- if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER)
+ if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
+ }
g_object_set_data( holder, "tweak_dos", act );
}
{
@@ -4419,8 +4487,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dol), desktop );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dol", true) );
- if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER)
+ if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
+ }
g_object_set_data( holder, "tweak_dol", act );
}
{
@@ -4434,8 +4503,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doo), desktop );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doo", true) );
- if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER)
+ if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
+ }
g_object_set_data( holder, "tweak_doo", act );
}
@@ -4452,8 +4522,9 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
sp_tweak_fidelity_value_changed, 0.01, 0, 100 );
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
- if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER)
+ if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) {
gtk_action_set_sensitive (GTK_ACTION(eact), FALSE);
+ }
g_object_set_data( holder, "tweak_fidelity", eact );
}
@@ -4477,19 +4548,19 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
//## Spray ##
//########################
-static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/width", adj->value );
}
-static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/mean", adj->value );
}
-static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/standard_deviation", adj->value );
@@ -4501,26 +4572,26 @@ static void sp_spray_pressure_state_changed( GtkToggleAction *act, gpointer /*da
prefs->setBool("/tools/spray/usepressure", gtk_toggle_action_get_active(act));
}
-static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject */*tbl*/ )
+static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject * /*tbl*/ )
{
int mode = ege_select_one_action_get_active( act );
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt("/tools/spray/mode", mode);
}
-static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/population", adj->value );
}
-static void sp_spray_rotation_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_rotation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/rotation_variation", adj->value );
}
-static void sp_spray_scale_value_changed( GtkAdjustment *adj, GObject */*tbl*/ )
+static void sp_spray_scale_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble( "/tools/spray/scale_variation", adj->value );
@@ -4698,11 +4769,12 @@ static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
//########################
//## Calligraphy ##
//########################
-static void update_presets_list (GObject *tbl)
+static void update_presets_list(GObject *tbl)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (g_object_get_data(tbl, "presets_blocked"))
+ if (g_object_get_data(tbl, "presets_blocked")) {
return;
+ }
EgeSelectOneAction *sel = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "profile_selector"));
if (!sel) {
@@ -4720,7 +4792,9 @@ static void update_presets_list (GObject *tbl)
std::vector<Inkscape::Preferences::Entry> preset = prefs->getAllEntries(*i);
for (std::vector<Inkscape::Preferences::Entry>::iterator j = preset.begin(); j != preset.end(); ++j) {
Glib::ustring entry_name = j->getEntryName();
- if (entry_name == "id" || entry_name == "name") continue;
+ if (entry_name == "id" || entry_name == "name") {
+ continue;
+ }
void *widget = g_object_get_data(tbl, entry_name.data());
if (widget) {
@@ -4813,28 +4887,13 @@ static void sp_ddc_cap_rounding_value_changed( GtkAdjustment *adj, GObject* tbl
update_presets_list(tbl);
}
-static void sp_ddc_pressure_state_changed( GtkToggleAction *act, GObject* tbl )
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/tools/calligraphic/usepressure", gtk_toggle_action_get_active( act ));
- update_presets_list(tbl);
-}
-
-static void sp_ddc_trace_background_changed( GtkToggleAction *act, GObject* tbl )
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/tools/calligraphic/tracebackground", gtk_toggle_action_get_active( act ));
- update_presets_list(tbl);
-}
-
static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GObject* tbl )
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ // TODO merge into PrefPusher
GtkAction * calligraphy_angle = static_cast<GtkAction *> (g_object_get_data(tbl,"angle_action"));
- prefs->setBool("/tools/calligraphic/usetilt", gtk_toggle_action_get_active( act ));
- update_presets_list(tbl);
- if (calligraphy_angle )
+ if (calligraphy_angle ) {
gtk_action_set_sensitive( calligraphy_angle, !gtk_toggle_action_get_active( act ) );
+ }
}
@@ -4891,15 +4950,18 @@ static void sp_dcc_build_presets_list(GObject *tbl)
update_presets_list (tbl);
}
-static void sp_dcc_save_profile (GtkWidget */*widget*/, GObject *tbl)
+static void sp_dcc_save_profile(GtkWidget * /*widget*/, GObject *tbl)
{
using Inkscape::UI::Dialog::CalligraphicProfileRename;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop" );
- if (! desktop) return;
+ if (! desktop) {
+ return;
+ }
- if (g_object_get_data(tbl, "presets_blocked"))
+ if (g_object_get_data(tbl, "presets_blocked")) {
return;
+ }
CalligraphicProfileRename::show(desktop);
if ( !CalligraphicProfileRename::applied()) {
@@ -4967,15 +5029,17 @@ static void sp_dcc_save_profile (GtkWidget */*widget*/, GObject *tbl)
}
-static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) {
-
+static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl)
+{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
gint preset_index = ege_select_one_action_get_active( act );
// This is necessary because EgeSelectOneAction spams us with GObject "changed" signal calls
// even when the preset is not changed. It would be good to replace it with something more
// modern. Index 0 means "No preset", so we don't do anything.
- if (preset_index == 0) return;
+ if (preset_index == 0) {
+ return;
+ }
gint save_presets_index = GPOINTER_TO_INT(g_object_get_data(tbl, "save_presets_index"));
@@ -4985,8 +5049,9 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) {
return;
}
- if (g_object_get_data(tbl, "presets_blocked"))
+ if (g_object_get_data(tbl, "presets_blocked")) {
return;
+ }
// preset_index is one-based so we subtract 1
std::vector<Glib::ustring> presets = prefs->getAllDirs("/tools/calligraphic/preset");
@@ -5000,7 +5065,9 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) {
// Shouldn't this be std::map?
for (std::vector<Inkscape::Preferences::Entry>::iterator i = preset.begin(); i != preset.end(); ++i) {
Glib::ustring entry_name = i->getEntryName();
- if (entry_name == "id" || entry_name == "name") continue;
+ if (entry_name == "id" || entry_name == "name") {
+ continue;
+ }
void *widget = g_object_get_data(tbl, entry_name.data());
if (widget) {
if (GTK_IS_ADJUSTMENT(widget)) {
@@ -5022,7 +5089,6 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) {
}
}
-
static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -5176,8 +5242,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
INKSCAPE_ICON_DRAW_TRACE_BACKGROUND,
Inkscape::ICON_SIZE_DECORATION );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_trace_background_changed), holder);
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/tracebackground", false) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/tracebackground", update_presets_list, holder);
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
g_object_set_data( holder, "tracebackground", act );
}
@@ -5189,8 +5255,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
INKSCAPE_ICON_DRAW_USE_PRESSURE,
Inkscape::ICON_SIZE_DECORATION );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_pressure_state_changed), holder);
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/usepressure", true) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usepressure", update_presets_list, holder);
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
g_object_set_data( holder, "usepressure", act );
}
@@ -5202,6 +5268,8 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
INKSCAPE_ICON_DRAW_USE_TILT,
Inkscape::ICON_SIZE_DECORATION );
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usetilt", update_presets_list, holder);
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_tilt_state_changed), holder );
gtk_action_set_sensitive( GTK_ACTION(calligraphy_angle), !prefs->getBool("/tools/calligraphic/usetilt", true) );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/usetilt", true) );
@@ -5278,10 +5346,11 @@ sp_arctb_startend_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *v
SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
SPArc *arc = SP_ARC(item);
- if (!strcmp(value_name, "start"))
+ if (!strcmp(value_name, "start")) {
ge->start = (adj->value * M_PI)/ 180;
- else
+ } else {
ge->end = (adj->value * M_PI)/ 180;
+ }
sp_genericellipse_normalize(ge);
((SPObject *)arc)->updateRepr();
@@ -5352,7 +5421,7 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl )
items != NULL;
items = items->next)
{
- if (SP_IS_ARC((SPItem *) items->data)) {
+ if (SP_IS_ARC((SPItem *) items->data)) {
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
repr->setAttribute("sodipodi:open", NULL);
SP_OBJECT((SPItem *) items->data)->updateRepr();
@@ -5383,8 +5452,8 @@ static void sp_arctb_defaults(GtkWidget *, GObject *obj)
spinbutton_defocus( GTK_OBJECT(obj) );
}
-static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const */*name*/,
- gchar const */*old_value*/, gchar const */*new_value*/,
+static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * /*name*/,
+ gchar const * /*old_value*/, gchar const * /*new_value*/,
bool /*is_interactive*/, gpointer data)
{
GObject *tbl = G_OBJECT(data);
@@ -5585,7 +5654,8 @@ static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
//## Dropper ##
//########################
-static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl ) {
+static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl )
+{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt( "/tools/dropper/pick", gtk_toggle_action_get_active( act ) );
GtkAction* set_action = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "set_action") );
@@ -5600,7 +5670,8 @@ static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl ) {
spinbutton_defocus(GTK_OBJECT(tbl));
}
-static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl ) {
+static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl )
+{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool( "/tools/dropper/setalpha", gtk_toggle_action_get_active( act ) );
spinbutton_defocus(GTK_OBJECT(tbl));
@@ -5614,7 +5685,7 @@ static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl ) {
* TODO: Add queue of last 5 or so colors selected with new swatches so that
* can drag and drop places. Will provide a nice mixing palette.
*/
-static void sp_dropper_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* mainActions, GObject* holder)
+static void sp_dropper_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
gint pickAlpha = prefs->getInt( "/tools/dropper/pick", 1 );
@@ -5700,22 +5771,21 @@ static void sp_lpetool_mode_changed(EgeSelectOneAction *act, GObject *tbl)
}
}
-void sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject */*tbl*/)
+static void sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject * /*tbl*/)
{
SPEventContext *ec = selection->desktop()->event_context;
- if (!SP_IS_LPETOOL_CONTEXT(ec))
- return;
-
- lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec));
+ if (SP_IS_LPETOOL_CONTEXT(ec)) {
+ lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec));
+ }
}
-void
-sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
+static void sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
{
using namespace Inkscape::LivePathEffect;
SPEventContext *ec = selection->desktop()->event_context;
- if (!SP_IS_LPETOOL_CONTEXT(ec))
+ if (!SP_IS_LPETOOL_CONTEXT(ec)) {
return;
+ }
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec);
lpetool_delete_measuring_items(lc);
@@ -5745,8 +5815,7 @@ sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
}
}
-static void
-lpetool_toggle_show_bbox (GtkToggleAction *act, gpointer data) {
+static void lpetool_toggle_show_bbox(GtkToggleAction *act, gpointer data) {
SPDesktop *desktop = static_cast<SPDesktop *>(data);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -5759,11 +5828,12 @@ lpetool_toggle_show_bbox (GtkToggleAction *act, gpointer data) {
}
}
-static void
-lpetool_toggle_show_measuring_info (GtkToggleAction *act, GObject *tbl) {
+static void lpetool_toggle_show_measuring_info(GtkToggleAction *act, GObject *tbl)
+{
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(tbl, "desktop"));
- if (!tools_isactive(desktop, TOOLS_LPETOOL))
+ if (!tools_isactive(desktop, TOOLS_LPETOOL)) {
return;
+ }
GtkAction *unitact = static_cast<GtkAction*>(g_object_get_data(tbl, "lpetool_units_action"));
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context);
@@ -5776,7 +5846,8 @@ lpetool_toggle_show_measuring_info (GtkToggleAction *act, GObject *tbl) {
}
}
-static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl) {
+static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl)
+{
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker"));
SPUnit const *unit = tracker->getActiveUnit();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -5790,8 +5861,8 @@ static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl) {
}
}
-static void
-lpetool_toggle_set_bbox (GtkToggleAction *act, gpointer data) {
+static void lpetool_toggle_set_bbox(GtkToggleAction *act, gpointer data)
+{
SPDesktop *desktop = static_cast<SPDesktop *>(data);
Inkscape::Selection *selection = desktop->selection;
@@ -5817,8 +5888,7 @@ lpetool_toggle_set_bbox (GtkToggleAction *act, gpointer data) {
gtk_toggle_action_set_active(act, false);
}
-static void
-sp_line_segment_build_list(GObject *tbl)
+static void sp_line_segment_build_list(GObject *tbl)
{
g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(TRUE));
@@ -5842,8 +5912,8 @@ sp_line_segment_build_list(GObject *tbl)
g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(FALSE));
}
-static void
-sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) {
+static void sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl)
+{
using namespace Inkscape::LivePathEffect;
// quit if run by the attr_changed listener
@@ -5865,8 +5935,8 @@ sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) {
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-static void
-lpetool_open_lpe_dialog (GtkToggleAction *act, gpointer data) {
+static void lpetool_open_lpe_dialog(GtkToggleAction *act, gpointer data)
+{
SPDesktop *desktop = static_cast<SPDesktop *>(data);
if (tools_isactive(desktop, TOOLS_LPETOOL)) {
@@ -6107,263 +6177,156 @@ static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
//########################
//## Text Toolbox ##
//########################
-/*
-static void
-sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
-{
- //Call back for letter sizing spinbutton
-}
-static void
-sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
-{
- //Call back for line height spinbutton
-}
+// Functions for debugging:
+#ifdef DEBUG_TEXT
-static void
-sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
-{
- //Call back for horizontal kerning spinbutton
-}
+static void sp_print_font( SPStyle *query ) {
-static void
-sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
-{
- //Call back for vertical kerning spinbutton
-}
-
-static void
-sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
-{
- //Call back for letter rotation spinbutton
-}*/
+ bool family_set = query->text->font_family.set;
+ bool style_set = query->font_style.set;
+ bool fontspec_set = query->text->font_specification.set;
-namespace {
-
-void
-sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *tbl)
-{
- // quit if run by the _changed callbacks
- if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
- return;
- }
+ std::cout << " Family set? " << family_set
+ << " Style set? " << style_set
+ << " FontSpec set? " << fontspec_set
+ << std::endl;
+ std::cout << " Family: "
+ << (query->text->font_family.value ? query->text->font_family.value : "No value")
+ << " Style: " << query->font_style.computed
+ << " Weight: " << query->font_weight.computed
+ << " FontSpec: "
+ << (query->text->font_specification.value ? query->text->font_specification.value : "No value")
+ << std::endl;
+}
+
+static void sp_print_fontweight( SPStyle *query ) {
+ const gchar* names[] = {"100", "200", "300", "400", "500", "600", "700", "800", "900",
+ "NORMAL", "BOLD", "LIGHTER", "BOLDER", "Out of range"};
+ // Missing book = 380
+ int index = query->font_weight.computed;
+ if( index < 0 || index > 13 ) index = 13;
+ std::cout << " Weight: " << names[ index ]
+ << " (" << query->font_weight.computed << ")" << std::endl;
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
+}
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
+static void sp_print_fontstyle( SPStyle *query ) {
- int result_family =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ const gchar* names[] = {"NORMAL", "ITALIC", "OBLIQUE", "Out of range"};
+ int index = query->font_style.computed;
+ if( index < 0 || index > 3 ) index = 3;
+ std::cout << " Style: " << names[ index ] << std::endl;
- int result_style =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+}
+#endif
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+// Format family drop-down menu.
+static void cell_data_func(GtkCellLayout * /*cell_layout*/,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer /*data*/)
+{
+ gchar *family;
+ gtk_tree_model_get(tree_model, iter, 0, &family, -1);
+ gchar *const family_escaped = g_markup_escape_text(family, -1);
- gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1);
+ if (show_sample) {
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) {
- // there are no texts in selection, read from prefs
+ Glib::ustring sample = prefs->getString("/tools/text/font_sample");
+ gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1);
- sp_style_read_from_prefs(query, "/tools/text");
+ std::stringstream markup;
+ markup << family_escaped << " <span foreground='gray' font_family='"
+ << family_escaped << "'>" << sample_escaped << "</span>";
+ g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
- if (g_object_get_data(tbl, "text_style_from_prefs")) {
- // do not reset the toolbar style from prefs if we already did it last time
- sp_style_unref(query);
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- return;
- }
- g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE));
+ g_free(sample_escaped);
} else {
- g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE));
- }
-
- if (query->text)
- {
- if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) {
- GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
- gtk_entry_set_text (GTK_ENTRY (entry), "");
-
- } else if (query->text->font_specification.value || query->text->font_family.value) {
-
- Gtk::ComboBoxEntry *combo = (Gtk::ComboBoxEntry *) (g_object_get_data (G_OBJECT (tbl), "family-entry-combo"));
- GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry"));
-
- // Get the font that corresponds
- Glib::ustring familyName;
-
- font_instance * font = font_factory::Default()->FaceFromStyle(query);
- if (font) {
- familyName = font_factory::Default()->GetUIFamilyString(font->descr);
- font->Unref();
- font = NULL;
- }
-
- gtk_entry_set_text (GTK_ENTRY (entry), familyName.c_str());
-
- Gtk::TreeIter iter;
- try {
- Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (familyName);
- Glib::RefPtr<Gtk::TreeModel> model = combo->get_model();
- iter = model->get_iter(path);
- } catch (...) {
- g_warning("Family name %s does not have an entry in the font lister.", familyName.c_str());
- sp_style_unref(query);
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- return;
- }
-
- combo->set_active (iter);
- }
-
- //Size
- {
- GtkWidget *cbox = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "combo-box-size"));
- gchar *const str = g_strdup_printf("%.5g", query->font_size.computed);
- gtk_entry_set_text(GTK_ENTRY(GTK_BIN(cbox)->child), str);
- g_free(str);
- }
-
- //Anchor
- if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
- {
- GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-fill"));
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- else
- {
- if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START)
- {
- GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start"));
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE)
- {
- GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle"));
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END)
- {
- GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end"));
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- }
-
- //Style
- {
- GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-bold"));
-
- gboolean active = gtk_toggle_button_get_active (button);
- gboolean check = ((query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700) && (query->font_weight.computed != SP_CSS_FONT_WEIGHT_NORMAL) && (query->font_weight.computed != SP_CSS_FONT_WEIGHT_LIGHTER));
-
- if (active != check)
- {
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- }
-
- {
- GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-italic"));
-
- gboolean active = gtk_toggle_button_get_active (button);
- gboolean check = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
-
- if (active != check)
- {
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- }
-
- //Orientation
- //locking both buttons, changing one affect all group (both)
- GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-horizontal"));
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
-
- GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical"));
- g_object_set_data (G_OBJECT (button1), "block", gpointer(1));
-
- if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB)
- {
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- }
- else
- {
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE);
- }
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- g_object_set_data (G_OBJECT (button1), "block", gpointer(0));
+ g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL);
}
- sp_style_unref(query);
-
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+ g_free(family);
+ g_free(family_escaped);
}
-void
-sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
+// Font family
+static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
{
- sp_text_toolbox_selection_changed (selection, tbl);
-}
-
-void
-sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
-{
- sp_text_toolbox_selection_changed (NULL, tbl);
-}
+#ifdef DEBUG_TEXT
+ std::cout << std::endl;
+ std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl;
+ std::cout << "sp_text_fontfamily_value_changed: " << std::endl;
+#endif
-void
-sp_text_toolbox_family_changed (GtkComboBoxEntry *,
- GObject *tbl)
-{
- // quit if run by the _changed callbacks
+ // quit if run by the _changed callbacks
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
return;
}
-
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
- const gchar* family = gtk_entry_get_text (GTK_ENTRY (entry));
+ gchar *family = ink_comboboxentry_action_get_active_text( act );
+#ifdef DEBUG_TEXT
+ std::cout << " New family: " << family << std::endl;
+#endif
- //g_print ("family changed to: %s\n", family);
+ // First try to get the old font spec from the stored value
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
+ Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
- int result_fontspec =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+ // If that didn't work, try to get font spec from style
+ if (fontSpec.empty()) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
+ // Must query all to fill font-family, font-style, font-weight, font-specification
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
- // First try to get the font spec from the stored value
- Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
+ // Construct a new font specification if it does not yet exist
+ font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
+ if( fontFromStyle ) {
+ fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
+ fontFromStyle->Unref();
+ }
+#ifdef DEBUG_TEXT
+ std::cout << " Fontspec not defined, reconstructed from style :" << fontSpec << ":" << std::endl;
+ sp_print_font( query );
+#endif
+ }
- if (fontSpec.empty()) {
+ // And if that didn't work use default
+ if( fontSpec.empty() ) {
+ sp_style_read_from_prefs(query, "/tools/text");
+#ifdef DEBUG_TEXT
+ std::cout << " read style from prefs:" << std::endl;
+ sp_print_font( query );
+#endif
// Construct a new font specification if it does not yet exist
font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
- fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
- fontFromStyle->Unref();
+ if( fontFromStyle ) {
+ fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
+ fontFromStyle->Unref();
+ }
+#ifdef DEBUG_TEXT
+ std::cout << " Fontspec not defined, reconstructed from style :" << fontSpec << ":" << std::endl;
+ sp_print_font( query );
+#endif
}
+ SPCSSAttr *css = sp_repr_css_attr_new ();
if (!fontSpec.empty()) {
- Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
+ // Now we have a font specification, replace family.
+ Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
+
+#ifdef DEBUG_TEXT
+ std::cout << " New FontSpec from ReplaceFontSpecificationFamily :" << newFontSpec << ":" << std::endl;
+#endif
if (!newFontSpec.empty()) {
@@ -6400,51 +6363,250 @@ sp_text_toolbox_family_changed (GtkComboBoxEntry *,
}
} else {
- // If the old font on selection (or default) was not existing on the system,
+
+ // newFontSpec empty
+ // If the old font on selection (or default) does not exist on the system,
+ // or the new font family does not exist,
// ReplaceFontSpecificationFamily does not work. In that case we fall back to blindly
// setting the family reported by the family chooser.
- //g_print ("fallback setting family: %s\n", family);
+ // g_print ("fallback setting family: %s\n", family);
sp_repr_css_set_property (css, "-inkscape-font-specification", family);
sp_repr_css_set_property (css, "font-family", family);
+ // Shoud we set other css font attributes?
}
- }
- // If querying returned nothing, set the default style of the tool (for new texts)
+ } // fontSpec not empty or not
+
+ // If querying returned nothing, update default style.
if (result_fontspec == QUERY_STYLE_NOTHING)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->mergeStyle("/tools/text/style", css);
- sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
+ sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace through a verb
}
else
{
- sp_desktop_set_style (desktop, css, true, true);
+ sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true);
}
sp_style_unref(query);
+ g_free (family);
+
+ // Save for undo
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
_("Text: Change font family"));
sp_repr_css_attr_unref (css);
- gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
-
// unfreeze
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
// focus to canvas
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ gtk_widget_grab_focus (GTK_WIDGET((SP_ACTIVE_DESKTOP)->canvas));
+
+#ifdef DEBUG_TEXT
+ std::cout << "sp_text_toolbox_fontfamily_changes: exit" << std::endl;
+ std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl;
+ std::cout << std::endl;
+#endif
}
+// Font size
+static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
+{
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
+
+ gchar *text = ink_comboboxentry_action_get_active_text( act );
+ gchar *endptr;
+ gdouble size = g_strtod( text, &endptr );
+ if (endptr == text) { // Conversion failed, non-numeric input.
+ g_warning( "Conversion of size text to double failed, input: %s\n", text );
+ g_free( text );
+ return;
+ }
+ g_free( text );
-void
-sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
- gpointer data)
+ // Set css font size.
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream osfs;
+ osfs << size << "px"; // For now always use px
+ sp_repr_css_set_property (css, "font-size", osfs.str().c_str());
+
+ // Apply font size to selected objects.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
+
+ // Save for undo
+ sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
+ _("Text: Change font size"));
+
+ // If no selected objects, set default.
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_numbers =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (result_numbers == QUERY_STYLE_NOTHING)
+ {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->mergeStyle("/tools/text/style", css);
+ }
+ sp_style_unref(query);
+
+ sp_repr_css_attr_unref (css);
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+// Handles both Bold and Italic/Oblique
+static void sp_text_style_changed( InkToggleAction* act, GObject *tbl )
+{
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
+
+ // Called by Bold or Italics button?
+ const gchar* name = gtk_action_get_name( GTK_ACTION( act ) );
+ gint prop = (strcmp(name, "TextBoldAction") == 0) ? 0 : 1;
+
+ // First query font-specification, this is the most complete font face description.
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ // font_specification will not be set unless defined explicitely on a tspan.
+ // This should be fixed!
+ Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
+
+ if (fontSpec.empty()) {
+ // Construct a new font specification if it does not yet exist
+ // Must query font-family, font-style, font-weight, to find correct font face.
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+
+ font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
+ if( fontFromStyle ) {
+ fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
+ fontFromStyle->Unref();
+ }
+ }
+
+ // Now that we have the old face, find the new face.
+ Glib::ustring newFontSpec = "";
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gboolean nochange = true;
+ gboolean active = gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(act) );
+
+ switch (prop)
+ {
+ case 0:
+ {
+ // Bold
+ if (!fontSpec.empty()) {
+
+ newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active);
+
+ if (!newFontSpec.empty()) {
+
+ // Set weight if we found font.
+ font_instance * font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
+ if (font) {
+ gchar c[256];
+ font->Attribute( "weight", c, 256);
+ sp_repr_css_set_property (css, "font-weight", c);
+ font->Unref();
+ font = NULL;
+ }
+ nochange = false;
+ }
+ }
+ // Reset button if no change.
+ // The reset code didn't work in 0.47 and doesn't here... one must prevent an infinite loop
+ /*
+ if(nochange) {
+ gtk_action_block_activate( GTK_ACTION(act) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active );
+ gtk_action_unblock_activate( GTK_ACTION(act) );
+ }
+ */
+ break;
+ }
+
+ case 1:
+ {
+ // Italic/Oblique
+ if (!fontSpec.empty()) {
+
+ newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active);
+
+ if (!newFontSpec.empty()) {
+
+ // Don't even set the italic/oblique if the font didn't exist on the system
+ if( active ) {
+ if( newFontSpec.find( "Italic" ) != Glib::ustring::npos ) {
+ sp_repr_css_set_property (css, "font-style", "italic");
+ } else {
+ sp_repr_css_set_property (css, "font-style", "oblique");
+ }
+ } else {
+ sp_repr_css_set_property (css, "font-style", "normal");
+ }
+ nochange = false;
+ }
+ }
+ // Reset button if no change.
+ // The reset code didn't work in 0.47... one must prevent an infinite loop
+ /*
+ if(nochange) {
+ gtk_action_block_activate( GTK_ACTION(act) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active );
+ gtk_action_unblock_activate( GTK_ACTION(act) );
+ }
+ */
+ break;
+ }
+ }
+
+ if (!newFontSpec.empty()) {
+ sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
+ }
+
+ // If querying returned nothing, update default style.
+ if (result_fontspec == QUERY_STYLE_NOTHING)
+ {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->mergeStyle("/tools/text/style", css);
+ }
+
+ sp_style_unref(query);
+
+ // Do we need to update other CSS values?
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
+ sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
+ _("Text: Change font style"));
+ sp_repr_css_attr_unref (css);
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl )
{
- if (g_object_get_data (G_OBJECT (button), "block")) return;
- if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return;
- int prop = GPOINTER_TO_INT(data);
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
+
+ int mode = ege_select_one_action_get_active( act );
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/tools/text/align_mode", mode);
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
@@ -6477,7 +6639,7 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
unsigned old_align = SP_OBJECT_STYLE(item)->text_align.value;
double move = 0;
if (old_align == SP_CSS_TEXT_ALIGN_START || old_align == SP_CSS_TEXT_ALIGN_LEFT) {
- switch (prop) {
+ switch (mode) {
case 0:
move = -left_slack;
break;
@@ -6489,7 +6651,7 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
break;
}
} else if (old_align == SP_CSS_TEXT_ALIGN_CENTER) {
- switch (prop) {
+ switch (mode) {
case 0:
move = -width/2 - left_slack;
break;
@@ -6501,7 +6663,7 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
break;
}
} else if (old_align == SP_CSS_TEXT_ALIGN_END || old_align == SP_CSS_TEXT_ALIGN_RIGHT) {
- switch (prop) {
+ switch (mode) {
case 0:
move = -width - left_slack;
break;
@@ -6526,7 +6688,7 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
}
SPCSSAttr *css = sp_repr_css_attr_new ();
- switch (prop)
+ switch (mode)
{
case 0:
{
@@ -6561,7 +6723,7 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
int result_numbers =
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
+ // If querying returned nothing, update default style.
if (result_numbers == QUERY_STYLE_NOTHING)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -6576,125 +6738,139 @@ sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
sp_repr_css_attr_unref (css);
gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-void
-sp_text_toolbox_style_toggled (GtkToggleButton *button,
- gpointer data)
+static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl )
{
- if (g_object_get_data (G_OBJECT (button), "block")) return;
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- SPCSSAttr *css = sp_repr_css_attr_new ();
- int prop = GPOINTER_TO_INT(data);
- bool active = gtk_toggle_button_get_active (button);
+ // At the moment this handles only numerical values (i.e. no percent).
+ // Set css line height.
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream osfs;
+ osfs << adj->value*100 << "%";
+ sp_repr_css_set_property (css, "line-height", osfs.str().c_str());
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
+ // Apply line-height to selected objects.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
- int result_fontspec =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+ // Save for undo
+ sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:line-height", SP_VERB_NONE,
+ _("Text: Change line-height"));
- //int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
- //int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
- //int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ // If no selected objects, set default.
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_numbers =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (result_numbers == QUERY_STYLE_NOTHING)
+ {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->mergeStyle("/tools/text/style", css);
+ }
+ sp_style_unref(query);
- Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
- Glib::ustring newFontSpec = "";
+ sp_repr_css_attr_unref (css);
- if (fontSpec.empty()) {
- // Construct a new font specification if it does not yet exist
- font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
- fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
- fontFromStyle->Unref();
- }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
- bool nochange = true;
- switch (prop)
- {
- case 0:
- {
- if (!fontSpec.empty()) {
- newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active);
- if (!newFontSpec.empty()) {
- // Don't even set the bold if the font didn't exist on the system
- sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
- nochange = false;
- }
- }
- // set or reset the button according
- if(nochange) {
- gboolean check = gtk_toggle_button_get_active (button);
+static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl )
+{
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- if (active != check)
- {
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- }
+ // At the moment this handles only numerical values (i.e. no em unit).
+ // Set css word-spacing
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream osfs;
+ osfs << adj->value;
+ sp_repr_css_set_property (css, "word-spacing", osfs.str().c_str());
- break;
- }
+ // Apply word-spacing to selected objects.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
- case 1:
- {
- if (!fontSpec.empty()) {
- newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active);
- if (!newFontSpec.empty()) {
- // Don't even set the italic if the font didn't exist on the system
- sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
- nochange = false;
- }
- }
- if(nochange) {
- gboolean check = gtk_toggle_button_get_active (button);
+ // Save for undo
+ sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:word-spacing", SP_VERB_NONE,
+ _("Text: Change word-spacing"));
- if (active != check)
- {
- g_object_set_data (G_OBJECT (button), "block", gpointer(1));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
- g_object_set_data (G_OBJECT (button), "block", gpointer(0));
- }
- }
- break;
- }
+ // If no selected objects, set default.
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_numbers =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (result_numbers == QUERY_STYLE_NOTHING)
+ {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->mergeStyle("/tools/text/style", css);
}
+ sp_style_unref(query);
- if (!newFontSpec.empty()) {
- sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
+ sp_repr_css_attr_unref (css);
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tbl )
+{
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
}
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_fontspec == QUERY_STYLE_NOTHING)
+ // At the moment this handles only numerical values (i.e. no em unit).
+ // Set css letter-spacing
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream osfs;
+ osfs << adj->value;
+ sp_repr_css_set_property (css, "letter-spacing", osfs.str().c_str());
+
+ // Apply letter-spacing to selected objects.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ sp_desktop_set_style (desktop, css, true, true);
+
+ // Save for undo
+ sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:letter-spacing", SP_VERB_NONE,
+ _("Text: Change letter-spacing"));
+
+ // If no selected objects, set default.
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_numbers =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (result_numbers == QUERY_STYLE_NOTHING)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->mergeStyle("/tools/text/style", css);
}
-
sp_style_unref(query);
- sp_desktop_set_style (desktop, css, true, true);
- sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
- _("Text: Change font style"));
sp_repr_css_attr_unref (css);
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-void
-sp_text_toolbox_orientation_toggled (GtkRadioButton *button,
- gpointer data)
+static void sp_text_orientation_mode_changed( EgeSelectOneAction *act, GObject *tbl )
{
- if (g_object_get_data (G_OBJECT (button), "block")) {
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
return;
}
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- SPCSSAttr *css = sp_repr_css_attr_new ();
- int prop = GPOINTER_TO_INT(data);
+ int mode = ege_select_one_action_get_active( act );
- switch (prop)
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ switch (mode)
{
case 0:
{
@@ -6714,555 +6890,572 @@ sp_text_toolbox_orientation_toggled (GtkRadioButton *button,
int result_numbers =
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
+ // If querying returned nothing, update default style.
if (result_numbers == QUERY_STYLE_NOTHING)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->mergeStyle("/tools/text/style", css);
}
- sp_desktop_set_style (desktop, css, true, true);
+ sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true);
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
_("Text: Change orientation"));
sp_repr_css_attr_unref (css);
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
}
-gboolean
-sp_text_toolbox_family_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl)
+/*
+ * This function sets up the text-tool tool-controls, setting the entry boxes
+ * etc. to the values from the current selection or the default if no selection.
+ * It is called whenever a text selection is changed, including stepping cursor
+ * through text.
+ */
+static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl)
{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return FALSE;
+#ifdef DEBUG_TEXT
+ static int count = 0;
+ ++count;
+ std::cout << std::endl;
+ std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
+ std::cout << "sp_text_toolbox_selection_changed: start " << count << std::endl;
- switch (get_group0_keyval (event)) {
- case GDK_KP_Enter: // chosen
- case GDK_Return:
- // unfreeze and update, which will defocus
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- sp_text_toolbox_family_changed (NULL, tbl);
- return TRUE; // I consumed the event
- break;
- case GDK_Escape:
- // defocus
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- return TRUE; // I consumed the event
- break;
- }
- return FALSE;
-}
-
-gboolean
-sp_text_toolbox_family_list_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject */*tbl*/)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return FALSE;
-
- switch (get_group0_keyval (event)) {
- case GDK_KP_Enter:
- case GDK_Return:
- case GDK_Escape: // defocus
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- return TRUE; // I consumed the event
- break;
- case GDK_w:
- case GDK_W:
- if (event->state & GDK_CONTROL_MASK) {
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- return TRUE; // I consumed the event
- }
- break;
+ std::cout << " Selected items:" << std::endl;
+ for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList();
+ items != NULL;
+ items = items->next)
+ {
+ const gchar* id = SP_OBJECT_ID((SPItem *) items->data);
+ std::cout << " " << id << std::endl;
}
- return FALSE;
-}
-
+#endif
-void
-sp_text_toolbox_size_changed (GtkComboBox *cbox,
- GObject *tbl)
-{
- // quit if run by the _changed callbacks
+ // quit if run by the _changed callbacks
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+#ifdef DEBUG_TEXT
+ std::cout << " Frozen, returning" << std::endl;
+ std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
+ std::cout << std::endl;
+#endif
return;
}
-
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ /*
+ * Query from current selection:
+ * Font family (font-family)
+ * Style (font-weight, font-style, font-stretch, font-variant, font-align)
+ * Numbers (font-size, letter-spacing, word-spacing, line-height, text-anchor, writing-mode)
+ * Font specification (Inkscape private attribute)
+ */
+ SPStyle *query =
+ sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ // Used later:
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ /*
+ * If no text in selection (querying returned nothing), read the style from
+ * the /tools/text preferencess (default style for new texts). Return if
+ * tool bar already set to these preferences.
+ */
+ if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) {
+ // There are no texts in selection, read from preferences.
+ sp_style_read_from_prefs(query, "/tools/text");
+#ifdef DEBUG_TEXT
+ std::cout << " read style from prefs:" << std::endl;
+ sp_print_font( query );
+#endif
+ if (g_object_get_data(tbl, "text_style_from_prefs")) {
+ // Do not reset the toolbar style from prefs if we already did it last time
+ sp_style_unref(query);
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+#ifdef DEBUG_TEXT
+ std::cout << " text_style_from_prefs: toolbar already set" << std:: endl;
+ std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
+ std::cout << std::endl;
+#endif
+ return;
+ }
- // If this is not from selecting a size in the list (in which case get_active will give the
- // index of the selected item, otherwise -1) and not from user pressing Enter/Return, do not
- // process this event. This fixes GTK's stupid insistence on sending an activate change every
- // time any character gets typed or deleted, which made this control nearly unusable in 0.45.
- if (gtk_combo_box_get_active (cbox) < 0 && !g_object_get_data (tbl, "enter-pressed")) {
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- return;
- }
+ g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE));
+ } else {
+ g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE));
+ }
- gdouble value = -1;
+ // If we have valid query data for text (font-family, font-specification) set toolbar accordingly.
+ if (query->text)
{
- gchar *endptr;
- gchar *const text = gtk_combo_box_get_active_text(cbox);
- if (text) {
- value = g_strtod(text, &endptr);
- if (endptr == text) { // Conversion failed, non-numeric input.
- value = -1;
- }
- g_free(text);
+ // Font family
+ if( query->text->font_family.value ) {
+ gchar *fontFamily = query->text->font_family.value;
+
+ Ink_ComboBoxEntry_Action* fontFamilyAction =
+ INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
+ ink_comboboxentry_action_set_active_text( fontFamilyAction, fontFamily );
}
- }
- if (value <= 0) {
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- return; // could not parse value
- }
- SPCSSAttr *css = sp_repr_css_attr_new ();
- Inkscape::CSSOStringStream osfs;
- osfs << value;
- sp_repr_css_set_property (css, "font-size", osfs.str().c_str());
+ // Size (average of text selected)
+ double size = query->font_size.computed;
+ gchar size_text[G_ASCII_DTOSTR_BUF_SIZE];
+ g_ascii_dtostr (size_text, sizeof (size_text), size);
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ Ink_ComboBoxEntry_Action* fontSizeAction =
+ INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) );
+ ink_comboboxentry_action_set_active_text( fontSizeAction, size_text );
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_numbers == QUERY_STYLE_NOTHING)
- {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->mergeStyle("/tools/text/style", css);
- }
+ // Weight (Bold)
+ // Note: in the enumeration, normal and lighter come at the end so we must explicitly test for them.
+ gboolean boldSet = ((query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700) &&
+ (query->font_weight.computed != SP_CSS_FONT_WEIGHT_NORMAL) &&
+ (query->font_weight.computed != SP_CSS_FONT_WEIGHT_LIGHTER));
- sp_style_unref(query);
+ InkToggleAction* textBoldAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextBoldAction" ) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textBoldAction), boldSet );
- sp_desktop_set_style (desktop, css, true, true);
- sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
- _("Text: Change font size"));
- sp_repr_css_attr_unref (css);
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ // Style (Italic/Oblique)
+ gboolean italicSet = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
-}
+ InkToggleAction* textItalicAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextItalicAction" ) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textItalicAction), italicSet );
-gboolean
-sp_text_toolbox_size_focusout (GtkWidget */*w*/, GdkEventFocus */*event*/, GObject *tbl)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return FALSE;
- if (!g_object_get_data (tbl, "esc-pressed")) {
- g_object_set_data (tbl, "enter-pressed", gpointer(1));
- GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
- sp_text_toolbox_size_changed (cbox, tbl);
- g_object_set_data (tbl, "enter-pressed", gpointer(0));
- }
- return FALSE; // I consumed the event
-}
+ // Alignment
+ // Note: SVG 1.1 doesn't include text-align, SVG 1.2 Tiny doesn't include text-align="justify"
+ // text-align="justify" was a draft SVG 1.2 item (along with flowed text).
+ // Only flowed text can be left and right justified at the same time.
+ // Check if we have flowed text and disable botton.
+ // NEED: ege_select_one_action_set_sensitve( )
+ /*
+ gboolean isFlow = false;
+ for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList();
+ items != NULL;
+ items = items->next) {
+ const gchar* id = SP_OBJECT_ID((SPItem *) items->data);
+ std::cout << " " << id << std::endl;
+ if( SP_IS_FLOWTEXT(( SPItem *) items->data )) {
+ isFlow = true;
+ std::cout << " Found flowed text" << std::endl;
+ break;
+ }
+ }
+ if( isFlow ) {
+ // enable justify button
+ } else {
+ // disable justify button
+ }
+ */
+
+ int activeButton = 0;
+ if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
+ {
+ activeButton = 3;
+ } else {
+ if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) activeButton = 0;
+ if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) activeButton = 1;
+ if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) activeButton = 2;
+ }
+ EgeSelectOneAction* textAlignAction = EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextAlignAction" ) );
+ ege_select_one_action_set_active( textAlignAction, activeButton );
-gboolean
-sp_text_toolbox_size_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return FALSE;
-
- switch (get_group0_keyval (event)) {
- case GDK_Escape: // defocus
- g_object_set_data (tbl, "esc-pressed", gpointer(1));
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- g_object_set_data (tbl, "esc-pressed", gpointer(0));
- return TRUE; // I consumed the event
- break;
- case GDK_Return: // defocus
- case GDK_KP_Enter:
- g_object_set_data (tbl, "enter-pressed", gpointer(1));
- GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
- sp_text_toolbox_size_changed (cbox, tbl);
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- g_object_set_data (tbl, "enter-pressed", gpointer(0));
- return TRUE; // I consumed the event
- break;
- }
- return FALSE;
-}
+ // Line height (spacing)
+ double height;
+ if (query->line_height.normal) {
+ height = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL;
+ } else {
+ if (query->line_height.unit == SP_CSS_UNIT_PERCENT) {
+ height = query->line_height.value;
+ } else {
+ height = query->line_height.computed;
+ }
+ }
+
+ GtkAction* lineHeightAction = GTK_ACTION( g_object_get_data( tbl, "TextLineHeightAction" ) );
+ GtkAdjustment *lineHeightAdjustment =
+ ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( lineHeightAction ));
+ gtk_adjustment_set_value( lineHeightAdjustment, height );
+
+
+ // Word spacing
+ double wordSpacing;
+ if (query->word_spacing.normal) wordSpacing = 0.0;
+ else wordSpacing = query->word_spacing.computed; // Assume no units (change in desktop-style.cpp)
+
+ GtkAction* wordSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextWordSpacingAction" ) );
+ GtkAdjustment *wordSpacingAdjustment =
+ ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( wordSpacingAction ));
+ gtk_adjustment_set_value( wordSpacingAdjustment, wordSpacing );
+
+
+ // Letter spacing
+ double letterSpacing;
+ if (query->letter_spacing.normal) letterSpacing = 0.0;
+ else letterSpacing = query->letter_spacing.computed; // Assume no units (change in desktop-style.cpp)
+
+ GtkAction* letterSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextLetterSpacingAction" ) );
+ GtkAdjustment *letterSpacingAdjustment =
+ ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( letterSpacingAction ));
+ gtk_adjustment_set_value( letterSpacingAdjustment, letterSpacing );
+
+
+ // Orientation
+ int activeButton2 = (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB ? 0 : 1);
+
+ EgeSelectOneAction* textOrientationAction =
+ EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextOrientationAction" ) );
+ ege_select_one_action_set_active( textOrientationAction, activeButton2 );
+
+
+ } // if( query->text )
+
+#ifdef DEBUG_TEXT
+ std::cout << " GUI: fontfamily.value: "
+ << (query->text->font_family.value ? query->text->font_family.value : "No value")
+ << std::endl;
+ std::cout << " GUI: font_size.computed: " << query->font_size.computed << std::endl;
+ std::cout << " GUI: font_weight.computed: " << query->font_weight.computed << std::endl;
+ std::cout << " GUI: font_style.computed: " << query->font_style.computed << std::endl;
+ std::cout << " GUI: text_anchor.computed: " << query->text_anchor.computed << std::endl;
+ std::cout << " GUI: text_align.computed: " << query->text_align.computed << std::endl;
+ std::cout << " GUI: line_height.computed: " << query->line_height.computed
+ << " line_height.value: " << query->line_height.value
+ << " line_height.unit: " << query->line_height.unit << std::endl;
+ std::cout << " GUI: word_spacing.computed: " << query->word_spacing.computed
+ << " word_spacing.value: " << query->word_spacing.value
+ << " word_spacing.unit: " << query->word_spacing.unit << std::endl;
+ std::cout << " GUI: letter_spacing.computed: " << query->letter_spacing.computed
+ << " letter_spacing.value: " << query->letter_spacing.value
+ << " letter_spacing.unit: " << query->letter_spacing.unit << std::endl;
+ std::cout << " GUI: writing_mode.computed: " << query->writing_mode.computed << std::endl;
+ std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ sp_style_unref(query);
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
-// While editing font name in the entry, disable family_changed by freezing, otherwise completion
-// does not work!
-gboolean
-sp_text_toolbox_entry_focus_in (GtkWidget *entry,
- GdkEventFocus */*event*/,
- GObject *tbl)
-{
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- gtk_entry_select_region (GTK_ENTRY (entry), 0, -1); // select all
- return FALSE;
}
-gboolean
-sp_text_toolbox_entry_focus_out (GtkWidget *entry,
- GdkEventFocus */*event*/,
- GObject *tbl)
+static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
{
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- gtk_entry_select_region (GTK_ENTRY (entry), 0, 0); // deselect
- return FALSE;
+ sp_text_toolbox_selection_changed (selection, tbl);
}
void
-cell_data_func (GtkCellLayout */*cell_layout*/,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gpointer /*data*/)
+sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
{
- gchar *family;
- gtk_tree_model_get(tree_model, iter, 0, &family, -1);
- gchar *const family_escaped = g_markup_escape_text(family, -1);
+ sp_text_toolbox_selection_changed (NULL, tbl);
+}
+// Define all the "widgets" in the toolbar.
+static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
+{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1);
- if (show_sample) {
+ Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
- Glib::ustring sample = prefs->getString("/tools/text/font_sample");
- gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1);
+ // Is this used?
+ UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
+ tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
+ g_object_set_data( holder, "tracker", tracker );
- std::stringstream markup;
- markup << family_escaped << " <span foreground='darkgray' font_family='"
- << family_escaped << "'>" << sample_escaped << "</span>";
- g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
+ /* Font family */
+ {
+ // Font list
+ Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
+ GtkListStore* model = store->gobj();
+
+ Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction",
+ _("Font Family"),
+ _("Select Font Family"),
+ NULL,
+ GTK_TREE_MODEL(model),
+ -1, // Set width
+ (gpointer)cell_data_func ); // Cell layout
+ ink_comboboxentry_action_popup_enable( act ); // Enable entry completion
+ gchar *const warning = _("Font not found on system");
+ ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font
+ g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontfamily_value_changed), holder );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ g_object_set_data( holder, "TextFontFamilyAction", act );
+ }
- g_free(sample_escaped);
- } else {
- g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL);
+ /* Font size */
+ {
+ // List of font sizes for drop-down menu
+ GtkListStore* model_size = gtk_list_store_new( 1, G_TYPE_STRING );
+ gchar const *const sizes[] = {
+ "4", "6", "8", "9", "10", "11", "12", "13", "14", "16",
+ "18", "20", "22", "24", "28", "32", "36", "40", "48", "56",
+ "64", "72", "144"
+ };
+ for( unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i ) {
+ GtkTreeIter iter;
+ gtk_list_store_append( model_size, &iter );
+ gtk_list_store_set( model_size, &iter, 0, sizes[i], -1 );
+ }
+
+ Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontSizeAction",
+ _("Font Size"),
+ _("Select Font Size"),
+ NULL,
+ GTK_TREE_MODEL(model_size),
+ 4 ); // Width in characters
+ g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ g_object_set_data( holder, "TextFontSizeAction", act );
}
- g_free(family);
- g_free(family_escaped);
-}
+ /* Style - Bold */
+ {
+ InkToggleAction* act = ink_toggle_action_new( "TextBoldAction", // Name
+ _("Toggle Bold"), // Label
+ _("Toggle On/Off Bold Style"), // Tooltip
+ GTK_STOCK_BOLD, // Icon (inkId)
+ secondarySize ); // Icon size
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/bold", false) );
+ g_object_set_data( holder, "TextBoldAction", act );
+ }
-gboolean text_toolbox_completion_match_selected(GtkEntryCompletion */*widget*/,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- GObject *tbl)
-{
- // We intercept this signal so as to fire family_changed at once (without it, you'd have to
- // press Enter again after choosing a completion)
- gchar *family = 0;
- gtk_tree_model_get(model, iter, 0, &family, -1);
+ /* Style - Italic/Oblique */
+ {
+ InkToggleAction* act = ink_toggle_action_new( "TextItalicAction", // Name
+ _("Toggle Italic/Oblique"), // Label
+ _("Toggle On/Off Italic/Oblique Style"),// Tooltip
+ GTK_STOCK_ITALIC, // Icon (inkId)
+ secondarySize ); // Icon size
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/italic", false) );
+ g_object_set_data( holder, "TextItalicAction", act );
+ }
- GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry"));
- gtk_entry_set_text (GTK_ENTRY (entry), family);
+ /* Alignment */
+ {
+ GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
- sp_text_toolbox_family_changed (NULL, tbl);
- return TRUE;
-}
+ GtkTreeIter iter;
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Align left"),
+ 1, _("Align left"),
+ 2, GTK_STOCK_JUSTIFY_LEFT,
+ -1 );
-static void
-cbe_add_completion (GtkComboBoxEntry *cbe, GObject *tbl){
- GtkEntry *entry;
- GtkEntryCompletion *completion;
- GtkTreeModel *model;
-
- entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbe)));
- completion = gtk_entry_completion_new();
- model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbe));
- gtk_entry_completion_set_model(completion, model);
- gtk_entry_completion_set_text_column(completion, 0);
- gtk_entry_completion_set_inline_completion(completion, FALSE);
- gtk_entry_completion_set_inline_selection(completion, FALSE);
- gtk_entry_completion_set_popup_completion(completion, TRUE);
- gtk_entry_set_completion(entry, completion);
-
- g_signal_connect (G_OBJECT (completion), "match-selected", G_CALLBACK (text_toolbox_completion_match_selected), tbl);
-
- g_object_unref(completion);
-}
-
-void sp_text_toolbox_family_popnotify(GtkComboBox *widget,
- void */*property*/,
- GObject *tbl)
-{
- // while the drop-down is open, we disable font family changing, reenabling it only when it closes
-
- gboolean shown;
- g_object_get (G_OBJECT(widget), "popup-shown", &shown, NULL);
- if (shown) {
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
- //g_print("POP: notify: SHOWN\n");
- } else {
- g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
-
- // stupid GTK doesn't let us attach to events in the drop-down window, so we peek here to
- // find out if the drop down was closed by Enter and if so, manually update (only
- // necessary on Windows, on Linux it updates itself - what a mess, but we'll manage)
- GdkEvent *ev = gtk_get_current_event();
- if (ev) {
- //g_print ("ev type: %d\n", ev->type);
- if (ev->type == GDK_KEY_PRESS) {
- switch (get_group0_keyval ((GdkEventKey *) ev)) {
- case GDK_KP_Enter: // chosen
- case GDK_Return:
- {
- // make sure the chosen one is inserted into the entry
- GtkComboBox *combo = GTK_COMBO_BOX (((Gtk::ComboBox *) (g_object_get_data (tbl, "family-entry-combo")))->gobj());
- GtkTreeModel *model = gtk_combo_box_get_model(combo);
- GtkTreeIter iter;
- gboolean has_active = gtk_combo_box_get_active_iter (combo, &iter);
- if (has_active) {
- gchar *family;
- gtk_tree_model_get(model, &iter, 0, &family, -1);
- GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (tbl), "family-entry"));
- gtk_entry_set_text (GTK_ENTRY (entry), family);
- }
-
- // update
- sp_text_toolbox_family_changed (NULL, tbl);
- break;
- }
- }
- }
- }
-
- // regardless of whether we updated, defocus the widget
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (desktop)
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- //g_print("POP: notify: HIDDEN\n");
- }
-}
-
-GtkWidget *sp_text_toolbox_new (SPDesktop *desktop)
-{
- GtkToolbar *tbl = GTK_TOOLBAR(gtk_toolbar_new());
- GtkIconSize secondarySize = static_cast<GtkIconSize>(ToolboxFactory::prefToSize("/toolbox/secondary", 1));
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Align center"),
+ 1, _("Align center"),
+ 2, GTK_STOCK_JUSTIFY_CENTER,
+ -1 );
- gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
- gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Align right"),
+ 1, _("Align right"),
+ 2, GTK_STOCK_JUSTIFY_RIGHT,
+ -1 );
- GtkTooltips *tt = gtk_tooltips_new();
-
- ////////////Family
- Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
- Gtk::ComboBoxEntry *font_sel = Gtk::manage(new Gtk::ComboBoxEntry(store));
-
- gtk_rc_parse_string (
- "style \"dropdown-as-list-style\"\n"
- "{\n"
- " GtkComboBox::appears-as-list = 1\n"
- "}\n"
- "widget \"*.toolbox-fontfamily-list\" style \"dropdown-as-list-style\"");
- gtk_widget_set_name(GTK_WIDGET (font_sel->gobj()), "toolbox-fontfamily-list");
- gtk_tooltips_set_tip (tt, GTK_WIDGET (font_sel->gobj()), _("Select font family (Alt+X to access)"), "");
-
- g_signal_connect (G_OBJECT (font_sel->gobj()), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl);
-
- cbe_add_completion(font_sel->gobj(), G_OBJECT(tbl));
-
- gtk_toolbar_append_widget( tbl, (GtkWidget*) font_sel->gobj(), "", "");
- g_object_set_data (G_OBJECT (tbl), "family-entry-combo", font_sel);
-
- // expand the field a bit so as to view more of the previews in the drop-down
- GtkRequisition req;
- gtk_widget_size_request (GTK_WIDGET (font_sel->gobj()), &req);
- gtk_widget_set_size_request (GTK_WIDGET (font_sel->gobj()), MIN(req.width + 50, 500), -1);
-
- GtkWidget* entry = (GtkWidget*) font_sel->get_entry()->gobj();
- g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
-
- g_signal_connect (G_OBJECT (font_sel->gobj()), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
- g_signal_connect (G_OBJECT (font_sel->gobj()), "notify::popup-shown",
- G_CALLBACK (sp_text_toolbox_family_popnotify), tbl);
- g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl);
- g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl);
- g_signal_connect (G_OBJECT (entry), "focus-out-event", G_CALLBACK (sp_text_toolbox_entry_focus_out), tbl);
-
- gtk_object_set_data(GTK_OBJECT(entry), "altx-text", entry);
- g_object_set_data (G_OBJECT (tbl), "family-entry", entry);
-
- GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
- gtk_cell_layout_clear( GTK_CELL_LAYOUT(font_sel->gobj()) );
- gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(font_sel->gobj()) , cell , TRUE );
- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(font_sel->gobj()), cell, GtkCellLayoutDataFunc (cell_data_func), NULL, NULL);
-
- GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, secondarySize);
- GtkWidget *box = gtk_event_box_new ();
- gtk_container_add (GTK_CONTAINER (box), image);
- gtk_toolbar_append_widget( tbl, box, "", "");
- g_object_set_data (G_OBJECT (tbl), "warning-image", box);
- gtk_tooltips_set_tip (tt, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), "");
- gtk_widget_hide (GTK_WIDGET (box));
- g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box);
-
- ////////////Size
- gchar const *const sizes[] = {
- "4", "6", "8", "9", "10", "11", "12", "13", "14",
- "16", "18", "20", "22", "24", "28",
- "32", "36", "40", "48", "56", "64", "72", "144"
- };
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Justify"),
+ 1, _("Justify - Only flowed text"),
+ 2, GTK_STOCK_JUSTIFY_FILL,
+ -1 );
- GtkWidget *cbox = gtk_combo_box_entry_new_text ();
- for (unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i) {
- gtk_combo_box_append_text(GTK_COMBO_BOX(cbox), sizes[i]);
- }
- gtk_widget_set_size_request (cbox, 80, -1);
- gtk_toolbar_append_widget( tbl, cbox, "", "");
- g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
- g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
- gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), tbl);
- gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "focus-out-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_focusout), tbl);
-
- ////////////Text anchor
- GtkWidget *group = gtk_radio_button_new (NULL);
- GtkWidget *row = gtk_hbox_new (FALSE, 4);
- g_object_set_data (G_OBJECT (tbl), "anchor-group", group);
-
- // left
- GtkWidget *rbutton = group;
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "text-start", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0));
- gtk_tooltips_set_tip(tt, rbutton, _("Align left"), NULL);
-
- // center
- rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "text-middle", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1));
- gtk_tooltips_set_tip(tt, rbutton, _("Center"), NULL);
-
- // right
- rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "text-end", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2));
- gtk_tooltips_set_tip(tt, rbutton, _("Align right"), NULL);
-
- // fill
- rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "text-fill", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(3));
- gtk_tooltips_set_tip(tt, rbutton, _("Justify"), NULL);
-
- gtk_toolbar_append_widget( tbl, row, "", "");
-
- //spacer
- gtk_toolbar_append_widget( tbl, gtk_vseparator_new(), "", "" );
-
- ////////////Text style
- row = gtk_hbox_new (FALSE, 4);
-
- // bold
- rbutton = gtk_toggle_button_new ();
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_BOLD, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
- gtk_tooltips_set_tip(tt, rbutton, _("Bold"), NULL);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "style-bold", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer(0));
-
- // italic
- rbutton = gtk_toggle_button_new ();
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_ITALIC, secondarySize));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
- gtk_tooltips_set_tip(tt, rbutton, _("Italic"), NULL);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "style-italic", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer (1));
-
- gtk_toolbar_append_widget( tbl, row, "", "");
-
- //spacer
- gtk_toolbar_append_widget( tbl, gtk_vseparator_new(), "", "" );
-
- // Text orientation
- group = gtk_radio_button_new (NULL);
- row = gtk_hbox_new (FALSE, 4);
- g_object_set_data (G_OBJECT (tbl), "orientation-group", group);
-
- // horizontal
- rbutton = group;
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton),
- sp_icon_new (static_cast<Inkscape::IconSize>(secondarySize), INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_HORIZONTAL));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
- gtk_tooltips_set_tip(tt, rbutton, _("Horizontal text"), NULL);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "orientation-horizontal", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer(0));
-
- // vertical
- rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
- gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
- gtk_container_add (GTK_CONTAINER (rbutton),
- sp_icon_new (static_cast<Inkscape::IconSize>(secondarySize), INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_VERTICAL));
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
- gtk_tooltips_set_tip(tt, rbutton, _("Vertical text"), NULL);
-
- gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
- g_object_set_data (G_OBJECT (tbl), "orientation-vertical", rbutton);
- g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer (1));
- gtk_toolbar_append_widget( tbl, row, "", "" );
+ EgeSelectOneAction* act = ege_select_one_action_new( "TextAlignAction", // Name
+ _("Alignment"), // Label
+ _("Text Alignment"), // Tooltip
+ NULL, // StockID
+ GTK_TREE_MODEL(model) ); // Model
+ g_object_set( act, "short_label", _("Align"), NULL );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ g_object_set_data( holder, "TextAlignAction", act );
+ ege_select_one_action_set_appearance( act, "full" );
+ ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
+ g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
+ ege_select_one_action_set_icon_column( act, 2 );
+ ege_select_one_action_set_icon_size( act, secondarySize );
+ ege_select_one_action_set_tooltip_column( act, 1 );
- //watch selection
- Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox");
+ gint mode = prefs->getInt("/tools/text/align_mode", 0);
+ ege_select_one_action_set_active( act, mode );
+ g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_align_mode_changed), holder );
+ }
+
+ /* Orientation (Left to Right, Top to Bottom */
+ {
+ GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
+
+ GtkTreeIter iter;
+
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Horizontal"),
+ 1, _("Horizontal Text"),
+ 2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_HORIZONTAL,
+ -1 );
+
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Vertical"),
+ 1, _("Vertical Text"),
+ 2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_VERTICAL,
+ -1 );
+
+ EgeSelectOneAction* act = ege_select_one_action_new( "TextOrientationAction", // Name
+ _("Orientation"), // Label
+ _("Text Orientation"), // Tooltip
+ NULL, // StockID
+ GTK_TREE_MODEL(model) ); // Model
+
+ g_object_set( act, "short_label", _("O:"), NULL );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+ g_object_set_data( holder, "TextOrientationAction", act );
+
+ ege_select_one_action_set_appearance( act, "full" );
+ ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
+ g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
+ ege_select_one_action_set_icon_column( act, 2 );
+ ege_select_one_action_set_icon_size( act, secondarySize );
+ ege_select_one_action_set_tooltip_column( act, 1 );
+
+ gint mode = prefs->getInt("/tools/text/orientation", 0);
+ ege_select_one_action_set_active( act, mode );
+ g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_orientation_mode_changed), holder );
+ }
+
+ /* Line height */
+ {
+ // Drop down menu
+ gchar const* labels[] = {_("Smaller spacing"), 0, 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, _("Larger spacing")};
+ gdouble values[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1,2, 1.3, 1.4, 1.5, 2.0};
+
+ EgeAdjustmentAction *eact = create_adjustment_action(
+ "TextLineHeightAction", /* name */
+ _("Line Height"), /* label */
+ _("Line:"), /* short label */
+ _("Spacing between lines."), /* tooltip */
+ "/tools/text/lineheight", /* path? */
+ 0.0, /* default */
+ GTK_WIDGET(desktop->canvas), /* focusTarget */
+ NULL, /* unit selector */
+ holder, /* dataKludge */
+ FALSE, /* altx? */
+ NULL, /* altx_mark? */
+ 0.0, 10.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
+ labels, values, G_N_ELEMENTS(labels), /* drop down menu */
+ sp_text_lineheight_value_changed, /* callback */
+ 0.1, /* step (used?) */
+ 2, /* digits to show */
+ 1.0 /* factor (multiplies default) */
+ );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ g_object_set_data( holder, "TextLineHeightAction", eact );
+ }
+
+ /* Word spacing */
+ {
+ // Drop down menu
+ gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")};
+ gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0};
+
+ EgeAdjustmentAction *eact = create_adjustment_action(
+ "TextWordSpacingAction", /* name */
+ _("Word spacing"), /* label */
+ _("Word:"), /* short label */
+ _("Spacing between words."), /* tooltip */
+ "/tools/text/wordspacing", /* path? */
+ 0.0, /* default */
+ GTK_WIDGET(desktop->canvas), /* focusTarget */
+ NULL, /* unit selector */
+ holder, /* dataKludge */
+ FALSE, /* altx? */
+ NULL, /* altx_mark? */
+ -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
+ labels, values, G_N_ELEMENTS(labels), /* drop down menu */
+ sp_text_wordspacing_value_changed, /* callback */
+ 0.1, /* step (used?) */
+ 2, /* digits to show */
+ 1.0 /* factor (multiplies default) */
+ );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ g_object_set_data( holder, "TextWordSpacingAction", eact );
+ }
+
+ /* Letter spacing */
+ {
+ // Drop down menu
+ gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")};
+ gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0};
+
+ EgeAdjustmentAction *eact = create_adjustment_action(
+ "TextLetterSpacingAction", /* name */
+ _("Letter spacing"), /* label */
+ _("Letter:"), /* short label */
+ _("Spacing between letters."), /* tooltip */
+ "/tools/text/letterspacing", /* path? */
+ 0.0, /* default */
+ GTK_WIDGET(desktop->canvas), /* focusTarget */
+ NULL, /* unit selector */
+ holder, /* dataKludge */
+ FALSE, /* altx? */
+ NULL, /* altx_mark? */
+ -100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
+ labels, values, G_N_ELEMENTS(labels), /* drop down menu */
+ sp_text_letterspacing_value_changed, /* callback */
+ 0.1, /* step (used?) */
+ 2, /* digits to show */
+ 1.0 /* factor (multiplies default) */
+ );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ g_object_set_data( holder, "TextLetterSpacingAction", eact );
+ }
+
+ // Is this necessary to call? Shouldn't hurt.
+ sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
+
+ // Watch selection
+ Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolboxGTK");
sigc::connection *c_selection_changed =
new sigc::connection (sp_desktop_selection (desktop)->connectChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl)));
+ (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)holder)));
pool->add_connection ("selection-changed", c_selection_changed);
sigc::connection *c_selection_modified =
new sigc::connection (sp_desktop_selection (desktop)->connectModified
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl)));
+ (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)holder)));
pool->add_connection ("selection-modified", c_selection_modified);
sigc::connection *c_subselection_changed =
new sigc::connection (desktop->connectToolSubselectionChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl)));
+ (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)holder)));
pool->add_connection ("tool-subselection-changed", c_subselection_changed);
- Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
-
-
- gtk_widget_show_all( GTK_WIDGET(tbl) );
+ Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
- return GTK_WIDGET(tbl);
-} // end of sp_text_toolbox_new()
+ g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
-}//<unnamed> namespace
+}
//#########################
//## Connector ##
//#########################
-static void sp_connector_mode_toggled( GtkToggleAction* act, GtkObject */*tbl*/ )
+static void sp_connector_mode_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/connector/mode",
@@ -7286,8 +7479,7 @@ static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl
Inkscape::Selection * selection = sp_desktop_selection(desktop);
SPDocument *doc = sp_desktop_document(desktop);
- if (!sp_document_get_undo_sensitive(doc))
- {
+ if (!sp_document_get_undo_sensitive(doc)) {
return;
}
@@ -7319,8 +7511,7 @@ static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl
l = l->next;
}
- if (!modmade)
- {
+ if (!modmade) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/connector/orthogonal", is_orthog);
}
@@ -7337,8 +7528,7 @@ static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl)
Inkscape::Selection * selection = sp_desktop_selection(desktop);
SPDocument *doc = sp_desktop_document(desktop);
- if (!sp_document_get_undo_sensitive(doc))
- {
+ if (!sp_document_get_undo_sensitive(doc)) {
return;
}
@@ -7369,8 +7559,7 @@ static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl)
l = l->next;
}
- if (!modmade)
- {
+ if (!modmade) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setDouble(Glib::ustring("/tools/connector/curvature"), newValue);
}
@@ -7387,8 +7576,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl)
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
SPDocument *doc = sp_desktop_document(desktop);
- if (!sp_document_get_undo_sensitive(doc))
- {
+ if (!sp_document_get_undo_sensitive(doc)) {
return;
}
@@ -7396,7 +7584,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl)
if ( !repr->attribute("inkscape:connector-spacing") &&
( adj->value == defaultConnSpacing )) {
- // Don't need to update the repr if the attribute doesn't
+ // Don't need to update the repr if the attribute doesn't
// exist and it is being set to the default value -- as will
// happen at startup.
return;
@@ -7432,7 +7620,9 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl)
static void sp_connector_graph_layout(void)
{
- if (!SP_ACTIVE_DESKTOP) return;
+ if (!SP_ACTIVE_DESKTOP) {
+ return;
+ }
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
// hack for clones, see comment in align-and-distribute.cpp
@@ -7446,14 +7636,14 @@ static void sp_connector_graph_layout(void)
sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Arrange connector network"));
}
-static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GtkObject */*tbl*/ )
+static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/connector/directedlayout",
gtk_toggle_action_get_active( act ));
}
-static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GtkObject */*tbl*/ )
+static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/connector/avoidoverlaplayout",
@@ -7468,7 +7658,7 @@ static void connector_length_changed(GtkAdjustment *adj, GObject* /*tbl*/)
}
static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
- gchar const *name, gchar const */*old_value*/, gchar const */*new_value*/,
+ gchar const *name, gchar const * /*old_value*/, gchar const * /*new_value*/,
bool /*is_interactive*/, gpointer data)
{
GtkWidget *tbl = GTK_WIDGET(data);
@@ -7495,8 +7685,9 @@ static void sp_connector_new_connection_point(GtkWidget *, GObject *tbl)
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context);
- if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE)
+ if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) {
cc_create_connection_point(cc);
+ }
}
static void sp_connector_remove_connection_point(GtkWidget *, GObject *tbl)
@@ -7504,8 +7695,9 @@ static void sp_connector_remove_connection_point(GtkWidget *, GObject *tbl)
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context);
- if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE)
+ if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) {
cc_remove_connection_point(cc);
+ }
}
static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
@@ -7715,13 +7907,13 @@ static void paintbucket_channels_changed(EgeSelectOneAction* act, GObject* /*tbl
flood_channels_set_channels( channels );
}
-static void paintbucket_threshold_changed(GtkAdjustment *adj, GObject */*tbl*/)
+static void paintbucket_threshold_changed(GtkAdjustment *adj, GObject * /*tbl*/)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt("/tools/paintbucket/threshold", (gint)adj->value);
}
-static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject */*tbl*/)
+static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject * /*tbl*/)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setBool("/tools/paintbucket/autogap", ege_select_one_action_get_active( act ));
@@ -7737,7 +7929,7 @@ static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl)
prefs->setString("/tools/paintbucket/offsetunits", sp_unit_get_abbreviation(unit));
}
-static void paintbucket_defaults (GtkWidget *, GObject *tbl)
+static void paintbucket_defaults(GtkWidget *, GObject *tbl)
{
// FIXME: make defaults settable via Inkscape Options
struct KeyValue {
@@ -7808,8 +8000,9 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
// Create the units menu.
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
Glib::ustring stored_unit = prefs->getString("/tools/paintbucket/offsetunits");
- if (!stored_unit.empty())
+ if (!stored_unit.empty()) {
tracker->setActiveUnit(sp_unit_get_by_abbreviation(stored_unit.data()));
+ }
g_object_set_data( holder, "tracker", tracker );
{
GtkAction* act = tracker->createAction( "PaintbucketUnitsAction", _("Units"), ("") );
diff --git a/src/winconsole.cpp b/src/winconsole.cpp
new file mode 100644
index 000000000..f6ee49e13
--- /dev/null
+++ b/src/winconsole.cpp
@@ -0,0 +1,153 @@
+/** \file
+ * @brief Command-line wrapper for Windows.
+ *
+ * Windows has two types of executables: GUI and console.
+ * The GUI executables detach immediately when run from the command
+ * prompt (cmd.exe), and whatever you write to standard output
+ * disappears into a black hole. Console executables handle
+ * do display standard output and take standard input from the console,
+ * but when you run them from the GUI, an extra console window appears.
+ * It's possible to hide it, but it still flashes from a fraction
+ * of a second.
+ *
+ * To provide an Unix-like experienve, where the application will behave
+ * correctly in command line mode and at the same time won't create
+ * the ugly console window when run from the GUI, we have to have two
+ * executables. The first one, inkscape.exe, is the GUI application.
+ * Its entry points are in main.cpp and winmain.cpp. The second one,
+ * called inkscape.com, is a small helper application contained in
+ * this file. It spawns the GUI application and redirects its output
+ * to the console.
+ *
+ * Note that inkscape.com has nothing to do with "compact executables"
+ * from DOS. It's a normal PE executable renamed to .com. The trick
+ * is that cmd.exe picks .com over .exe when both are present in PATH,
+ * so when you type "inkscape" into the command prompt, inkscape.com
+ * gets run. The Windows program loader does not inspect the extension,
+ * just like an Unix program loader; it determines the binary format
+ * based on the contents of the file.
+ *
+ *//*
+ * Authors:
+ * Jos Hirth <jh@kaioa.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2008-2010 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef WIN32
+#undef DATADIR
+#include <windows.h>
+
+struct echo_thread_info {
+ HANDLE echo_read;
+ HANDLE echo_write;
+ unsigned buffer_size;
+};
+
+// thread function for echoing from one file handle to another
+DWORD WINAPI echo_thread(void *info_void)
+{
+ echo_thread_info *info = static_cast<echo_thread_info*>(info_void);
+ char *buffer = reinterpret_cast<char *>(LocalAlloc(LMEM_FIXED, info->buffer_size));
+ DWORD bytes_read, bytes_written;
+
+ while(true){
+ if (!ReadFile(info->echo_read, buffer, info->buffer_size, &bytes_read, NULL) || bytes_read == 0)
+ if (GetLastError() == ERROR_BROKEN_PIPE)
+ break;
+
+ if (!WriteFile(info->echo_write, buffer, bytes_read, &bytes_written, NULL)) {
+ if (GetLastError() == ERROR_NO_DATA)
+ break;
+ }
+ }
+
+ LocalFree(reinterpret_cast<HLOCAL>(buffer));
+ CloseHandle(info->echo_read);
+ CloseHandle(info->echo_write);
+
+ return 1;
+}
+
+int main()
+{
+ // structs that will store information for our I/O threads
+ echo_thread_info stdin = {NULL, NULL, 4096};
+ echo_thread_info stdout = {NULL, NULL, 4096};
+ echo_thread_info stderr = {NULL, NULL, 4096};
+ // handles we'll pass to inkscape.exe
+ HANDLE inkscape_stdin, inkscape_stdout, inkscape_stderr;
+ HANDLE stdin_thread, stdout_thread, stderr_thread;
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength=sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor=NULL;
+ sa.bInheritHandle=TRUE;
+
+ // Determine the path to the Inkscape executable.
+ // Do this by looking up the name of this one and redacting the extension to ".exe"
+ const int pathbuf = 2048;
+ WCHAR *inkscape = reinterpret_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, pathbuf * sizeof(WCHAR)));
+ GetModuleFileNameW(NULL, inkscape, pathbuf);
+ WCHAR *dot_index = wcsrchr(inkscape, L'.');
+ wcsncpy(dot_index, L".exe", 4);
+
+ // we simply reuse our own command line for inkscape.exe
+ // it guarantees perfect behavior w.r.t. quoting
+ WCHAR *cmd = GetCommandLineW();
+
+ // set up the pipes and handles
+ stdin.echo_read = GetStdHandle(STD_INPUT_HANDLE);
+ stdout.echo_write = GetStdHandle(STD_OUTPUT_HANDLE);
+ stderr.echo_write = GetStdHandle(STD_ERROR_HANDLE);
+ CreatePipe(&inkscape_stdin, &stdin.echo_write, &sa, 0);
+ CreatePipe(&stdout.echo_read, &inkscape_stdout, &sa, 0);
+ CreatePipe(&stderr.echo_read, &inkscape_stderr, &sa, 0);
+
+ // fill in standard IO handles to be used by the process
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+
+ ZeroMemory(&si,sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = inkscape_stdin;
+ si.hStdOutput = inkscape_stdout;
+ si.hStdError = inkscape_stderr;
+
+ // spawn inkscape.exe
+ CreateProcessW(inkscape, // path to inkscape.exe
+ cmd, // command line as a single string
+ NULL, // process security attributes - unused
+ NULL, // thread security attributes - unused
+ TRUE, // inherit handles
+ 0, // flags
+ NULL, // environment - NULL = inherit from us
+ NULL, // working directory - NULL = inherit ours
+ &si, // startup info - see above
+ &pi); // information about the created process - unused
+
+ // clean up a bit
+ LocalFree(reinterpret_cast<HLOCAL>(inkscape));
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ CloseHandle(inkscape_stdin);
+ CloseHandle(inkscape_stdout);
+ CloseHandle(inkscape_stderr);
+
+ // create IO echo threads
+ DWORD unused;
+ stdin_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdin, 0, &unused);
+ stdout_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdout, 0, &unused);
+ stderr_thread = CreateThread(NULL, 0, echo_thread, (void*) &stderr, 0, &unused);
+
+ // wait until the standard output thread terminates
+ WaitForSingleObject(stdout_thread, INFINITE);
+
+ return 0;
+}
+
+#endif