~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu5

« back to all changes in this revision

Viewing changes to src/helper/units.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Wolfram Quester
  • Date: 2004-06-02 10:35:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040602103545-q3x0q6xd2k1yj0fr
Tags: upstream-0.38.1
ImportĀ upstreamĀ versionĀ 0.38.1

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
 *
 
13
 * Copyright 1999-2001 Ximian, Inc. and authors
 
14
 *
 
15
 */
 
16
 
 
17
#include <config.h>
 
18
 
 
19
#include <math.h>
 
20
#include <string.h>
 
21
#include <glib.h>
 
22
#include "units.h"
 
23
#include "sp-intl.h"
 
24
 
 
25
/* fixme: use some fancy unit program */
 
26
 
 
27
/*
 
28
 * WARNING! Do not mess up with that - we use hardcoded numbers for base units!
 
29
 */
 
30
 
 
31
enum {
 
32
        SP_UNIT_BASE_DIMENSIONLESS,
 
33
        SP_UNIT_BASE_ABSOLUTE,
 
34
        SP_UNIT_BASE_DEVICE,
 
35
        SP_UNIT_BASE_USERSPACE
 
36
};
 
37
 
 
38
static const SPUnit sp_units[] = {
 
39
        /* Do not insert any elements before/between first 4 */
 
40
        {0, SP_UNIT_DIMENSIONLESS, 1.0, N_("Unit"), "", N_("Units"), ""},
 
41
        {0, SP_UNIT_ABSOLUTE, 1.0, N_("Point"), N_("pt"), N_("Points"), N_("Pt")},
 
42
        {0, SP_UNIT_DEVICE, 1.0, N_("Pixel"), N_("px"), N_("Pixels"), N_("Px")},
 
43
        {0, SP_UNIT_USERSPACE, 1.0, N_("Userspace unit"), N_("User"), N_("Userspace units"), N_("User")},
 
44
        /* Volatiles do not have default, so there are none here */
 
45
        /* You can add new elements from this point forward */
 
46
        {0, SP_UNIT_DIMENSIONLESS, 0.01, N_("Percent"), N_("%"), N_("Percents"), N_("%")},
 
47
        {0, SP_UNIT_ABSOLUTE, (72.0 / 25.4), N_("Millimeter"), N_("mm"), N_("Millimeters"), N_("mm")},
 
48
        {0, SP_UNIT_ABSOLUTE, (72.0 / 2.54), N_("Centimeter"), N_("cm"), N_("Centimeters"), N_("cm")},
 
49
        {0, SP_UNIT_ABSOLUTE, (72.0 / 0.0254), N_("Meter"), N_("m"), N_("meters"), N_("m")},
 
50
        {0, SP_UNIT_ABSOLUTE, (72.0), N_("Inch"), N_("in"), N_("Inches"), N_("in")},
 
51
        {0, SP_UNIT_VOLATILE, 1.0, N_("Em square"), N_("em"), N_("Em squares"), N_("em")},
 
52
        {0, SP_UNIT_VOLATILE, 1.0, N_("Ex square"), N_("ex"), N_("Ex squares"), N_("ex")},
 
53
};
 
54
 
 
55
#define sp_num_units (sizeof (sp_units) / sizeof (sp_units[0]))
 
56
 
 
57
/* Base units are the ones used by gnome-print and paper descriptions */
 
58
 
 
59
const SPUnit *
 
60
sp_unit_get_identity (guint base)
 
61
{
 
62
        switch (base) {
 
63
        case SP_UNIT_DIMENSIONLESS:
 
64
                return &sp_units[SP_UNIT_BASE_DIMENSIONLESS];
 
65
                break;
 
66
        case SP_UNIT_ABSOLUTE:
 
67
                return &sp_units[SP_UNIT_BASE_ABSOLUTE];
 
68
                break;
 
69
        case SP_UNIT_DEVICE:
 
70
                return &sp_units[SP_UNIT_BASE_DEVICE];
 
71
                break;
 
72
        case SP_UNIT_USERSPACE:
 
73
                return &sp_units[SP_UNIT_BASE_USERSPACE];
 
74
                break;
 
75
        default:
 
76
                g_warning ("file %s: line %d: Illegal unit base %d", __FILE__, __LINE__, base);
 
77
                return NULL;
 
78
                break;
 
79
        }
 
80
}
 
81
 
 
82
/* fixme: */
 
83
const SPUnit *
 
84
sp_unit_get_default (void)
 
85
{
 
86
        return &sp_units[0];
 
87
}
 
88
 
 
89
const SPUnit *
 
90
sp_unit_get_by_name (const gchar *name)
 
91
{
 
92
        gint i;
 
93
 
 
94
        g_return_val_if_fail (name != NULL, NULL);
 
95
 
 
96
        for (i = 0 ; i < static_cast< gint > sp_num_units ; i++) {
 
97
                if (!g_strcasecmp (name, sp_units[i].name)) return &sp_units[i];
 
98
                if (!g_strcasecmp (name, sp_units[i].plural)) return &sp_units[i];
 
99
        }
 
100
 
 
101
        return NULL;
 
102
}
 
103
 
 
104
const SPUnit *
 
105
sp_unit_get_by_abbreviation (const gchar *abbreviation)
 
106
{
 
107
        gint i;
 
108
 
 
109
        g_return_val_if_fail (abbreviation != NULL, NULL);
 
110
 
 
111
        for (i = 0 ; i < static_cast< gint > sp_num_units ; i++) {
 
112
                if (!g_strcasecmp (abbreviation, sp_units[i].abbr)) return &sp_units[i];
 
113
                if (!g_strcasecmp (abbreviation, sp_units[i].abbr_plural)) return &sp_units[i];
 
114
        }
 
115
 
 
116
        return NULL;
 
117
}
 
118
 
 
119
GSList *
 
120
sp_unit_get_list (guint bases)
 
121
{
 
122
        GSList *units;
 
123
        gint i;
 
124
 
 
125
        g_return_val_if_fail ((bases & ~SP_UNITS_ALL) == 0, NULL);
 
126
 
 
127
        units = NULL;
 
128
 
 
129
        for (i = 0; i < static_cast< gint > sp_num_units ; i++) {
 
130
                if (bases & sp_units[i].base) {
 
131
                        units = g_slist_prepend (units, (gpointer) &sp_units[i]);
 
132
                }
 
133
        }
 
134
 
 
135
        units = g_slist_reverse (units);
 
136
 
 
137
        return units;
 
138
}
 
139
 
 
140
void
 
141
sp_unit_free_list (GSList *units)
 
142
{
 
143
        g_slist_free (units);
 
144
}
 
145
 
 
146
/* These are pure utility */
 
147
/* Return TRUE if conversion is possible */
 
148
gboolean
 
149
sp_convert_distance (gdouble *distance, const SPUnit *from, const SPUnit *to)
 
150
{
 
151
        g_return_val_if_fail (distance != NULL, FALSE);
 
152
        g_return_val_if_fail (from != NULL, FALSE);
 
153
        g_return_val_if_fail (to != NULL, FALSE);
 
154
 
 
155
        if (from == to) return TRUE;
 
156
        if ((from->base == SP_UNIT_DIMENSIONLESS) || (to->base == SP_UNIT_DIMENSIONLESS)) {
 
157
                *distance = *distance * from->unittobase / to->unittobase;
 
158
                return TRUE;
 
159
        }
 
160
        if (from->base != to->base) return FALSE;
 
161
        if ((from->base == SP_UNIT_VOLATILE) || (to->base == SP_UNIT_VOLATILE)) return FALSE;
 
162
 
 
163
        *distance = *distance * from->unittobase / to->unittobase;
 
164
 
 
165
        return TRUE;
 
166
}
 
167
 
 
168
/* ctm is for userspace, devicetransform is for device units */
 
169
gboolean
 
170
sp_convert_distance_full (gdouble *distance, const SPUnit *from, const SPUnit *to,
 
171
                                   gdouble ctmscale, gdouble devicescale)
 
172
{
 
173
        gdouble absolute;
 
174
 
 
175
        g_return_val_if_fail (distance != NULL, FALSE);
 
176
        g_return_val_if_fail (from != NULL, FALSE);
 
177
        g_return_val_if_fail (to != NULL, FALSE);
 
178
 
 
179
        if (from == to) return TRUE;
 
180
        if (from->base == to->base) return sp_convert_distance (distance, from, to);
 
181
        if ((from->base == SP_UNIT_DIMENSIONLESS) || (to->base == SP_UNIT_DIMENSIONLESS)) {
 
182
                *distance = *distance * from->unittobase / to->unittobase;
 
183
                return TRUE;
 
184
        }
 
185
        if ((from->base == SP_UNIT_VOLATILE) || (to->base == SP_UNIT_VOLATILE)) return FALSE;
 
186
 
 
187
        switch (from->base) {
 
188
        case SP_UNIT_ABSOLUTE:
 
189
                absolute = *distance * from->unittobase;
 
190
                break;
 
191
        case SP_UNIT_DEVICE:
 
192
                if (devicescale) {
 
193
                        absolute = *distance * from->unittobase * devicescale;
 
194
                } else {
 
195
                        return FALSE;
 
196
                }
 
197
                break;
 
198
        case SP_UNIT_USERSPACE:
 
199
                if (ctmscale) {
 
200
                        absolute = *distance * from->unittobase * ctmscale;
 
201
                } else {
 
202
                        return FALSE;
 
203
                }
 
204
                break;
 
205
        default:
 
206
                g_warning ("file %s: line %d: Illegal unit (base %d)", __FILE__, __LINE__, from->base);
 
207
                return FALSE;
 
208
                break;
 
209
        }
 
210
 
 
211
        switch (to->base) {
 
212
        case SP_UNIT_DIMENSIONLESS:
 
213
        case SP_UNIT_ABSOLUTE:
 
214
                *distance = absolute / to->unittobase;
 
215
                break;
 
216
        case SP_UNIT_DEVICE:
 
217
                if (devicescale) {
 
218
                        *distance = absolute / (to->unittobase * devicescale);
 
219
                } else {
 
220
                        return FALSE;
 
221
                }
 
222
                break;
 
223
        case SP_UNIT_USERSPACE:
 
224
                if (ctmscale) {
 
225
                        *distance = absolute / (to->unittobase * ctmscale);
 
226
                } else {
 
227
                        return FALSE;
 
228
                }
 
229
                break;
 
230
        default:
 
231
                g_warning ("file %s: line %d: Illegal unit (base %d)", __FILE__, __LINE__, to->base);
 
232
                return FALSE;
 
233
                break;
 
234
        }
 
235
 
 
236
        return TRUE;
 
237
}
 
238
 
 
239
/* Some more convenience */
 
240
/* Be careful to not mix bases */
 
241
 
 
242
gdouble
 
243
sp_distance_get_units (SPDistance *distance, const SPUnit *unit)
 
244
{
 
245
        gdouble val;
 
246
 
 
247
        g_return_val_if_fail (distance != NULL, 0.0);
 
248
        g_return_val_if_fail (unit != NULL, 0.0);
 
249
 
 
250
        val = distance->distance;
 
251
        sp_convert_distance (&val, distance->unit, unit);
 
252
 
 
253
        return val;
 
254
}
 
255
 
 
256
gdouble
 
257
sp_distance_get_points (SPDistance *distance)
 
258
{
 
259
        gdouble val;
 
260
 
 
261
        g_return_val_if_fail (distance != NULL, 0.0);
 
262
 
 
263
        val = distance->distance;
 
264
        sp_convert_distance (&val, distance->unit, &sp_units[SP_UNIT_BASE_ABSOLUTE]);
 
265
 
 
266
        return val;
 
267
}
 
268
 
 
269
gdouble
 
270
sp_points_get_units (gdouble points, const SPUnit *unit)
 
271
{
 
272
        sp_convert_distance (&points, &sp_units[SP_UNIT_BASE_ABSOLUTE], unit);
 
273
 
 
274
        return points;
 
275
}
 
276
 
 
277
gdouble
 
278
sp_units_get_points (gdouble units, const SPUnit *unit)
 
279
{
 
280
        sp_convert_distance (&units, unit, &sp_units[SP_UNIT_BASE_ABSOLUTE]);
 
281
 
 
282
        return units;
 
283
}
 
284