~ubuntu-branches/ubuntu/vivid/rawstudio/vivid

« back to all changes in this revision

Viewing changes to src/rs-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2011-07-28 17:36:32 UTC
  • mfrom: (2.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110728173632-5czluz9ye3c83zc5
Tags: 2.0-1
* [3750b2cf] Merge commit 'upstream/2.0'
* [63637468] Removing Patch, not necessary anymore.
* [2fb580dc] Add new build-dependencies.
* [c57d953b] Run dh_autoreconf due to patches in configure.in
* [13febe39] Add patch to remove the libssl requirement.
* [5ae773fe] Replace libjpeg62-dev by libjpeg8-dev :)
* [1969d755] Don't build static libraries.
* [7cfe0a2e] Add a patch to fix the plugin directory path.
  As plugins are shared libraries, they need to go into /usr/lib,
  not into /usr/share.
  Thanks to Andrew McMillan
* [c1d0d9dd] Don't install .la files for all plugins and libraries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2006-2009 Anders Brander <anders@brander.dk> and 
3
 
 * Anders Kvist <akv@lnxbx.dk>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU General Public License
7
 
 * as published by the Free Software Foundation; either version 2
8
 
 * of the License, or (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
 
 */
19
 
 
20
 
#define _XOPEN_SOURCE /* strptime() */
21
 
#include <config.h>
22
 
#include <glib.h>
23
 
#include <glib/gstdio.h>
24
 
#include <time.h>
25
 
#include "conf_interface.h"
26
 
#include "rs-utils.h"
27
 
 
28
 
#define DOTDIR ".rawstudio"
29
 
 
30
 
/**
31
 
 * A version of atof() that isn't locale specific
32
 
 * @note This doesn't do any error checking!
33
 
 * @param str A NULL terminated string representing a number
34
 
 * @return The number represented by str or 0.0 if str is NULL
35
 
 */
36
 
gdouble
37
 
rs_atof(const gchar *str)
38
 
{
39
 
        gdouble result = 0.0f;
40
 
        gdouble div = 1.0f;
41
 
        gboolean point_passed = FALSE;
42
 
 
43
 
        gchar *ptr = (gchar *) str;
44
 
 
45
 
        while(str && *ptr)
46
 
        {
47
 
                if (g_ascii_isdigit(*ptr))
48
 
                {
49
 
                        result = result * 10.0f + g_ascii_digit_value(*ptr);
50
 
                        if (point_passed)
51
 
                                div *= 10.0f;
52
 
                }
53
 
                else if (*ptr == '-')
54
 
                        div *= -1.0f;
55
 
                else if (g_ascii_ispunct(*ptr))
56
 
                        point_passed = TRUE;
57
 
                ptr++;
58
 
        }
59
 
 
60
 
        return result / div;
61
 
}
62
 
 
63
 
/**
64
 
 * A convenience function to convert an EXIF timestamp to a unix timestamp.
65
 
 * @note This will only work until 2038 unless glib fixes its GTime
66
 
 * @param str A NULL terminated string containing a timestamp in the format "YYYY:MM:DD HH:MM:SS" (EXIF 2.2 section 4.6.4)
67
 
 * @return A unix timestamp or -1 on error
68
 
 */
69
 
GTime
70
 
rs_exiftime_to_unixtime(const gchar *str)
71
 
{
72
 
        struct tm *tm = g_new0(struct tm, 1);
73
 
        GTime timestamp = -1;
74
 
 
75
 
        if (strptime(str, "%Y:%m:%d %H:%M:%S", tm))
76
 
                timestamp = (GTime) mktime(tm);
77
 
 
78
 
        g_free(tm);
79
 
 
80
 
        return timestamp;
81
 
}
82
 
 
83
 
/**
84
 
 * A convenience function to convert an unix timestamp to an EXIF timestamp.
85
 
 * @note This will only work until 2038 unless glib fixes its GTime
86
 
 * @param timestamp A unix timestamp
87
 
 * @return A string formatted as specified in EXIF 2.2 section 4.6.4
88
 
 */
89
 
gchar *
90
 
rs_unixtime_to_exiftime(GTime timestamp)
91
 
{
92
 
        struct tm *tm = g_new0(struct tm, 1);
93
 
        time_t tt = (time_t) timestamp;
94
 
        gchar *result = g_new0(gchar, 20);
95
 
 
96
 
        gmtime_r(&tt, tm);
97
 
 
98
 
        if (strftime(result, 20, "%Y:%m:%d %H:%M:%S", tm) != 19)
99
 
        {
100
 
                g_free(result);
101
 
                result = NULL;
102
 
        }
103
 
 
104
 
        g_free(tm);
105
 
 
106
 
        return result;
107
 
}
108
 
 
109
 
/**
110
 
 * Constrains a box to fill a bounding box without changing aspect
111
 
 * @param target_width The width of the bounding box
112
 
 * @param target_height The height of the bounding box
113
 
 * @param width The input and output width
114
 
 * @param height The input and output height
115
 
 */
116
 
void
117
 
rs_constrain_to_bounding_box(gint target_width, gint target_height, gint *width, gint *height)
118
 
{
119
 
        gdouble target_aspect = ((gdouble)target_width) / ((gdouble)target_height);
120
 
        gdouble input_aspect = ((gdouble)*width) / ((gdouble)*height);
121
 
        gdouble scale;
122
 
 
123
 
        if (target_aspect < input_aspect)
124
 
                scale = ((gdouble) *width) / ((gdouble) target_width);
125
 
        else
126
 
                scale = ((gdouble) *height) / ((gdouble) target_height);
127
 
 
128
 
        *width = (gint) ((gdouble)*width) / scale;
129
 
        *height = (gint) ((gdouble)*height) / scale;
130
 
}
131
 
 
132
 
/**
133
 
 * Try to count the number of processor cores in a system.
134
 
 * @note This currently only works for systems with /proc/cpuinfo
135
 
 * @return The numver of cores or 1 if the system is unsupported
136
 
 */
137
 
gint
138
 
rs_get_number_of_processor_cores()
139
 
{
140
 
        static GStaticMutex lock = G_STATIC_MUTEX_INIT;
141
 
 
142
 
        /* We assume processors will not be added/removed during our lifetime */
143
 
        static gint num = 0;
144
 
 
145
 
        g_static_mutex_lock (&lock);
146
 
        if (num == 0)
147
 
        {
148
 
                GIOChannel *io;
149
 
                gchar *line;
150
 
 
151
 
                io = g_io_channel_new_file("/proc/cpuinfo", "r", NULL);
152
 
                if (io)
153
 
                {
154
 
                        /* Count the "processor"-lines, there should be one for each processor/core */
155
 
                        while (G_IO_STATUS_NORMAL == g_io_channel_read_line(io, &line, NULL, NULL, NULL))
156
 
                                if (line)
157
 
                                {
158
 
                                        if (g_str_has_prefix(line, "processor"))
159
 
                                                num++;
160
 
                                        g_free(line);
161
 
                                }
162
 
                        g_io_channel_shutdown(io, FALSE, NULL);
163
 
                        g_io_channel_unref(io);
164
 
                }
165
 
                else
166
 
                        num = 1;
167
 
        }
168
 
        g_static_mutex_unlock (&lock);
169
 
 
170
 
        return num;
171
 
}
172
 
 
173
 
/**
174
 
 * Return a path to the current config directory for Rawstudio - this is the
175
 
 * .rawstudio direcotry in home
176
 
 * @return A path to an existing directory
177
 
 */
178
 
const gchar *
179
 
rs_confdir_get()
180
 
{
181
 
        static gchar *dir = NULL;
182
 
        static GStaticMutex lock = G_STATIC_MUTEX_INIT;
183
 
 
184
 
        g_static_mutex_lock(&lock);
185
 
        if (!dir)
186
 
        {
187
 
                const gchar *home = g_get_home_dir();
188
 
                dir = g_build_filename(home, ".rawstudio", NULL);
189
 
        }
190
 
 
191
 
        g_mkdir_with_parents(dir, 00755);
192
 
        g_static_mutex_unlock(&lock);
193
 
 
194
 
        return dir;
195
 
}
196
 
 
197
 
/**
198
 
 * Return a cache directory for filename
199
 
 * @param filename A complete path to a photo
200
 
 * @return A directory to hold the cache. This is guarenteed to exist
201
 
 */
202
 
gchar *
203
 
rs_dotdir_get(const gchar *filename)
204
 
{
205
 
        gchar *ret;
206
 
        gchar *directory;
207
 
        GString *dotdir;
208
 
        gboolean dotdir_is_local = FALSE;
209
 
        rs_conf_get_boolean(CONF_CACHEDIR_IS_LOCAL, &dotdir_is_local);
210
 
 
211
 
        directory = g_path_get_dirname(filename);
212
 
        if (dotdir_is_local)
213
 
        {
214
 
                dotdir = g_string_new(g_get_home_dir());
215
 
                dotdir = g_string_append(dotdir, G_DIR_SEPARATOR_S);
216
 
                dotdir = g_string_append(dotdir, DOTDIR);
217
 
                dotdir = g_string_append(dotdir, G_DIR_SEPARATOR_S);
218
 
                dotdir = g_string_append(dotdir, directory);
219
 
        }
220
 
        else
221
 
        {
222
 
                dotdir = g_string_new(directory);
223
 
                dotdir = g_string_append(dotdir, G_DIR_SEPARATOR_S);
224
 
                dotdir = g_string_append(dotdir, DOTDIR);
225
 
        }
226
 
 
227
 
        if (!g_file_test(dotdir->str, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
228
 
        {
229
 
                if (g_mkdir_with_parents(dotdir->str, 0700) != 0)
230
 
                        ret = NULL;
231
 
                else
232
 
                        ret = dotdir->str;
233
 
        }
234
 
        else
235
 
                ret = dotdir->str;
236
 
        g_free(directory);
237
 
        g_string_free(dotdir, FALSE);
238
 
        return (ret);
239
 
}
240
 
 
241
 
/**
242
 
 * Normalize a RS_RECT, ie makes sure that x1 < x2 and y1<y2
243
 
 * @param in A RS_RECT to read values from
244
 
 * @param out A RS_RECT to write the values to (can be the same as in)
245
 
 */
246
 
void
247
 
rs_rect_normalize(RS_RECT *in, RS_RECT *out)
248
 
{
249
 
        gint n;
250
 
        gint x1,y1;
251
 
        gint x2,y2;
252
 
 
253
 
        x1 = in->x2;
254
 
        x2 = in->x1;
255
 
        y1 = in->y1;
256
 
        y2 = in->y2;
257
 
 
258
 
        if (x1>x2)
259
 
        {
260
 
                n = x1;
261
 
                x1 = x2;
262
 
                x2 = n;
263
 
        }
264
 
        if (y1>y2)
265
 
        {
266
 
                n = y1;
267
 
                y1 = y2;
268
 
                y2 = n;
269
 
        }
270
 
 
271
 
        out->x1 = x1;
272
 
        out->x2 = x2;
273
 
        out->y1 = y1;
274
 
        out->y2 = y2;
275
 
}
276
 
 
277
 
/**
278
 
 * Flip a RS_RECT
279
 
 * @param in A RS_RECT to read values from
280
 
 * @param out A RS_RECT to write the values to (can be the same as in)
281
 
 * @param w The width of the data OUTSIDE the RS_RECT
282
 
 * @param h The height of the data OUTSIDE the RS_RECT
283
 
 */
284
 
void
285
 
rs_rect_flip(RS_RECT *in, RS_RECT *out, gint w, gint h)
286
 
{
287
 
        gint x1,y1;
288
 
        gint x2,y2;
289
 
 
290
 
        x1 = in->x1;
291
 
        x2 = in->x2;
292
 
        y1 = h - in->y2 - 1;
293
 
        y2 = h - in->y1 - 1;
294
 
 
295
 
        out->x1 = x1;
296
 
        out->x2 = x2;
297
 
        out->y1 = y1;
298
 
        out->y2 = y2;
299
 
        rs_rect_normalize(out, out);
300
 
}
301
 
 
302
 
/**
303
 
 * Mirrors a RS_RECT
304
 
 * @param in A RS_RECT to read values from
305
 
 * @param out A RS_RECT to write the values to (can be the same as in)
306
 
 * @param w The width of the data OUTSIDE the RS_RECT
307
 
 * @param h The height of the data OUTSIDE the RS_RECT
308
 
 */
309
 
void
310
 
rs_rect_mirror(RS_RECT *in, RS_RECT *out, gint w, gint h)
311
 
{
312
 
        gint x1,y1;
313
 
        gint x2,y2;
314
 
 
315
 
        x1 = w - in->x2 - 1;
316
 
        x2 = w - in->x1 - 1;
317
 
        y1 = in->y1;
318
 
        y2 = in->y2;
319
 
 
320
 
        out->x1 = x1;
321
 
        out->x2 = x2;
322
 
        out->y1 = y1;
323
 
        out->y2 = y2;
324
 
        rs_rect_normalize(out, out);
325
 
}
326
 
 
327
 
/**
328
 
 * Rotate a RS_RECT in 90 degrees steps
329
 
 * @param in A RS_RECT to read values from
330
 
 * @param out A RS_RECT to write the values to (can be the same as in)
331
 
 * @param w The width of the data OUTSIDE the RS_RECT
332
 
 * @param h The height of the data OUTSIDE the RS_RECT
333
 
 * @param quarterturns How many times to turn the rect clockwise
334
 
 */
335
 
void
336
 
rs_rect_rotate(RS_RECT *in, RS_RECT *out, gint w, gint h, gint quarterturns)
337
 
{
338
 
        gint x1,y1;
339
 
        gint x2,y2;
340
 
 
341
 
        x1 = in->x2;
342
 
        x2 = in->x1;
343
 
        y1 = in->y1;
344
 
        y2 = in->y2;
345
 
 
346
 
        switch(quarterturns)
347
 
        {
348
 
                case 1:
349
 
                        x1 = h - in->y1-1;
350
 
                        x2 = h - in->y2-1;
351
 
                        y1 = in->x1;
352
 
                        y2 = in->x2;
353
 
                        break;
354
 
                case 2:
355
 
                        x1 = w - in->x1 - 1;
356
 
                        x2 = w - in->x2 - 1;
357
 
                        y1 = h - in->y1 - 1;
358
 
                        y2 = h - in->y2 - 1;
359
 
                        break;
360
 
                case 3:
361
 
                        x1 = in->y1;
362
 
                        x2 = in->y2;
363
 
                        y1 = w - in->x1 - 1;
364
 
                        y2 = w - in->x2 - 1;
365
 
                        break;
366
 
        }
367
 
 
368
 
        out->x1 = x1;
369
 
        out->x2 = x2;
370
 
        out->y1 = y1;
371
 
        out->y2 = y2;
372
 
        rs_rect_normalize(out, out);
373
 
}
374
 
 
375
 
/**
376
 
 * Check (and complain if needed) the Rawstudio install
377
 
 */
378
 
void
379
 
check_install()
380
 
{
381
 
#define TEST_FILE_ACCESS(path) do { if (g_access(path, R_OK)!=0) g_debug("Cannot access %s\n", path);} while (0)
382
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/icons/" PACKAGE ".png");
383
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/overlay_priority1.png");
384
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/overlay_priority2.png");
385
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/overlay_priority3.png");
386
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/overlay_deleted.png");
387
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/overlay_exported.png");
388
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/transform_flip.png");
389
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/transform_mirror.png");
390
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/transform_90.png");
391
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/transform_180.png");
392
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/pixmaps/" PACKAGE "/transform_270.png");
393
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/" PACKAGE "/ui.xml");
394
 
        TEST_FILE_ACCESS(PACKAGE_DATA_DIR "/" PACKAGE "/rawstudio.gtkrc");
395
 
#undef TEST_FILE_ACCESS
396
 
}