diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2013-10-05 03:54:43 +0000 |
|---|---|---|
| committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | 2013-10-05 03:54:43 +0000 |
| commit | 706294ff1fa82c86089221d8ee4a0d5bd032925a (patch) | |
| tree | 4f57389a922f2cb3fdcec99cb21599580e954867 /src | |
| parent | C++ (diff) | |
| download | inkscape-706294ff1fa82c86089221d8ee4a0d5bd032925a.tar.gz inkscape-706294ff1fa82c86089221d8ee4a0d5bd032925a.zip | |
Rewrite the internals of the unit code for somewhat better performance
(bzr r12661)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/canvas-axonomgrid.cpp | 10 | ||||
| -rw-r--r-- | src/display/canvas-grid.cpp | 12 | ||||
| -rw-r--r-- | src/svg/svg-length.cpp | 2 | ||||
| -rw-r--r-- | src/ui/widget/selected-style.cpp | 2 | ||||
| -rw-r--r-- | src/ui/widget/unit-menu.cpp | 8 | ||||
| -rw-r--r-- | src/ui/widget/unit-tracker.cpp | 8 | ||||
| -rw-r--r-- | src/util/units.cpp | 307 | ||||
| -rw-r--r-- | src/util/units.h | 81 | ||||
| -rw-r--r-- | src/util/unordered-containers.h | 29 |
9 files changed, 269 insertions, 190 deletions
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index f7a7cb39a..654144122 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -214,18 +214,18 @@ CanvasAxonomGrid::readRepr() { gchar const *value; if ( (value = repr->attribute("originx")) ) { - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; - origin[Geom::X] = unit_table.getQuantity(value).value("px"); + origin[Geom::X] = q.value("px"); } if ( (value = repr->attribute("originy")) ) { - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; - origin[Geom::Y] = unit_table.getQuantity(value).value("px"); + origin[Geom::Y] = q.value("px"); } if ( (value = repr->attribute("spacingy")) ) { - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; lengthy = q.value("px"); if (lengthy < 0.0500) lengthy = 0.0500; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index ef32c113b..5701b91a1 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -588,20 +588,20 @@ CanvasXYGrid::readRepr() { gchar const *value; if ( (value = repr->attribute("originx")) ) { - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; - origin[Geom::X] = unit_table.getQuantity(value).value("px"); + origin[Geom::X] = q.value("px"); } if ( (value = repr->attribute("originy")) ) { - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; - origin[Geom::Y] = unit_table.getQuantity(value).value("px"); + origin[Geom::Y] = q.value("px"); } if ( (value = repr->attribute("spacingx")) ) { double oldVal = spacing[Geom::X]; - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; spacing[Geom::X] = q.quantity; validateScalar(oldVal, &spacing[Geom::X]); @@ -609,7 +609,7 @@ CanvasXYGrid::readRepr() } if ( (value = repr->attribute("spacingy")) ) { double oldVal = spacing[Geom::Y]; - Inkscape::Util::Quantity q = unit_table.getQuantity(value); + Inkscape::Util::Quantity q = unit_table.parseQuantity(value); gridunit = q.unit; spacing[Geom::Y] = q.quantity; validateScalar(oldVal, &spacing[Geom::Y]); diff --git a/src/svg/svg-length.cpp b/src/svg/svg-length.cpp index 8d26a95d2..6f1a88a58 100644 --- a/src/svg/svg-length.cpp +++ b/src/svg/svg-length.cpp @@ -541,6 +541,8 @@ std::string sp_svg_length_write_with_units(SVGLength const &length) Inkscape::SVGOStringStream os; if (length.unit == SVGLength::PERCENT) { os << 100*length.value << sp_svg_length_get_css_units(length.unit); + } else if (length.unit == SVGLength::FOOT) { + os << 12*length.value << sp_svg_length_get_css_units(SVGLength::INCH); } else { os << length.value << sp_svg_length_get_css_units(length.unit); } diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 894700046..97581aa83 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -313,7 +313,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/) Inkscape::Util::UnitTable::UnitMap::iterator iter = m.begin(); while(iter != m.end()) { Gtk::RadioMenuItem *mi = Gtk::manage(new Gtk::RadioMenuItem(_sw_group)); - mi->add(*(new Gtk::Label((*iter).first, 0.0, 0.5))); + mi->add(*(new Gtk::Label(iter->first, 0.0, 0.5))); _unit_mis = g_slist_append(_unit_mis, mi); Inkscape::Util::Unit const *u = new Inkscape::Util::Unit(unit_table.getUnit(iter->first)); mi->signal_activate().connect(sigc::bind<Inkscape::Util::Unit>(sigc::mem_fun(*this, &SelectedStyle::on_popup_units), *u)); diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp index 111226774..684016471 100644 --- a/src/ui/widget/unit-menu.cpp +++ b/src/ui/widget/unit-menu.cpp @@ -33,11 +33,9 @@ bool UnitMenu::setUnitType(UnitType unit_type) { // Expand the unit widget with unit entries from the unit table UnitTable::UnitMap m = unit_table.units(unit_type); - UnitTable::UnitMap::iterator iter = m.begin(); - while(iter != m.end()) { - Glib::ustring text = (*iter).first; - append(text); - ++iter; + + for (UnitTable::UnitMap::iterator i = m.begin(); i != m.end(); ++i) { + append(i->first); } _type = unit_type; set_active_text(unit_table.primary(unit_type)); diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp index f9b0c3a44..155f3fafe 100644 --- a/src/ui/widget/unit-tracker.cpp +++ b/src/ui/widget/unit-tracker.cpp @@ -38,10 +38,10 @@ UnitTracker::UnitTracker(UnitType unit_type) : GtkTreeIter iter; UnitTable::UnitMap m = unit_table.units(unit_type); - UnitTable::UnitMap::iterator m_iter = m.begin(); - while(m_iter != m.end()) { - Glib::ustring text = (*m_iter).first; - ++m_iter; + + + for (UnitTable::UnitMap::iterator m_iter = m.begin(); m_iter != m.end(); ++m_iter) { + Glib::ustring text = m_iter->first; gtk_list_store_append(_store, &iter); gtk_list_store_set(_store, &iter, COLUMN_STRING, text.c_str(), -1); } diff --git a/src/util/units.cpp b/src/util/units.cpp index 59717d0b5..cabbc044d 100644 --- a/src/util/units.cpp +++ b/src/util/units.cpp @@ -33,29 +33,85 @@ using Inkscape::Util::UNIT_TYPE_FONT_HEIGHT; namespace { -/** - * A std::map that gives the data type value for the string version. - * - * Note that we'd normally not return a reference to an internal version, but - * for this constant case it allows us to check against getTypeMappings().end(). - */ -/** @todo consider hiding map behind hasFoo() and getFoo() type functions.*/ -std::map<Glib::ustring, Inkscape::Util::UnitType> &getTypeMappings() +#define MAKE_UNIT_CODE(a, b) \ + ((((unsigned)(a) & 0xdf) << 8) | ((unsigned)(b) & 0xdf)) + +enum UnitCode { + UNIT_CODE_PX = MAKE_UNIT_CODE('p','x'), + UNIT_CODE_PT = MAKE_UNIT_CODE('p','t'), + UNIT_CODE_PC = MAKE_UNIT_CODE('p','c'), + UNIT_CODE_MM = MAKE_UNIT_CODE('m','m'), + UNIT_CODE_CM = MAKE_UNIT_CODE('c','m'), + UNIT_CODE_IN = MAKE_UNIT_CODE('i','n'), + UNIT_CODE_FT = MAKE_UNIT_CODE('f','t'), + UNIT_CODE_EM = MAKE_UNIT_CODE('e','m'), + UNIT_CODE_EX = MAKE_UNIT_CODE('e','x'), + UNIT_CODE_PERCENT = MAKE_UNIT_CODE('%',0) +}; + +// TODO: convert to constexpr in C++11, so that the above constants can be eliminated +inline unsigned make_unit_code(char a, char b) { + // this should work without the casts, but let's be 100% sure + // also ensure that the codes are in lowercase + return MAKE_UNIT_CODE(a,b); +} +inline unsigned make_unit_code(char const *str) { + if (!str || str[0] == 0) return 0; + return MAKE_UNIT_CODE(str[0], str[1]); +} + + + +unsigned const svg_length_lookup[] = { + 0, + UNIT_CODE_PX, + UNIT_CODE_PT, + UNIT_CODE_PC, + UNIT_CODE_MM, + UNIT_CODE_CM, + UNIT_CODE_IN, + UNIT_CODE_FT, + UNIT_CODE_EM, + UNIT_CODE_EX, + UNIT_CODE_PERCENT +}; + + + +// maps unit codes obtained from their abbreviations to their SVGLength unit indexes +typedef INK_UNORDERED_MAP<unsigned, SVGLength::Unit> UnitCodeLookup; + +UnitCodeLookup make_unit_code_lookup() { - static bool init = false; - static std::map<Glib::ustring, Inkscape::Util::UnitType> typeMap; - if (!init) - { - init = true; - typeMap["DIMENSIONLESS"] = UNIT_TYPE_DIMENSIONLESS; - typeMap["LINEAR"] = UNIT_TYPE_LINEAR; - typeMap["RADIAL"] = UNIT_TYPE_RADIAL; - typeMap["FONT_HEIGHT"] = UNIT_TYPE_FONT_HEIGHT; - // Note that code was not yet handling LINEAR_SCALED, TIME, QTY and NONE + UnitCodeLookup umap; + for (unsigned i = 1; i < G_N_ELEMENTS(svg_length_lookup); ++i) { + umap[svg_length_lookup[i]] = static_cast<SVGLength::Unit>(i); } - return typeMap; + return umap; +} + +UnitCodeLookup const unit_code_lookup = make_unit_code_lookup(); + + + +typedef INK_UNORDERED_MAP<Glib::ustring, Inkscape::Util::UnitType> TypeMap; + +/** A std::map that gives the data type value for the string version. + * @todo consider hiding map behind hasFoo() and getFoo() type functions. */ +TypeMap make_type_map() +{ + TypeMap tmap; + tmap["DIMENSIONLESS"] = UNIT_TYPE_DIMENSIONLESS; + tmap["LINEAR"] = UNIT_TYPE_LINEAR; + tmap["RADIAL"] = UNIT_TYPE_RADIAL; + tmap["FONT_HEIGHT"] = UNIT_TYPE_FONT_HEIGHT; + // Note that code was not yet handling LINEAR_SCALED, TIME, QTY and NONE + + return tmap; } +TypeMap const type_map = make_type_map(); + } // namespace namespace Inkscape { @@ -106,13 +162,13 @@ Unit::Unit(UnitType type, Glib::ustring const &name, Glib::ustring const &name_plural, Glib::ustring const &abbr, - Glib::ustring const &description) : - type(type), - factor(factor), - name(name), - name_plural(name_plural), - abbr(abbr), - description(description) + Glib::ustring const &description) + : type(type) + , factor(factor) + , name(name) + , name_plural(name_plural) + , abbr(abbr) + , description(description) { g_return_if_fail(factor <= 0); } @@ -133,62 +189,48 @@ int Unit::defaultDigits() const return factor_digits; } -bool Unit::compatibleWith(const Unit &u) const +bool Unit::compatibleWith(Unit const &u) const { // Percentages if (type == UNIT_TYPE_DIMENSIONLESS || u.type == UNIT_TYPE_DIMENSIONLESS) { return true; } - + // Other units with same type if (type == u.type) { return true; } - + // Different, incompatible types return false; } -bool Unit::compatibleWith(const Glib::ustring u) const +bool Unit::compatibleWith(Glib::ustring const &u) const { static UnitTable unit_table; return compatibleWith(unit_table.getUnit(u)); } -bool operator== (const Unit &u1, const Unit &u2) +bool Unit::operator==(Unit const &other) const { - return (u1.type == u2.type && u1.name.compare(u2.name) == 0); -} - -bool operator!= (const Unit &u1, const Unit &u2) -{ - return !(u1 == u2); + return (type == other.type && name.compare(other.name) == 0); } int Unit::svgUnit() const { - if (!abbr.compare("px")) - return SVGLength::PX; - if (!abbr.compare("pt")) - return SVGLength::PT; - if (!abbr.compare("pc")) - return SVGLength::PC; - if (!abbr.compare("mm")) - return SVGLength::MM; - if (!abbr.compare("cm")) - return SVGLength::CM; - if (!abbr.compare("in")) - return SVGLength::INCH; - if (!abbr.compare("ft")) - return SVGLength::FOOT; - if (!abbr.compare("em")) - return SVGLength::EM; - if (!abbr.compare("ex")) - return SVGLength::EX; - if (!abbr.compare("%")) - return SVGLength::PERCENT; + char const *astr = abbr.c_str(); + unsigned code = make_unit_code(astr); + + UnitCodeLookup::const_iterator u = unit_code_lookup.find(code); + if (u != unit_code_lookup.end()) { + return u->second; + } return 0; } + + +Unit UnitTable::_empty_unit; + UnitTable::UnitTable() { gchar *filename = g_build_filename(INKSCAPE_UIDIR, "units.xml", NULL); @@ -198,64 +240,50 @@ UnitTable::UnitTable() UnitTable::~UnitTable() { - for (UnitMap::iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter) + for (UnitCodeMap::iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter) { - delete (*iter).second; + delete iter->second; } } void UnitTable::addUnit(Unit const &u, bool primary) { - _unit_map[u.abbr] = new Unit(u); + _unit_map[make_unit_code(u.abbr.c_str())] = new Unit(u); if (primary) { _primary_unit[u.type] = u.abbr; } } -Unit UnitTable::getUnit(Glib::ustring const &unit_abbr) const +Unit const &UnitTable::getUnit(char const *abbr) const { - UnitMap::const_iterator iter = _unit_map.find(unit_abbr); - if (iter != _unit_map.end()) { - return *((*iter).second); - } else { - return Unit(); + UnitCodeMap::const_iterator f = _unit_map.find(make_unit_code(abbr)); + if (f != _unit_map.end()) { + return *f->second; } + return _empty_unit; } -Unit UnitTable::getUnit(SVGLength::Unit const u) const -{ - Glib::ustring u_str; - switch(u) { - case SVGLength::PX: - u_str = "px"; break; - case SVGLength::PT: - u_str = "pt"; break; - case SVGLength::PC: - u_str = "pc"; break; - case SVGLength::MM: - u_str = "mm"; break; - case SVGLength::CM: - u_str = "cm"; break; - case SVGLength::INCH: - u_str = "in"; break; - case SVGLength::FOOT: - u_str = "ft"; break; - case SVGLength::EM: - u_str = "em"; break; - case SVGLength::EX: - u_str = "ex"; break; - case SVGLength::PERCENT: - u_str = "%"; break; - default: - u_str = ""; + +Unit const &UnitTable::getUnit(Glib::ustring const &unit_abbr) const +{ + return getUnit(unit_abbr.c_str()); +} +Unit const &UnitTable::getUnit(SVGLength::Unit u) const +{ + if (u == 0 || u > SVGLength::LAST_UNIT) { + return _empty_unit; } - - return getUnit(u_str); + + UnitCodeMap::const_iterator f = _unit_map.find(svg_length_lookup[u]); + if (f != _unit_map.end()) { + return *f->second; + } + return _empty_unit; } -Quantity UnitTable::getQuantity(Glib::ustring const& q) const +Quantity UnitTable::parseQuantity(Glib::ustring const &q) const { Glib::MatchInfo match_info; - + // Extract value double value = 0; Glib::RefPtr<Glib::Regex> value_regex = Glib::Regex::create("[-+]*[\\d+]*[\\.,]*[\\d+]*[eE]*[-+]*\\d+"); @@ -263,15 +291,16 @@ Quantity UnitTable::getQuantity(Glib::ustring const& q) const std::istringstream tmp_v(match_info.fetch(0)); tmp_v >> value; } - + // Extract unit abbreviation Glib::ustring abbr; Glib::RefPtr<Glib::Regex> unit_regex = Glib::Regex::create("[A-z%]+"); if (unit_regex->match(q, match_info)) { abbr = match_info.fetch(0); } - - return Quantity(value, abbr); + + Quantity qty(value, abbr); + return qty; } bool UnitTable::deleteUnit(Unit const &u) @@ -280,7 +309,7 @@ bool UnitTable::deleteUnit(Unit const &u) // Cannot delete the primary unit type since it's // used for conversions if (u.abbr != _primary_unit[u.type]) { - UnitMap::iterator iter = _unit_map.find(u.abbr); + UnitCodeMap::iterator iter = _unit_map.find(make_unit_code(u.abbr.c_str())); if (iter != _unit_map.end()) { delete (*iter).second; _unit_map.erase(iter); @@ -292,16 +321,16 @@ bool UnitTable::deleteUnit(Unit const &u) bool UnitTable::hasUnit(Glib::ustring const &unit) const { - UnitMap::const_iterator iter = _unit_map.find(unit); + UnitCodeMap::const_iterator iter = _unit_map.find(make_unit_code(unit.c_str())); return (iter != _unit_map.end()); } UnitTable::UnitMap UnitTable::units(UnitType type) const { UnitMap submap; - for (UnitMap::const_iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter) { - if (((*iter).second)->type == type) { - submap.insert(UnitMap::value_type((*iter).first, new Unit(*((*iter).second)))); + for (UnitCodeMap::const_iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter) { + if (iter->second->type == type) { + submap.insert(UnitMap::value_type(iter->second->abbr, *iter->second)); } } @@ -351,8 +380,9 @@ void UnitParser::on_start_element(Ctx &ctx, Glib::ustring const &name, AttrMap c AttrMap::const_iterator f; if ((f = attrs.find("type")) != attrs.end()) { Glib::ustring type = f->second; - if (getTypeMappings().find(type) != getTypeMappings().end()) { - unit.type = getTypeMappings()[type]; + TypeMap::const_iterator tf = type_map.find(type); + if (tf != type_map.end()) { + unit.type = tf->second; } else { g_warning("Skipping unknown unit type '%s'.\n", type.c_str()); skip = true; @@ -388,46 +418,59 @@ void UnitParser::on_end_element(Ctx &ctx, Glib::ustring const &name) } } -Quantity::Quantity(double q, const Unit &u) +Quantity::Quantity(double q, Unit const &u) { unit = new Unit(u); quantity = q; } -Quantity::Quantity(double q, const Glib::ustring u) +Quantity::Quantity(double q, Glib::ustring const &u) +{ + unit = new Unit(unit_table.getUnit(u.c_str())); + quantity = q; +} +Quantity::Quantity(double q, char const *u) { unit = new Unit(unit_table.getUnit(u)); quantity = q; } -bool Quantity::compatibleWith(const Unit &u) const +bool Quantity::compatibleWith(Unit const &u) const { return unit->compatibleWith(u); } -bool Quantity::compatibleWith(const Glib::ustring u) const +bool Quantity::compatibleWith(Glib::ustring const &u) const +{ + return compatibleWith(u.c_str()); +} +bool Quantity::compatibleWith(char const *u) const { return compatibleWith(unit_table.getUnit(u)); } -double Quantity::value(const Unit &u) const +double Quantity::value(Unit const &u) const { return convert(quantity, *unit, u); } -double Quantity::value(const Glib::ustring u) const +double Quantity::value(Glib::ustring const &u) const +{ + return value(u.c_str()); +} +double Quantity::value(char const *u) const { return value(unit_table.getUnit(u)); } -Glib::ustring Quantity::string(const Unit &u) const { +Glib::ustring Quantity::string(Unit const &u) const { return Glib::ustring::format(std::fixed, std::setprecision(2), value(u)) + " " + unit->abbr; } -Glib::ustring Quantity::string(const Glib::ustring u) const { - return string(unit_table.getUnit(u)); +Glib::ustring Quantity::string(Glib::ustring const &u) const { + return string(unit_table.getUnit(u.c_str())); } Glib::ustring Quantity::string() const { return string(*unit); } -double Quantity::convert(const double from_dist, const Unit &from, const Unit &to) +double Quantity::convert(double from_dist, Unit const &from, Unit const &to) { // Percentage if (to.type == UNIT_TYPE_DIMENSIONLESS) { @@ -442,38 +485,34 @@ double Quantity::convert(const double from_dist, const Unit &from, const Unit &t // Compatible units return from_dist * from.factor / to.factor; } -double Quantity::convert(const double from_dist, const Glib::ustring from, const Unit &to) +double Quantity::convert(double from_dist, Glib::ustring const &from, Unit const &to) { - return convert(from_dist, unit_table.getUnit(from), to); + return convert(from_dist, unit_table.getUnit(from.c_str()), to); } -double Quantity::convert(const double from_dist, const Unit &from, const Glib::ustring to) +double Quantity::convert(double from_dist, Unit const &from, Glib::ustring const &to) { - return convert(from_dist, from, unit_table.getUnit(to)); + return convert(from_dist, from, unit_table.getUnit(to.c_str())); } -double Quantity::convert(const double from_dist, const Glib::ustring from, const Glib::ustring to) +double Quantity::convert(double from_dist, Glib::ustring const &from, Glib::ustring const &to) { - return convert(from_dist, unit_table.getUnit(from), unit_table.getUnit(to)); + return convert(from_dist, unit_table.getUnit(from.c_str()), unit_table.getUnit(to.c_str())); } - -bool operator< (const Quantity &ql, const Quantity &qr) +double Quantity::convert(double from_dist, char const *from, char const *to) { - if (ql.unit->type != qr.unit->type) { - g_warning("Incompatible units"); - return false; - } - return ql.quantity < qr.value(*ql.unit); + return convert(from_dist, unit_table.getUnit(from), unit_table.getUnit(to)); } -bool operator> (const Quantity &ql, const Quantity &qr) + +bool Quantity::operator<(Quantity const &other) const { - if (ql.unit->type != qr.unit->type) { + if (unit->type != other.unit->type) { g_warning("Incompatible units"); return false; } - return ql.quantity > qr.value(*ql.unit); + return quantity < other.value(*unit); } -bool operator!= (const Quantity &q1, const Quantity &q2) +bool Quantity::operator==(Quantity const &other) const { - return (*q1.unit != *q2.unit) || (q1.quantity != q2.quantity); + return (*unit == *other.unit) && (quantity == other.quantity); } } // namespace Util diff --git a/src/util/units.h b/src/util/units.h index 7ba6e1e86..7566715d8 100644 --- a/src/util/units.h +++ b/src/util/units.h @@ -14,8 +14,10 @@ #define INKSCAPE_UTIL_UNITS_H #include <map> +#include <boost/operators.hpp> #include <glibmm/ustring.h> #include "svg/svg-length.h" +#include "unordered-containers.h" namespace Inkscape { namespace Util { @@ -33,8 +35,10 @@ enum UnitType { const char DEG[] = "°"; -class Unit { - public: +class Unit + : boost::equality_comparable<Unit> +{ +public: Unit(); Unit(UnitType type, double factor, @@ -54,8 +58,9 @@ class Unit { int defaultDigits() const; /** Checks if a unit is compatible with the specified unit. */ - bool compatibleWith(const Unit &u) const; - bool compatibleWith(const Glib::ustring) const; + bool compatibleWith(Unit const &u) const; + bool compatibleWith(Glib::ustring const &) const; + bool compatibleWith(char const *) const; UnitType type; double factor; @@ -65,50 +70,53 @@ class Unit { Glib::ustring description; /** Check if units are equal. */ - friend bool operator== (const Unit &u1, const Unit &u2); - /** Check if units are not equal. */ - friend bool operator!= (const Unit &u1, const Unit &u2); + bool operator==(Unit const &other) const; - /** Get SVG unit. */ + /** Get SVG unit code. */ int svgUnit() const; }; -class Quantity { +class Quantity + : boost::totally_ordered<Quantity> +{ public: - const Unit *unit; + Unit const *unit; double quantity; /** Initialize a quantity. */ - Quantity(double q, const Unit &u); // constructor - Quantity(double q, const Glib::ustring u); // constructor + Quantity(double q, Unit const &u); + Quantity(double q, Glib::ustring const &u); + Quantity(double q, char const *u); /** Checks if a quantity is compatible with the specified unit. */ - bool compatibleWith(const Unit &u) const; - bool compatibleWith(const Glib::ustring u) const; + bool compatibleWith(Unit const &u) const; + bool compatibleWith(Glib::ustring const &u) const; + bool compatibleWith(char const *u) const; /** Return the quantity's value in the specified unit. */ - double value(const Unit &u) const; - double value(const Glib::ustring u) const; + double value(Unit const &u) const; + double value(Glib::ustring const &u) const; + double value(char const *u) const; /** Return a printable string of the value in the specified unit. */ - Glib::ustring string(const Unit &u) const; - Glib::ustring string(const Glib::ustring u) const; + Glib::ustring string(Unit const &u) const; + Glib::ustring string(Glib::ustring const &u) const; Glib::ustring string() const; /** Convert distances. */ - static double convert(const double from_dist, const Unit &from, const Unit &to); - static double convert(const double from_dist, const Glib::ustring from, const Unit &to); - static double convert(const double from_dist, const Unit &from, const Glib::ustring to); - static double convert(const double from_dist, const Glib::ustring from, const Glib::ustring to); - + static double convert(double from_dist, Unit const &from, Unit const &to); + static double convert(double from_dist, Glib::ustring const &from, Unit const &to); + static double convert(double from_dist, Unit const &from, Glib::ustring const &to); + static double convert(double from_dist, Glib::ustring const &from, Glib::ustring const &to); + static double convert(double from_dist, char const *from, char const *to); + /** Comparison operators. */ - friend bool operator< (const Quantity &ql, const Quantity &qr); - friend bool operator> (const Quantity &ql, const Quantity &qr); - friend bool operator!= (const Quantity &q1, const Quantity &q2); + bool operator<(Quantity const &other) const; + bool operator==(Quantity const &other) const; }; class UnitTable { - public: +public: /** * Initializes the unit tables and identifies the primary unit types. * @@ -117,19 +125,21 @@ class UnitTable { UnitTable(); virtual ~UnitTable(); - typedef std::map<Glib::ustring, Unit*> UnitMap; + typedef INK_UNORDERED_MAP<Glib::ustring, Unit> UnitMap; + typedef INK_UNORDERED_MAP<unsigned, Unit*> UnitCodeMap; /** Add a new unit to the table */ void addUnit(Unit const &u, bool primary); /** Retrieve a given unit based on its string identifier */ - Unit getUnit(Glib::ustring const &name) const; + Unit const &getUnit(Glib::ustring const &name) const; + Unit const &getUnit(char const *name) const; /** Retrieve a given unit based on its SVGLength unit */ - Unit getUnit(SVGLength::Unit const u) const; + Unit const &getUnit(SVGLength::Unit u) const; /** Retrieve a quantity based on its string identifier */ - Quantity getQuantity(Glib::ustring const &q) const; + Quantity parseQuantity(Glib::ustring const &q) const; /** Remove a unit definition from the given unit type table */ bool deleteUnit(Unit const &u); @@ -138,7 +148,7 @@ class UnitTable { bool hasUnit(Glib::ustring const &name) const; /** Provides an iteratable list of items in the given unit table */ - UnitTable::UnitMap units(UnitType type) const; + UnitMap units(UnitType type) const; /** Returns the default unit abbr for the given type */ Glib::ustring primary(UnitType type) const; @@ -159,13 +169,14 @@ class UnitTable { /** Saves the current UnitTable to the given file. */ bool save(std::string const &filename); - protected: - UnitTable::UnitMap _unit_map; +protected: + UnitCodeMap _unit_map; Glib::ustring _primary_unit[UNIT_TYPE_QTY]; double _linear_scale; + static Unit _empty_unit; - private: +private: UnitTable(UnitTable const &t); UnitTable operator=(UnitTable const &t); diff --git a/src/util/unordered-containers.h b/src/util/unordered-containers.h index 6f738f0ce..70d36c4dc 100644 --- a/src/util/unordered-containers.h +++ b/src/util/unordered-containers.h @@ -16,6 +16,8 @@ # include "config.h" #endif +#include <glibmm/ustring.h> + #ifndef DOXYGEN_SHOULD_SKIP_THIS #if defined(HAVE_TR1_UNORDERED_SET) @@ -25,6 +27,17 @@ # define INK_UNORDERED_MAP std::tr1::unordered_map # define INK_HASH std::tr1::hash +namespace std { +namespace tr1 { +template <> +struct hash<Glib::ustring> : public std::unary_function<Glib::ustring, std::size_t> { + std::size_t operator()(Glib::ustring const &s) const { + return hash<std::string>()(s.raw()); + } +}; +} // namespace tr1 +} // namespace std + #elif defined(HAVE_BOOST_UNORDERED_SET) # include <boost/unordered_set.hpp> # include <boost/unordered_map.hpp> @@ -32,6 +45,15 @@ # define INK_UNORDERED_MAP boost::unordered_map # define INK_HASH boost::hash +namespace boost { +template <> +struct hash<Glib::ustring> : public std::unary_function<Glib::ustring, std::size_t> { + std::size_t operator()(Glib::ustring const &s) const { + return hash<std::string>()(s.raw()); + } +}; +} // namespace boost + #elif defined(HAVE_EXT_HASH_SET) # include <functional> @@ -54,6 +76,13 @@ struct hash<T *> : public std::unary_function<T *, std::size_t> { return x + (x >> 3); } }; + +template <> +struct hash<Glib::ustring> : public std::unary_function<Glib::ustring, std::size_t> { + std::size_t operator()(Glib::ustring const &s) const { + return hash<std::string>()(s.raw()); + } +}; } // namespace __gnu_cxx #endif |
