diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2013-03-05 08:43:18 +0000 |
|---|---|---|
| committer | Jabiertxo Arraiza Zenotz <jtx@jtx.marker.es> | 2013-03-05 08:43:18 +0000 |
| commit | a33dbbc4fbad29c187611660d3651bbe57243903 (patch) | |
| tree | 1260bfa9c376aa441bb26087283ed0014f5986ec /src | |
| parent | Fix sintax (diff) | |
| parent | merge from branch (diff) | |
| download | inkscape-a33dbbc4fbad29c187611660d3651bbe57243903.tar.gz inkscape-a33dbbc4fbad29c187611660d3651bbe57243903.zip | |
refactor bsplineSpirolive
(bzr r11950.1.44)
Diffstat (limited to 'src')
35 files changed, 887 insertions, 1292 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a899c7b35..2a4e2960c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,7 +65,7 @@ BUILT_SOURCES = # Extra files to distribute EXTRA_DIST = -INCLUDES = \ +AM_CPPFLAGS = \ $(PERL_CFLAGS) $(PYTHON_CFLAGS) \ $(EXIF_CFLAGS) \ $(FREETYPE_CFLAGS) \ @@ -88,8 +88,7 @@ INCLUDES = \ $(WIN32_CFLAGS) \ -I$(srcdir)/bind/javainc \ -I$(srcdir)/bind/javainc/linux \ - -I$(builddir)/extension/dbus \ - $(AM_CPPFLAGS) + -I$(builddir)/extension/dbus CXXTEST_TEMPLATE = $(srcdir)/cxxtest-template.tpl CXXTESTGENFLAGS = --root --have-eh --template=$(CXXTEST_TEMPLATE) diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 8eeee0277..a55b05fe3 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -26,6 +26,7 @@ #include "color.h" #include "style.h" #include "helper/geom-curves.h" +#include "display/cairo-templates.h" namespace { @@ -633,6 +634,22 @@ static guint32 linear_to_srgb( const guint32 c, const guint32 a ) { return premul_alpha( c2, a ); } +struct SurfaceSrgbToLinear { + + guint32 operator()(guint32 in) { + EXTRACT_ARGB32(in, a,r,g,b) ; // Unneeded semi-colon for indenting + if( a != 0 ) { + r = srgb_to_linear( r, a ); + g = srgb_to_linear( g, a ); + b = srgb_to_linear( b, a ); + } + ASSEMBLE_ARGB32(out, a,r,g,b); + return out; + } +private: + /* None */ +}; + int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface) { cairo_surface_flush(surface); @@ -641,23 +658,41 @@ int ink_cairo_surface_srgb_to_linear(cairo_surface_t *surface) int stride = cairo_image_surface_get_stride(surface); unsigned char *data = cairo_image_surface_get_data(surface); + ink_cairo_surface_filter( surface, surface, SurfaceSrgbToLinear() ); + /* TODO convert this to OpenMP somehow */ - for (int y = 0; y < height; ++y, data += stride) { - for (int x = 0; x < width; ++x) { - guint32 px = *reinterpret_cast<guint32*>(data + 4*x); - EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting - if( a != 0 ) { - r = srgb_to_linear( r, a ); - g = srgb_to_linear( g, a ); - b = srgb_to_linear( b, a ); - } - ASSEMBLE_ARGB32(px2, a,r,g,b); - *reinterpret_cast<guint32*>(data + 4*x) = px2; - } - } + // for (int y = 0; y < height; ++y, data += stride) { + // for (int x = 0; x < width; ++x) { + // guint32 px = *reinterpret_cast<guint32*>(data + 4*x); + // EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting + // if( a != 0 ) { + // r = srgb_to_linear( r, a ); + // g = srgb_to_linear( g, a ); + // b = srgb_to_linear( b, a ); + // } + // ASSEMBLE_ARGB32(px2, a,r,g,b); + // *reinterpret_cast<guint32*>(data + 4*x) = px2; + // } + // } return width * height; } +struct SurfaceLinearToSrgb { + + guint32 operator()(guint32 in) { + EXTRACT_ARGB32(in, a,r,g,b) ; // Unneeded semi-colon for indenting + if( a != 0 ) { + r = linear_to_srgb( r, a ); + g = linear_to_srgb( g, a ); + b = linear_to_srgb( b, a ); + } + ASSEMBLE_ARGB32(out, a,r,g,b); + return out; + } +private: + /* None */ +}; + int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface) { cairo_surface_flush(surface); @@ -666,20 +701,22 @@ int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface) int stride = cairo_image_surface_get_stride(surface); unsigned char *data = cairo_image_surface_get_data(surface); - /* TODO convert this to OpenMP somehow */ - for (int y = 0; y < height; ++y, data += stride) { - for (int x = 0; x < width; ++x) { - guint32 px = *reinterpret_cast<guint32*>(data + 4*x); - EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting - if( a != 0 ) { - r = linear_to_srgb( r, a ); - g = linear_to_srgb( g, a ); - b = linear_to_srgb( b, a ); - } - ASSEMBLE_ARGB32(px2, a,r,g,b); - *reinterpret_cast<guint32*>(data + 4*x) = px2; - } - } + ink_cairo_surface_filter( surface, surface, SurfaceLinearToSrgb() ); + + // /* TODO convert this to OpenMP somehow */ + // for (int y = 0; y < height; ++y, data += stride) { + // for (int x = 0; x < width; ++x) { + // guint32 px = *reinterpret_cast<guint32*>(data + 4*x); + // EXTRACT_ARGB32(px, a,r,g,b) ; // Unneeded semi-colon for indenting + // if( a != 0 ) { + // r = linear_to_srgb( r, a ); + // g = linear_to_srgb( g, a ); + // b = linear_to_srgb( b, a ); + // } + // ASSEMBLE_ARGB32(px2, a,r,g,b); + // *reinterpret_cast<guint32*>(data + 4*x) = px2; + // } + // } return width * height; } diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp index 76b877fbc..333074f55 100644 --- a/src/display/nr-filter-turbulence.cpp +++ b/src/display/nr-filter-turbulence.cpp @@ -283,7 +283,12 @@ private: // other constants static int const BSize = 0x100; static int const BMask = 0xff; + +#if __cplusplus < 201103L static double const PerlinOffset = 4096.0; +#else + static double constexpr PerlinOffset = 4096.0; +#endif Geom::Rect _tile; Geom::Point _baseFreq; diff --git a/src/dom/io/domstream.cpp b/src/dom/io/domstream.cpp index 21d09662a..b9ff7e9d2 100644 --- a/src/dom/io/domstream.cpp +++ b/src/dom/io/domstream.cpp @@ -424,12 +424,11 @@ static int dprintf(Writer &outs, const DOMString &fmt, va_list ap) //# B A S I C I N P U T S T R E A M //######################################################################### - /** * - */ -BasicInputStream::BasicInputStream(const InputStream &sourceStream) - : source((InputStream &)sourceStream) + */ +BasicInputStream::BasicInputStream(InputStream &sourceStream) + : source(sourceStream) { closed = false; } @@ -438,7 +437,7 @@ BasicInputStream::BasicInputStream(const InputStream &sourceStream) * Returns the number of bytes that can be read (or skipped over) from * this input stream without blocking by the next caller of a method for * this input stream. - */ + */ int BasicInputStream::available() { if (closed) @@ -446,11 +445,11 @@ int BasicInputStream::available() return source.available(); } - + /** * Closes this input stream and releases any system resources * associated with the stream. - */ + */ void BasicInputStream::close() { if (closed) @@ -458,10 +457,10 @@ void BasicInputStream::close() source.close(); closed = true; } - + /** * Reads the next byte of data from the input stream. -1 if EOF - */ + */ int BasicInputStream::get() { if (closed) @@ -477,9 +476,9 @@ int BasicInputStream::get() /** * - */ -BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream) - : destination((OutputStream &)destinationStream) + */ +BasicOutputStream::BasicOutputStream(OutputStream &destinationStream) + : destination(destinationStream) { closed = false; } @@ -487,7 +486,7 @@ BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream) /** * Closes this output stream and releases any system resources * associated with this stream. - */ + */ void BasicOutputStream::close() { if (closed) @@ -495,40 +494,33 @@ void BasicOutputStream::close() destination.close(); closed = true; } - + /** * Flushes this output stream and forces any buffered output * bytes to be written out. - */ + */ void BasicOutputStream::flush() { if (closed) return; destination.flush(); } - + /** * Writes the specified byte to this output stream. - */ + */ int BasicOutputStream::put(gunichar ch) { if (closed) return -1; - if (destination.put(ch) < 0) - return -1; - return 1; + destination.put(ch); + return 1; } - //######################################################################### //# B A S I C R E A D E R //######################################################################### - - -/** - * - */ BasicReader::BasicReader(Reader &sourceReader) { source = &sourceReader; @@ -538,7 +530,7 @@ BasicReader::BasicReader(Reader &sourceReader) * Returns the number of bytes that can be read (or skipped over) from * this reader without blocking by the next caller of a method for * this reader. - */ + */ int BasicReader::available() { if (source) @@ -547,69 +539,65 @@ int BasicReader::available() return 0; } - + /** * Closes this reader and releases any system resources * associated with the reader. - */ + */ void BasicReader::close() { if (source) source->close(); } - + /** * Reads the next byte of data from the reader. - */ -int BasicReader::get() + */ +gunichar BasicReader::get() { if (source) return source->get(); else - return -1; + return (gunichar)-1; } - - - - - + /** * Reads a line of data from the reader. - */ -DOMString BasicReader::readLine() + */ +Glib::ustring BasicReader::readLine() { - DOMString str; + Glib::ustring str; while (available() > 0) { - XMLCh ch = get(); + gunichar ch = get(); if (ch == '\n') break; str.push_back(ch); } return str; } - + /** * Reads a line of data from the reader. - */ -DOMString BasicReader::readWord() + */ +Glib::ustring BasicReader::readWord() { - DOMString str; + Glib::ustring str; while (available() > 0) { - XMLCh ch = get(); - if (uni_is_space(ch)) + gunichar ch = get(); + if (!g_unichar_isprint(ch)) break; str.push_back(ch); } return str; } + - -static bool getLong(DOMString &str, long *val) +static bool getLong(Glib::ustring &str, long *val) { - const char *begin = str.c_str(); + const char *begin = str.raw().c_str(); char *end; long ival = strtol(begin, &end, 10); if (str == end) @@ -618,25 +606,23 @@ static bool getLong(DOMString &str, long *val) return true; } -static bool getULong(const DOMString &str, unsigned long *val) +static bool getULong(Glib::ustring &str, unsigned long *val) { - DOMString tmp = str; - char *begin = (char *)tmp.c_str(); + const char *begin = str.raw().c_str(); char *end; unsigned long ival = strtoul(begin, &end, 10); - if (begin == end) + if (str == end) return false; *val = ival; return true; } -static bool getDouble(const DOMString &str, double *val) +static bool getDouble(Glib::ustring &str, double *val) { - DOMString tmp = str; - const char *begin = tmp.c_str(); + const char *begin = str.raw().c_str(); char *end; double ival = strtod(begin, &end); - if (begin == end) + if (str == end) return false; *val = ival; return true; @@ -644,13 +630,9 @@ static bool getDouble(const DOMString &str, double *val) - -/** - * - */ -Reader &BasicReader::readBool (bool& val ) +const Reader &BasicReader::readBool (bool& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); if (buf == "true") val = true; else @@ -658,96 +640,72 @@ Reader &BasicReader::readBool (bool& val ) return *this; } -/** - * - */ -Reader &BasicReader::readShort (short& val ) +const Reader &BasicReader::readShort (short& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); long ival; if (getLong(buf, &ival)) val = (short) ival; return *this; } -/** - * - */ -Reader &BasicReader::readUnsignedShort (unsigned short& val ) +const Reader &BasicReader::readUnsignedShort (unsigned short& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); unsigned long ival; if (getULong(buf, &ival)) val = (unsigned short) ival; return *this; } -/** - * - */ -Reader &BasicReader::readInt (int& val ) +const Reader &BasicReader::readInt (int& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); long ival; if (getLong(buf, &ival)) val = (int) ival; return *this; } -/** - * - */ -Reader &BasicReader::readUnsignedInt (unsigned int& val ) +const Reader &BasicReader::readUnsignedInt (unsigned int& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); unsigned long ival; if (getULong(buf, &ival)) val = (unsigned int) ival; return *this; } -/** - * - */ -Reader &BasicReader::readLong (long& val ) +const Reader &BasicReader::readLong (long& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); long ival; if (getLong(buf, &ival)) val = ival; return *this; } -/** - * - */ -Reader &BasicReader::readUnsignedLong (unsigned long& val ) +const Reader &BasicReader::readUnsignedLong (unsigned long& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); unsigned long ival; if (getULong(buf, &ival)) val = ival; return *this; } -/** - * - */ -Reader &BasicReader::readFloat (float& val ) +const Reader &BasicReader::readFloat (float& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); double ival; if (getDouble(buf, &ival)) val = (float)ival; return *this; } -/** - * - */ -Reader &BasicReader::readDouble (double& val ) +const Reader &BasicReader::readDouble (double& val ) { - DOMString buf = readWord(); + Glib::ustring buf = readWord(); double ival; if (getDouble(buf, &ival)) val = ival; @@ -761,12 +719,12 @@ Reader &BasicReader::readDouble (double& val ) //######################################################################### -InputStreamReader::InputStreamReader(const InputStream &inputStreamSource) - : inputStream((InputStream &)inputStreamSource) +InputStreamReader::InputStreamReader(InputStream &inputStreamSource) + : inputStream(inputStreamSource) { } - + /** * Close the underlying OutputStream @@ -775,7 +733,7 @@ void InputStreamReader::close() { inputStream.close(); } - + /** * Flush the underlying OutputStream */ @@ -783,15 +741,15 @@ int InputStreamReader::available() { return inputStream.available(); } - + /** * Overloaded to receive its bytes from an InputStream * rather than a Reader */ -int InputStreamReader::get() +gunichar InputStreamReader::get() { //Do we need conversions here? - int ch = (XMLCh)inputStream.get(); + gunichar ch = (gunichar)inputStream.get(); return ch; } @@ -818,7 +776,7 @@ StdReader::~StdReader() delete inputStream; } - + /** * Close the underlying OutputStream @@ -827,7 +785,7 @@ void StdReader::close() { inputStream->close(); } - + /** * Flush the underlying OutputStream */ @@ -835,22 +793,21 @@ int StdReader::available() { return inputStream->available(); } - + /** * Overloaded to receive its bytes from an InputStream * rather than a Reader */ -int StdReader::get() +gunichar StdReader::get() { //Do we need conversions here? - XMLCh ch = (XMLCh)inputStream->get(); + gunichar ch = (gunichar)inputStream->get(); return ch; } - //######################################################################### //# B A S I C W R I T E R //######################################################################### @@ -1145,13 +1102,6 @@ int StdWriter::put(gunichar ch) - - - - - - - //############################################### //# O P E R A T O R S //############################################### @@ -1165,31 +1115,31 @@ int StdWriter::put(gunichar ch) -Reader& operator>> (Reader &reader, bool& val ) +const Reader& operator>> (Reader &reader, bool& val ) { return reader.readBool(val); } -Reader& operator>> (Reader &reader, short &val) +const Reader& operator>> (Reader &reader, short &val) { return reader.readShort(val); } -Reader& operator>> (Reader &reader, unsigned short &val) +const Reader& operator>> (Reader &reader, unsigned short &val) { return reader.readUnsignedShort(val); } -Reader& operator>> (Reader &reader, int &val) +const Reader& operator>> (Reader &reader, int &val) { return reader.readInt(val); } -Reader& operator>> (Reader &reader, unsigned int &val) +const Reader& operator>> (Reader &reader, unsigned int &val) { return reader.readUnsignedInt(val); } -Reader& operator>> (Reader &reader, long &val) +const Reader& operator>> (Reader &reader, long &val) { return reader.readLong(val); } -Reader& operator>> (Reader &reader, unsigned long &val) +const Reader& operator>> (Reader &reader, unsigned long &val) { return reader.readUnsignedLong(val); } -Reader& operator>> (Reader &reader, float &val) +const Reader& operator>> (Reader &reader, float &val) { return reader.readFloat(val); } -Reader& operator>> (Reader &reader, double &val) +const Reader& operator>> (Reader &reader, double &val) { return reader.readDouble(val); } diff --git a/src/dom/io/domstream.h b/src/dom/io/domstream.h index 925e52bfe..a021676fa 100644 --- a/src/dom/io/domstream.h +++ b/src/dom/io/domstream.h @@ -44,23 +44,21 @@ namespace dom namespace io { - - -class StreamException +class StreamException : public std::exception { public: - StreamException(const DOMString &theReason) throw() - : reason(theReason) - {} + StreamException(const char *theReason) throw() + { reason = theReason; } + StreamException(Glib::ustring &theReason) throw() + { reason = theReason; } virtual ~StreamException() throw() { } - char const *what() + char const *what() const throw() { return reason.c_str(); } - + private: - - DOMString reason; + Glib::ustring reason; }; @@ -95,14 +93,14 @@ public: * to be read */ virtual int available() = 0; - + /** * Do whatever it takes to 'close' this input stream * The most likely implementation of this method will be * for endpoints that use a resource for their data. */ virtual void close() = 0; - + /** * Read one byte from this input stream. This is a blocking * call. If no data is currently available, this call will @@ -113,7 +111,7 @@ public: * This call returns -1 on end-of-file. */ virtual int get() = 0; - + }; // class InputStream @@ -129,22 +127,22 @@ class BasicInputStream : public InputStream public: - BasicInputStream(const InputStream &sourceStream); - + BasicInputStream(InputStream &sourceStream); + virtual ~BasicInputStream() {} - + virtual int available(); - + virtual void close(); - + virtual int get(); - + protected: bool closed; InputStream &source; - + private: @@ -161,10 +159,10 @@ public: int available() { return 0; } - + void close() { /* do nothing */ } - + int get() { return getchar(); } @@ -174,7 +172,6 @@ public: - //######################################################################### //# O U T P U T S T R E A M //######################################################################### @@ -207,14 +204,14 @@ public: * 3. close the destination stream */ virtual void close() = 0; - + /** * This call should push any pending data it might have to * the destination stream. It should NOT call flush() on * the destination stream. */ virtual void flush() = 0; - + /** * Send one byte to the destination stream. */ @@ -233,14 +230,14 @@ class BasicOutputStream : public OutputStream public: - BasicOutputStream(const OutputStream &destinationStream); - + BasicOutputStream(OutputStream &destinationStream); + virtual ~BasicOutputStream() {} virtual void close(); - + virtual void flush(); - + virtual int put(gunichar ch); protected: @@ -263,12 +260,12 @@ public: void close() { } - + void flush() { } - + int put(gunichar ch) - { putchar(ch); return 1; } + { return putchar(ch); } }; @@ -279,7 +276,6 @@ public: //# R E A D E R //######################################################################### - /** * This interface and its descendants are for unicode character-oriented input * @@ -301,33 +297,42 @@ public: virtual int available() = 0; - + virtual void close() = 0; - - virtual int get() = 0; - - virtual DOMString readLine() = 0; - - virtual DOMString readWord() = 0; - + + virtual gunichar get() = 0; + + virtual Glib::ustring readLine() = 0; + + virtual Glib::ustring readWord() = 0; + /* Input formatting */ - virtual Reader& readBool (bool& val ) = 0; - - virtual Reader& readShort (short &val) = 0; - - virtual Reader& readUnsignedShort (unsigned short &val) = 0; - - virtual Reader& readInt (int &val) = 0; - - virtual Reader& readUnsignedInt (unsigned int &val) = 0; - - virtual Reader& readLong (long &val) = 0; - - virtual Reader& readUnsignedLong (unsigned long &val) = 0; - - virtual Reader& readFloat (float &val) = 0; - - virtual Reader& readDouble (double &val) = 0; + virtual const Reader& readBool (bool& val ) = 0; + virtual const Reader& operator>> (bool& val ) = 0; + + virtual const Reader& readShort (short &val) = 0; + virtual const Reader& operator>> (short &val) = 0; + + virtual const Reader& readUnsignedShort (unsigned short &val) = 0; + virtual const Reader& operator>> (unsigned short &val) = 0; + + virtual const Reader& readInt (int &val) = 0; + virtual const Reader& operator>> (int &val) = 0; + + virtual const Reader& readUnsignedInt (unsigned int &val) = 0; + virtual const Reader& operator>> (unsigned int &val) = 0; + + virtual const Reader& readLong (long &val) = 0; + virtual const Reader& operator>> (long &val) = 0; + + virtual const Reader& readUnsignedLong (unsigned long &val) = 0; + virtual const Reader& operator>> (unsigned long &val) = 0; + + virtual const Reader& readFloat (float &val) = 0; + virtual const Reader& operator>> (float &val) = 0; + + virtual const Reader& readDouble (double &val) = 0; + virtual const Reader& operator>> (double &val) = 0; }; // interface Reader @@ -343,37 +348,56 @@ class BasicReader : public Reader public: BasicReader(Reader &sourceStream); - + virtual ~BasicReader() {} virtual int available(); - + virtual void close(); - - virtual int get(); - - virtual DOMString readLine(); - - virtual DOMString readWord(); - + + virtual gunichar get(); + + virtual Glib::ustring readLine(); + + virtual Glib::ustring readWord(); + /* Input formatting */ - virtual Reader& readBool (bool& val ); - - virtual Reader& readShort (short &val) ; - - virtual Reader& readUnsignedShort (unsigned short &val) ; - - virtual Reader& readInt (int &val) ; - - virtual Reader& readUnsignedInt (unsigned int &val) ; - - virtual Reader& readLong (long &val) ; - - virtual Reader& readUnsignedLong (unsigned long &val) ; - - virtual Reader& readFloat (float &val) ; - - virtual Reader& readDouble (double &val) ; + virtual const Reader& readBool (bool& val ); + virtual const Reader& operator>> (bool& val ) + { return readBool(val); } + + virtual const Reader& readShort (short &val); + virtual const Reader& operator>> (short &val) + { return readShort(val); } + + virtual const Reader& readUnsignedShort (unsigned short &val); + virtual const Reader& operator>> (unsigned short &val) + { return readUnsignedShort(val); } + + virtual const Reader& readInt (int &val); + virtual const Reader& operator>> (int &val) + { return readInt(val); } + + virtual const Reader& readUnsignedInt (unsigned int &val); + virtual const Reader& operator>> (unsigned int &val) + { return readUnsignedInt(val); } + + virtual const Reader& readLong (long &val); + virtual const Reader& operator>> (long &val) + { return readLong(val); } + + virtual const Reader& readUnsignedLong (unsigned long &val); + virtual const Reader& operator>> (unsigned long &val) + { return readUnsignedLong(val); } + + virtual const Reader& readFloat (float &val); + virtual const Reader& operator>> (float &val) + { return readFloat(val); } + + virtual const Reader& readDouble (double &val); + virtual const Reader& operator>> (double &val) + { return readDouble(val); } + protected: @@ -388,27 +412,6 @@ private: -Reader& operator>> (Reader &reader, bool& val ); - -Reader& operator>> (Reader &reader, short &val); - -Reader& operator>> (Reader &reader, unsigned short &val); - -Reader& operator>> (Reader &reader, int &val); - -Reader& operator>> (Reader &reader, unsigned int &val); - -Reader& operator>> (Reader &reader, long &val); - -Reader& operator>> (Reader &reader, unsigned long &val); - -Reader& operator>> (Reader &reader, float &val); - -Reader& operator>> (Reader &reader, double &val); - - - - /** * Class for placing a Reader on an open InputStream * @@ -417,14 +420,14 @@ class InputStreamReader : public BasicReader { public: - InputStreamReader(const InputStream &inputStreamSource); - + InputStreamReader(InputStream &inputStreamSource); + /*Overload these 3 for your implementation*/ virtual int available(); - + virtual void close(); - - virtual int get(); + + virtual gunichar get(); private: @@ -445,13 +448,13 @@ public: StdReader(); virtual ~StdReader(); - + /*Overload these 3 for your implementation*/ virtual int available(); - + virtual void close(); - - virtual int get(); + + virtual gunichar get(); private: @@ -463,8 +466,6 @@ private: - - //######################################################################### //# W R I T E R //######################################################################### diff --git a/src/dom/io/uristream.cpp b/src/dom/io/uristream.cpp index 68a14a166..f6172d9e0 100644 --- a/src/dom/io/uristream.cpp +++ b/src/dom/io/uristream.cpp @@ -235,10 +235,10 @@ void UriReader::close() throw(StreamException) /** * */ -int UriReader::get() throw(StreamException) +gunichar UriReader::get() throw(StreamException) { - int ch = (int)inputStream->get(); - return ch; + //int ch = (int)inputStream->get(); + return inputStream->get();//ch; } diff --git a/src/dom/io/uristream.h b/src/dom/io/uristream.h index 2a659d030..51227acc9 100644 --- a/src/dom/io/uristream.h +++ b/src/dom/io/uristream.h @@ -111,7 +111,7 @@ public: virtual void close() throw(StreamException); - virtual int get() throw(StreamException); + virtual gunichar get() throw(StreamException); private: diff --git a/src/extension/internal/filter/paint.h b/src/extension/internal/filter/paint.h index ad396e08f..f04dd92f9 100644 --- a/src/extension/internal/filter/paint.h +++ b/src/extension/internal/filter/paint.h @@ -88,7 +88,7 @@ public: "<param name=\"noise\" gui-text=\"" N_("Noise reduction:") "\" type=\"int\" appearance=\"full\" min=\"1\" max=\"1000\">10</param>\n" "<param name=\"smooth\" gui-text=\"" N_("Smoothness:") "\" type=\"float\" appearance=\"full\" precision=\"2\" min=\"0.01\" max=\"10.00\">1</param>\n" "</page>\n" - "<page name=\"graintab\" _gui-text=\""N_("Grain") "\">\n" + "<page name=\"graintab\" _gui-text=\"" N_("Grain") "\">\n" "<param name=\"grain\" gui-text=\"" N_("Grain mode") "\" type=\"boolean\" >true</param>\n" "<param name=\"grainxf\" gui-text=\"" N_("Horizontal frequency:") "\" type=\"float\" appearance=\"full\" precision=\"2\" min=\"0\" max=\"1000\">1000</param>\n" "<param name=\"grainyf\" gui-text=\"" N_("Vertical frequency:") "\" type=\"float\" appearance=\"full\" precision=\"2\" min=\"0\" max=\"1000\">1000</param>\n" diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index 0639ae8d0..bd74ba47c 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -83,8 +83,8 @@ #include "dom/io/stringstream.h" +#include "inkscape-version.h" #include "document.h" - #include "extension/extension.h" @@ -1240,7 +1240,8 @@ bool OdfOutput::writeMeta(ZipFile &zf) outs.printf("xmlns:anim=\"urn:oasis:names:tc:opendocument:xmlns:animation:1.0\"\n"); outs.printf("office:version=\"1.0\">\n"); outs.printf("<office:meta>\n"); - outs.printf(" <meta:generator>Inkscape.org - 0.45</meta:generator>\n"); + Glib::ustring tmp = Glib::ustring(" <meta:generator>Inkscape.org - ") + Inkscape::version_string + "</meta:generator>\n"; + outs.writeString(tmp); outs.printf(" <meta:initial-creator>%#s</meta:initial-creator>\n", creator.c_str()); outs.printf(" <meta:creation-date>%#s</meta:creation-date>\n", date.c_str()); @@ -1465,7 +1466,7 @@ bool OdfOutput::writeStyle(ZipFile &zf) outs.printf("<!--\n"); outs.printf("*************************************************************************\n"); outs.printf(" E N D O F F I L E\n"); - outs.printf(" Have a nice day - ishmal\n"); + outs.printf(" Have a nice day\n"); outs.printf("*************************************************************************\n"); outs.printf("-->\n"); outs.printf("\n"); @@ -2170,7 +2171,7 @@ bool OdfOutput::writeStyleFooter(Writer &outs) outs.printf("<!--\n"); outs.printf("*************************************************************************\n"); outs.printf(" E N D O F F I L E\n"); - outs.printf(" Have a nice day - ishmal\n"); + outs.printf(" Have a nice day\n"); outs.printf("*************************************************************************\n"); outs.printf("-->\n"); outs.printf("\n"); @@ -2281,7 +2282,7 @@ bool OdfOutput::writeContentFooter(Writer &outs) outs.printf("<!--\n"); outs.printf("*************************************************************************\n"); outs.printf(" E N D O F F I L E\n"); - outs.printf(" Have a nice day - ishmal\n"); + outs.printf(" Have a nice day\n"); outs.printf("*************************************************************************\n"); outs.printf("-->\n"); outs.printf("\n"); @@ -2441,27 +2442,6 @@ OdfOutput::check (Inkscape::Extension::Extension */*module*/) -//######################################################################## -//# I N P U T -//######################################################################## - - - -//####################### -//# L A T E R !!! :-) -//####################### - - - - - - - - - - - - } //namespace Internal } //namespace Extension diff --git a/src/io/base64stream.cpp b/src/io/base64stream.cpp index 42a6ba1e4..28c819347 100644 --- a/src/io/base64stream.cpp +++ b/src/io/base64stream.cpp @@ -290,12 +290,12 @@ void Base64OutputStream::putCh(int ch) /** * Writes the specified byte to this output stream. */ -void Base64OutputStream::put(gunichar ch) +int Base64OutputStream::put(gunichar ch) { if (closed) { //probably throw an exception here - return; + return -1; } outBuf <<= 8; @@ -322,6 +322,7 @@ void Base64OutputStream::put(gunichar ch) bitCount = 0; outBuf = 0L; } + return 1; } diff --git a/src/io/base64stream.h b/src/io/base64stream.h index 836939130..4bc99acac 100644 --- a/src/io/base64stream.h +++ b/src/io/base64stream.h @@ -88,7 +88,7 @@ public: virtual void flush(); - virtual void put(gunichar ch); + virtual int put(gunichar ch); /** * Sets the maximum line length for base64 output. If diff --git a/src/io/gzipstream.cpp b/src/io/gzipstream.cpp index 071179b48..8db7155db 100644 --- a/src/io/gzipstream.cpp +++ b/src/io/gzipstream.cpp @@ -433,19 +433,19 @@ void GzipOutputStream::flush() /** * Writes the specified byte to this output stream. */ -void GzipOutputStream::put(gunichar ch) +int GzipOutputStream::put(gunichar ch) { if (closed) { //probably throw an exception here - return; + return -1; } //Add char to buffer inputBuf.push_back(ch); totalIn++; - + return 1; } diff --git a/src/io/gzipstream.h b/src/io/gzipstream.h index 5af57b4c5..390ec1225 100644 --- a/src/io/gzipstream.h +++ b/src/io/gzipstream.h @@ -98,7 +98,7 @@ public: virtual void flush(); - virtual void put(gunichar ch); + virtual int put(gunichar ch); private: diff --git a/src/io/inkscapestream.cpp b/src/io/inkscapestream.cpp index 3270127d6..4c7fa4d49 100644 --- a/src/io/inkscapestream.cpp +++ b/src/io/inkscapestream.cpp @@ -125,11 +125,12 @@ void BasicOutputStream::flush() /** * Writes the specified byte to this output stream. */ -void BasicOutputStream::put(gunichar ch) +int BasicOutputStream::put(gunichar ch) { if (closed) - return; + return -1; destination.put(ch); + return 1; } @@ -137,8 +138,6 @@ void BasicOutputStream::put(gunichar ch) //######################################################################### //# B A S I C R E A D E R //######################################################################### - - /** * */ @@ -183,10 +182,6 @@ gunichar BasicReader::get() } - - - - /** * Reads a line of data from the reader. */ @@ -255,13 +250,6 @@ static bool getDouble(Glib::ustring &str, double *val) - - - - -/** - * - */ const Reader &BasicReader::readBool (bool& val ) { Glib::ustring buf = readWord(); @@ -272,9 +260,6 @@ const Reader &BasicReader::readBool (bool& val ) return *this; } -/** - * - */ const Reader &BasicReader::readShort (short& val ) { Glib::ustring buf = readWord(); @@ -284,9 +269,6 @@ const Reader &BasicReader::readShort (short& val ) return *this; } -/** - * - */ const Reader &BasicReader::readUnsignedShort (unsigned short& val ) { Glib::ustring buf = readWord(); @@ -296,9 +278,6 @@ const Reader &BasicReader::readUnsignedShort (unsigned short& val ) return *this; } -/** - * - */ const Reader &BasicReader::readInt (int& val ) { Glib::ustring buf = readWord(); @@ -308,9 +287,6 @@ const Reader &BasicReader::readInt (int& val ) return *this; } -/** - * - */ const Reader &BasicReader::readUnsignedInt (unsigned int& val ) { Glib::ustring buf = readWord(); @@ -320,9 +296,6 @@ const Reader &BasicReader::readUnsignedInt (unsigned int& val ) return *this; } -/** - * - */ const Reader &BasicReader::readLong (long& val ) { Glib::ustring buf = readWord(); @@ -332,9 +305,6 @@ const Reader &BasicReader::readLong (long& val ) return *this; } -/** - * - */ const Reader &BasicReader::readUnsignedLong (unsigned long& val ) { Glib::ustring buf = readWord(); @@ -344,9 +314,6 @@ const Reader &BasicReader::readUnsignedLong (unsigned long& val ) return *this; } -/** - * - */ const Reader &BasicReader::readFloat (float& val ) { Glib::ustring buf = readWord(); @@ -356,9 +323,6 @@ const Reader &BasicReader::readFloat (float& val ) return *this; } -/** - * - */ const Reader &BasicReader::readDouble (double& val ) { Glib::ustring buf = readWord(); diff --git a/src/io/inkscapestream.h b/src/io/inkscapestream.h index a9854ae6d..d19dbbe95 100644 --- a/src/io/inkscapestream.h +++ b/src/io/inkscapestream.h @@ -189,7 +189,7 @@ public: /** * Send one byte to the destination stream. */ - virtual void put(gunichar ch) = 0; + virtual int put(gunichar ch) = 0; }; // class OutputStream @@ -212,7 +212,7 @@ public: virtual void flush(); - virtual void put(gunichar ch); + virtual int put(gunichar ch); protected: @@ -238,8 +238,8 @@ public: void flush() { } - void put(gunichar ch) - { putchar(ch); } + int put(gunichar ch) + {return putchar(ch); } }; diff --git a/src/io/stringstream.cpp b/src/io/stringstream.cpp index f204a99d5..5a76e24a3 100644 --- a/src/io/stringstream.cpp +++ b/src/io/stringstream.cpp @@ -112,9 +112,10 @@ void StringOutputStream::flush() /** * Writes the specified byte to this output stream. */ -void StringOutputStream::put(gunichar ch) +int StringOutputStream::put(gunichar ch) { buffer.push_back(ch); + return 1; } diff --git a/src/io/stringstream.h b/src/io/stringstream.h index a78935599..939a87455 100644 --- a/src/io/stringstream.h +++ b/src/io/stringstream.h @@ -67,7 +67,7 @@ public: virtual void flush(); - virtual void put(gunichar ch); + virtual int put(gunichar ch); virtual Glib::ustring &getString() { return buffer; } diff --git a/src/io/uristream.cpp b/src/io/uristream.cpp index 8d7fd9b38..37c13ada0 100644 --- a/src/io/uristream.cpp +++ b/src/io/uristream.cpp @@ -402,17 +402,17 @@ void UriOutputStream::flush() throw(StreamException) /** * Writes the specified byte to this output stream. */ -void UriOutputStream::put(gunichar ch) throw(StreamException) +int UriOutputStream::put(gunichar ch) throw(StreamException) { if (closed) - return; + return -1; unsigned char uch; switch (scheme) { case SCHEME_FILE: if (!outf) - return; + return -1; uch = (unsigned char)(ch & 0xff); if (fputc(uch, outf) == EOF) { Glib::ustring err = "ERROR writing to file "; @@ -425,7 +425,7 @@ void UriOutputStream::put(gunichar ch) throw(StreamException) break; }//switch - + return 1; } diff --git a/src/io/uristream.h b/src/io/uristream.h index e519335e8..3080519de 100644 --- a/src/io/uristream.h +++ b/src/io/uristream.h @@ -115,7 +115,7 @@ public: virtual void flush() throw(StreamException); - virtual void put(gunichar ch) throw(StreamException); + virtual int put(gunichar ch) throw(StreamException); private: diff --git a/src/io/xsltstream.cpp b/src/io/xsltstream.cpp index 1c260c0b3..7a6632233 100644 --- a/src/io/xsltstream.cpp +++ b/src/io/xsltstream.cpp @@ -230,9 +230,10 @@ void XsltOutputStream::flush() throw (StreamException) /** * Writes the specified byte to this output stream. */ -void XsltOutputStream::put(gunichar ch) throw (StreamException) +int XsltOutputStream::put(gunichar ch) throw (StreamException) { outbuf.push_back(ch); + return 1; } diff --git a/src/io/xsltstream.h b/src/io/xsltstream.h index 9b8e19215..31ee89e10 100644 --- a/src/io/xsltstream.h +++ b/src/io/xsltstream.h @@ -120,7 +120,7 @@ public: virtual void flush() throw (StreamException); - virtual void put(gunichar ch) throw (StreamException); + virtual int put(gunichar ch) throw (StreamException); private: diff --git a/src/isinf.h b/src/isinf.h index 7799d2876..b4c56f79d 100644 --- a/src/isinf.h +++ b/src/isinf.h @@ -12,6 +12,9 @@ #elif defined(__APPLE__) && __GNUC__ == 3 #define isinf(x) __isinf(x) +#elif __cplusplus >= 201103L +# include <cmath> +# define isinf std::isinf #endif #endif /* __ISINF_H__ */ diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 5e67c5991..97d3c66d4 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -82,7 +82,6 @@ namespace Inkscape font_list_store->thaw_notify(); style_list_store = Gtk::ListStore::create (FontStyleList); - style_list_store_trial = Gtk::ListStore::create (FontStyleList); } // Example of how to use "foreach_iter" @@ -375,6 +374,24 @@ namespace Inkscape } + // Set fontspec. If check is false, best style match will not be done. + void + FontLister::set_fontspec (Glib::ustring new_fontspec, gboolean check) { + + std::pair<Glib::ustring,Glib::ustring> ui = ui_from_fontspec( new_fontspec ); + Glib::ustring new_family = ui.first; + Glib::ustring new_style = ui.second; + +#ifdef DEBUG_FONT + std::cout << "FontLister::set_fontspec: family: " << new_family + << " style:" << new_style << std::endl; +#endif + + set_font_family( new_family, false ); + set_font_style( new_style ); + } + + // TODO: use to determine font-selector best style std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustring new_family, gboolean check_style ) { @@ -419,7 +436,6 @@ namespace Inkscape } // Update style list. - // TODO: create a second "temporary" style_list_store for font_selector. style_list_store->freeze_notify(); style_list_store->clear(); @@ -524,11 +540,6 @@ namespace Inkscape } - // void - // FontLister::new_font_style (Glib::ustring new_style) { - // // Is this needed? What do we do? - // } - void FontLister::set_font_style (Glib::ustring new_style) { @@ -554,27 +565,22 @@ namespace Inkscape #endif } - // For use by font-selector where we already know that the style is valid - void - FontLister::set_font (Glib::ustring new_family, Glib::ustring new_style) { - -#ifdef DEBUG_FONT - std::cout << "FonLister::set_font: " << new_family << " " << new_style << std::endl; -#endif - set_font_family( new_family, false ); - set_font_style( new_style ); - } // We do this ourselves as we can't rely on FontFactory. void - FontLister::set_css( SPCSSAttr *css ) { + FontLister::fill_css( SPCSSAttr *css, Glib::ustring fontspec ) { + + if( fontspec.empty() ) { + fontspec = current_fontspec; + } + std::pair<Glib::ustring,Glib::ustring> ui = ui_from_fontspec( fontspec ); - //std::cout << "FontLister:set_css: " << std::endl; + Glib::ustring family = ui.first; - sp_repr_css_set_property (css, "-inkscape-font-specification", current_fontspec.c_str() ); - sp_repr_css_set_property (css, "font-family", current_family.c_str() ); //Canonized w/ spaces + sp_repr_css_set_property (css, "-inkscape-font-specification", fontspec.c_str() ); + sp_repr_css_set_property (css, "font-family", family.c_str() ); //Canonized w/ spaces - PangoFontDescription *desc = pango_font_description_from_string( current_fontspec.c_str() ); + PangoFontDescription *desc = pango_font_description_from_string( fontspec.c_str() ); PangoWeight weight = pango_font_description_get_weight( desc ); switch ( weight ) { case PANGO_WEIGHT_THIN: @@ -837,6 +843,26 @@ namespace Inkscape return font_list_store->get_path( get_row_for_font ( family ) ); } + Gtk::TreeModel::Row + FontLister::get_row_for_style (Glib::ustring style) + { + Gtk::TreePath path; + + Gtk::TreeModel::iterator iter = style_list_store->get_iter( "0" ); + while( iter != style_list_store->children().end() ) { + + Gtk::TreeModel::Row row = *iter; + + if( style.compare( row[FontStyleList.styles] ) == 0 ) { + return row; + } + + ++iter; + } + + throw STYLE_NOT_FOUND; + } + /* Returns style string */ // TODO: Remove or turn into function to be used by new_font_family. Glib::ustring @@ -905,12 +931,6 @@ namespace Inkscape { return style_list_store; } - - const Glib::RefPtr<Gtk::ListStore> - FontLister::get_style_list_trial () const - { - return style_list_store_trial; - } } // Helper functions diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h index aaa996247..5c48bf7a8 100644 --- a/src/libnrtype/font-lister.h +++ b/src/libnrtype/font-lister.h @@ -111,7 +111,6 @@ namespace Inkscape }; FontStyleListClass FontStyleList; - FontStyleListClass FontStyleListTrial; /** Returns the ListStore with the family names * @@ -128,12 +127,6 @@ namespace Inkscape const Glib::RefPtr<Gtk::ListStore> get_style_list () const; - /** Returns the ListStore with the styles - trial - * - */ - const Glib::RefPtr<Gtk::ListStore> - get_style_list_trial () const; - /** Updates font list to include fonts in document * */ @@ -173,6 +166,19 @@ namespace Inkscape std::pair<Glib::ustring, Glib::ustring> selection_update (); + /** Sets current_fontspec, etc. If check is false, won't + * try to find best style match (assumes style in fontspec + * valid for given font-family). + */ + void + set_fontspec (Glib::ustring fontspec, gboolean check=true); + + Glib::ustring + get_fontspec () + { + return current_fontspec; + } + /** Changes font-family, updating style list and attempting to find * closest style to current_style style (if check_style is true). * New font-family and style returned. @@ -215,10 +221,6 @@ namespace Inkscape return current_family_row; } - /* Not Used */ - void - new_font_style (Glib::ustring style); - /** Sets style. Does not validate style for family. */ void @@ -230,32 +232,13 @@ namespace Inkscape return current_style; } - /** Sets both family and style. Does not attempt to find - * best match for style (assume that style is already valid - * for family). - */ - void - set_font (Glib::ustring family, Glib::ustring style); - - /** Sets both family and style. Does not attempt to find - * best match for style (assume that style is already valid - * for family). - */ - void - new_font (Glib::ustring family, Glib::ustring style); - - std::pair<Glib::ustring, Glib::ustring> - get_try_font () { - return ( std::make_pair( try_family, try_style ) ); - } - Glib::ustring fontspec_from_style (SPStyle* style); /** Fill css using current_fontspec. */ void - set_css( SPCSSAttr *css ); + fill_css( SPCSSAttr *css, Glib::ustring fontspec = "" ); Gtk::TreeModel::Row get_row_for_font (Glib::ustring family); @@ -292,7 +275,6 @@ namespace Inkscape Glib::RefPtr<Gtk::ListStore> font_list_store; Glib::RefPtr<Gtk::ListStore> style_list_store; - Glib::RefPtr<Gtk::ListStore> style_list_store_trial; /** Info for currently selected font (what is shown in the UI). * May include font-family lists and fonts not on system. @@ -307,12 +289,6 @@ namespace Inkscape */ Glib::ustring current_fontspec_system; - /** Info for proposed font (what is shown in the font-selection UI). - * May include font-family lists and fonts not on system. - */ - Glib::ustring try_family; - Glib::ustring try_style; - /** If a font-family is not on system, this list of styles is used. */ GList *default_styles; diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index ed4791155..d91f7297e 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -53,7 +53,6 @@ LPEBSpline::doEffect(SPCurve * curve) //Esto hace que la curva BSpline no pierda su condición aunque se trasladen //dichos manejadores SPCurve *nCurve = new SPCurve(); - Geom::Point startNode(0,0); Geom::Point previousNode(0,0); Geom::Point node(0,0); Geom::Point pointAt1(0,0); @@ -65,63 +64,19 @@ LPEBSpline::doEffect(SPCurve * curve) Geom::D2< Geom::SBasis > SBasisOut; Geom::D2< Geom::SBasis > SBasisHelper; Geom::CubicBezier const *cubic = NULL; - //Si la curva está cerrada calculamos el punto donde - //deveria estar el nodo BSpline de cierre/inicio de la curva - //en posible caso de que se cierre con una linea recta creando un nodo BSPline - if (path_it->closed()) { - //Calculamos el nodo de inicio BSpline - const Geom::Curve &closingline = path_it->back_closed(); + // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength. + const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment. if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors... + // the closing line segment has zero-length. So stop before that one! curve_endit = path_it->end_open(); } - - SPCurve * in = new SPCurve(); - in->moveto(curve_it1->initialPoint()); - in->lineto(curve_it1->finalPoint()); - SBasisIn = in->first_segment()->toSBasis(); - - SPCurve *lineHelper = new SPCurve(); - cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); - if(cubic){ - lineHelper->moveto(SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()))); - }else{ - lineHelper->moveto(in->first_segment()->initialPoint()); - } - in->reset(); - delete in; - - SPCurve * end = new SPCurve(); - end->moveto(curve_endit->initialPoint()); - end->lineto(curve_endit->finalPoint()); - Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); - //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit); - cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit); - if(cubic){ - lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); - }else{ - lineHelper->lineto(end->first_segment()->finalPoint()); - } - end->reset(); - delete end; - SBasisHelper = lineHelper->first_segment()->toSBasis(); - lineHelper->reset(); - delete lineHelper; - //Guardamos el principio de la curva - startNode = SBasisHelper.valueAt(0.5); - //Definimos el punto de inicio original de la curva resultante - node = startNode; - }else{ - //Guardamos el principio de la curva - SPCurve * in = new SPCurve(); - in->moveto(curve_it1->initialPoint()); - in->lineto(curve_it1->finalPoint()); - startNode = in->first_segment()->initialPoint(); - in->reset(); - delete in; - //Definimos el punto de inicio original de la curva resultante - node = startNode; } + //Si la curva está cerrada calculamos el punto donde + //deveria estar el nodo BSpline de cierre/inicio de la curva + //en posible caso de que se cierre con una linea recta creando un nodo BSPline + //Recorremos todos los segmentos menos el último while ( curve_it2 != curve_endit ) { @@ -190,13 +145,54 @@ LPEBSpline::doEffect(SPCurve * curve) curveHelper->moveto(node); //Si está cerrada la curva, la cerramos sobre el valor guardado previamente //Si no finalizamos en el punto final + Geom::Point startNode(0,0); if (path_it->closed()) { + SPCurve * start = new SPCurve(); + start->moveto(path_it->begin()->initialPoint()); + start->lineto(path_it->begin()->finalPoint()); + Geom::D2< Geom::SBasis > SBasisStart = start->first_segment()->toSBasis(); + SPCurve *lineHelper = new SPCurve(); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*path_it->begin()); + if(cubic){ + lineHelper->moveto(SBasisStart.valueAt(Geom::nearest_point((*cubic)[1],*start->first_segment()))); + }else{ + lineHelper->moveto(start->first_segment()->initialPoint()); + } + start->reset(); + delete start; + + SPCurve * end = new SPCurve(); + end->moveto(curve_it1->initialPoint()); + end->lineto(curve_it1->finalPoint()); + Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); + //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); + }else{ + lineHelper->lineto(end->first_segment()->finalPoint()); + } + end->reset(); + delete end; + SBasisHelper = lineHelper->first_segment()->toSBasis(); + lineHelper->reset(); + delete lineHelper; + //Guardamos el principio de la curva + startNode = SBasisHelper.valueAt(0.5); curveHelper->curveto(nextPointAt1, nextPointAt2, startNode); + nCurve->append_continuous(curveHelper, 0.0625); + nCurve->move_endpoints(startNode,startNode); }else{ + SPCurve * start = new SPCurve(); + start->moveto(path_it->begin()->initialPoint()); + start->lineto(path_it->begin()->finalPoint()); + startNode = start->first_segment()->initialPoint(); + start->reset(); + delete start; curveHelper->curveto(nextPointAt1, nextPointAt2, nextPointAt3); + nCurve->append_continuous(curveHelper, 0.0625); + nCurve->move_endpoints(startNode,nextPointAt3); } - //añadimos este último segmento - nCurve->append_continuous(curveHelper, 0.0625); curveHelper->reset(); delete curveHelper; //y cerramos la curva diff --git a/src/pen-context.cpp b/src/pen-context.cpp index e781a048f..26f800328 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -94,35 +94,22 @@ static void spdc_pen_set_initial_point(SPPenContext *pc, Geom::Point const p); */ static void sp_pen_context_set_mode(SPPenContext *const pc, guint mode); //Esta función cambia los colores rojo,verde y azul haciendolos transparentes o no en función de si se usa spiro -static void spiro_color(SPPenContext *const pc); -//Guarda el valor si se ha pulsado la tecla SHIFT al continuar una curva -static void spiro(SPPenContext *const pc,bool shift); -static void spiroOn(SPPenContext *const pc); -static void spiroOff(SPPenContext *const pc); -static void spiroStartAnchor(SPPenContext *const pc,bool shift); -static void spiroStartAnchorOn(SPPenContext *const pc); -static void spiroStartAnchorOff(SPPenContext *const pc); -static void spiroMotion(SPPenContext *const pc,bool shift); -static void spiroEndAnchorOn(SPPenContext *const pc); -static void spiroEndAnchorOff(SPPenContext *const pc); +static void bspline_spiro_color(SPPenContext *const pc); +static void bspline_spiro(SPPenContext *const pc,bool shift); +static void bspline_spiro_on(SPPenContext *const pc); +static void bspline_spiro_off(SPPenContext *const pc); +static void bspline_spiro_start_anchor(SPPenContext *const pc,bool shift); +static void bspline_spiro_start_anchor_on(SPPenContext *const pc); +static void bspline_spiro_start_anchor_off(SPPenContext *const pc); +static void bspline_spiro_motion(SPPenContext *const pc,bool shift); +static void bspline_spiro_end_anchor_on(SPPenContext *const pc); +static void bspline_spiro_end_anchor_off(SPPenContext *const pc); //Unimos todas las curvas en juego y llamamos a la función doEffect. -static void spiro_build(SPPenContext *const pc); -//function spiro cloned from lpe-spiro.cpp -static void spiro_doEffect(SPCurve * curve); -//Preparamos la curva roja para que se muestre según esté pulsada la tecla SHIFT -static void bspline(SPPenContext *const pc,bool shift); -static void bsplineOn(SPPenContext *const pc); -static void bsplineOff(SPPenContext *const pc); -static void bsplineStartAnchor(SPPenContext *const pc,bool shift); -static void bsplineStartAnchorOn(SPPenContext *const pc); -static void bsplineStartAnchorOff(SPPenContext *const pc); -static void bsplineMotion(SPPenContext *const pc,bool shift); -static void bsplineEndAnchorOn(SPPenContext *const pc); -static void bsplineEndAnchorOff(SPPenContext *const pc); -//Unimos todas las curvas en juego y llamamos a la función doEffect. -static void bspline_build(SPPenContext *const pc); +static void bspline_spiro_build(SPPenContext *const pc); //function bspline cloned from lpe-bspline.cpp static void bspline_doEffect(SPCurve * curve); +//function spiro cloned from lpe-spiro.cpp +static void spiro_doEffect(SPCurve * curve); //BSpline end @@ -472,9 +459,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const Geom::Point event_dt(desktop->w2d(event_w)); SPEventContext *event_context = SP_EVENT_CONTEXT(pc); //Test whether we hit any anchor. - //Anchor changed from Const because need to update pc->ea for BSpline. - SPDrawAnchor * anchor = spdc_test_inside(pc, event_w); - //BSpline + SPDrawAnchor * const anchor = spdc_test_inside(pc, event_w); //with this we avoid creating a new point over the existing one if((pc->spiro || pc->bspline) && pc->npoints > 0 && pc->p[0] == pc->p[3]){ return FALSE; @@ -545,12 +530,8 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const pc->sa = anchor; //BSpline if(anchor){ - if(pc->spiro){ - spiroStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK)); - } - if(pc->bspline){ - bsplineStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK)); - } + if(pc->bspline || pc->spiro) + bspline_spiro_start_anchor(pc,(bevent.state & GDK_SHIFT_MASK)); } //BSpline End if (anchor && !sp_pen_context_has_waiting_LPE(pc)) { @@ -674,7 +655,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint const tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); //"spiro_color" lo ejecutamos siempre sea o no spiro - spiro_color(pc); + bspline_spiro_color(pc); if (pen_within_tolerance) { if ( Geom::LInfty( event_w - pen_drag_origin_w ) < tolerance) { return FALSE; // Do not drag if we're within tolerance from origin. @@ -798,12 +779,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons } //BSpline if ( Geom::LInfty( event_w - pen_drag_origin_w ) > tolerance || mevent.time == 0) { - if(pc->spiro){ - spiroMotion(pc,(mevent.state & GDK_SHIFT_MASK)); - } - if(pc->bspline){ - bsplineMotion(pc,(mevent.state & GDK_SHIFT_MASK)); - } + bspline_spiro_motion(pc,(mevent.state & GDK_SHIFT_MASK)); pen_drag_origin_w = event_w; } //BSpline End @@ -852,11 +828,8 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con pc->sa = anchor; //BSpline if (anchor) { - if(pc->spiro){ - spiroStartAnchor(pc,(revent.state & GDK_SHIFT_MASK)); - } - if(pc->bspline){ - bsplineStartAnchor(pc,(revent.state & GDK_SHIFT_MASK)); + if(pc->bspline || pc->spiro){ + bspline_spiro_start_anchor(pc,(revent.state & GDK_SHIFT_MASK)); } } //BSpline End @@ -1042,14 +1015,9 @@ static void pen_redraw_all (SPPenContext *const pc) //Simplemente redibujamos la spiro teniendo en cuenta si el nodo es cusp o symm. //como es un redibujo simplemente no llamamos a la función global //sino al final de esta - if(pc->spiro){ - //we redraw spiro - spiro_build(pc); - } - if(pc->bspline){ - //we redraw bspline - bspline_build(pc); - } + + //BSpline + bspline_spiro_build(pc); //BSpline End } @@ -1432,7 +1400,7 @@ static gint pen_handle_key_press(SPPenContext *const pc, GdkEvent *event) spdc_pen_set_subsequent_point(pc, pt, true); pen_last_paraxial_dir = !pen_last_paraxial_dir; //BSpline - if(pc->spiro || pc->bspline) bspline_build(pc); + bspline_spiro_build(pc); //BSpline End ret = TRUE; } @@ -1506,7 +1474,7 @@ static void spdc_pen_set_angle_distance_status_message(SPPenContext *const pc, G //Esta función cambia los colores rojo,verde y azul haciendolos transparentes o no en función de si se usa spiro -static void spiro_color(SPPenContext *const pc) +static void bspline_spiro_color(SPPenContext *const pc) { bool remake_green_bpaths = false; if(pc->spiro){ @@ -1550,435 +1518,19 @@ static void spiro_color(SPPenContext *const pc) sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(pc->red_bpath), pc->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); } - -//Unimos todas las curvas en juego y llamamos a la función doEffect. - -static void spiro(SPPenContext *const pc, bool shift) -{ - if(!pc->anchor_statusbar) - shift?spiroOff(pc):spiroOn(pc); - - spiro_build(pc); -} - -static void spiroOn(SPPenContext *const pc){ - if(!pc->red_curve->is_empty()){ - using Geom::X; - using Geom::Y; - pc->npoints = 5; - pc->p[0] = pc->red_curve->first_segment()->initialPoint(); - pc->p[3] = pc->red_curve->first_segment()->finalPoint(); - pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); - pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); - } -} - -static void spiroOff(SPPenContext *const pc) -{ - if(!pc->red_curve->is_empty()){ - pc->npoints = 5; - pc->p[0] = pc->red_curve->first_segment()->initialPoint(); - pc->p[3] = pc->red_curve->first_segment()->finalPoint(); - pc->p[2] = pc->p[3]; - } -} - -static void spiroStartAnchor(SPPenContext *const pc, bool shift) +static void bspline_spiro(SPPenContext *const pc, bool shift) { - if(pc->sa->curve->is_empty()) + if(!pc->spiro && !pc->bspline) return; - if(shift) - bsplineStartAnchorOff(pc); - else - bsplineStartAnchorOn(pc); -} - -static void spiroStartAnchorOn(SPPenContext *const pc) -{ - using Geom::X; - using Geom::Y; - SPCurve *tmpCurve = new SPCurve(); - tmpCurve = pc->sa->curve->copy(); - if(pc->sa->start) - tmpCurve = tmpCurve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - SPCurve *lastSeg = new SPCurve(); - Geom::Point A = tmpCurve->last_segment()->initialPoint(); - Geom::Point D = tmpCurve->last_segment()->finalPoint(); - Geom::Point C = D + (1./3)*(A - D); - C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); - if(cubic){ - lastSeg->moveto(A); - lastSeg->curveto((*cubic)[1],C,D); - }else{ - lastSeg->moveto(A); - lastSeg->curveto(A,C,D); - } - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - if (pc->sa->start) { - tmpCurve = tmpCurve->create_reverse(); - } - pc->sa->curve->reset(); - pc->sa->curve = tmpCurve; -} - -static void spiroStartAnchorOff(SPPenContext *const pc) -{ - SPCurve *tmpCurve = new SPCurve(); - tmpCurve = pc->sa->curve->copy(); - if(pc->sa->start) - tmpCurve = tmpCurve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - if(cubic){ - SPCurve *lastSeg = new SPCurve(); - lastSeg->moveto((*cubic)[0]); - lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - if (pc->sa->start) { - tmpCurve = tmpCurve->create_reverse(); - } - pc->sa->curve->reset(); - pc->sa->curve = tmpCurve; - } - -} - -static void spiroMotion(SPPenContext *const pc, bool shift){ - using Geom::X; - using Geom::Y; - SPCurve *tmpCurve = new SPCurve(); - if(shift) - pc->p[2] = pc->p[3]; - else - pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); - pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); - - if(pc->green_curve->is_empty() && !pc->sa){ - pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]); - }else if(!pc->green_curve->is_empty()){ - tmpCurve = pc->green_curve->copy(); - }else{ - tmpCurve = pc->sa->curve->copy(); - if(pc->sa->start) - tmpCurve = tmpCurve->create_reverse(); - } - if(!tmpCurve->is_empty() && !pc->red_curve->is_empty()){ - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - if(cubic){ - pc->p[1] = (*cubic)[3] + (Geom::Point)((*cubic)[3] - (*cubic)[2] ); - }else{ - pc->p[1] = pc->p[0]; - } - } - - if(pc->anchor_statusbar && !pc->red_curve->is_empty()){ - if(shift) - bsplineEndAnchorOff(pc); - else - bsplineEndAnchorOn(pc); - } - - spiro_build(pc); -} - -static void spiroEndAnchorOn(SPPenContext *const pc) -{ - using Geom::X; - using Geom::Y; - pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); - pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); - SPCurve *tmpCurve = new SPCurve(); - SPCurve *lastSeg = new SPCurve(); - Geom::Point C(0,0); - if(!pc->sa || pc->sa->curve->is_empty()){ - tmpCurve = pc->green_curve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - C = tmpCurve->last_segment()->finalPoint() + (Geom::Point)(tmpCurve->last_segment()->finalPoint() - pc->p[2]); - if(cubic){ - lastSeg->moveto((*cubic)[0]); - lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); - }else{ - lastSeg->moveto(tmpCurve->last_segment()->initialPoint()); - lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint()); - } - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - tmpCurve = tmpCurve->create_reverse(); - pc->green_curve->reset(); - pc->green_curve = tmpCurve; - }else{ - tmpCurve = pc->sa->curve->copy(); - if(!pc->sa->start) - tmpCurve = tmpCurve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - C = tmpCurve->last_segment()->finalPoint() + (Geom::Point)(tmpCurve->last_segment()->finalPoint() - pc->p[2]); - if(cubic){ - lastSeg->moveto((*cubic)[0]); - lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); - }else{ - lastSeg->moveto(tmpCurve->last_segment()->initialPoint()); - lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint()); - } - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - if (!pc->sa->start) { - tmpCurve = tmpCurve->create_reverse(); - } - pc->sa->curve->reset(); - pc->sa->curve = tmpCurve; - } -} - -static void spiroEndAnchorOff(SPPenContext *const pc) -{ - pc->p[2] = pc->p[3]; - SPCurve *tmpCurve = new SPCurve(); - SPCurve *lastSeg = new SPCurve(); - if(!pc->sa || pc->sa->curve->is_empty()){ - tmpCurve = pc->green_curve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - if(cubic){ - lastSeg->moveto((*cubic)[0]); - lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - tmpCurve = tmpCurve->create_reverse(); - pc->green_curve->reset(); - pc->green_curve = tmpCurve; - } - }else{ - tmpCurve = pc->sa->curve->copy(); - if(!pc->sa->start) - tmpCurve = tmpCurve->create_reverse(); - Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - if(cubic){ - lastSeg->moveto((*cubic)[0]); - lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); - if( tmpCurve->get_segment_count() == 1){ - tmpCurve = lastSeg; - }else{ - //we eliminate the last segment - tmpCurve->backspace(); - //and we add it again with the recreation - tmpCurve->append_continuous(lastSeg, 0.0625); - } - if (!pc->sa->start) { - tmpCurve = tmpCurve->create_reverse(); - } - pc->sa->curve->reset(); - pc->sa->curve = tmpCurve; - } - } -} - -//Unimos todas las curvas en juego y llamamos a la función doEffect. -static void spiro_build(SPPenContext *const pc) -{ - //We create the base curve - SPCurve *curve = new SPCurve(); - //If we continuate the existing curve we add it at the start - if(pc->sa && !pc->sa->curve->is_empty()){ - curve = pc->sa->curve->copy(); - if (pc->sa->start) { - curve = curve->create_reverse(); - } - } - //We add also the green curve - if (!pc->green_curve->is_empty()) - curve->append_continuous(pc->green_curve, 0.0625); - - //and the red one - if (!pc->red_curve->is_empty()){ - pc->red_curve->reset(); - pc->red_curve->moveto(pc->p[0]); - pc->red_curve->curveto(pc->p[1],pc->p[2],pc->p[3]); - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), pc->red_curve); - curve->append_continuous(pc->red_curve, 0.0625); - } - - if(!curve->is_empty()){ - //cerramos la curva si estan cerca los puntos finales de la curva spiro - if(Geom::are_near(curve->first_path()->initialPoint(), curve->last_path()->finalPoint())){ - curve->closepath_current(); - } - //TODO: CALL TO CLONED FUNCTION SPIRO::doEffect IN lpe-spiro.cpp - //For example - //using namespace Inkscape::LivePathEffect; - //LivePathEffectObject *lpeobj = static_cast<LivePathEffectObject*> (curve); - //Effect *spr = static_cast<Effect*> ( new LPEspiro(lpeobj) ); - //spr->doEffect(curve); - spiro_doEffect(curve); - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->blue_bpath), curve); - sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(pc->blue_bpath), pc->blue_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - sp_canvas_item_show(pc->blue_bpath); - curve->unref(); - sp_canvas_item_show(pc->c1); - pc->blue_curve->reset(); - SP_CTRL(pc->c1)->moveto(pc->p[0]); - //We hide the holders that doesn't contribute anything - sp_canvas_item_hide(pc->cl1); - sp_canvas_item_hide(pc->c0); - sp_canvas_item_hide(pc->cl0); - }else{ - //if the curve is empty - sp_canvas_item_hide(pc->blue_bpath); - } -} -//Spiro function cloned from lpe-spiro.cpp -static void spiro_doEffect(SPCurve * curve) -{ - using Geom::X; - using Geom::Y; - - // Make copy of old path as it is changed during processing - Geom::PathVector const original_pathv = curve->get_pathvector(); - guint len = curve->get_segment_count() + 2; - - curve->reset(); - Spiro::spiro_cp *path = g_new (Spiro::spiro_cp, len); - int ip = 0; - - for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { - if (path_it->empty()) - continue; - - // start of path - { - Geom::Point p = path_it->front().pointAt(0); - path[ip].x = p[X]; - path[ip].y = p[Y]; - path[ip].ty = '{' ; // for closed paths, this is overwritten - ip++; - } - - // midpoints - Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - - Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop - if (path_it->closed()) { - // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength. - const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment. - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors... - // the closing line segment has zero-length. So stop before that one! - curve_endit = path_it->end_open(); - } - } - - while ( curve_it2 != curve_endit ) - { - /* This deals with the node between curve_it1 and curve_it2. - * Loop to end_default (so without last segment), loop ends when curve_it2 hits the end - * and then curve_it1 points to end or closing segment */ - Geom::Point p = curve_it1->finalPoint(); - path[ip].x = p[X]; - path[ip].y = p[Y]; - - // Determine type of spiro node this is, determined by the tangents (angles) of the curves - // TODO: see if this can be simplified by using /helpers/geom-nodetype.cpp:get_nodetype - bool this_is_line = is_straight_curve(*curve_it1); - bool next_is_line = is_straight_curve(*curve_it2); - - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); - - if ( nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM ) - { - if (this_is_line && !next_is_line) { - path[ip].ty = ']'; - } else if (next_is_line && !this_is_line) { - path[ip].ty = '['; - } else { - path[ip].ty = 'c'; - } - } else { - path[ip].ty = 'v'; - } - - ++curve_it1; - ++curve_it2; - ip++; - } - - // add last point to the spiropath - Geom::Point p = curve_it1->finalPoint(); - path[ip].x = p[X]; - path[ip].y = p[Y]; - if (path_it->closed()) { - // curve_it1 points to the (visually) closing segment. determine the match between first and this last segment (the closing node) - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, path_it->front()); - switch (nodetype) { - case Geom::NODE_NONE: // can't happen! but if it does, it means the path isn't closed :-) - path[ip].ty = '}'; - ip++; - break; - case Geom::NODE_CUSP: - path[0].ty = path[ip].ty = 'v'; - break; - case Geom::NODE_SMOOTH: - case Geom::NODE_SYMM: - path[0].ty = path[ip].ty = 'c'; - break; - } - } else { - // set type to path closer - path[ip].ty = '}'; - ip++; - } - - // run subpath through spiro - int sp_len = ip; - Spiro::spiro_run(path, sp_len, *curve); - ip = 0; - } - - g_free (path); -} - -//Unimos todas las curvas en juego y llamamos a la función doEffect. - -static void bspline(SPPenContext *const pc, bool shift) -{ if(!pc->anchor_statusbar) - shift?bsplineOff(pc):bsplineOn(pc); + shift?bspline_spiro_off(pc):bspline_spiro_on(pc); - bspline_build(pc); + bspline_spiro_build(pc); } -static void bsplineOn(SPPenContext *const pc){ +static void bspline_spiro_on(SPPenContext *const pc) +{ if(!pc->red_curve->is_empty()){ using Geom::X; using Geom::Y; @@ -1990,7 +1542,7 @@ static void bsplineOn(SPPenContext *const pc){ } } -static void bsplineOff(SPPenContext *const pc) +static void bspline_spiro_off(SPPenContext *const pc) { if(!pc->red_curve->is_empty()){ pc->npoints = 5; @@ -2000,18 +1552,21 @@ static void bsplineOff(SPPenContext *const pc) } } -static void bsplineStartAnchor(SPPenContext *const pc, bool shift) +static void bspline_spiro_start_anchor(SPPenContext *const pc, bool shift) { + if(!pc->spiro && !pc->bspline) + return; + if(pc->sa->curve->is_empty()) return; if(shift) - bsplineStartAnchorOff(pc); + bspline_spiro_start_anchor_off(pc); else - bsplineStartAnchorOn(pc); + bspline_spiro_start_anchor_on(pc); } -static void bsplineStartAnchorOn(SPPenContext *const pc) +static void bspline_spiro_start_anchor_on(SPPenContext *const pc) { using Geom::X; using Geom::Y; @@ -2047,7 +1602,7 @@ static void bsplineStartAnchorOn(SPPenContext *const pc) pc->sa->curve = tmpCurve; } -static void bsplineStartAnchorOff(SPPenContext *const pc) +static void bspline_spiro_start_anchor_off(SPPenContext *const pc) { SPCurve *tmpCurve = new SPCurve(); tmpCurve = pc->sa->curve->copy(); @@ -2075,7 +1630,10 @@ static void bsplineStartAnchorOff(SPPenContext *const pc) } -static void bsplineMotion(SPPenContext *const pc, bool shift){ +static void bspline_spiro_motion(SPPenContext *const pc, bool shift){ + if(!pc->spiro && !pc->bspline) + return; + using Geom::X; using Geom::Y; SPCurve *tmpCurve = new SPCurve(); @@ -2097,18 +1655,22 @@ static void bsplineMotion(SPPenContext *const pc, bool shift){ if(!tmpCurve->is_empty() && !pc->red_curve->is_empty()){ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); if(cubic){ - SPCurve * WPower = new SPCurve(); - Geom::D2< Geom::SBasis > SBasisWPower; - WPower->moveto(tmpCurve->last_segment()->finalPoint()); - WPower->lineto(tmpCurve->last_segment()->initialPoint()); - float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment()); - WPower->reset(); - WPower->moveto(pc->red_curve->last_segment()->initialPoint()); - WPower->lineto(pc->red_curve->last_segment()->finalPoint()); - SBasisWPower = WPower->first_segment()->toSBasis(); - WPower->reset(); - pc->p[1] = SBasisWPower.valueAt(WP); - pc->p[1] = Geom::Point(pc->p[1][X] + 0.0625,pc->p[1][Y] + 0.0625); + if(pc->bspline){ + SPCurve * WPower = new SPCurve(); + Geom::D2< Geom::SBasis > SBasisWPower; + WPower->moveto(tmpCurve->last_segment()->finalPoint()); + WPower->lineto(tmpCurve->last_segment()->initialPoint()); + float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment()); + WPower->reset(); + WPower->moveto(pc->red_curve->last_segment()->initialPoint()); + WPower->lineto(pc->red_curve->last_segment()->finalPoint()); + SBasisWPower = WPower->first_segment()->toSBasis(); + WPower->reset(); + pc->p[1] = SBasisWPower.valueAt(WP); + pc->p[1] = Geom::Point(pc->p[1][X] + 0.0625,pc->p[1][Y] + 0.0625); + }else{ + pc->p[1] = (*cubic)[3] + (Geom::Point)((*cubic)[3] - (*cubic)[2] ); + } }else{ pc->p[1] = pc->p[0]; } @@ -2116,16 +1678,17 @@ static void bsplineMotion(SPPenContext *const pc, bool shift){ if(pc->anchor_statusbar && !pc->red_curve->is_empty()){ if(shift) - bsplineEndAnchorOff(pc); + bspline_spiro_end_anchor_off(pc); else - bsplineEndAnchorOn(pc); + bspline_spiro_end_anchor_on(pc); } - bspline_build(pc); + bspline_spiro_build(pc); } -static void bsplineEndAnchorOn(SPPenContext *const pc) +static void bspline_spiro_end_anchor_on(SPPenContext *const pc) { + using Geom::X; using Geom::Y; pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); @@ -2136,8 +1699,12 @@ static void bsplineEndAnchorOn(SPPenContext *const pc) if(!pc->sa || pc->sa->curve->is_empty()){ tmpCurve = pc->green_curve->create_reverse(); Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); - C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + if(pc->bspline){ + C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); + C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + }else{ + C = pc->p[3] + (Geom::Point)(pc->p[3] - pc->p[2] ); + } if(cubic){ lastSeg->moveto((*cubic)[0]); lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); @@ -2161,8 +1728,12 @@ static void bsplineEndAnchorOn(SPPenContext *const pc) if(!pc->sa->start) tmpCurve = tmpCurve->create_reverse(); Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); - C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); - C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + if(pc->bspline){ + C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); + C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + }else{ + C = pc->p[3] + (Geom::Point)(pc->p[3] - pc->p[2] ); + } if(cubic){ lastSeg->moveto((*cubic)[0]); lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); @@ -2186,8 +1757,9 @@ static void bsplineEndAnchorOn(SPPenContext *const pc) } } -static void bsplineEndAnchorOff(SPPenContext *const pc) +static void bspline_spiro_end_anchor_off(SPPenContext *const pc) { + pc->p[2] = pc->p[3]; SPCurve *tmpCurve = new SPCurve(); SPCurve *lastSeg = new SPCurve(); @@ -2236,8 +1808,11 @@ static void bsplineEndAnchorOff(SPPenContext *const pc) //preparates the curves for its trasformation into BSline curves. -static void bspline_build(SPPenContext *const pc) +static void bspline_spiro_build(SPPenContext *const pc) { + if(!pc->spiro && !pc->bspline) + return; + //We create the base curve SPCurve *curve = new SPCurve(); //If we continuate the existing curve we add it at the start @@ -2271,7 +1846,10 @@ static void bspline_build(SPPenContext *const pc) //LivePathEffectObject *lpeobj = static_cast<LivePathEffectObject*> (curve); //Effect *spr = static_cast<Effect*> ( new LPEbspline(lpeobj) ); //spr->doEffect(curve); - bspline_doEffect(curve); + if(pc->bspline) + bspline_doEffect(curve); + else + spiro_doEffect(curve); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->blue_bpath), curve); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(pc->blue_bpath), pc->blue_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_item_show(pc->blue_bpath); @@ -2311,7 +1889,6 @@ static void bspline_doEffect(SPCurve * curve) //Esto hace que la curva BSpline no pierda su condición aunque se trasladen //dichos manejadores SPCurve *nCurve = new SPCurve(); - Geom::Point startNode(0,0); Geom::Point previousNode(0,0); Geom::Point node(0,0); Geom::Point pointAt1(0,0); @@ -2323,63 +1900,19 @@ static void bspline_doEffect(SPCurve * curve) Geom::D2< Geom::SBasis > SBasisOut; Geom::D2< Geom::SBasis > SBasisHelper; Geom::CubicBezier const *cubic = NULL; - //Si la curva está cerrada calculamos el punto donde - //deveria estar el nodo BSpline de cierre/inicio de la curva - //en posible caso de que se cierre con una linea recta creando un nodo BSPline - if (path_it->closed()) { - //Calculamos el nodo de inicio BSpline - const Geom::Curve &closingline = path_it->back_closed(); + // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength. + const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment. if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors... + // the closing line segment has zero-length. So stop before that one! curve_endit = path_it->end_open(); } - - SPCurve * in = new SPCurve(); - in->moveto(curve_it1->initialPoint()); - in->lineto(curve_it1->finalPoint()); - SBasisIn = in->first_segment()->toSBasis(); - - SPCurve *lineHelper = new SPCurve(); - cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); - if(cubic){ - lineHelper->moveto(SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()))); - }else{ - lineHelper->moveto(in->first_segment()->initialPoint()); - } - in->reset(); - delete in; - - SPCurve * end = new SPCurve(); - end->moveto(curve_endit->initialPoint()); - end->lineto(curve_endit->finalPoint()); - Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); - //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit); - cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit); - if(cubic){ - lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); - }else{ - lineHelper->lineto(end->first_segment()->finalPoint()); - } - end->reset(); - delete end; - SBasisHelper = lineHelper->first_segment()->toSBasis(); - lineHelper->reset(); - delete lineHelper; - //Guardamos el principio de la curva - startNode = SBasisHelper.valueAt(0.5); - //Definimos el punto de inicio original de la curva resultante - node = startNode; - }else{ - //Guardamos el principio de la curva - SPCurve * in = new SPCurve(); - in->moveto(curve_it1->initialPoint()); - in->lineto(curve_it1->finalPoint()); - startNode = in->first_segment()->initialPoint(); - in->reset(); - delete in; - //Definimos el punto de inicio original de la curva resultante - node = startNode; } + //Si la curva está cerrada calculamos el punto donde + //deveria estar el nodo BSpline de cierre/inicio de la curva + //en posible caso de que se cierre con una linea recta creando un nodo BSPline + //Recorremos todos los segmentos menos el último while ( curve_it2 != curve_endit ) { @@ -2448,13 +1981,54 @@ static void bspline_doEffect(SPCurve * curve) curveHelper->moveto(node); //Si está cerrada la curva, la cerramos sobre el valor guardado previamente //Si no finalizamos en el punto final + Geom::Point startNode(0,0); if (path_it->closed()) { + SPCurve * start = new SPCurve(); + start->moveto(path_it->begin()->initialPoint()); + start->lineto(path_it->begin()->finalPoint()); + Geom::D2< Geom::SBasis > SBasisStart = start->first_segment()->toSBasis(); + SPCurve *lineHelper = new SPCurve(); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*path_it->begin()); + if(cubic){ + lineHelper->moveto(SBasisStart.valueAt(Geom::nearest_point((*cubic)[1],*start->first_segment()))); + }else{ + lineHelper->moveto(start->first_segment()->initialPoint()); + } + start->reset(); + delete start; + + SPCurve * end = new SPCurve(); + end->moveto(curve_it1->initialPoint()); + end->lineto(curve_it1->finalPoint()); + Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); + //Geom::BezierCurve const *bezier = dynamic_cast<Geom::BezierCurve const*>(&*curve_endit); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); + }else{ + lineHelper->lineto(end->first_segment()->finalPoint()); + } + end->reset(); + delete end; + SBasisHelper = lineHelper->first_segment()->toSBasis(); + lineHelper->reset(); + delete lineHelper; + //Guardamos el principio de la curva + startNode = SBasisHelper.valueAt(0.5); curveHelper->curveto(nextPointAt1, nextPointAt2, startNode); + nCurve->append_continuous(curveHelper, 0.0625); + nCurve->move_endpoints(startNode,startNode); }else{ + SPCurve * start = new SPCurve(); + start->moveto(path_it->begin()->initialPoint()); + start->lineto(path_it->begin()->finalPoint()); + startNode = start->first_segment()->initialPoint(); + start->reset(); + delete start; curveHelper->curveto(nextPointAt1, nextPointAt2, nextPointAt3); + nCurve->append_continuous(curveHelper, 0.0625); + nCurve->move_endpoints(startNode,nextPointAt3); } - //añadimos este último segmento - nCurve->append_continuous(curveHelper, 0.0625); curveHelper->reset(); delete curveHelper; //y cerramos la curva @@ -2466,6 +2040,118 @@ static void bspline_doEffect(SPCurve * curve) delete nCurve; } } + +//Spiro function cloned from lpe-spiro.cpp +static void spiro_doEffect(SPCurve * curve) +{ + using Geom::X; + using Geom::Y; + + // Make copy of old path as it is changed during processing + Geom::PathVector const original_pathv = curve->get_pathvector(); + guint len = curve->get_segment_count() + 2; + + curve->reset(); + Spiro::spiro_cp *path = g_new (Spiro::spiro_cp, len); + int ip = 0; + + for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { + if (path_it->empty()) + continue; + + // start of path + { + Geom::Point p = path_it->front().pointAt(0); + path[ip].x = p[X]; + path[ip].y = p[Y]; + path[ip].ty = '{' ; // for closed paths, this is overwritten + ip++; + } + + // midpoints + Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve + Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve + + Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop + if (path_it->closed()) { + // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength. + const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment. + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors... + // the closing line segment has zero-length. So stop before that one! + curve_endit = path_it->end_open(); + } + } + + while ( curve_it2 != curve_endit ) + { + /* This deals with the node between curve_it1 and curve_it2. + * Loop to end_default (so without last segment), loop ends when curve_it2 hits the end + * and then curve_it1 points to end or closing segment */ + Geom::Point p = curve_it1->finalPoint(); + path[ip].x = p[X]; + path[ip].y = p[Y]; + + // Determine type of spiro node this is, determined by the tangents (angles) of the curves + // TODO: see if this can be simplified by using /helpers/geom-nodetype.cpp:get_nodetype + bool this_is_line = is_straight_curve(*curve_it1); + bool next_is_line = is_straight_curve(*curve_it2); + + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); + + if ( nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM ) + { + if (this_is_line && !next_is_line) { + path[ip].ty = ']'; + } else if (next_is_line && !this_is_line) { + path[ip].ty = '['; + } else { + path[ip].ty = 'c'; + } + } else { + path[ip].ty = 'v'; + } + + ++curve_it1; + ++curve_it2; + ip++; + } + + // add last point to the spiropath + Geom::Point p = curve_it1->finalPoint(); + path[ip].x = p[X]; + path[ip].y = p[Y]; + if (path_it->closed()) { + // curve_it1 points to the (visually) closing segment. determine the match between first and this last segment (the closing node) + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, path_it->front()); + switch (nodetype) { + case Geom::NODE_NONE: // can't happen! but if it does, it means the path isn't closed :-) + path[ip].ty = '}'; + ip++; + break; + case Geom::NODE_CUSP: + path[0].ty = path[ip].ty = 'v'; + break; + case Geom::NODE_SMOOTH: + case Geom::NODE_SYMM: + path[0].ty = path[ip].ty = 'c'; + break; + } + } else { + // set type to path closer + path[ip].ty = '}'; + ip++; + } + + // run subpath through spiro + int sp_len = ip; + Spiro::spiro_run(path, sp_len, *curve); + ip = 0; + } + + g_free (path); +} + //BSpline end static void spdc_pen_set_subsequent_point(SPPenContext *const pc, Geom::Point const p, bool statusbar, guint status) @@ -2569,12 +2255,7 @@ static void spdc_pen_finish_segment(SPPenContext *const pc, Geom::Point const p, ++pc->num_clicks; if (!pc->red_curve->is_empty()) { - if(pc->spiro){ - spiro(pc,(state & GDK_SHIFT_MASK)); - } - if(pc->bspline){ - bspline(pc,(state & GDK_SHIFT_MASK)); - } + bspline_spiro(pc,(state & GDK_SHIFT_MASK)); pc->green_curve->append_continuous(pc->red_curve, 0.0625); SPCurve *curve = pc->red_curve->copy(); /// \todo fixme: diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index 7445b0b75..48596cbc0 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -280,10 +280,10 @@ sp_guide_create_guides_around_page(SPDesktop *dt) { Geom::Point B(C[Geom::X], 0); Geom::Point D(0, C[Geom::Y]); - pts.push_back(std::make_pair<Geom::Point, Geom::Point>(A, B)); - pts.push_back(std::make_pair<Geom::Point, Geom::Point>(B, C)); - pts.push_back(std::make_pair<Geom::Point, Geom::Point>(C, D)); - pts.push_back(std::make_pair<Geom::Point, Geom::Point>(D, A)); + pts.push_back(std::pair<Geom::Point, Geom::Point>(A, B)); + pts.push_back(std::pair<Geom::Point, Geom::Point>(B, C)); + pts.push_back(std::pair<Geom::Point, Geom::Point>(C, D)); + pts.push_back(std::pair<Geom::Point, Geom::Point>(D, A)); sp_guide_pt_pairs_to_guides(doc, pts); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 7dc94c92f..fd368ed9f 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -20,6 +20,11 @@ #include "dialog-manager.h" #include <gtkmm/imagemenuitem.h> + +#if GTK_CHECK_VERSION(3,0,0) +# include <gdkmm/devicemanager.h> +#endif + #include "ui/widget/spinbutton.h" #include <glibmm/i18n.h> @@ -1784,7 +1789,15 @@ bool FilterEffectsDialog::PrimitiveList::on_draw_signal(const Cairo::RefPtr<Cair // Check mouse state int mx, my; Gdk::ModifierType mask; + +#if GTK_CHECK_VERSION(3,0,0) + Glib::RefPtr<Gdk::Display> display = get_bin_window()->get_display(); + Glib::RefPtr<Gdk::DeviceManager> dm = display->get_device_manager(); + Glib::RefPtr<const Gdk::Device> device = dm->get_client_pointer(); + get_bin_window()->get_device_position(device, mx, my, mask); +#else get_bin_window()->get_pointer(mx, my, mask); +#endif // Outline the bottom of the connection area const int outline_x = x + fheight * (row_count - row_index); diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index eec904ee4..be44794d0 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -1,6 +1,7 @@ /* Authors: * Jon A. Cruz * Abhishek Sharma + * Tavmjong Bah * * Copyright (C) 2010 Jon A. Cruz * Released under GNU GPL, read the file 'COPYING' for more information @@ -343,7 +344,8 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : 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); + sp_font_selector_set_fontspec( fsel, sp_font_selector_get_fontspec(fsel), 12.0 ); + gtk_widget_set_size_request (fontsel, 0, 150); g_signal_connect( G_OBJECT(fontsel), "font_set", G_CALLBACK(fontChangeCB), this ); @@ -520,6 +522,7 @@ void GlyphsPanel::setTargetDesktop(SPDesktop *desktop) } } +// Append selected glyphs to selected text void GlyphsPanel::insertText() { SPItem *textItem = 0; @@ -611,7 +614,7 @@ void GlyphsPanel::glyphSelectionChanged() calcCanInsert(); } -void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*font*/, GlyphsPanel *self) +void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, Glib::ustring /*fontspec*/, GlyphsPanel *self) { if (self) { self->rebuild(); @@ -667,7 +670,13 @@ void GlyphsPanel::readSelection( bool updateStyle, bool /*updateContent*/ ) void GlyphsPanel::rebuild() { - font_instance *font = fsel ? sp_font_selector_get_font(fsel) : 0; + Glib::ustring fontspec = fsel ? sp_font_selector_get_fontspec(fsel) : ""; + + font_instance* font = 0; + if( !fontspec.empty() ) { + font = font_factory::Default()->FaceFromFontSpecification( fontspec.c_str() ); + } + if (font) { //double sp_font_selector_get_size (SPFontSelector *fsel); diff --git a/src/ui/dialog/glyphs.h b/src/ui/dialog/glyphs.h index 162c7b296..6571af0a4 100644 --- a/src/ui/dialog/glyphs.h +++ b/src/ui/dialog/glyphs.h @@ -54,7 +54,7 @@ private: static GlyphColumns *getColumns(); - static void fontChangeCB(SPFontSelector *fontsel, font_instance *font, GlyphsPanel *self); + static void fontChangeCB(SPFontSelector *fontsel, Glib::ustring fontspec, GlyphsPanel *self); void rebuild(); diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 97cd28cdd..a71227861 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -8,8 +8,9 @@ * Johan Engelen <goejendaagh@zonnet.nl> * Abhishek Sharma * John Smith + * Tavmjong Bah * - * Copyright (C) 1999-2012 Authors + * Copyright (C) 1999-2013 Authors * Copyright (C) 2000-2001 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -32,6 +33,7 @@ extern "C" { #include <gtkmm/stock.h> #include <libnrtype/font-instance.h> #include <libnrtype/font-style-to-pos.h> +#include <libnrtype/font-lister.h> #include <xml/repr.h> #include "macros.h" @@ -305,18 +307,20 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ ) // FIXME: process result_family/style == QUERY_STYLE_MULTIPLE_DIFFERENT by showing "Many" in the lists - // Get a font_instance using the font-specification attribute stored in SPStyle if available - font_instance *font = font_factory::Default()->FaceFromStyle(query); + Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); - if (font) { + // This is done for us by text-toolbar. No need to do it twice. + // fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP )); + // fontlister->selection_update(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); - sp_font_selector_set_font (fsel, font, sp_style_css_size_px_to_units(query->font_size.computed, unit) ); - setPreviewText(font, phrase); - font->Unref(); - font=NULL; - } + Glib::ustring fontspec = fontlister->get_fontspec(); + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); + double size = sp_style_css_size_px_to_units(query->font_size.computed, unit); + sp_font_selector_set_fontspec(fsel, fontspec, size ); + + setPreviewText (fontspec, phrase); if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) { if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY) { @@ -351,30 +355,31 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ ) blocked = false; } -void TextEdit::setPreviewText (font_instance *font, Glib::ustring phrase) + +void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase) { - if (!font) { + if (font_spec.empty()) { return; } - char *desc = pango_font_description_to_string(font->descr); + Glib::ustring phrase_escaped = Glib::Markup::escape_text( phrase ); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); double pt_size = sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit) * PT_PER_PX; - gchar *const phrase_escaped = g_markup_escape_text(phrase.c_str(), -1); - // Pango font size is in 1024ths of a point - gchar *markup = g_strdup_printf("<span font=\"%s\" size=\"%d\">%s</span>", - desc, (int) (pt_size * PANGO_SCALE ), phrase_escaped); + // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE ); + std::ostringstream size_st; + size_st << pt_size * PANGO_SCALE; - preview_label.set_markup(markup); + Glib::ustring markup = "<span font=\"" + font_spec + + "\" size=\"" + size_st.str() + "\">" + phrase_escaped + "</span>"; - g_free(desc); - g_free(phrase_escaped); - g_free(markup); + preview_label.set_markup(markup.c_str()); } + SPItem *TextEdit::getSelectedTextItem (void) { if (!SP_ACTIVE_DESKTOP) @@ -430,34 +435,18 @@ void TextEdit::updateObjectText ( SPItem *text ) } } -SPCSSAttr *TextEdit::getTextStyle () +SPCSSAttr *TextEdit::fillTextStyle () { SPCSSAttr *css = sp_repr_css_attr_new (); - // font - font_instance *font = sp_font_selector_get_font (fsel); - - if ( font ) { - Glib::ustring fontName = font_factory::Default()->ConstructFontSpecification(font); - sp_repr_css_set_property (css, "-inkscape-font-specification", fontName.c_str()); - - gchar c[256]; - - font->Family(c, 256); - sp_repr_css_set_property (css, "font-family", c); - - font->Attribute( "weight", c, 256); - sp_repr_css_set_property (css, "font-weight", c); + Glib::ustring fontspec = sp_font_selector_get_fontspec (fsel); - font->Attribute("style", c, 256); - sp_repr_css_set_property (css, "font-style", c); + if( !fontspec.empty() ) { - font->Attribute("stretch", c, 256); - sp_repr_css_set_property (css, "font-stretch", c); - - font->Attribute("variant", c, 256); - sp_repr_css_set_property (css, "font-variant", c); + Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); + fontlister->fill_css( css, fontspec ); + // TODO, possibly move this to FontLister::set_css to be shared. Inkscape::CSSOStringStream os; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); @@ -467,9 +456,6 @@ SPCSSAttr *TextEdit::getTextStyle () os << sp_font_selector_get_size (fsel) << sp_style_get_css_unit_string(unit); } sp_repr_css_set_property (css, "font-size", os.str().c_str()); - - font->Unref(); - font=NULL; } // Layout @@ -505,7 +491,7 @@ SPCSSAttr *TextEdit::getTextStyle () void TextEdit::onSetDefault() { - SPCSSAttr *css = getTextStyle (); + SPCSSAttr *css = fillTextStyle (); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); blocked = true; @@ -525,7 +511,7 @@ void TextEdit::onApply() unsigned items = 0; const GSList *item_list = sp_desktop_selection(desktop)->itemList(); - SPCSSAttr *css = getTextStyle (); + SPCSSAttr *css = fillTextStyle (); sp_desktop_set_style(desktop, css, true); for (; item_list != NULL; item_list = item_list->next) { @@ -556,6 +542,13 @@ void TextEdit::onApply() } } + // Update FontLister + Glib::ustring fontspec = sp_font_selector_get_fontspec (fsel); + if( !fontspec.empty() ) { + Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); + fontlister->set_fontspec( fontspec, false ); + } + // complete the transaction DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Set text style")); @@ -577,11 +570,11 @@ void TextEdit::onTextChange (GtkTextBuffer *text_buffer, TextEdit *self) GtkTextIter end; gtk_text_buffer_get_bounds (text_buffer, &start, &end); gchar *str = gtk_text_buffer_get_text(text_buffer, &start, &end, TRUE); - font_instance *font = sp_font_selector_get_font(self->fsel); + Glib::ustring fontspec = sp_font_selector_get_fontspec(self->fsel); - if (font) { + if( !fontspec.empty() ) { const gchar *phrase = str && *str ? str : self->samplephrase.c_str(); - self->setPreviewText(font, phrase); + self->setPreviewText(fontspec, phrase); } else { self->preview_label.set_markup(""); } @@ -594,7 +587,7 @@ void TextEdit::onTextChange (GtkTextBuffer *text_buffer, TextEdit *self) self->setasdefault_button.set_sensitive ( true); } -void TextEdit::onFontChange(SPFontSelector * /*fontsel*/, font_instance * font, TextEdit *self) +void TextEdit::onFontChange(SPFontSelector * /*fontsel*/, gchar* fontspec, TextEdit *self) { GtkTextIter start, end; gchar *str; @@ -607,9 +600,9 @@ void TextEdit::onFontChange(SPFontSelector * /*fontsel*/, font_instance * font, gtk_text_buffer_get_bounds (self->text_buffer, &start, &end); str = gtk_text_buffer_get_text (self->text_buffer, &start, &end, TRUE); - if (font) { + if (fontspec) { const gchar *phrase = str && *str ? str : self->samplephrase.c_str(); - self->setPreviewText(font, phrase); + self->setPreviewText(fontspec, phrase); } else { self->preview_label.set_markup(""); } diff --git a/src/ui/dialog/text-edit.h b/src/ui/dialog/text-edit.h index bca6cee90..3fdeea05d 100644 --- a/src/ui/dialog/text-edit.h +++ b/src/ui/dialog/text-edit.h @@ -7,8 +7,9 @@ * Johan Engelen <goejendaagh@zonnet.nl> * John Smith * Kris De Gussem <Kris.DeGussem@gmail.com> + * Tavmjong Bah * - * Copyright (C) 1999-2012 Authors + * Copyright (C) 1999-2013 Authors * Copyright (C) 2000-2001 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -100,10 +101,10 @@ protected: * onFontChange updates the dialog UI. The subfunction setPreviewText updates the preview label. * * @param fontsel pointer to SPFontSelector (currently not used). - * @param font pointer to the font instance for the text to be previewed + * @param fontspec for the text to be previewed. * @param self pointer to the current instance of the dialog. */ - static void onFontChange (SPFontSelector *fontsel, font_instance *font, TextEdit *self); + static void onFontChange (SPFontSelector *fontsel, gchar* fontspec, TextEdit *self); /** * Get the selected text off the main canvas. @@ -118,15 +119,15 @@ protected: unsigned getSelectedTextCount (void); /** - * Helper function to create markup from a font definition and display in the preview label. + * Helper function to create markup from a fontspec and display in the preview label. * - * @param font pointer to the font instance for the text to be previewed + * @param fontspec for the text to be previewed * @param phrase text to be shown */ - void setPreviewText (font_instance *font, Glib::ustring phrase); + void setPreviewText (Glib::ustring font_spec, Glib::ustring phrase); void updateObjectText ( SPItem *text ); - SPCSSAttr *getTextStyle (); + SPCSSAttr *fillTextStyle (); /** * Helper function to style radio buttons with icons, tooltips. diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp index 59fe25fa1..453ef683f 100644 --- a/src/widgets/font-selector.cpp +++ b/src/widgets/font-selector.cpp @@ -8,10 +8,11 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Tavmjong Bah <tavmjong@free.fr> * * Copyright (C) 1999-2001 Ximian, Inc. * Copyright (C) 2002 Lauris Kaplinski - * Copyright (C) -2007 Authors + * Copyright (C) -2013 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -53,7 +54,7 @@ struct SPFontSelector NRStyleList styles; gfloat fontsize; bool fontsize_dirty; - font_instance *font; + Glib::ustring *fontspec; }; @@ -61,7 +62,7 @@ struct SPFontSelectorClass { GtkHBoxClass parent_class; - void (* font_set) (SPFontSelector *fsel, font_instance *font); + void (* font_set) (SPFontSelector *fsel, gchar *fontspec); }; enum { @@ -136,6 +137,9 @@ static void sp_font_selector_set_size_tooltip(SPFontSelector *fsel) } +/* + * Create a widget with children for selecting font-family, font-style, and font-size. + */ static void sp_font_selector_init(SPFontSelector *fsel) { gtk_box_set_homogeneous(GTK_BOX(fsel), TRUE); @@ -153,8 +157,6 @@ static void sp_font_selector_init(SPFontSelector *fsel) gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(f), sw); - Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); - fsel->family_treeview = gtk_tree_view_new (); GtkTreeViewColumn *column = gtk_tree_view_column_new (); GtkCellRenderer *cell = gtk_cell_renderer_text_new (); @@ -175,6 +177,7 @@ static void sp_font_selector_init(SPFontSelector *fsel) "widget \"*font_selector_family\" style \"fontfamily-separator-style\""); + Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); Glib::RefPtr<Gtk::ListStore> store = fontlister->get_font_list(); gtk_tree_view_set_model (GTK_TREE_VIEW(fsel->family_treeview), GTK_TREE_MODEL (Glib::unwrap (store))); gtk_container_add(GTK_CONTAINER(sw), fsel->family_treeview); @@ -229,6 +232,7 @@ static void sp_font_selector_init(SPFontSelector *fsel) gtk_widget_show(hb); gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, FALSE, 0); + // Font-size fsel->size = gtk_combo_box_text_new_with_entry (); sp_font_selector_set_size_tooltip(fsel); @@ -244,18 +248,20 @@ static void sp_font_selector_init(SPFontSelector *fsel) gtk_widget_show_all (fsel->size); + // Set default size... next two lines must match + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(fsel->size))), "18.0"); fsel->fontsize = 18.0; fsel->fontsize_dirty = false; - fsel->font = NULL; + + fsel->fontspec = new Glib::ustring; } static void sp_font_selector_dispose(GObject *object) { SPFontSelector *fsel = SP_FONT_SELECTOR (object); - if (fsel->font) { - fsel->font->Unref(); - fsel->font = NULL; + if (fsel->fontspec) { + delete fsel->fontspec; } if (fsel->families.length > 0) { @@ -273,46 +279,62 @@ static void sp_font_selector_dispose(GObject *object) } } +// Callback when family changed, updates style list for new family. static void sp_font_selector_family_select_row(GtkTreeSelection *selection, SPFontSelector *fsel) { - GtkTreeIter iter; - GtkTreeModel *model; - GtkListStore *store; - GtkTreePath *path; - GList *list=0; + // We need our own copy of the style list store since the font-family + // may not be the same in the font-selector as stored in the font-lister + // TODO: use font-lister class for this by modifying new_font_family to accept an optional style list + // TODO: add store to SPFontSelector struct and reuse. + + // Start by getting iterator to selected font + GtkTreeModel *model; + GtkTreeIter iter; if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_model_get (model, &iter, 1, &list, -1); + // Next get family name with its style list + gchar *family; + GList *list=0; + gtk_tree_model_get (model, &iter, 0, &family, 1, &list, -1); - store = gtk_list_store_new (1, G_TYPE_STRING); + // Find best style match for selected family with current style (e.g. of selected text). + Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); + Glib::ustring style = fontlister->get_font_style(); + Glib::ustring best = fontlister->get_best_style_match (family, style); + // Create our own store of styles for selected font-family and find index of best style match + int path_index = 0; + int index = 0; + GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); // Where is this deleted? for ( ; list ; list = list->next ) { gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, static_cast<char*>(list->data), -1); + gtk_list_store_set (store, &iter, 0, (char*)list->data, -1); + + if( best.compare( (char*)list->data ) == 0 ) { + path_index = index; + } + ++index; } + // Attach store to tree view. Can trigger style changed signal (but not FONT_SET): gtk_tree_view_set_model (GTK_TREE_VIEW (fsel->style_treeview), GTK_TREE_MODEL (store)); - path = gtk_tree_path_new (); - gtk_tree_path_append_index (path, 0); + + // Get path to best style + GtkTreePath *path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, path_index); + + // Highlight best style. Triggers style changed signal: gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path); gtk_tree_path_free (path); } +// Callback when row changed static void sp_font_selector_style_select_row (GtkTreeSelection *selection, SPFontSelector *fsel) { - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - - path = gtk_tree_model_get_path (model, &iter); - if (!fsel->block_emit) { sp_font_selector_emit_set (fsel); @@ -322,6 +344,7 @@ static void sp_font_selector_style_select_row (GtkTreeSelection *selection, /* * Set the default list of font sizes, scaled to the users preferred unit + * TODO: This routine occurs both here and in text-toolbar. Move to font-lister? */ static void sp_font_selector_set_sizes( SPFontSelector *fsel ) { @@ -348,6 +371,7 @@ static void sp_font_selector_set_sizes( SPFontSelector *fsel ) } +// Callback when size changed static void sp_font_selector_size_changed( GtkComboBox */*cbox*/, SPFontSelector *fsel ) { char *text = NULL; @@ -381,9 +405,13 @@ static void sp_font_selector_size_changed( GtkComboBox */*cbox*/, SPFontSelector sp_font_selector_emit_set (fsel); } + +// Called from sp_font_selector_style_select_row +// Called from sp_font_selector_size_changed +// Called indirectly for sp_font_selector_family_select_row (since style changes). +// Emits FONT_SET signal (handled by TextEdit::onFontChange, GlyphsPanel::fontChangeCB). static void sp_font_selector_emit_set (SPFontSelector *fsel) { - font_instance *font; GtkTreeSelection *selection_family; GtkTreeSelection *selection_style; @@ -398,41 +426,27 @@ static void sp_font_selector_emit_set (SPFontSelector *fsel) model_family = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->family_treeview)); if (!model_family) return; - model_style = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->style_treeview)); - if (!model_style) return; + model_style = gtk_tree_view_get_model (GTK_TREE_VIEW (fsel->style_treeview)); + if (!model_style ) return; selection_family = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)); - selection_style = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)); + selection_style = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview )); if (!gtk_tree_selection_get_selected (selection_family, NULL, &iter_family)) return; - if (!gtk_tree_selection_get_selected (selection_style, NULL, &iter_style)) return; + if (!gtk_tree_selection_get_selected (selection_style, NULL, &iter_style )) return; gtk_tree_model_get (model_family, &iter_family, 0, &family, -1); - gtk_tree_model_get (model_style, &iter_style, 0, &style, -1); + gtk_tree_model_get (model_style, &iter_style, 0, &style, -1); if ((!family) || (!style)) return; - font = (font_factory::Default())->FaceFromUIStrings (family, style); + Glib::ustring fontspec = family; + fontspec += ", "; + fontspec += style; - // FIXME: when a text object uses non-available font, font==NULL and we can't set size - // (and the size shown in the widget is invalid). To fix, here we must always get some - // default font, exactly the same as sptext uses for on-canvas display, so that - // font!=NULL ever. - if (font != fsel->font || ( font && fsel->fontsize_dirty ) ) { - if ( font ) { - font->Ref(); - } - if ( fsel->font ) { - fsel->font->Unref(); - } - fsel->font = font; - g_signal_emit(fsel, fs_signals[FONT_SET], 0, fsel->font); - } - fsel->fontsize_dirty = false; - if (font) { - font->Unref(); - } - font = NULL; + *(fsel->fontspec) = fontspec; + + g_signal_emit(fsel, fs_signals[FONT_SET], 0, fontspec.c_str()); } GtkWidget *sp_font_selector_new() @@ -442,116 +456,53 @@ GtkWidget *sp_font_selector_new() return GTK_WIDGET(fsel); } + /* - * Returns the index of the fonts closest style match from the provided list of styles - * Used in both the Text dialog and the Text toolbar to set the style combo on selection change + * Sets the values displayed in the font-selector from a fontspec. + * It is only called from TextEdit with a new selection and from GlyphsPanel */ -unsigned int sp_font_selector_get_best_style (font_instance *font, GList *list) +void sp_font_selector_set_fontspec (SPFontSelector *fsel, Glib::ustring fontspec, double size) { - if ( !font || !list) { - return 0; - } - - font_instance *tempFont = NULL; - unsigned int currentStyleNumber = 0; - unsigned int bestStyleNumber = 0; - - Glib::ustring family = font_factory::Default()->GetUIFamilyString(font->descr); - - PangoFontDescription *incomingFont = pango_font_description_copy(font->descr); - pango_font_description_unset_fields(incomingFont, PANGO_FONT_MASK_SIZE); - - char *incomingFontString = pango_font_description_to_string(incomingFont); - - tempFont = (font_factory::Default())->FaceFromUIStrings(family.c_str(), static_cast<char*>(list->data)); - - PangoFontDescription *bestMatchForFont = NULL; - if (tempFont) { - bestMatchForFont = pango_font_description_copy(tempFont->descr); - tempFont->Unref(); - tempFont = NULL; - } - - if( bestMatchForFont != NULL ) { - pango_font_description_unset_fields(bestMatchForFont, PANGO_FONT_MASK_SIZE); - } - - list = list->next; - - while (list) { - currentStyleNumber++; - - tempFont = font_factory::Default()->FaceFromUIStrings(family.c_str(), static_cast<char*>(list->data)); - - PangoFontDescription *currentMatchForFont = NULL; - if (tempFont) { - currentMatchForFont = pango_font_description_copy(tempFont->descr); - tempFont->Unref(); - tempFont = NULL; - } - - if (currentMatchForFont) { - pango_font_description_unset_fields(currentMatchForFont, PANGO_FONT_MASK_SIZE); - - char *currentMatchString = pango_font_description_to_string(currentMatchForFont); - - if (!strcmp(incomingFontString, currentMatchString) - || pango_font_description_better_match(incomingFont, bestMatchForFont, currentMatchForFont)) { - // Found a better match for the font we are looking for - pango_font_description_free(bestMatchForFont); - bestMatchForFont = pango_font_description_copy(currentMatchForFont); - bestStyleNumber = currentStyleNumber; - } - - g_free(currentMatchString); - - pango_font_description_free(currentMatchForFont); - } - - list = list->next; - } - - if (bestMatchForFont) - pango_font_description_free(bestMatchForFont); - if (incomingFont) - pango_font_description_free(incomingFont); - g_free(incomingFontString); + if (!fontspec.empty()) + { - return bestStyleNumber; -} + Inkscape::FontLister *font_lister = Inkscape::FontLister::get_instance(); + std::pair<Glib::ustring, Glib::ustring> ui = font_lister->ui_from_fontspec( fontspec ); + Glib::ustring family = ui.first; + Glib::ustring style = ui.second; -void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, double size) -{ - if (font) - { Gtk::TreePath path; - - Glib::ustring family = font_factory::Default()->GetUIFamilyString(font->descr); - try { - path = Inkscape::FontLister::get_instance()->get_row_for_font (family); + path = font_lister->get_row_for_font (family); } catch (...) { + g_warning( "Couldn't find row for font-family: %s", family.c_str() ); return; } + // High light selected family and scroll so it is in view. fsel->block_emit = TRUE; gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)), path.gobj()); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->family_treeview), path.gobj(), NULL, TRUE, 0.5, 0.5); - fsel->block_emit = FALSE; + fsel->block_emit = FALSE; // TODO: Should this be moved to the end? - GList *list = 0; - GtkTreeIter iter; - GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(fsel->family_treeview)); - gtk_tree_model_get_iter (model, &iter, path.gobj()); - gtk_tree_model_get (model, &iter, 1, &list, -1); - unsigned int bestStyleNumber = sp_font_selector_get_best_style(font, list); + // We don't need to get best style since this is only called on a new + // selection where we already know the "best" style. + // Glib::ustring bestStyle = font_lister->get_best_style_match (family, style); + // std::cout << "Best: " << bestStyle << std::endl; + + // The "trial" style list and the regular list are the same in this case. + Gtk::TreePath path_c; + try { + path_c = font_lister->get_row_for_style( style ); + } catch (...) { + g_warning( "Couldn't find row for style: %s (%s)", style.c_str(), family.c_str() ); + return; + } + + gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c.gobj()); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c.gobj(), NULL, TRUE, 0.5, 0.5); - GtkTreePath *path_c = gtk_tree_path_new (); - gtk_tree_path_append_index (path_c, bestStyleNumber); - gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c, NULL, TRUE, 0.5, 0.5); - if (size != fsel->fontsize) { gchar s[8]; @@ -565,13 +516,9 @@ void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, doubl } -font_instance* sp_font_selector_get_font(SPFontSelector *fsel) +Glib::ustring sp_font_selector_get_fontspec(SPFontSelector *fsel) { - if (fsel->font) { - fsel->font->Ref(); - } - - return fsel->font; + return *(fsel->fontspec); } /* diff --git a/src/widgets/font-selector.h b/src/widgets/font-selector.h index 80e8b1e4d..66715f048 100644 --- a/src/widgets/font-selector.h +++ b/src/widgets/font-selector.h @@ -7,9 +7,11 @@ * Authors: * Chris Lahey <clahey@ximian.com> * Lauris Kaplinski <lauris@kaplinski.com> + * Tavmjong Bah <tavmjong@free.fr> * * Copyright (C) 1999-2001 Ximian, Inc. * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 1999-2013 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -22,7 +24,24 @@ struct SPFontSelector; #define SP_FONT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_FONT_SELECTOR, SPFontSelector)) #define SP_IS_FONT_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_FONT_SELECTOR)) -class font_instance; +/* + * The routines here create and manage a font selector widget with three parts, + * one each for font-family, font-style, and font-size. + * + * It is used by the TextEdit and Glyphs panel dialogs. The FontLister class is used + * to access the list of font-families and their associated styles for fonts either + * on the system or in the document. The FontLister class is also used by the Text + * toolbar. Fonts are kept track of by their "fontspecs" which are the same as the + * strings that Pango generates. + * + * The main functions are: + * Create the font-seletor widget. + * Update the lists when a new text selection is made. + * Update the Style list when a new font-family is selected, highlighting the + * best match to the original font style (as not all fonts have the same style options). + * Emit a signal when any change is made so that the Text Preview can be updated. + * Provide the currently selected values. + */ /* SPFontSelector */ @@ -30,13 +49,11 @@ GType sp_font_selector_get_type (void); GtkWidget *sp_font_selector_new (void); -void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, double size); +void sp_font_selector_set_fontspec (SPFontSelector *fsel, Glib::ustring fontspec, double size); +Glib::ustring sp_font_selector_get_fontspec (SPFontSelector *fsel); -font_instance *sp_font_selector_get_font (SPFontSelector *fsel); double sp_font_selector_get_size (SPFontSelector *fsel); -unsigned int sp_font_selector_get_best_style (font_instance *font, GList *list); - #endif // SP_FONT_SELECTOR_H /* diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index cc6d02ea8..ef7d31d76 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -18,8 +18,8 @@ * * Copyright (C) 2004 David Turner * Copyright (C) 2003 MenTaLguY - * Copyright (C) 1999-2013 authors * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 1999-2013 authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -170,7 +170,7 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb // active text set in sp_text_toolbox_selection_changed() SPCSSAttr *css = sp_repr_css_attr_new (); - fontlister->set_css( css ); + fontlister->fill_css( css ); SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, true); // Results in selection change called twice. @@ -272,7 +272,7 @@ static void sp_text_fontstyle_value_changed( Ink_ComboBoxEntry_Action *act, GObj // active text set in sp_text_toolbox_seletion_changed() SPCSSAttr *css = sp_repr_css_attr_new (); - fontlister->set_css( css ); + fontlister->fill_css( css ); SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, true); |
