units.h revision 9622b20e1241107619ee74c18f5e4a65e2f863cb
/*
* Inkscape Units
* These classes are used for defining different unit systems.
*
* Authors:
* Matthew Petroff <matthew@mpetroff.net>
*
* Copyright (C) 2013 Matthew Petroff
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifndef INKSCAPE_UTIL_UNITS_H
#define INKSCAPE_UTIL_UNITS_H
#include <map>
#include <boost/operators.hpp>
#include <glibmm/ustring.h>
#include <2geom/coord.h>
#include "svg/svg-length.h"
#include "unordered-containers.h"
namespace Inkscape {
namespace Util {
enum UnitType {
UNIT_TYPE_DIMENSIONLESS, /* Percentage */
UNIT_TYPE_LINEAR,
UNIT_TYPE_LINEAR_SCALED,
UNIT_TYPE_RADIAL,
UNIT_TYPE_TIME,
UNIT_TYPE_FONT_HEIGHT,
UNIT_TYPE_QTY,
UNIT_TYPE_NONE = -1
};
const char DEG[] = "°";
class Unit
: boost::equality_comparable<Unit>
{
public:
Unit();
Unit(UnitType type,
double factor,
Glib::ustring const &name,
Glib::ustring const &name_plural,
Glib::ustring const &abbr,
Glib::ustring const &description);
void clear();
bool isAbsolute() const { return type != UNIT_TYPE_DIMENSIONLESS; }
/**
* Returns the suggested precision to use for displaying numbers
* of this unit.
*/
int defaultDigits() const;
/** Checks if a unit is compatible with the specified unit. */
bool compatibleWith(Unit const *u) const;
bool compatibleWith(Glib::ustring const &) const;
bool compatibleWith(char const *) const;
UnitType type;
double factor;
Glib::ustring name;
Glib::ustring name_plural;
Glib::ustring abbr;
Glib::ustring description;
/** Check if units are equal. */
bool operator==(Unit const &other) const;
/** Get SVG unit code. */
int svgUnit() const;
};
class Quantity
: boost::totally_ordered<Quantity>
{
public:
Unit const *unit;
double quantity;
/** Initialize a quantity. */
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(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(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(Unit const *u) const;
Glib::ustring string(Glib::ustring const &u) const;
Glib::ustring string() const;
/** Convert distances.
no NULL check is performed on the passed pointers to Unit objects! */
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. */
bool operator<(Quantity const &rhs) const;
bool operator==(Quantity const &other) const;
};
inline bool are_near(Quantity const &a, Quantity const &b, double eps=Geom::EPSILON)
{
return Geom::are_near(a.quantity, b.value(a.unit), eps);
}
class UnitTable {
public:
/**
* Initializes the unit tables and identifies the primary unit types.
*
* The primary unit's conversion factor is required to be 1.00
*/
UnitTable();
virtual ~UnitTable();
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 const *getUnit(Glib::ustring const &name) const;
Unit const *getUnit(char const *name) const;
/** Retrieve a given unit based on its SVGLength unit */
Unit const *getUnit(SVGLength::Unit u) const;
/** Retrieve a quantity based on its string identifier */
Quantity parseQuantity(Glib::ustring const &q) const;
/** Remove a unit definition from the given unit type table * /
* DISABLED, unsafe with the current passing around pointers to Unit objects in this table */
//bool deleteUnit(Unit const &u);
/** Returns true if the given string 'name' is a valid unit in the table */
bool hasUnit(Glib::ustring const &name) const;
/** Provides an iteratable list of items in the given unit table */
UnitMap units(UnitType type) const;
/** Returns the default unit abbr for the given type */
Glib::ustring primary(UnitType type) const;
double getScale() const;
void setScale();
/** Load units from an XML file.
*
* Loads and merges the contents of the given file into the UnitTable,
* possibly overwriting existing unit definitions.
*
* @param filename file to be loaded
*/
bool load(std::string const &filename);
/* * Saves the current UnitTable to the given file. */
//bool save(std::string const &filename);
protected:
UnitCodeMap _unit_map;
Glib::ustring _primary_unit[UNIT_TYPE_QTY];
double _linear_scale;
static Unit _empty_unit;
private:
UnitTable(UnitTable const &t);
UnitTable operator=(UnitTable const &t);
};
extern UnitTable unit_table;
} // namespace Util
} // namespace Inkscape
#endif // define INKSCAPE_UTIL_UNITS_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :