~7-eric/inkscape/boolop-fix

« back to all changes in this revision

Viewing changes to src/helper/units.cpp

Merge Google Summer of Code unit refactor.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __SP_PAPER_C__
2
 
 
3
 
/*
4
 
 * SPUnit
5
 
 *
6
 
 * Ported from libgnomeprint
7
 
 *
8
 
 * Authors:
9
 
 *   Dirk Luetjens <dirk@luedi.oche.de>
10
 
 *   Yves Arrouye <Yves.Arrouye@marin.fdn.fr>
11
 
 *   Lauris Kaplinski <lauris@ximian.com>
12
 
 *   bulia byak <buliabyak@users.sf.net>
13
 
 *
14
 
 * Copyright 1999-2001 Ximian, Inc. and authors
15
 
 *
16
 
 */
17
 
 
18
 
#ifdef HAVE_CONFIG_H
19
 
# include "config.h"
20
 
#endif
21
 
 
22
 
#include "helper/units.h"
23
 
#include <glib.h> // g_assert()
24
 
#include <glibmm/i18n.h>
25
 
#include "unit-constants.h"
26
 
#include "svg/svg-length.h"
27
 
 
28
 
/* todo: use some fancy unit program */
29
 
 
30
 
/* The order determines the order of the list returned by sp_unit_get_list.
31
 
 * (It can also affect string lookups if there are any duplicates in the
32
 
 * current locale... hopefully none.)  If you re-order this list, then you must
33
 
 * also re-order the SPUnitId enum values accordingly.  Run `make check' (which
34
 
 * calls sp_unit_table_sane) to ensure that the two are in sync.
35
 
 */
36
 
SPUnit const sp_units[] = {
37
 
    {SP_UNIT_SCALE, SP_UNIT_DIMENSIONLESS, 1.0, SP_NONE, SVGLength::NONE, N_("Unit"), "", N_("Units"), ""},
38
 
    {SP_UNIT_PT, SP_UNIT_ABSOLUTE, PX_PER_PT, SP_PT, SVGLength::PT, N_("Point"), N_("pt"), N_("Points"), N_("Pt")},
39
 
    {SP_UNIT_PC, SP_UNIT_ABSOLUTE, PX_PER_PC, SP_PC, SVGLength::PC, N_("Pica"), N_("pc"), N_("Picas"), N_("Pc")},
40
 
    {SP_UNIT_PX, SP_UNIT_DEVICE, PX_PER_PX, SP_PX, SVGLength::PX, N_("Pixel"), N_("px"), N_("Pixels"), N_("Px")}, 
41
 
    /* You can add new elements from this point forward */
42
 
    {SP_UNIT_PERCENT, SP_UNIT_DIMENSIONLESS, 0.01, SP_NONE, SVGLength::PERCENT, N_("Percent"), N_("%"), N_("Percents"), N_("%")},
43
 
    {SP_UNIT_MM, SP_UNIT_ABSOLUTE, PX_PER_MM, SP_MM, SVGLength::MM, N_("Millimeter"), N_("mm"), N_("Millimeters"), N_("mm")},
44
 
    {SP_UNIT_CM, SP_UNIT_ABSOLUTE, PX_PER_CM, SP_CM, SVGLength::CM, N_("Centimeter"), N_("cm"), N_("Centimeters"), N_("cm")},
45
 
    {SP_UNIT_M, SP_UNIT_ABSOLUTE, PX_PER_M, SP_M, SVGLength::NONE, N_("Meter"), N_("m"), N_("Meters"), N_("m")}, // no svg_unit
46
 
    {SP_UNIT_IN, SP_UNIT_ABSOLUTE, PX_PER_IN, SP_IN, SVGLength::INCH, N_("Inch"), N_("in"), N_("Inches"), N_("in")},
47
 
    {SP_UNIT_FT, SP_UNIT_ABSOLUTE, PX_PER_FT, SP_FT, SVGLength::FOOT, N_("Foot"), N_("ft"), N_("Feet"), N_("ft")},
48
 
    /* Volatiles do not have default, so there are none here */
49
 
    // TRANSLATORS: for info, see http://www.w3.org/TR/REC-CSS2/syndata.html#length-units
50
 
    {SP_UNIT_EM, SP_UNIT_VOLATILE, 1.0, SP_NONE, SVGLength::EM, N_("Em square"), N_("em"), N_("Em squares"), N_("em")},
51
 
    // TRANSLATORS: for info, see http://www.w3.org/TR/REC-CSS2/syndata.html#length-units
52
 
    {SP_UNIT_EX, SP_UNIT_VOLATILE, 1.0, SP_NONE, SVGLength::EX, N_("Ex square"), N_("ex"), N_("Ex squares"), N_("ex")},
53
 
};
54
 
 
55
 
#define sp_num_units G_N_ELEMENTS(sp_units)
56
 
 
57
 
SPUnit const *
58
 
sp_unit_get_by_abbreviation(gchar const *abbreviation)
59
 
{
60
 
    g_return_val_if_fail(abbreviation != NULL, NULL);
61
 
 
62
 
    for (unsigned i = 0 ; i < sp_num_units ; i++) {
63
 
        if (!g_ascii_strcasecmp(abbreviation, sp_units[i].abbr)) return &sp_units[i];
64
 
        if (!g_ascii_strcasecmp(abbreviation, sp_units[i].abbr_plural)) return &sp_units[i];
65
 
    }
66
 
 
67
 
    return NULL;
68
 
}
69
 
 
70
 
gchar const *
71
 
sp_unit_get_abbreviation(SPUnit const *unit)
72
 
{
73
 
    g_return_val_if_fail(unit != NULL, NULL);
74
 
 
75
 
    return unit->abbr;
76
 
}
77
 
 
78
 
gchar const *
79
 
sp_unit_get_plural (SPUnit const *unit)
80
 
{
81
 
    g_return_val_if_fail(unit != NULL, NULL);
82
 
 
83
 
    return unit->plural;
84
 
}
85
 
 
86
 
SPMetric sp_unit_get_metric(SPUnit const *unit)
87
 
{
88
 
    g_return_val_if_fail(unit != NULL, SP_NONE);
89
 
 
90
 
    return unit->metric;
91
 
}
92
 
 
93
 
guint sp_unit_get_svg_unit(SPUnit const *unit)
94
 
{
95
 
    g_return_val_if_fail(unit != NULL, SP_NONE);
96
 
 
97
 
    return unit->svg_unit;
98
 
}
99
 
 
100
 
GSList *
101
 
sp_unit_get_list(guint bases)
102
 
{
103
 
    g_return_val_if_fail((bases & ~SP_UNITS_ALL) == 0, NULL);
104
 
 
105
 
    GSList *units = NULL;
106
 
    for (unsigned i = sp_num_units ; i--; ) {
107
 
        if (bases & sp_units[i].base) {
108
 
            units = g_slist_prepend(units, (gpointer) &sp_units[i]);
109
 
        }
110
 
    }
111
 
 
112
 
    return units;
113
 
}
114
 
 
115
 
void
116
 
sp_unit_free_list(GSList *units)
117
 
{
118
 
    g_slist_free(units);
119
 
}
120
 
 
121
 
/* These are pure utility */
122
 
/* Return TRUE if conversion is possible */
123
 
gboolean
124
 
sp_convert_distance(gdouble *distance, SPUnit const *from, SPUnit const *to)
125
 
{
126
 
    g_return_val_if_fail(distance != NULL, FALSE);
127
 
    g_return_val_if_fail(from != NULL, FALSE);
128
 
    g_return_val_if_fail(to != NULL, FALSE);
129
 
 
130
 
    if (from == to) return TRUE;
131
 
    if ((from->base == SP_UNIT_DIMENSIONLESS) || (to->base == SP_UNIT_DIMENSIONLESS)) {
132
 
        *distance = *distance * from->unittobase / to->unittobase;
133
 
        return TRUE;
134
 
    }
135
 
    if ((from->base == SP_UNIT_VOLATILE) || (to->base == SP_UNIT_VOLATILE)) return FALSE;
136
 
 
137
 
    if ((from->base == to->base)
138
 
        || ((from->base == SP_UNIT_DEVICE) && (to->base == SP_UNIT_ABSOLUTE))
139
 
        || ((from->base == SP_UNIT_ABSOLUTE) && (to->base == SP_UNIT_DEVICE)))
140
 
    {
141
 
        *distance = *distance * from->unittobase / to->unittobase;
142
 
        return TRUE;
143
 
    }
144
 
 
145
 
    return FALSE;
146
 
}
147
 
 
148
 
/** @param devicetransform for device units. */
149
 
/* TODO: Remove the ctmscale parameter given that we no longer have SP_UNIT_USERSPACE. */
150
 
gdouble
151
 
sp_convert_distance_full(gdouble const from_dist, SPUnit const &from, SPUnit const &to)
152
 
{
153
 
    if (&from == &to) {
154
 
        return from_dist;
155
 
    }
156
 
    if (from.base == to.base) {
157
 
        gdouble ret = from_dist;
158
 
        bool const succ = sp_convert_distance(&ret, &from, &to);
159
 
        g_assert(succ);
160
 
        return ret;
161
 
    }
162
 
    if ((from.base == SP_UNIT_DIMENSIONLESS)
163
 
        || (to.base == SP_UNIT_DIMENSIONLESS))
164
 
    {
165
 
        return from_dist * from.unittobase / to.unittobase;
166
 
    }
167
 
    g_return_val_if_fail(((from.base != SP_UNIT_VOLATILE)
168
 
                          && (to.base != SP_UNIT_VOLATILE)),
169
 
                         from_dist);
170
 
 
171
 
    gdouble absolute;
172
 
    switch (from.base) {
173
 
        case SP_UNIT_ABSOLUTE:
174
 
        case SP_UNIT_DEVICE:
175
 
            absolute = from_dist * from.unittobase;
176
 
            break;
177
 
        default:
178
 
            g_warning("file %s: line %d: Illegal unit (base 0x%x)", __FILE__, __LINE__, from.base);
179
 
            return from_dist;
180
 
    }
181
 
 
182
 
    gdouble ret;
183
 
    switch (to.base) {
184
 
        default:
185
 
            g_warning("file %s: line %d: Illegal unit (base 0x%x)", __FILE__, __LINE__, to.base);
186
 
            /* FALL-THROUGH */
187
 
        case SP_UNIT_ABSOLUTE:
188
 
        case SP_UNIT_DEVICE:
189
 
            ret = absolute / to.unittobase;
190
 
            break;
191
 
    }
192
 
 
193
 
    return ret;
194
 
}
195
 
 
196
 
/* Some more convenience */
197
 
 
198
 
gdouble
199
 
sp_units_get_pixels(gdouble const units, SPUnit const &unit)
200
 
{
201
 
    if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) {
202
 
        return units * unit.unittobase;
203
 
    } else {
204
 
        g_warning("Different unit bases: No exact unit conversion available");
205
 
        return units * unit.unittobase;
206
 
    }
207
 
}
208
 
 
209
 
gdouble
210
 
sp_pixels_get_units(gdouble const pixels, SPUnit const &unit)
211
 
{
212
 
    if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) {
213
 
        return pixels / unit.unittobase;
214
 
    } else {
215
 
        g_warning("Different unit bases: No exact unit conversion available");
216
 
        return pixels / unit.unittobase;
217
 
    }
218
 
}
219
 
 
220
 
bool
221
 
sp_units_table_sane()
222
 
{
223
 
    for (unsigned i = 0; i < G_N_ELEMENTS(sp_units); ++i) {
224
 
        if (unsigned(sp_units[i].unit_id) != i) {
225
 
            return false;
226
 
        }
227
 
    }
228
 
    return true;
229
 
}
230
 
 
231
 
/** Converts angle (in deg) to compass display */
232
 
double 
233
 
angle_to_compass(double angle)
234
 
{
235
 
    double ret = 90 - angle;
236
 
    if (ret < 0)
237
 
        ret = 360 + ret;
238
 
    return ret;
239
 
}
240
 
 
241
 
/** Converts angle (in deg) to compass display */
242
 
double 
243
 
angle_from_compass(double angle)
244
 
{
245
 
    double ret = 90 - angle;
246
 
    if (ret > 180)
247
 
        ret = ret - 180;
248
 
    return ret;
249
 
}
250
 
 
251
 
 
252
 
/*
253
 
  Local Variables:
254
 
  mode:c++
255
 
  c-file-style:"stroustrup"
256
 
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
257
 
  indent-tabs-mode:nil
258
 
  fill-column:99
259
 
  End:
260
 
*/
261
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :