diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2016-06-11 15:34:03 +0000 |
|---|---|---|
| committer | jabiertxof <info@marker.es> | 2016-06-11 15:34:03 +0000 |
| commit | d6b2e2cdeb563026cc9f4633e687a607b095da87 (patch) | |
| tree | b25e3e95e5e96782232e65d0d9889fcb12c2f285 /src | |
| parent | Fixing satellites bug on erase (diff) | |
| parent | A little cleaning up of attributes. (diff) | |
| download | inkscape-d6b2e2cdeb563026cc9f4633e687a607b095da87.tar.gz inkscape-d6b2e2cdeb563026cc9f4633e687a607b095da87.zip | |
update to trunk
(bzr r13645.1.147)
Diffstat (limited to 'src')
47 files changed, 614 insertions, 348 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index df25728f4..cf5130317 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -513,17 +513,6 @@ add_library(inkscape_base SHARED ${inkscape_SRC} ${sp_SRC}) add_executable(inkscape ${main_SRC} ) add_executable(inkview inkview.cpp ) - - -if(UNIX) -# message after building. -add_custom_command( - TARGET inkscape - POST_BUILD MAIN_DEPENDENCY inkscape - COMMAND ${CMAKE_COMMAND} -E echo 'now run: \"make install\" to copy runtime files & scripts to ${CMAKE_INSTALL_PREFIX}' -) -endif() - add_dependencies(inkscape inkscape_version) if(WITH_DBUS) diff --git a/src/attributes-test.h b/src/attributes-test.h index b8d5d98a5..bfb67064b 100644 --- a/src/attributes-test.h +++ b/src/attributes-test.h @@ -104,21 +104,6 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"end", true}, {"exponent", true}, {"externalResourcesRequired", false}, - {"feBlend", false}, - {"feColorMatrix", false}, - {"feComponentTransfer", false}, - {"feComposite", false}, - {"feConvolveMatrix", false}, - {"feDiffuseLighting", false}, - {"feDisplacementMap", false}, - {"feFlood", false}, - {"feGaussianBlur", false}, - {"feImage", false}, - {"feMerge", false}, - {"feMorphology", false}, - {"feOffset", false}, - {"feSpecularLighting", false}, - {"feTile", false}, {"fill", true}, {"fill-opacity", true}, {"fill-rule", true}, @@ -361,55 +346,33 @@ struct {char const *attr; bool supported;} const all_attrs[] = { /* Extra attributes. */ {"id", true}, + {"sodipodi:docname", true}, + {"sodipodi:insensitive", true}, + {"sodipodi:type", true}, {"inkscape:collect", true}, {"inkscape:document-units", true}, {"inkscape:label", true}, - {"sodipodi:insensitive", true}, - {"sodipodi:nonprintable", true}, {"inkscape:groupmode", true}, - {"sodipodi:version", false}, {"inkscape:version", true}, {"inkscape:object-paths", true}, - {"inkscape:snap-perpendicular", true}, - {"inkscape:snap-tangential", true}, - {"inkscape:snap-path-clip", true}, - {"inkscape:snap-path-mask", true}, - {"inkscape:object-nodes", true}, - {"inkscape:bbox-paths", true}, - {"inkscape:bbox-nodes", true}, - {"inkscape:snap-page", true}, - {"inkscape:snap-global", true}, - {"inkscape:snap-bbox", true}, - {"inkscape:snap-nodes", true}, - {"inkscape:snap-others", true}, - {"inkscape:snap-center", true}, - {"inkscape:snap-smooth-nodes", true}, - {"inkscape:snap-midpoints", true}, - {"inkscape:snap-object-midpoints", true}, - {"inkscape:snap-text-baseline", true}, - {"inkscape:snap-bbox-edge-midpoints", true}, - {"inkscape:snap-bbox-midpoints", true}, - {"inkscape:snap-grids", true}, - {"inkscape:snap-to-guides", true}, - {"inkscape:snap-intersection-paths", true}, + {"inkscape:original-d", true}, {"inkscape:pageopacity", true}, {"inkscape:pageshadow", true}, {"inkscape:path-effect", true}, + // SPItem {"inkscape:transform-center-x", true}, {"inkscape:transform-center-y", true}, {"inkscape:highlight-color", true}, - // Namedview - {"inkscape:zoom", true}, - {"inkscape:cx", true}, - {"inkscape:cy", true}, - {"inkscape:window-width", true}, - {"inkscape:window-height", true}, - {"inkscape:window-x", true}, - {"inkscape:window-y", true}, - {"inkscape:window-maximized", true}, - {"inkscape:current-layer", true}, + + // Measure tool + {"inkscape:measure-start", true}, + {"inkscape:measure-end", true}, + + // Spray tool + {"inkscape:spray-origin", true}, + // Connector tool {"inkscape:connector-type", true}, {"inkscape:connection-start", true}, @@ -420,11 +383,13 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:connector-curvature", true}, {"inkscape:connector-avoid", true}, {"inkscape:connector-spacing", true}, + // Ellipse, Spiral, Star {"sodipodi:cx", true}, {"sodipodi:cy", true}, {"sodipodi:rx", true}, {"sodipodi:ry", true}, + // Box tool {"inkscape:perspectiveID", true}, {"inkscape:corner0", true}, @@ -435,6 +400,7 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:vp_y", true}, {"inkscape:vp_z", true}, {"inkscape:persp3d-origin", true}, + // Star tool {"sodipodi:start", true}, {"sodipodi:end", true}, @@ -517,8 +483,47 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"borderopacity", true}, {"pagecolor", true}, + {"inkscape:zoom", true}, + {"inkscape:cx", true}, + {"inkscape:cy", true}, + {"inkscape:window-width", true}, + {"inkscape:window-height", true}, + {"inkscape:window-x", true}, + {"inkscape:window-y", true}, + {"inkscape:window-maximized", true}, + {"inkscape:current-layer", true}, + {"inkscape:pagecheckerboard", true}, + /* SPGuide */ {"position", true}, + {"inkscape:color", true}, + {"inkscape:lockguides", true}, + {"inkscape:locked", true}, + + /* Snapping */ + {"inkscape:snap-perpendicular", true}, + {"inkscape:snap-tangential", true}, + {"inkscape:snap-path-clip", true}, + {"inkscape:snap-path-mask", true}, + {"inkscape:object-nodes", true}, + {"inkscape:bbox-paths", true}, + {"inkscape:bbox-nodes", true}, + {"inkscape:snap-page", true}, + {"inkscape:snap-global", true}, + {"inkscape:snap-bbox", true}, + {"inkscape:snap-nodes", true}, + {"inkscape:snap-others", true}, + {"inkscape:snap-from-guide", true}, + {"inkscape:snap-center", true}, + {"inkscape:snap-smooth-nodes", true}, + {"inkscape:snap-midpoints", true}, + {"inkscape:snap-object-midpoints", true}, + {"inkscape:snap-text-baseline", true}, + {"inkscape:snap-bbox-edge-midpoints", true}, + {"inkscape:snap-bbox-midpoints", true}, + {"inkscape:snap-grids", true}, + {"inkscape:snap-to-guides", true}, + {"inkscape:snap-intersection-paths", true}, /* SPTag */ {"inkscape:expanded", true} diff --git a/src/attributes.cpp b/src/attributes.cpp index 646c2ab0c..24c16d5fc 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -14,6 +14,7 @@ #include <glib.h> // g_assert() #include "attributes.h" +#include <iostream> typedef struct { gint code; @@ -28,15 +29,24 @@ static SPStyleProp const props[] = { {SP_ATTR_INVALID, NULL}, /* SPObject */ {SP_ATTR_ID, "id"}, + {SP_ATTR_STYLE, "style"}, {SP_ATTR_INKSCAPE_COLLECT, "inkscape:collect"}, {SP_ATTR_INKSCAPE_LABEL, "inkscape:label"}, + /* SPRoot */ + {SP_ATTR_VERSION, "version"}, + {SP_ATTR_INKSCAPE_VERSION, "inkscape:version"}, + {SP_ATTR_WIDTH, "width"}, + {SP_ATTR_HEIGHT, "height"}, + {SP_ATTR_VIEWBOX, "viewBox"}, + {SP_ATTR_PRESERVEASPECTRATIO, "preserveAspectRatio"}, + {SP_ATTR_ONLOAD, "onload"}, + {SP_ATTR_SODIPODI_DOCNAME, "sodipodi:docname"}, /* SPItem */ {SP_ATTR_TRANSFORM, "transform"}, + {SP_ATTR_SODIPODI_TYPE, "sodipodi:type"}, {SP_ATTR_SODIPODI_INSENSITIVE, "sodipodi:insensitive"}, - {SP_ATTR_SODIPODI_NONPRINTABLE, "sodipodi:nonprintable"}, {SP_ATTR_CONNECTOR_AVOID, "inkscape:connector-avoid"}, {SP_ATTR_CONNECTION_POINTS, "inkscape:connection-points"}, - {SP_ATTR_STYLE, "style"}, {SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"}, {SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"}, {SP_ATTR_INKSCAPE_PATH_EFFECT, "inkscape:path-effect"}, @@ -53,14 +63,6 @@ static SPStyleProp const props[] = { {SP_ATTR_TARGET, "target"}, {SP_ATTR_INKSCAPE_GROUPMODE, "inkscape:groupmode"}, {SP_ATTR_INKSCAPE_EXPANDED, "inkscape:expanded"}, - /* SPRoot */ - {SP_ATTR_VERSION, "version"}, - {SP_ATTR_WIDTH, "width"}, - {SP_ATTR_HEIGHT, "height"}, - {SP_ATTR_VIEWBOX, "viewBox"}, - {SP_ATTR_PRESERVEASPECTRATIO, "preserveAspectRatio"}, - {SP_ATTR_INKSCAPE_VERSION, "inkscape:version"}, - {SP_ATTR_ONLOAD, "onload"}, /* SPNamedView */ {SP_ATTR_VIEWONLY, "viewonly"}, {SP_ATTR_SHOWGUIDES, "showguides"}, @@ -99,6 +101,7 @@ static SPStyleProp const props[] = { {SP_ATTR_INKSCAPE_SNAP_BBOX, "inkscape:snap-bbox"}, {SP_ATTR_INKSCAPE_SNAP_NODE, "inkscape:snap-nodes"}, {SP_ATTR_INKSCAPE_SNAP_OTHERS, "inkscape:snap-others"}, + {SP_ATTR_INKSCAPE_SNAP_FROM_GUIDE, "inkscape:snap-from-guide"}, {SP_ATTR_INKSCAPE_SNAP_ROTATION_CENTER, "inkscape:snap-center"}, {SP_ATTR_INKSCAPE_SNAP_GRID, "inkscape:snap-grids"}, {SP_ATTR_INKSCAPE_SNAP_GUIDE, "inkscape:snap-to-guides"}, @@ -120,7 +123,6 @@ static SPStyleProp const props[] = { {SP_ATTR_INKSCAPE_DOCUMENT_UNITS, "inkscape:document-units"}, // This setting sets the Display units, *not* the units used in SVG {SP_ATTR_INKSCAPE_LOCKGUIDES, "inkscape:lockguides"}, {SP_ATTR_UNITS, "units"}, - {SP_ATTR_INKSCAPE_CONNECTOR_SPACING, "inkscape:connector-spacing"}, /* SPColorProfile */ {SP_ATTR_LOCAL, "local"}, {SP_ATTR_NAME, "name"}, @@ -130,6 +132,9 @@ static SPStyleProp const props[] = { {SP_ATTR_POSITION, "position"}, {SP_ATTR_INKSCAPE_COLOR, "inkscape:color"}, {SP_ATTR_INKSCAPE_LOCKED, "inkscape:locked"}, + /* Measure tool */ + {SP_ATTR_INKSCAPE_MEASURE_START, "inkscape:measure-start"}, + {SP_ATTR_INKSCAPE_MEASURE_END, "inkscape:measure-end"}, /* SPImage */ {SP_ATTR_X, "x"}, {SP_ATTR_Y, "y"}, @@ -139,6 +144,7 @@ static SPStyleProp const props[] = { /* (Note: XML representation of connectors may change in future.) */ {SP_ATTR_CONNECTOR_TYPE, "inkscape:connector-type"}, {SP_ATTR_CONNECTOR_CURVATURE, "inkscape:connector-curvature"}, + {SP_ATTR_INKSCAPE_CONNECTOR_SPACING, "inkscape:connector-spacing"}, {SP_ATTR_CONNECTION_START, "inkscape:connection-start"}, {SP_ATTR_CONNECTION_END, "inkscape:connection-end"}, {SP_ATTR_CONNECTION_START_POINT, "inkscape:connection-start-point"}, @@ -544,6 +550,8 @@ sp_attribute_lookup(gchar const *key) if(g_str_equal(const_cast<void *>(static_cast<void const *>(props[i].name)), key)) return GPOINTER_TO_UINT(GINT_TO_POINTER(props[i].code)); } + // std::cerr << "sp_attribute_lookup: invalid attribute: " + // << (key?key:"Null") << std::endl; return SP_ATTR_INVALID; } diff --git a/src/attributes.h b/src/attributes.h index f5544d0a1..e82db5f2a 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -28,15 +28,24 @@ enum SPAttributeEnum { SP_ATTR_INVALID, ///< Must have value 0. /* SPObject */ SP_ATTR_ID, + SP_ATTR_STYLE, SP_ATTR_INKSCAPE_COLLECT, SP_ATTR_INKSCAPE_LABEL, + /* SPRoot Put these near top as the apply to the entire SVG */ + SP_ATTR_VERSION, + SP_ATTR_INKSCAPE_VERSION, + SP_ATTR_WIDTH, + SP_ATTR_HEIGHT, + SP_ATTR_VIEWBOX, + SP_ATTR_PRESERVEASPECTRATIO, + SP_ATTR_ONLOAD, + SP_ATTR_SODIPODI_DOCNAME, /* SPItem */ SP_ATTR_TRANSFORM, + SP_ATTR_SODIPODI_TYPE, SP_ATTR_SODIPODI_INSENSITIVE, - SP_ATTR_SODIPODI_NONPRINTABLE, SP_ATTR_CONNECTOR_AVOID, SP_ATTR_CONNECTION_POINTS, - SP_ATTR_STYLE, SP_ATTR_TRANSFORM_CENTER_X, SP_ATTR_TRANSFORM_CENTER_Y, SP_ATTR_INKSCAPE_PATH_EFFECT, @@ -54,14 +63,6 @@ enum SPAttributeEnum { /* SPGroup */ SP_ATTR_INKSCAPE_GROUPMODE, SP_ATTR_INKSCAPE_EXPANDED, - /* SPRoot */ - SP_ATTR_VERSION, - SP_ATTR_WIDTH, - SP_ATTR_HEIGHT, - SP_ATTR_VIEWBOX, - SP_ATTR_PRESERVEASPECTRATIO, - SP_ATTR_INKSCAPE_VERSION, - SP_ATTR_ONLOAD, /* SPNamedView */ SP_ATTR_VIEWONLY, SP_ATTR_SHOWGUIDES, @@ -100,7 +101,7 @@ enum SPAttributeEnum { SP_ATTR_INKSCAPE_SNAP_BBOX, SP_ATTR_INKSCAPE_SNAP_NODE, SP_ATTR_INKSCAPE_SNAP_OTHERS, - //SP_ATTR_INKSCAPE_SNAP_FROM_GUIDE, + SP_ATTR_INKSCAPE_SNAP_FROM_GUIDE, SP_ATTR_INKSCAPE_SNAP_ROTATION_CENTER, SP_ATTR_INKSCAPE_SNAP_GRID, SP_ATTR_INKSCAPE_SNAP_GUIDE, @@ -122,7 +123,6 @@ enum SPAttributeEnum { SP_ATTR_INKSCAPE_DOCUMENT_UNITS, SP_ATTR_INKSCAPE_LOCKGUIDES, SP_ATTR_UNITS, - SP_ATTR_INKSCAPE_CONNECTOR_SPACING, /* SPColorProfile */ SP_ATTR_LOCAL, SP_ATTR_NAME, @@ -132,7 +132,10 @@ enum SPAttributeEnum { SP_ATTR_POSITION, SP_ATTR_INKSCAPE_COLOR, SP_ATTR_INKSCAPE_LOCKED, - /* SPImage */ + /* Measure tool */ + SP_ATTR_INKSCAPE_MEASURE_START, + SP_ATTR_INKSCAPE_MEASURE_END, + /* SPImage, SPRect, etc. */ SP_ATTR_X, SP_ATTR_Y, /* SPPath */ @@ -140,6 +143,7 @@ enum SPAttributeEnum { SP_ATTR_INKSCAPE_ORIGINAL_D, SP_ATTR_CONNECTOR_TYPE, SP_ATTR_CONNECTOR_CURVATURE, + SP_ATTR_INKSCAPE_CONNECTOR_SPACING, SP_ATTR_CONNECTION_START, SP_ATTR_CONNECTION_END, SP_ATTR_CONNECTION_START_POINT, @@ -334,6 +338,7 @@ enum SPAttributeEnum { SP_ATTR_RESTART, SP_ATTR_REPEATCOUNT, SP_ATTR_REPEATDUR, + /* Interpolating animations */ SP_ATTR_CALCMODE, //SP_ATTR_VALUES, diff --git a/src/color-profile.cpp b/src/color-profile.cpp index 523026aa5..9e545df03 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -705,7 +705,16 @@ gint Inkscape::CMSSystem::getChannelCount(ColorProfile const *profile) #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -std::vector<Glib::ustring> ColorProfile::getBaseProfileDirs() { +// sort home dir before the rest, and alphabetically oterhwise +bool compareProfileBoolPair(const std::pair<Glib::ustring, bool> & a, const std::pair<Glib::ustring, bool> & b) +{ + if (a.second != b.second) return a.second; // a comes first iff it's home, i.e., second == true + return a.first < b.first; +} + +// the bool return value tells if it's a user's directory or a system location +// note that this will treat places under $HOME as system directories when they are found via $XDG_DATA_DIRS +std::vector<std::pair<Glib::ustring, bool> > ColorProfile::getBaseProfileDirs() { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) static bool warnSet = false; if (!warnSet) { @@ -715,17 +724,17 @@ std::vector<Glib::ustring> ColorProfile::getBaseProfileDirs() { warnSet = true; } #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - std::vector<Glib::ustring> sources; + std::vector<std::pair<Glib::ustring, bool> > sources; // first try user's local dir gchar* path = g_build_filename(g_get_user_data_dir(), "color", "icc", NULL); - sources.push_back(path); + sources.push_back(std::make_pair(path, true)); g_free(path); const gchar* const * dataDirs = g_get_system_data_dirs(); for ( int i = 0; dataDirs[i]; i++ ) { gchar* path = g_build_filename(dataDirs[i], "color", "icc", NULL); - sources.push_back(path); + sources.push_back(std::make_pair(path, false)); g_free(path); } @@ -737,14 +746,14 @@ std::vector<Glib::ustring> ColorProfile::getBaseProfileDirs() { possible.push_back("/Library/ColorSync/Profiles"); for ( std::vector<Glib::ustring>::const_iterator it = possible.begin(); it != possible.end(); ++it ) { if ( g_file_test(it->c_str(), G_FILE_TEST_EXISTS) && g_file_test(it->c_str(), G_FILE_TEST_IS_DIR) ) { - sources.push_back(it->c_str()); + sources.push_back(std::make_pair(it->c_str(), false)); onOSX = true; } } if ( onOSX ) { gchar* path = g_build_filename(g_get_home_dir(), "Library", "ColorSync", "Profiles", NULL); if ( g_file_test(path, G_FILE_TEST_EXISTS) && g_file_test(path, G_FILE_TEST_IS_DIR) ) { - sources.push_back(path); + sources.push_back(std::make_pair(path, true)); } g_free(path); } @@ -760,12 +769,17 @@ std::vector<Glib::ustring> ColorProfile::getBaseProfileDirs() { if ( !g_utf8_validate(utf8Path, -1, NULL) ) { g_warning( "GetColorDirectoryW() resulted in invalid UTF-8" ); } else { - sources.push_back(utf8Path); + sources.push_back(std::make_pair(utf8Path, false)); } g_free( utf8Path ); } #endif // WIN32 + std::sort(sources.begin(), sources.end(), compareProfileBoolPair); + std::vector<std::pair<Glib::ustring, bool> >::iterator last = std::unique(sources.begin(), sources.end()); + sources.erase(last, sources.end()); + + return sources; } @@ -808,28 +822,28 @@ static bool isIccFile( gchar const *filepath ) return isIccFile; } -std::vector<Glib::ustring> ColorProfile::getProfileFiles() +std::vector<std::pair<Glib::ustring, bool> > ColorProfile::getProfileFiles() { - std::vector<Glib::ustring> files; + std::vector<std::pair<Glib::ustring, bool> > files; - std::list<Glib::ustring> sources; + std::list<std::pair<Glib::ustring, bool> > sources; { - std::vector<Glib::ustring> tmp = ColorProfile::getBaseProfileDirs(); + std::vector<std::pair<Glib::ustring, bool> > tmp = ColorProfile::getBaseProfileDirs(); sources.insert(sources.begin(), tmp.begin(), tmp.end()); } - for ( std::list<Glib::ustring>::const_iterator it = sources.begin(); it != sources.end(); ++it ) { - if ( g_file_test( it->c_str(), G_FILE_TEST_EXISTS ) && g_file_test( it->c_str(), G_FILE_TEST_IS_DIR ) ) { + for ( std::list<std::pair<Glib::ustring, bool> >::const_iterator it = sources.begin(); it != sources.end(); ++it ) { + if ( g_file_test( it->first.c_str(), G_FILE_TEST_EXISTS ) && g_file_test( it->first.c_str(), G_FILE_TEST_IS_DIR ) ) { GError *err = 0; - GDir *dir = g_dir_open(it->c_str(), 0, &err); + GDir *dir = g_dir_open(it->first.c_str(), 0, &err); if (dir) { for (gchar const *file = g_dir_read_name(dir); file != NULL; file = g_dir_read_name(dir)) { - gchar *filepath = g_build_filename(it->c_str(), file, NULL); + gchar *filepath = g_build_filename(it->first.c_str(), file, NULL); if ( g_file_test( filepath, G_FILE_TEST_IS_DIR ) ) { - sources.push_back( filepath ); + sources.push_back( std::make_pair(filepath, it->second) ); } else { if ( isIccFile( filepath ) ) { - files.push_back( filepath ); + files.push_back( std::make_pair(filepath, it->second) ); } } @@ -838,31 +852,44 @@ std::vector<Glib::ustring> ColorProfile::getProfileFiles() g_dir_close(dir); dir = 0; } else { - gchar *safeDir = Inkscape::IO::sanitizeString(it->c_str()); + gchar *safeDir = Inkscape::IO::sanitizeString(it->first.c_str()); g_warning(_("Color profiles directory (%s) is unavailable."), safeDir); g_free(safeDir); } } } + std::sort(files.begin(), files.end(), compareProfileBoolPair); + std::vector<std::pair<Glib::ustring, bool> >::iterator last = std::unique(files.begin(), files.end()); + files.erase(last, files.end()); + return files; } -std::vector<std::pair<Glib::ustring, Glib::ustring> > ColorProfile::getProfileFilesWithNames() +bool compareProfilePairByName(const std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> & a, + const std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> & b) { - std::vector<std::pair<Glib::ustring, Glib::ustring> > result; + if (a.first.second != b.first.second) return a.first.second; + return a.second < b.second; +} + +std::vector<std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> > ColorProfile::getProfileFilesWithNames() +{ + std::vector<std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> > result; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - std::vector<Glib::ustring> files = getProfileFiles(); - for ( std::vector<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) { - cmsHPROFILE hProfile = cmsOpenProfileFromFile(it->c_str(), "r"); + std::vector<std::pair<Glib::ustring, bool> > files = getProfileFiles(); + for ( std::vector<std::pair<Glib::ustring, bool> >::const_iterator it = files.begin(); it != files.end(); ++it ) { + cmsHPROFILE hProfile = cmsOpenProfileFromFile(it->first.c_str(), "r"); if ( hProfile ) { Glib::ustring name = getNameFromProfile(hProfile); result.push_back( std::make_pair(*it, name) ); cmsCloseProfile(hProfile); } } - std::sort(result.begin(), result.end()); + + std::sort(result.begin(), result.end(), compareProfilePairByName); + #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) return result; @@ -942,12 +969,12 @@ void loadProfiles() static bool profiles_searched = false; if ( !profiles_searched ) { knownProfiles.clear(); - std::vector<Glib::ustring> files = ColorProfile::getProfileFiles(); + std::vector<std::pair<Glib::ustring, bool> > files = ColorProfile::getProfileFiles(); - for ( std::vector<Glib::ustring>::const_iterator it = files.begin(); it != files.end(); ++it ) { - cmsHPROFILE prof = cmsOpenProfileFromFile( it->c_str(), "r" ); + for ( std::vector<std::pair<Glib::ustring, bool> >::const_iterator it = files.begin(); it != files.end(); ++it ) { + cmsHPROFILE prof = cmsOpenProfileFromFile( it->first.c_str(), "r" ); if ( prof ) { - ProfileInfo info( prof, Glib::filename_to_utf8( it->c_str() ) ); + ProfileInfo info( prof, Glib::filename_to_utf8( it->first.c_str() ) ); cmsCloseProfile( prof ); prof = 0; diff --git a/src/color-profile.h b/src/color-profile.h index cb6b25945..fed8c8c13 100644 --- a/src/color-profile.h +++ b/src/color-profile.h @@ -33,9 +33,9 @@ public: friend cmsHPROFILE colorprofile_get_handle( SPDocument*, unsigned int*, char const* ); friend class CMSSystem; - static std::vector<Glib::ustring> getBaseProfileDirs(); - static std::vector<Glib::ustring> getProfileFiles(); - static std::vector<std::pair<Glib::ustring, Glib::ustring> > getProfileFilesWithNames(); + static std::vector<std::pair<Glib::ustring, bool> > getBaseProfileDirs(); + static std::vector<std::pair<Glib::ustring, bool> > getProfileFiles(); + static std::vector<std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> > getProfileFilesWithNames(); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) //icColorSpaceSignature getColorSpace() const; ColorSpaceSig getColorSpace() const; diff --git a/src/document.cpp b/src/document.cpp index 2500a5cee..d8c3f1269 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -369,11 +369,6 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc, // Recursively build object tree document->root->invoke_build(document, rroot, false); - /* fixme: Not sure about this, but lets assume ::build updates */ - rroot->setAttribute("inkscape:version", Inkscape::version_string); - /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */ - - /* Eliminate obsolete sodipodi:docbase, for privacy reasons */ rroot->setAttribute("sodipodi:docbase", NULL); @@ -589,15 +584,6 @@ Inkscape::Util::Unit const* SPDocument::getDisplayUnit() const return nv ? nv->getDisplayUnit() : unit_table.getUnit("px"); } -/// guaranteed not to return nullptr -// returns 'px' units as default, like legacy Inkscape -// THIS SHOULD NOT BE USED... INSTEAD USE DOCUMENT SCALE -Inkscape::Util::Unit const& SPDocument::getSVGUnit() const -{ - SPNamedView const* nv = sp_document_namedview(this, NULL); - return nv ? nv->getSVGUnit() : *unit_table.getUnit("px"); -} - /// Sets document scale (by changing viewBox) void SPDocument::setDocumentScale( double scaleX, double scaleY ) { diff --git a/src/document.h b/src/document.h index 653e9d0db..e95042155 100644 --- a/src/document.h +++ b/src/document.h @@ -243,7 +243,6 @@ public: SPDocument *doRef(); SPDocument *doUnref(); Inkscape::Util::Unit const* getDisplayUnit() const; - Inkscape::Util::Unit const& getSVGUnit() const; void setDocumentScale( const double scaleX, const double scaleY ); void setDocumentScale( const double scale ); Geom::Scale getDocumentScale() const; diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 9aaf4b952..01323bee2 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -808,15 +808,17 @@ void Script::effect(Inkscape::Extension::Effect *module, \param oldroot The root node of the old (destination) document. \param newroot The root node of the new (source) document. - This function first deletes all the elements in the old document by + This function first deletes all the root attributes in the old document followed + by copying all the root attributes from the new document to the old document. + + It then deletes all the elements in the old document by making two pass, the first to create a list of the old elements and the second to actually delete them. This two pass approach removes issues with the list being change while parsing through it... lots of nasty bugs. Then, it copies all the element in the new document into the old document. - Finally, it replaces the attributes in the root element of the old document - by the attributes in root of the new document. + Finally, it copies the attributes in namedview. */ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) { @@ -829,6 +831,28 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr // For copying attributes in root and in namedview using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; + std::vector<gchar const *> attribs; + + // Must explicitly copy root attributes. This must be done first since + // copying grid lines calls "SPGuide::set()" which needs to know the + // width, height, and viewBox of the root element. + + // Make a list of all attributes of the old root node. + for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) { + attribs.push_back(g_quark_to_string(iter->key)); + } + + // Delete the attributes of the old root node. + for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { + oldroot->setAttribute(*it, NULL); + } + + // Set the new attributes. + for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { + gchar const *name = g_quark_to_string(iter->key); + oldroot->setAttribute(name, newroot->attribute(name)); + } + // Question: Why is the "sodipodi:namedview" special? Treating it as a normal // elmement results in crashes. @@ -882,30 +906,9 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr } } - std::vector<gchar const *> attribs; - - // Must explicitly copy root attributes. - - // Make a list of all attributes of the old root node. - for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) { - attribs.push_back(g_quark_to_string(iter->key)); - } - - // Delete the attributes of the old root node. - for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { - oldroot->setAttribute(*it, NULL); - } - - // Set the new attributes. - for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { - gchar const *name = g_quark_to_string(iter->key); - oldroot->setAttribute(name, newroot->attribute(name)); - } - attribs.clear(); // Must explicitly copy namedview attributes. - // Make a list of all attributes of the old namedview node. for (List<AttributeRecord const> iter = oldroot_namedview->attributeList(); iter; ++iter) { attribs.push_back(g_quark_to_string(iter->key)); diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 1c85182ae..9f3b5475f 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -144,7 +144,7 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) // width and height in px _width = doc->getWidth().value("px"); _height = doc->getHeight().value("px"); - _doc_unit_scale = Inkscape::Util::Quantity::convert(1, &doc->getSVGUnit(), "px"); + _doc_unit_scale = doc->getDocumentScale()[Geom::X]; // initialize a few global variables hbrush = hbrushOld = hpen = 0; diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 8a9c7a72f..e6938b9e2 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -108,7 +108,8 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc bounding_area = temprec; } - gdouble scale = Inkscape::Util::Quantity::convert(1, "px", &document->doc()->getSVGUnit()); + double scale = document->doc()->getDocumentScale().inverse()[Geom::X]; + bounding_area *= Geom::Scale(scale); Geom::Point spacings( scale * module->get_param_float("xspacing"), scale * module->get_param_float("yspacing") ); @@ -127,15 +128,9 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc path->setAttribute("d", path_data.c_str()); - Glib::ustring style("fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"); - style += ";stroke-width:"; - gchar floatstring[64]; std::ostringstream stringstream; - stringstream << line_width; - sprintf(floatstring, "%s", stringstream.str().c_str()); - style += floatstring; - style += "pt"; - path->setAttribute("style", style.c_str()); + stringstream << "fill:none;stroke:#000000;stroke-width:" << line_width << "px"; + path->setAttribute("style", stringstream.str().c_str()); current_layer->appendChild(path); Inkscape::GC::release(path); diff --git a/src/extension/param/bool.cpp b/src/extension/param/bool.cpp index de9b1c586..87364d80f 100644 --- a/src/extension/param/bool.cpp +++ b/src/extension/param/bool.cpp @@ -137,7 +137,7 @@ Gtk::Widget *ParamBool::get_widget(SPDocument * doc, Inkscape::XML::Node * node, Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); #endif - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_end(*label, true, true); diff --git a/src/extension/param/enum.cpp b/src/extension/param/enum.cpp index 8bc0fbda7..4e7420807 100644 --- a/src/extension/param/enum.cpp +++ b/src/extension/param/enum.cpp @@ -251,7 +251,7 @@ Gtk::Widget *ParamComboBox::get_widget(SPDocument * doc, Inkscape::XML::Node * n } Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, false, false, _indent); diff --git a/src/extension/param/float.cpp b/src/extension/param/float.cpp index 81508f6c0..4e3cbfedc 100644 --- a/src/extension/param/float.cpp +++ b/src/extension/param/float.cpp @@ -186,7 +186,7 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod if (_mode == FULL) { - UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, _precision); + UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_text, fadjust, _precision); scale->set_size_request(400, -1); scale->show(); hbox->pack_start(*scale, false, false); @@ -194,7 +194,7 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod } else if (_mode == MINIMAL) { - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, true, true, _indent); diff --git a/src/extension/param/int.cpp b/src/extension/param/int.cpp index c286018fd..605aab5ad 100644 --- a/src/extension/param/int.cpp +++ b/src/extension/param/int.cpp @@ -168,14 +168,14 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal if (_mode == FULL) { - UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, 0); + UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_text, fadjust, 0); scale->set_size_request(400, -1); scale->show(); hbox->pack_start(*scale, false, false); } else if (_mode == MINIMAL) { - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, true, true, _indent); diff --git a/src/extension/param/parameter.cpp b/src/extension/param/parameter.cpp index 10029893f..27d9bdf9b 100644 --- a/src/extension/param/parameter.cpp +++ b/src/extension/param/parameter.cpp @@ -20,6 +20,7 @@ #endif #include <cstring> +#include <glibmm/i18n.h> #include "ui/widget/color-notebook.h" #include <xml/node.h> @@ -56,6 +57,16 @@ Parameter *Parameter::make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Ex const char *guitext = in_repr->attribute("gui-text"); if (guitext == NULL) { guitext = in_repr->attribute("_gui-text"); + if (guitext == NULL) { + // guitext = ""; // propably better to require devs to explicitly set an empty gui-text if this is what they want + } else { + const char *context = in_repr->attribute("msgctxt"); + if (context != NULL) { + guitext = g_dpgettext2(NULL, context, guitext); + } else { + guitext = _(guitext); + } + } } const char *gui_tip = in_repr->attribute("gui-tip"); if (gui_tip == NULL) { diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp index 8181c6f51..1d1b860c6 100644 --- a/src/extension/param/radiobutton.cpp +++ b/src/extension/param/radiobutton.cpp @@ -313,7 +313,7 @@ Gtk::Widget * ParamRadioButton::get_widget(SPDocument * doc, Inkscape::XML::Node Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0)); #endif - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START, Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, false, false, _indent); diff --git a/src/extension/param/string.cpp b/src/extension/param/string.cpp index 1d9205502..6b082b133 100644 --- a/src/extension/param/string.cpp +++ b/src/extension/param/string.cpp @@ -166,7 +166,7 @@ Gtk::Widget * ParamString::get_widget(SPDocument * doc, Inkscape::XML::Node * no } Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, false, false, _indent); diff --git a/src/extension/plugins/grid2/grid.cpp b/src/extension/plugins/grid2/grid.cpp index 3a2ed7867..6880c574d 100644 --- a/src/extension/plugins/grid2/grid.cpp +++ b/src/extension/plugins/grid2/grid.cpp @@ -114,7 +114,8 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc bounding_area = temprec; } - gdouble scale = Inkscape::Util::Quantity::convert(1, "px", &document->doc()->getSVGUnit()); + double scale = document->doc()->getDocumentScale().inverse()[Geom::X]; + bounding_area *= Geom::Scale(scale); Geom::Point spacings( scale * module->get_param_float("xspacing"), scale * module->get_param_float("yspacing") ); @@ -133,15 +134,9 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc path->setAttribute("d", path_data.c_str()); - Glib::ustring style("fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"); - style += ";stroke-width:"; - gchar floatstring[64]; std::ostringstream stringstream; - stringstream << line_width; - sprintf(floatstring, "%s", stringstream.str().c_str()); - style += floatstring; - style += "pt"; - path->setAttribute("style", style.c_str()); + stringstream << "fill:none;stroke:#000000;stroke-width:" << line_width << "px"; + path->setAttribute("style", stringstream.str().c_str()); current_layer->appendChild(path); Inkscape::GC::release(path); diff --git a/src/file.cpp b/src/file.cpp index 9d390908e..650ce5d0f 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -45,7 +45,7 @@ #include "helper/png-write.h" #include "id-clash.h" #include "inkscape.h" -#include "inkscape.h" +#include "inkscape-version.h" #include "ui/interface.h" #include "io/sys.h" #include "message.h" @@ -318,6 +318,12 @@ bool sp_file_open(const Glib::ustring &uri, // everyone who cares now has a reference, get rid of our`s doc->doUnref(); + SPRoot *root = doc->getRoot(); + + // This is the only place original values should be set. + root->original.inkscape = root->version.inkscape; + root->original.svg = root->version.svg; + // resize the window to match the document properties sp_namedview_window_from_document(desktop); sp_namedview_update_layers_from_document(desktop); @@ -669,6 +675,8 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri, if (!doc || uri.size()<1) //Safety check return false; + Inkscape::Version save = doc->getRoot()->version.inkscape; + doc->getReprRoot()->setAttribute("inkscape:version", Inkscape::version_string); try { Inkscape::Extension::save(key, doc, uri.c_str(), false, @@ -681,6 +689,8 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri, sp_ui_error_dialog(text); g_free(text); g_free(safeUri); + // Restore Inkscape version + doc->getReprRoot()->setAttribute("inkscape:version", sp_version_to_string( save )); return false; } catch (Inkscape::Extension::Output::file_read_only &e) { gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str()); @@ -689,6 +699,7 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri, sp_ui_error_dialog(text); g_free(text); g_free(safeUri); + doc->getReprRoot()->setAttribute("inkscape:version", sp_version_to_string( save )); return false; } catch (Inkscape::Extension::Output::save_failed &e) { gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str()); @@ -697,14 +708,17 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri, sp_ui_error_dialog(text); g_free(text); g_free(safeUri); + doc->getReprRoot()->setAttribute("inkscape:version", sp_version_to_string( save )); return false; } catch (Inkscape::Extension::Output::save_cancelled &e) { SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved.")); + doc->getReprRoot()->setAttribute("inkscape:version", sp_version_to_string( save )); return false; } catch (Inkscape::Extension::Output::no_overwrite &e) { return sp_file_save_dialog(parentWindow, doc, save_method); } catch (...) { SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved.")); + doc->getReprRoot()->setAttribute("inkscape:version", sp_version_to_string( save )); return false; } diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 337d2a656..6b1aba53f 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -243,8 +243,11 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){ bool _goToNextWrapShape(); - bool _findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition *start_span_pos, - std::vector<ChunkInfo> *chunk_info, FontMetrics *line_box_height); + bool _findChunksForLine(ParagraphInfo const ¶, + UnbrokenSpanPosition *start_span_pos, + std::vector<ChunkInfo> *chunk_info, + FontMetrics *line_box_height, + FontMetrics const *strut_height); static inline PangoLogAttr const &_charAttributes(ParagraphInfo const ¶, UnbrokenSpanPosition const &span_pos) @@ -1138,31 +1141,17 @@ void Layout::Calculator::_buildPangoItemizationForPara(ParagraphInfo *para) con */ double Layout::Calculator::_computeFontLineHeight( SPStyle const *style ) { - // yet another borked SPStyle member that we're going to have to fix ourselves - // We shouldn't need to climb the element tree... - for ( ; ; ) { - if (style->line_height.set && !style->line_height.inherit) { - if (style->line_height.normal) - break; - switch (style->line_height.unit) { - case SP_CSS_UNIT_NONE: - return style->line_height.computed; - case SP_CSS_UNIT_EX: - return style->line_height.value * 0.5; - // 0.5 is an approximation of the x-height. Fixme. - case SP_CSS_UNIT_EM: - case SP_CSS_UNIT_PERCENT: - return style->line_height.value; - default: // absolute values - return style->line_height.computed / style->font_size.computed; - } - break; - } - if (style->object == NULL || style->object->parent == NULL) break; - style = style->object->parent->style; - if (style == NULL) break; + // This is a bit backwards... we should be returning the absolute height + // but as the code expects line_height_multiplier we return that. + if (style->line_height.normal) { + return (LINE_HEIGHT_NORMAL); + } else if (style->line_height.unit == SP_CSS_UNIT_NONE) { + // Special case per CSS, computed value is multiplier + return style->line_height.computed; + } else { + // Normal case, computed value is absolute height. Turn it into multiplier. + return style->line_height.computed / style->font_size.computed; } - return (LINE_HEIGHT_NORMAL); } bool compareGlyphWidth(const PangoGlyphInfo &a, const PangoGlyphInfo &b) @@ -1449,35 +1438,25 @@ bool Layout::Calculator::_goToNextWrapShape() * line to #_flow. Returns with \a start_span_pos set to the end of the * text that was fitted, \a chunk_info completely filled out and * \a line_box_height set with the largest ascent and the largest - * descent (individually per CSS) on the line. The return + * descent (individually per CSS) on the line. The line_box_height + * can never be smaller than the line_box_strut (which is determined + * by the block level value of line_height). The return * value is false only if we've run out of shapes to wrap inside (and * hence couldn't create any chunks). */ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition *start_span_pos, std::vector<ChunkInfo> *chunk_info, - FontMetrics *line_box_height) + FontMetrics *line_box_height, + FontMetrics const *strut_height) { TRACE((" begin _findChunksForLine: chunks: %lu, em size: %f\n", chunk_info->size(), line_box_height->emSize() )); - // CSS 2.1 dictates that the minimum line height (i.e. the strut height) is found from the block element. This, - // however, is not what the browsers seem to be doing. Instead, find the height from the first text source. - InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_flow._input_stream.front()); - font_instance *font = text_source->styleGetFontInstance(); - if (font) { - double multiplier = _computeFontLineHeight(text_source->style); - line_box_height->set( font ); - *line_box_height *= text_source->style->font_size.computed; - font->Unref(); - line_box_height->computeEffective( multiplier ); - } else { - std::cerr << "Layout::Calculator::_findChunksForLine: Font not found." << std::endl; - } + // CSS 2.1 dictates that the minimum line height (i.e. the strut height) + // is found from the block element. + *line_box_height = *strut_height; TRACE((" initial line_box_height (em size): %f\n", line_box_height->emSize() )); - // Save strut height for use when recalculating line height after backing out chunks that don't fit. - FontMetrics strut_height = *line_box_height; - UnbrokenSpanPosition span_pos; for( ; ; ) { std::vector<ScanlineMaker::ScanRun> scan_runs; @@ -1495,7 +1474,7 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, unsigned scan_run_index; span_pos = *start_span_pos; for (scan_run_index = 0 ; scan_run_index < scan_runs.size() ; scan_run_index++) { - if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, &strut_height)) + if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, strut_height)) break; if (!chunk_info->empty() && !chunk_info->back().broken_spans.empty()) span_pos = chunk_info->back().broken_spans.back().end; @@ -1568,6 +1547,7 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, // see if this span is too tall to fit on the current line FontMetrics new_span_height = new_span.start.iter_span->line_height; new_span_height.computeEffective( new_span.start.iter_span->line_height_multiplier ); + /* floating point 80-bit/64-bit rounding problems require epsilon. See discussion http://inkscape.gristle.org/2005-03-16.txt around 22:00 */ if ( new_span_height.ascent > line_height->ascent + std::numeric_limits<float>::epsilon() || @@ -1705,11 +1685,13 @@ bool Layout::Calculator::calculate() pango_context_set_base_gravity(_pango_context, PANGO_GRAVITY_AUTO); } + // Minimum line box height determined by block container. + FontMetrics strut_height = _flow.strut; _y_offset = 0.0; _createFirstScanlineMaker(); ParagraphInfo para; - FontMetrics line_box_height; // needs to be maintained across paragraphs to be able to deal with blank paras + FontMetrics line_box_height; // Current value of line box height for line. for(para.first_input_index = 0 ; para.first_input_index < _flow._input_stream.size() ; ) { // jump to the next wrap shape if this is a SHAPE_BREAK control code if (_flow._input_stream[para.first_input_index]->Type() == CONTROL_CODE) { @@ -1749,7 +1731,7 @@ bool Layout::Calculator::calculate() do { // for each line in the paragraph TRACE(("begin line\n")); std::vector<ChunkInfo> line_chunk_info; - if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height)) + if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height, &strut_height )) break; // out of shapes to wrap in to _outputLine(para, line_box_height, line_chunk_info); diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index 97a05bde8..8b46758f0 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -671,6 +671,9 @@ public: }; // End FontMetrics + /** The strut is the minimum value used in calculating line height. */ + FontMetrics strut; + /// see _enum_converter() struct EnumConversionItem { int input, output; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index cee872f9f..0a78b199e 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -714,6 +714,7 @@ Effect::getParameter(const char * key) { Glib::ustring stringkey(key); + if (param_vector.empty()) return NULL; std::vector<Parameter *>::iterator it = param_vector.begin(); while (it != param_vector.end()) { Parameter * param = *it; diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp index 5b29df4a7..ae951dfc9 100644 --- a/src/live_effects/lpe-perspective-envelope.cpp +++ b/src/live_effects/lpe-perspective-envelope.cpp @@ -42,6 +42,7 @@ LPEPerspectiveEnvelope::LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject) Effect(lpeobject), horizontal_mirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontal_mirror", &wr, this, false), vertical_mirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "vertical_mirror", &wr, this, false), + overflow_perspective(_("Overflow perspective"), _("Overflow perspective"), "overflow_perspective", &wr, this, false), deform_type(_("Type"), _("Select the type of deformation"), "deform_type", DeformationTypeConverter, &wr, this, DEFORMATION_PERSPECTIVE), up_left_point(_("Top Left"), _("Top Left - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "up_left_point", &wr, this), up_right_point(_("Top Right"), _("Top Right - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "up_right_point", &wr, this), @@ -52,6 +53,7 @@ LPEPerspectiveEnvelope::LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject) registerParameter(&deform_type); registerParameter(&horizontal_mirror); registerParameter(&vertical_mirror); + registerParameter(&overflow_perspective); registerParameter(&up_left_point); registerParameter(&up_right_point); registerParameter(&down_left_point); @@ -76,11 +78,107 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) } double projmatrix[3][3]; if(deform_type == DEFORMATION_PERSPECTIVE) { - std::vector<Geom::Point> handles(4); - handles[0] = down_left_point; - handles[1] = up_left_point; - handles[2] = up_right_point; - handles[3] = down_right_point; + if (!overflow_perspective && handles.size() == 4) { + bool move0 = false; + if (handles[0] != down_left_point) { + move0 = true; + } + bool move1 = false; + if (handles[1] != up_left_point) { + move1 = true; + } + bool move2 = false; + if (handles[2] != up_right_point) { + move2 = true; + } + bool move3 = false; + if (handles[3] != down_right_point) { + move3 = true; + } + handles.resize(4); + handles[0] = down_left_point; + handles[1] = up_left_point; + handles[2] = up_right_point; + handles[3] = down_right_point; + Geom::Line line_a(handles[3],handles[1]); + Geom::Line line_b(handles[1],handles[2]); + Geom::Line line_c(handles[2],handles[3]); + int position_a = Geom::sgn(Geom::cross(handles[3] - handles[1], handles[0] - handles[1])); + int position_b = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[0] - handles[2])); + int position_c = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[0] - handles[3])); + if (position_a != 1 && move0) { + Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[0])); + down_left_point.param_setValue(point_a, true); + } + if (position_b == 1 && move0) { + Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[0])); + down_left_point.param_setValue(point_b, true); + } + if (position_c == 1 && move0) { + Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[0])); + down_left_point.param_setValue(point_c, true); + } + line_a.setPoints(handles[0],handles[2]); + line_b.setPoints(handles[2],handles[3]); + line_c.setPoints(handles[3],handles[0]); + position_a = Geom::sgn(Geom::cross(handles[0] - handles[2], handles[1] - handles[2])); + position_b = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[1] - handles[3])); + position_c = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[1] - handles[0])); + if (position_a != 1 && move1) { + Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[1])); + up_left_point.param_setValue(point_a, true); + } + if (position_b == 1 && move1) { + Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[1])); + up_left_point.param_setValue(point_b, true); + } + if (position_c == 1 && move1) { + Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[1])); + up_left_point.param_setValue(point_c, true); + } + line_a.setPoints(handles[1],handles[3]); + line_b.setPoints(handles[3],handles[0]); + line_c.setPoints(handles[0],handles[1]); + position_a = Geom::sgn(Geom::cross(handles[1] - handles[3], handles[2] - handles[3])); + position_b = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[2] - handles[0])); + position_c = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[2] - handles[1])); + if (position_a != 1 && move2) { + Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[2])); + up_right_point.param_setValue(point_a, true); + } + if (position_b == 1 && move2) { + Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[2])); + up_right_point.param_setValue(point_b, true); + } + if (position_c == 1 && move2) { + Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[2])); + up_right_point.param_setValue(point_c, true); + } + line_a.setPoints(handles[2],handles[0]); + line_b.setPoints(handles[0],handles[1]); + line_c.setPoints(handles[1],handles[2]); + position_a = Geom::sgn(Geom::cross(handles[2] - handles[0], handles[3] - handles[0])); + position_b = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[3] - handles[1])); + position_c = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[3] - handles[2])); + if (position_a != 1 && move3) { + Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[3])); + down_right_point.param_setValue(point_a, true); + } + if (position_b == 1 && move3) { + Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[3])); + down_right_point.param_setValue(point_b, true); + } + if (position_c == 1 && move3) { + Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[3])); + down_right_point.param_setValue(point_c, true); + } + } else { + handles.resize(4); + handles[0] = down_left_point; + handles[1] = up_left_point; + handles[2] = up_right_point; + handles[3] = down_right_point; + } std::vector<Geom::Point> source_handles(4); source_handles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max()); source_handles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min()); @@ -206,14 +304,14 @@ LPEPerspectiveEnvelope::projectPoint(Geom::Point p) double delta_y = boundingbox_Y.max() - p[Y]; Geom::Coord x_ratio = (delta_x * -1) / width; Geom::Coord y_ratio = delta_y / height; - Geom::Line* horiz = new Geom::Line(); - Geom::Line* vert = new Geom::Line(); - vert->setPoints (pointAtRatio(y_ratio,down_left_point,up_left_point),pointAtRatio(y_ratio,down_right_point,up_right_point)); - horiz->setPoints (pointAtRatio(x_ratio,down_left_point,down_right_point),pointAtRatio(x_ratio,up_left_point,up_right_point)); + Geom::Line horiz; + Geom::Line vert; + vert.setPoints (pointAtRatio(y_ratio,down_left_point,up_left_point),pointAtRatio(y_ratio,down_right_point,up_right_point)); + horiz.setPoints (pointAtRatio(x_ratio,down_left_point,down_right_point),pointAtRatio(x_ratio,up_left_point,up_right_point)); - OptCrossing crossPoint = intersection(*horiz,*vert); + OptCrossing crossPoint = intersection(horiz,vert); if(crossPoint) { - return horiz->pointAt(Geom::Coord(crossPoint->ta)); + return horiz.pointAt(Geom::Coord(crossPoint->ta)); } else { return p; } diff --git a/src/live_effects/lpe-perspective-envelope.h b/src/live_effects/lpe-perspective-envelope.h index dd14dc212..727b7839d 100644 --- a/src/live_effects/lpe-perspective-envelope.h +++ b/src/live_effects/lpe-perspective-envelope.h @@ -60,12 +60,13 @@ private: BoolParam horizontal_mirror; BoolParam vertical_mirror; + BoolParam overflow_perspective; EnumParam<unsigned> deform_type; PointParam up_left_point; PointParam up_right_point; PointParam down_left_point; PointParam down_right_point; - + std::vector<Geom::Point> handles; LPEPerspectiveEnvelope(const LPEPerspectiveEnvelope&); LPEPerspectiveEnvelope& operator=(const LPEPerspectiveEnvelope&); }; diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index 7ea1d465c..bed191e83 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -73,7 +73,21 @@ PathParam::PathParam( const Glib::ustring& label, const Glib::ustring& tip, PathParam::~PathParam() { remove_link(); - + using namespace Inkscape::UI; + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + if (tools_isactive(desktop, TOOLS_NODES)) { + SPItem * item = SP_ACTIVE_DESKTOP->getSelection()->singleItem(); + if (item != NULL) { + Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context); + std::set<ShapeRecord> shapes; + ShapeRecord r; + r.item = item; + shapes.insert(r); + nt->_multipath->setItems(shapes); + } + } + } g_free(defvalue); } @@ -207,6 +221,9 @@ PathParam::param_newWidget() void PathParam::param_editOncanvas(SPItem *item, SPDesktop * dt) { + SPDocument *document = dt->getDocument(); + bool saved = DocumentUndo::getUndoSensitive(document); + DocumentUndo::setUndoSensitive(document, false); using namespace Inkscape::UI; // TODO remove the tools_switch atrocity. @@ -220,14 +237,20 @@ PathParam::param_editOncanvas(SPItem *item, SPDesktop * dt) r.role = SHAPE_ROLE_LPE_PARAM; r.edit_transform = item->i2dt_affine(); // TODO is it right? + r.edit_transform *= item->transform.inverse(); if (!href) { r.item = reinterpret_cast<SPItem*>(param_effect->getLPEObj()); r.lpe_key = param_key; + Geom::PathVector stored_pv = _pathvector; + param_write_to_repr("M0,0 L1,0"); + const char *svgd = sp_svg_write_path(stored_pv); + param_write_to_repr(svgd); } else { r.item = ref.getObject(); } shapes.insert(r); nt->_multipath->setItems(shapes); + DocumentUndo::setUndoSensitive(document, saved); } void @@ -435,7 +458,8 @@ PathParam::paste_param_path(const char *svgd) SPItem * item = SP_ACTIVE_DESKTOP->getSelection()->singleItem(); if (item != NULL) { Geom::PathVector path_clipboard = sp_svg_read_pathv(svgd); - path_clipboard *= item->i2doc_affine().inverse(); + path_clipboard *= item->i2doc_affine().inverse() * item->transform; + path_clipboard *= Geom::Translate(path_clipboard.initialPoint() - _pathvector.initialPoint()).inverse(); svgd = sp_svg_write_path( path_clipboard ); } diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index b87507e18..51fb3ae89 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -30,6 +30,8 @@ #include "text-editing.h" #include "sp-text.h" +#include "libnrtype/font-instance.h" + #include "livarot/Shape.h" #include "display/drawing-text.h" @@ -339,6 +341,26 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, bool with_indent = false; if (dynamic_cast<SPFlowpara *>(root)) { + + layout.strut.reset(); + if (style) { + font_instance *font = font_factory::Default()->FaceFromStyle( style ); + if (font) { + font->FontMetrics(layout.strut.ascent, layout.strut.descent, layout.strut.xheight); + font->Unref(); + } + layout.strut *= style->font_size.computed; + if (style->line_height.normal ) { + layout.strut.computeEffective( Inkscape::Text::Layout::LINE_HEIGHT_NORMAL ); + } else if (style->line_height.unit == SP_CSS_UNIT_NONE) { + layout.strut.computeEffective( style->line_height.computed ); + } else { + if( style->font_size.computed > 0.0 ) { + layout.strut.computeEffective( style->line_height.computed/style->font_size.computed ); + } + } + } + // emulate par-indent with the first char's kern SPObject *t = root; SPFlowtext *ft = NULL; diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index c80fc7122..58a1a746e 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -196,6 +196,7 @@ void SPGuide::set(unsigned int key, const gchar *value) { } } +/* Only used internally and in sp-line.cpp */ SPGuide *SPGuide::createSPGuide(SPDocument *doc, Geom::Point const &pt1, Geom::Point const &pt2) { Inkscape::XML::Document *xml_doc = doc->getReprDoc(); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index af81194c2..9fd6e8ecc 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -399,7 +399,6 @@ void SPItem::build(SPDocument *document, Inkscape::XML::Node *repr) { object->readAttr( "clip-path" ); object->readAttr( "mask" ); object->readAttr( "sodipodi:insensitive" ); - object->readAttr( "sodipodi:nonprintable" ); object->readAttr( "inkscape:transform-center-x" ); object->readAttr( "inkscape:transform-center-y" ); object->readAttr( "inkscape:connector-avoid" ); diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp index 9598a14ec..616ec3921 100644 --- a/src/sp-namedview.cpp +++ b/src/sp-namedview.cpp @@ -59,25 +59,25 @@ static gboolean sp_str_to_bool(const gchar *str); static gboolean sp_nv_read_opacity(const gchar *str, guint32 *color); SPNamedView::SPNamedView() : SPObjectGroup(), snap_manager(this) { - this->zoom = 0; - this->guidecolor = 0; - this->guidehicolor = 0; - this->views.clear(); - this->borderlayer = 0; - this->page_size_units = NULL; - this->window_x = 0; - this->cy = 0; - this->window_y = 0; - this->svg_units = unit_table.getUnit("px"); // legacy behavior: if no viewbox present, default to 'px' units + + this->zoom = 0; + this->guidecolor = 0; + this->guidehicolor = 0; + this->views.clear(); + this->borderlayer = 0; + this->page_size_units = NULL; + this->window_x = 0; + this->cy = 0; + this->window_y = 0; this->display_units = NULL; - this->page_size_units = NULL; - this->pagecolor = 0; - this->cx = 0; - this->pageshadow = 0; - this->window_width = 0; - this->window_height = 0; - this->window_maximized = 0; - this->bordercolor = 0; + this->page_size_units = NULL; + this->pagecolor = 0; + this->cx = 0; + this->pageshadow = 0; + this->window_width = 0; + this->window_height = 0; + this->window_maximized = 0; + this->bordercolor = 0; this->editable = TRUE; this->showguides = TRUE; @@ -261,16 +261,6 @@ void SPNamedView::build(SPDocument *document, Inkscape::XML::Node *repr) { // backwards compatibility with grid settings (pre 0.46) sp_namedview_generate_old_grid(this, document, repr); - - // If viewbox defined: try to calculate the SVG unit from document width and viewbox - if (document->getRoot()->viewBox_set) { - Inkscape::Util::Quantity svgwidth = document->getWidth(); - Geom::Rect viewbox = document->getRoot()->viewBox; - double factor = svgwidth.value(unit_table.primary(Inkscape::Util::UNIT_TYPE_LINEAR)) / viewbox.width(); - svg_units = unit_table.findUnit(factor, Inkscape::Util::UNIT_TYPE_LINEAR); - } else { // force the document units to be px - repr->setAttribute("inkscape:document-units", "px"); - } } void SPNamedView::release() { @@ -1098,7 +1088,6 @@ void SPNamedView::setGuides(bool v) g_assert(this->getRepr() != NULL); sp_repr_set_boolean(this->getRepr(), "showguides", v); sp_repr_set_boolean(this->getRepr(), "inkscape:guide-bbox", v); - sp_repr_set_boolean(this->getRepr(), "inkscape:locked", false); } bool SPNamedView::getGuides() @@ -1155,12 +1144,6 @@ Inkscape::Util::Unit const * SPNamedView::getDisplayUnit() const return display_units ? display_units : unit_table.getUnit("px"); } -Inkscape::Util::Unit const & SPNamedView::getSVGUnit() const -{ - assert(svg_units); - return *svg_units; -} - /** * Returns the first grid it could find that isEnabled(). Returns NULL, if none is enabled */ diff --git a/src/sp-namedview.h b/src/sp-namedview.h index 3d63f2b97..d8ac1a77e 100644 --- a/src/sp-namedview.h +++ b/src/sp-namedview.h @@ -64,7 +64,6 @@ public: std::vector<Inkscape::CanvasGrid *> grids; bool grids_visible; - Inkscape::Util::Unit const *svg_units; // Units used for the values in SVG Inkscape::Util::Unit const *display_units; // Units used for the UI (*not* the same as units of SVG coordinates) Inkscape::Util::Unit const *page_size_units; // Only used in "Custom size" part of Document Properties dialog @@ -90,7 +89,6 @@ public: unsigned int getViewCount(); std::vector<SPDesktop *> const getViewList() const; Inkscape::Util::Unit const * getDisplayUnit() const; - Inkscape::Util::Unit const & getSVGUnit() const; void translateGuides(Geom::Translate const &translation); void translateGrids(Geom::Translate const &translation); diff --git a/src/sp-root.cpp b/src/sp-root.cpp index 8bedec0a5..98eae2159 100644 --- a/src/sp-root.cpp +++ b/src/sp-root.cpp @@ -313,9 +313,11 @@ Inkscape::XML::Node *SPRoot::write(Inkscape::XML::Document *xml_doc, Inkscape::X repr = xml_doc->createElement("svg:svg"); } - if (flags & SP_OBJECT_WRITE_EXT) { - repr->setAttribute("inkscape:version", Inkscape::version_string); - } + /* Only update version string on successful write to file. This is handled by 'file_save()'. + * if (flags & SP_OBJECT_WRITE_EXT) { + * repr->setAttribute("inkscape:version", Inkscape::version_string); + * } + */ if (!repr->attribute("version")) { gchar *myversion = sp_version_to_string(this->version.svg); diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 6ae1c4fba..4afc38524 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -535,7 +535,28 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio if (SP_IS_TEXT(root)) { SP_TEXT(root)->attributes.mergeInto(&optional_attrs, parent_optional_attrs, parent_attrs_offset, true, true); - if (SP_TEXT(root)->attributes.getTextLength()->_set) { // set textLength on the entire layout, see note in TNG-Layout.h + + layout.strut.reset(); + if (style) { + font_instance *font = font_factory::Default()->FaceFromStyle( style ); + if (font) { + font->FontMetrics(layout.strut.ascent, layout.strut.descent, layout.strut.xheight); + font->Unref(); + } + layout.strut *= style->font_size.computed; + if (style->line_height.normal ) { + layout.strut.computeEffective( Inkscape::Text::Layout::LINE_HEIGHT_NORMAL ); + } else if (style->line_height.unit == SP_CSS_UNIT_NONE) { + layout.strut.computeEffective( style->line_height.computed ); + } else { + if( style->font_size.computed > 0.0 ) { + layout.strut.computeEffective( style->line_height.computed/style->font_size.computed ); + } + } + } + + // set textLength on the entire layout, see note in TNG-Layout.h + if (SP_TEXT(root)->attributes.getTextLength()->_set) { layout.textLength._set = true; layout.textLength.value = SP_TEXT(root)->attributes.getTextLength()->value; layout.textLength.computed = SP_TEXT(root)->attributes.getTextLength()->computed; diff --git a/src/style-internal.cpp b/src/style-internal.cpp index b425a1c80..62b0de52d 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -1810,9 +1810,11 @@ SPIDashArray::read( gchar const *str ) { return; } + // std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("[,\\s]+", str ); + gchar *e = NULL; bool LineSolid = true; - while (e != str) { + while (e != str && *str != '\0') { /* TODO: Should allow <length> rather than just a unitless (px) number. */ double number = g_ascii_strtod(str, (char **) &e); values.push_back( number ); @@ -1821,7 +1823,7 @@ SPIDashArray::read( gchar const *str ) { if (e != str) { str = e; } - while (str && *str && !isalnum(*str)) str += 1; + while (str && *str && !(isalnum(*str) || *str=='.')) str += 1; } if (LineSolid) { diff --git a/src/style-internal.h b/src/style-internal.h index 767552784..6cc8c6c4e 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -520,7 +520,7 @@ public: {} SPIEnumBits( Glib::ustring const &name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) : - SPIEnum( name, enums, value, inherit ) + SPIEnum( name, enums, value, inherits ) {} virtual ~SPIEnumBits() diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index 9656878e0..b727c87ee 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -2266,7 +2266,8 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg) clonetiler_remove (NULL, dlg, false); - double scale_units = Inkscape::Util::Quantity::convert(1, "px", &desktop->getDocument()->getSVGUnit()); + Geom::Scale scale = desktop->getDocument()->getDocumentScale().inverse(); + double scale_units = scale[Geom::X]; // Use just x direction.... double shiftx_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shiftx_per_i", 0, -10000, 10000); double shifty_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shifty_per_i", 0, -10000, 10000); diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 12eaba72a..589973162 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -283,7 +283,7 @@ inline void attach_all(Gtk::Table &table, Gtk::Widget *const arr[], unsigned con } else { #if WITH_GTKMM_3_0 arr[i+1]->set_hexpand(); - + if (yoptions & Gtk::EXPAND) arr[i+1]->set_vexpand(); else @@ -428,13 +428,30 @@ void DocumentProperties::build_snap() #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) /// Populates the available color profiles combo box void DocumentProperties::populate_available_profiles(){ - _combo_avail.remove_all(); // Clear any existing items in the combo box + _AvailableProfilesListStore->clear(); // Clear any existing items in the combo box // Iterate through the list of profiles and add the name to the combo box. - std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames(); - for ( std::vector<std::pair<Glib::ustring, Glib::ustring> >::const_iterator it = pairs.begin(); it != pairs.end(); ++it ) { + std::vector<std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames(); + bool home = true; // initial value doesn't matter, it's just to avoid a compiler warning + for ( std::vector<std::pair<std::pair<Glib::ustring, bool>, Glib::ustring> >::const_iterator it = pairs.begin(); it != pairs.end(); ++it ) { + Gtk::TreeModel::Row row; + Glib::ustring file = it->first.first; Glib::ustring name = it->second; - _combo_avail.append(name); + + // add a separator between profiles from the user's home directory and system profiles + if (it != pairs.begin() && it->first.second != home) + { + row = *(_AvailableProfilesListStore->append()); + row[_AvailableProfilesListColumns.fileColumn] = "<separator>"; + row[_AvailableProfilesListColumns.nameColumn] = "<separator>"; + row[_AvailableProfilesListColumns.separatorColumn] = true; + } + home = it->first.second; + + row = *(_AvailableProfilesListStore->append()); + row[_AvailableProfilesListColumns.fileColumn] = file; + row[_AvailableProfilesListColumns.nameColumn] = name; + row[_AvailableProfilesListColumns.separatorColumn] = false; } } @@ -442,7 +459,7 @@ void DocumentProperties::populate_available_profiles(){ * Cleans up name to remove disallowed characters. * Some discussion at http://markmail.org/message/bhfvdfptt25kgtmj * Allowed ASCII first characters: ':', 'A'-'Z', '_', 'a'-'z' - * Allowed ASCII remaining chars add: '-', '.', '0'-'9', + * Allowed ASCII remaining chars add: '-', '.', '0'-'9', * * @param str the string to clean up. */ @@ -474,24 +491,23 @@ static void sanitizeName( Glib::ustring& str ) /// Links the selected color profile in the combo box to the document void DocumentProperties::linkSelectedProfile() { -//store this profile in the SVG document (create <color-profile> element in the XML) + //store this profile in the SVG document (create <color-profile> element in the XML) // TODO remove use of 'active' desktop SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop){ g_warning("No active desktop"); } else { - // Find the index of the currently-selected row in the color profiles combobox - int row = _combo_avail.get_active_row_number(); + // Find the index of the currently-selected row in the color profiles combobox + Gtk::TreeModel::iterator iter = _AvailableProfilesList.get_active(); - if (row == -1){ + if (!iter) { g_warning("No color profile available."); return; } - // Read the filename and description from the list of available profiles - std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames(); - Glib::ustring file = pairs[row].first; - Glib::ustring name = pairs[row].second; + // Read the filename and description from the list of available profiles + Glib::ustring file = (*iter)[_AvailableProfilesListColumns.fileColumn]; + Glib::ustring name = (*iter)[_AvailableProfilesListColumns.nameColumn]; std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { SPObject* obj = *it; @@ -511,7 +527,7 @@ void DocumentProperties::linkSelectedProfile() // Checks whether there is a defs element. Creates it when needed Inkscape::XML::Node *defsRepr = sp_repr_lookup_name(xml_doc, "svg:defs"); - if (!defsRepr){ + if (!defsRepr) { defsRepr = xml_doc->createElement("svg:defs"); xml_doc->root()->addChild(defsRepr, NULL); } @@ -529,6 +545,20 @@ void DocumentProperties::linkSelectedProfile() } } +struct _cmp { + bool operator()(const SPObject * const & a, const SPObject * const & b) + { + const Inkscape::ColorProfile &a_prof = reinterpret_cast<const Inkscape::ColorProfile &>(*a); + const Inkscape::ColorProfile &b_prof = reinterpret_cast<const Inkscape::ColorProfile &>(*b); + gchar *a_name_casefold = g_utf8_casefold(a_prof.name, -1 ); + gchar *b_name_casefold = g_utf8_casefold(b_prof.name, -1 ); + int result = g_strcmp0(a_name_casefold, b_name_casefold); + g_free(a_name_casefold); + g_free(b_name_casefold); + return result < 0; + } +}; + void DocumentProperties::populate_linked_profiles_box() { _LinkedProfilesListStore->clear(); @@ -536,7 +566,8 @@ void DocumentProperties::populate_linked_profiles_box() if (! current.empty()) { _emb_profiles_observer.set((*(current.begin()))->parent); } - for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::set<SPObject *, _cmp> _current (current.begin(), current.end()); + for (std::set<SPObject *, _cmp>::const_iterator it = _current.begin(); it != _current.end(); ++it) { SPObject* obj = *it; Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj); Gtk::TreeModel::Row row = *(_LinkedProfilesListStore->append()); @@ -629,6 +660,12 @@ void DocumentProperties::removeSelectedProfile(){ onColorProfileSelectRow(); } +bool DocumentProperties::_AvailableProfilesList_separator(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter) +{ + bool separator = (*iter)[_AvailableProfilesListColumns.separatorColumn]; + return separator; +} + void DocumentProperties::build_cms() { _page_cms->show(); @@ -694,9 +731,9 @@ void DocumentProperties::build_cms() row++; #if WITH_GTKMM_3_0 - _combo_avail.set_hexpand(); - _combo_avail.set_valign(Gtk::ALIGN_CENTER); - _page_cms->table().attach(_combo_avail, 0, row, 1, 1); + _AvailableProfilesList.set_hexpand(); + _AvailableProfilesList.set_valign(Gtk::ALIGN_CENTER); + _page_cms->table().attach(_AvailableProfilesList, 0, row, 1, 1); _link_btn.set_halign(Gtk::ALIGN_CENTER); _link_btn.set_valign(Gtk::ALIGN_CENTER); @@ -708,11 +745,17 @@ void DocumentProperties::build_cms() _unlink_btn.set_valign(Gtk::ALIGN_CENTER); _page_cms->table().attach(_unlink_btn, 2, row, 1, 1); #else - _page_cms->table().attach(_combo_avail, 0, 1, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + _page_cms->table().attach(_AvailableProfilesList, 0, 1, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); _page_cms->table().attach(_link_btn, 1, 2, row, row + 1, (Gtk::AttachOptions)0, (Gtk::AttachOptions)0, 2, 0); _page_cms->table().attach(_unlink_btn, 2, 3, row, row + 1, (Gtk::AttachOptions)0, (Gtk::AttachOptions)0, 0, 0); #endif + // Set up the Avialable Profiles combo box + _AvailableProfilesListStore = Gtk::ListStore::create(_AvailableProfilesListColumns); + _AvailableProfilesList.set_model(_AvailableProfilesListStore); + _AvailableProfilesList.pack_start(_AvailableProfilesListColumns.nameColumn); + _AvailableProfilesList.set_row_separator_func(sigc::mem_fun(*this, &DocumentProperties::_AvailableProfilesList_separator)); + populate_available_profiles(); //# Set up the Linked Profiles combo box @@ -1693,7 +1736,7 @@ void DocumentProperties::onDocUnitChange() // Disable changing of SVG Units. The intent here is to change the units in the UI, not the units in SVG. // This code should be moved (and fixed) once we have an "SVG Units" setting that sets what units are used in SVG data. -#if 0 +#if 0 // Set viewBox if (doc->getRoot()->viewBox_set) { gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); @@ -1703,12 +1746,12 @@ void DocumentProperties::onDocUnitChange() Inkscape::Util::Quantity height = doc->getHeight(); doc->setViewBox(Geom::Rect::from_xywh(0, 0, width.value(doc_unit), height.value(doc_unit))); } - + // TODO: Fix bug in nodes tool instead of switching away from it if (tools_active(getDesktop()) == TOOLS_NODES) { tools_switch(getDesktop(), TOOLS_SELECT); } - + // Scale and translate objects // set transform options to scale all things with the transform, so all things scale properly after the viewbox change. /// \todo this "low-level" code of changing viewbox/unit should be moved somewhere else @@ -1748,7 +1791,7 @@ void DocumentProperties::onDocUnitChange() #endif doc->setModifiedSinceSave(); - + DocumentUndo::done(doc, SP_VERB_NONE, _("Changed default display unit")); } diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 7340b67f5..7f91d9ea0 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -139,14 +139,26 @@ protected: UI::Widget::RegisteredCheckButton _rcb_perp; UI::Widget::RegisteredCheckButton _rcb_tang; //--------------------------------------------------------------- - Gtk::ComboBoxText _combo_avail; Gtk::Button _link_btn; Gtk::Button _unlink_btn; + class AvailableProfilesColumns : public Gtk::TreeModel::ColumnRecord + { + public: + AvailableProfilesColumns() + { add(fileColumn); add(nameColumn); add(separatorColumn); } + Gtk::TreeModelColumn<Glib::ustring> fileColumn; + Gtk::TreeModelColumn<Glib::ustring> nameColumn; + Gtk::TreeModelColumn<bool> separatorColumn; + }; + AvailableProfilesColumns _AvailableProfilesListColumns; + Glib::RefPtr<Gtk::ListStore> _AvailableProfilesListStore; + Gtk::ComboBox _AvailableProfilesList; + bool _AvailableProfilesList_separator(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter); class LinkedProfilesColumns : public Gtk::TreeModel::ColumnRecord { public: LinkedProfilesColumns() - { add(nameColumn); add(previewColumn); } + { add(nameColumn); add(previewColumn); } Gtk::TreeModelColumn<Glib::ustring> nameColumn; Gtk::TreeModelColumn<Glib::ustring> previewColumn; }; @@ -218,7 +230,7 @@ private: // callback methods for buttons on grids page. void onNewGrid(); void onRemoveGrid(); - + // callback for document unit change void onDocUnitChange(); }; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 30bbd95c9..6dd62d3bb 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -514,7 +514,7 @@ void InkscapePreferences::initPageTools() this->AddPage(_page_dropper, _("Dropper"), iter_tools, PREFS_PAGE_TOOLS_DROPPER); this->AddSelcueCheckbox(_page_dropper, "/tools/dropper", true); this->AddGradientCheckbox(_page_dropper, "/tools/dropper", true); - + //Connector this->AddPage(_page_connector, _("Connector"), iter_tools, PREFS_PAGE_TOOLS_CONNECTOR); this->AddSelcueCheckbox(_page_connector, "/tools/connector", true); @@ -665,16 +665,16 @@ void InkscapePreferences::initPageUI() _dockbar_style.init( "/options/dock/dockbarstyle", dockbarstyleLabels, dockbarstyleValues, G_N_ELEMENTS(dockbarstyleLabels), 0); _page_ui.add_line(false, _("Dockbar style (requires restart):"), _dockbar_style, "", _("Selects whether the vertical bars on the dockbar will show text labels, icons, or both"), false); - + Glib::ustring switcherstyleLabels[] = {_("Text only"), _("Icons only"), _("Icons and text")}; /* see bug #1098437 */ int switcherstyleValues[] = {0, 1, 2}; - + /* switcher style */ _switcher_style.init( "/options/dock/switcherstyle", switcherstyleLabels, switcherstyleValues, G_N_ELEMENTS(switcherstyleLabels), 0); _page_ui.add_line(false, _("Switcher style (requires restart):"), _switcher_style, "", _("Selects whether the dockbar switcher will show text labels, icons, or both"), false); } - + // Windows _win_save_geom.init ( _("Save and restore window geometry for each document"), "/options/savewindowgeometry/value", 1, true, 0); _win_save_geom_prefs.init ( _("Remember and use last window's geometry"), "/options/savewindowgeometry/value", 2, false, &_win_save_geom); @@ -689,7 +689,7 @@ void InkscapePreferences::initPageUI() _win_native.init ( _("Native open/save dialogs"), "/options/desktopintegration/value", 1, true, 0); _win_gtk.init ( _("GTK open/save dialogs"), "/options/desktopintegration/value", 0, false, &_win_native); - + _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "/options/dialogsskiptaskbar/value", true); _win_save_viewport.init ( _("Save and restore documents viewport"), "/options/savedocviewport/value", true); _win_zoom_resize.init ( _("Zoom when window is resized"), "/options/stickyzoom/value", false); @@ -1005,9 +1005,9 @@ void InkscapePreferences::initPageIO() _page_cms.add_group_header( _("Display adjustment")); Glib::ustring tmpStr; - std::vector<Glib::ustring> sources = ColorProfile::getBaseProfileDirs(); - for ( std::vector<Glib::ustring>::const_iterator it = sources.begin(); it != sources.end(); ++it ) { - gchar* part = g_strdup_printf( "\n%s", it->c_str() ); + std::vector<std::pair<Glib::ustring, bool> > sources = ColorProfile::getBaseProfileDirs(); + for ( std::vector<std::pair<Glib::ustring, bool> >::const_iterator it = sources.begin(); it != sources.end(); ++it ) { + gchar* part = g_strdup_printf( "\n%s", it->first.c_str() ); tmpStr += part; g_free(part); } @@ -1377,28 +1377,28 @@ void InkscapePreferences::initPageBehavior() _mask_mask_remove.init ( _("Remove clippath/mask object after applying"), "/options/maskobject/remove", true); _page_mask.add_line(false, "", _mask_mask_remove, "", _("After applying, remove the object used as the clipping path or mask from the drawing")); - + _page_mask.add_group_header( _("Before applying")); - + _mask_grouping_none.init( _("Do not group clipped/masked objects"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE, true, 0); _mask_grouping_separate.init( _("Put every clipped/masked object in its own group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_SEPARATE, false, &_mask_grouping_none); _mask_grouping_all.init( _("Put all clipped/masked objects into one group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_ALL, false, &_mask_grouping_none); - + _page_mask.add_line(true, "", _mask_grouping_none, "", _("Apply clippath/mask to every object")); - + _page_mask.add_line(true, "", _mask_grouping_separate, "", _("Apply clippath/mask to groups containing single object")); - + _page_mask.add_line(true, "", _mask_grouping_all, "", _("Apply clippath/mask to group containing all objects")); - + _page_mask.add_group_header( _("After releasing")); - + _mask_ungrouping.init ( _("Ungroup automatically created groups"), "/options/maskobject/ungrouping", true); _page_mask.add_line(true, "", _mask_ungrouping, "", _("Ungroup groups created when setting clip/mask")); - + this->AddPage(_page_mask, _("Clippaths and masks"), iter_behavior, PREFS_PAGE_BEHAVIOR_MASKS); @@ -1411,8 +1411,8 @@ void InkscapePreferences::initPageBehavior() _("Update marker color when object color changes")); this->AddPage(_page_markers, _("Markers"), iter_behavior, PREFS_PAGE_BEHAVIOR_MARKERS); - - + + _page_cleanup.add_group_header( _("Document cleanup")); _cleanup_swatches.init ( _("Remove unused swatches when doing a document cleanup"), "/options/cleanupswatches/value", false); // text label _page_cleanup.add_line( true, "", _cleanup_swatches, "", @@ -1896,15 +1896,15 @@ void InkscapePreferences::initPageSpellcheck() /* the returned pointer should _not_ need to be deleted */ AspellDictInfoList *dlist = get_aspell_dict_info_list(config); - + /* config is no longer needed */ delete_aspell_config(config); - + AspellDictInfoEnumeration *dels = aspell_dict_info_list_elements(dlist); - + languages.push_back(Glib::ustring(C_("Spellchecker language", "None"))); langValues.push_back(Glib::ustring("")); - + const AspellDictInfo *entry; int en_index = 0; int i = 0; diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index d70147f80..9268d9730 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -526,7 +526,7 @@ Glib::ustring Handle::_getTip(unsigned state) const snap_increment_degrees()); } else if(isBSpline){ return format_tip(C_("Path handle tip", - "<b>Ctrl</b>: Move handle by his actual steps in BSpline Live Effect")); + "<b>Ctrl</b>: Snap handle to steps defined in BSpline Live Path Effect")); }else{ return format_tip(C_("Path handle tip", "<b>Ctrl</b>: snap rotation angle to %g° increments, click to retract"), diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 287828d32..5900a2359 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -778,7 +778,7 @@ void MeasureTool::toPhantom() measure_tmp_items.clear(); showCanvasItems(false, false, true); doc->ensureUpToDate(); - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add Stored to measure tool")); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Keep last measure on the canvas, for reference")); } void MeasureTool::toItem() diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index abac2c091..36fe26e76 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -683,6 +683,11 @@ bool ToolBase::root_handler(GdkEvent* event) { } break; + case GDK_KEY_Menu: + sp_event_root_menu_popup(desktop, NULL, event); + ret = TRUE; + break; + case GDK_KEY_F10: if (MOD__SHIFT_ONLY(event)) { sp_event_root_menu_popup(desktop, NULL, event); diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp index 2e30a48b5..b422892fe 100644 --- a/src/ui/widget/color-icc-selector.cpp +++ b/src/ui/widget/color-icc-selector.cpp @@ -671,6 +671,20 @@ void ColorICCSelectorImpl::_switchToProfile(gchar const *name) #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +struct _cmp { + bool operator()(const SPObject * const & a, const SPObject * const & b) + { + const Inkscape::ColorProfile &a_prof = reinterpret_cast<const Inkscape::ColorProfile &>(*a); + const Inkscape::ColorProfile &b_prof = reinterpret_cast<const Inkscape::ColorProfile &>(*b); + gchar *a_name_casefold = g_utf8_casefold(a_prof.name, -1 ); + gchar *b_name_casefold = g_utf8_casefold(b_prof.name, -1 ); + int result = g_strcmp0(a_name_casefold, b_name_casefold); + g_free(a_name_casefold); + g_free(b_name_casefold); + return result < 0; + } +}; + void ColorICCSelectorImpl::_profilesChanged(std::string const &name) { GtkComboBox *combo = GTK_COMBO_BOX(_profileSel); @@ -688,7 +702,8 @@ void ColorICCSelectorImpl::_profilesChanged(std::string const &name) int index = 1; std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile"); - for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) { + std::set<SPObject *, _cmp> _current(current.begin(), current.end()); + for (std::set<SPObject *, _cmp>::const_iterator it = _current.begin(); it != _current.end(); ++it) { SPObject *obj = *it; Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj); diff --git a/src/util/expression-evaluator.cpp b/src/util/expression-evaluator.cpp index 48064e647..dd7ce97f7 100644 --- a/src/util/expression-evaluator.cpp +++ b/src/util/expression-evaluator.cpp @@ -28,6 +28,8 @@ #include "util/expression-evaluator.h" #include "util/units.h" +#include <glib/gconvert.h> + #include <math.h> #include <string.h> @@ -49,7 +51,7 @@ EvaluatorToken::EvaluatorToken() } ExpressionEvaluator::ExpressionEvaluator(const char *string, Unit const *unit) : - string(string), + string(g_locale_to_utf8(string,-1,0,0,0)), unit(unit) { current_token.type = TOKEN_END; @@ -206,8 +208,11 @@ EvaluatorQuantity ExpressionEvaluator::evaluateFactor() { EvaluatorQuantity evaluated_factor = EvaluatorQuantity(); EvaluatorToken consumed_token = EvaluatorToken(); - - if (acceptToken(TOKEN_NUM, &consumed_token)) { + + if (acceptToken(TOKEN_END, &consumed_token)) { + return evaluated_factor; + } + else if (acceptToken(TOKEN_NUM, &consumed_token)) { evaluated_factor.value = consumed_token.value.fl; } else if (acceptToken('(', NULL)) { evaluated_factor = evaluateExpression(); diff --git a/src/version.cpp b/src/version.cpp index abe855ee7..7610cd8e7 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -21,28 +21,36 @@ bool sp_version_from_string(const char *string, Inkscape::Version *version) if (!string) { return false; } - + try { std::stringstream ss; + + // Throw exception if error. + ss.exceptions(std::ios::failbit | std::ios::badbit); ss << string; ss >> version->_major; char tmp=0; ss >> tmp; ss >>version->_minor; + + // Don't throw exception if failbit gets set (empty string OK). + ss.exceptions(std::ios::goodbit); + getline(ss, version->_tail); return true; } catch(...) { version->_major = 0; version->_minor = 0; + version->_tail.clear(); return false; } } char *sp_version_to_string(Inkscape::Version version) { - return g_strdup_printf("%u.%u", version._major, version._minor); + return g_strdup_printf("%u.%u%s", version._major, version._minor, version._tail.c_str()); } bool sp_version_inside_range(Inkscape::Version version, diff --git a/src/version.h b/src/version.h index e17688b6d..f6221f6a6 100644 --- a/src/version.h +++ b/src/version.h @@ -13,6 +13,8 @@ #define SVG_VERSION "1.1" +#include <string> + namespace Inkscape { class Version { @@ -43,6 +45,7 @@ public: unsigned int _major; unsigned int _minor; + std::string _tail; // Development version }; } diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index aafa6bd1e..58a178aec 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -789,7 +789,7 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_LINEAR); //sp_gradient_selector_set_mode(SP_GRADIENT_SELECTOR(gsel), SP_GRADIENT_SELECTOR_MODE_LINEAR); gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Linear gradient</b>")); - } else if (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) { + } else if (mode == SPPaintSelector::MODE_GRADIENT_RADIAL) { SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL); gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Radial gradient</b>")); } |
