tangled
alpha
login
or
join now
pyrox.dev
/
nixpkgs
lol
0
fork
atom
overview
issues
pulls
pipelines
rawtherapee: 5.8 -> 5.9
Weijia Wang
3 years ago
260d6e52
59ec2e61
+62
-384
3 changed files
expand all
collapse all
unified
split
pkgs
applications
graphics
rawtherapee
default.nix
do-not-bundle.patch
fix-6324.patch
+62
-15
pkgs/applications/graphics/rawtherapee/default.nix
···
1
-
{ lib, stdenv, fetchFromGitHub, pkg-config, cmake, pixman, libpthreadstubs, gtkmm3, libXau
2
-
, libXdmcp, lcms2, libiptcdata, libcanberra-gtk3, fftw, expat, pcre, libsigcxx, wrapGAppsHook
3
-
, lensfun, librsvg, gtk-mac-integration
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4
}:
5
6
stdenv.mkDerivation rec {
7
-
version = "5.8";
8
pname = "rawtherapee";
0
9
10
src = fetchFromGitHub {
11
owner = "Beep6581";
12
repo = "RawTherapee";
13
rev = version;
14
-
sha256 = "0d644s4grfia6f3k6y0byd5pwajr12kai2kc280yxi8v3w1b12ik";
15
};
16
17
-
nativeBuildInputs = [ cmake pkg-config wrapGAppsHook ];
0
0
0
0
18
19
-
# This patch is upstream; remove it in 5.9.
20
-
patches = [ ./fix-6324.patch ]
21
-
# Disable upstream-enforced bundling on macOS.
22
-
++ lib.optionals stdenv.isDarwin [ ./do-not-bundle.patch ];
0
0
0
23
24
buildInputs = [
25
-
pixman libpthreadstubs gtkmm3 libXau libXdmcp
26
-
lcms2 libiptcdata fftw expat pcre libsigcxx lensfun librsvg
0
0
0
0
0
0
0
0
0
0
0
27
] ++ lib.optionals stdenv.isLinux [
28
libcanberra-gtk3
29
] ++ lib.optionals stdenv.isDarwin [
···
33
cmakeFlags = [
34
"-DPROC_TARGET_NUMBER=2"
35
"-DCACHE_NAME_SUFFIX=\"\""
0
0
36
];
37
38
-
CMAKE_CXX_FLAGS = "-std=c++11 -Wno-deprecated-declarations -Wno-unused-result";
0
0
0
0
39
40
-
postUnpack = ''
41
-
echo "set(HG_VERSION $version)" > $sourceRoot/ReleaseInfo.cmake
0
0
0
0
42
'';
43
44
meta = {
···
1
+
{ lib
2
+
, stdenv
3
+
, fetchFromGitHub
4
+
, cmake
5
+
, pkg-config
6
+
, wrapGAppsHook
7
+
, makeWrapper
8
+
, pixman
9
+
, libpthreadstubs
10
+
, gtkmm3
11
+
, libXau
12
+
, libXdmcp
13
+
, lcms2
14
+
, libiptcdata
15
+
, fftw
16
+
, expat
17
+
, pcre
18
+
, libsigcxx
19
+
, lensfun
20
+
, librsvg
21
+
, libcanberra-gtk3
22
+
, gtk-mac-integration
23
}:
24
25
stdenv.mkDerivation rec {
0
26
pname = "rawtherapee";
27
+
version = "5.9";
28
29
src = fetchFromGitHub {
30
owner = "Beep6581";
31
repo = "RawTherapee";
32
rev = version;
33
+
hash = "sha256-kdctfjss/DHEcaSDPXcmT20wXTwkI8moRX/i/5wT5Hg=";
34
};
35
36
+
postPatch = ''
37
+
echo "set(HG_VERSION ${version})" > ReleaseInfo.cmake
38
+
substituteInPlace tools/osx/Info.plist.in rtgui/config.h.in \
39
+
--replace "/Applications" "${placeholder "out"}/Applications"
40
+
'';
41
42
+
nativeBuildInputs = [
43
+
cmake
44
+
pkg-config
45
+
wrapGAppsHook
46
+
] ++ lib.optionals stdenv.isDarwin [
47
+
makeWrapper
48
+
];
49
50
buildInputs = [
51
+
pixman
52
+
libpthreadstubs
53
+
gtkmm3
54
+
libXau
55
+
libXdmcp
56
+
lcms2
57
+
libiptcdata
58
+
fftw
59
+
expat
60
+
pcre
61
+
libsigcxx
62
+
lensfun
63
+
librsvg
64
] ++ lib.optionals stdenv.isLinux [
65
libcanberra-gtk3
66
] ++ lib.optionals stdenv.isDarwin [
···
70
cmakeFlags = [
71
"-DPROC_TARGET_NUMBER=2"
72
"-DCACHE_NAME_SUFFIX=\"\""
73
+
] ++ lib.optionals stdenv.isDarwin [
74
+
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${stdenv.hostPlatform.darwinMinVersion}"
75
];
76
77
+
CMAKE_CXX_FLAGS = toString [
78
+
"-std=c++11"
79
+
"-Wno-deprecated-declarations"
80
+
"-Wno-unused-result"
81
+
];
82
83
+
postInstall = lib.optionalString stdenv.isDarwin ''
84
+
mkdir -p $out/Applications/RawTherapee.app $out/bin
85
+
cp -R Release $out/Applications/RawTherapee.app/Contents
86
+
for f in $out/Applications/RawTherapee.app/Contents/MacOS/*; do
87
+
makeWrapper $f $out/bin/$(basename $f)
88
+
done
89
'';
90
91
meta = {
-13
pkgs/applications/graphics/rawtherapee/do-not-bundle.patch
···
1
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
2
-
index 0a55ca6d5..68c059aa5 100644
3
-
--- a/CMakeLists.txt
4
-
+++ b/CMakeLists.txt
5
-
@@ -233,6 +233,6 @@ if(WIN32 OR APPLE)
6
-
endif()
7
-
- set(BUILD_BUNDLE ON FORCE)
8
-
+ set(BUILD_BUNDLE OFF)
9
-
endif()
10
-
11
-
if(NOT DEFINED BUNDLE_BASE_INSTALL_DIR)
12
-
- if(APPLE)
13
-
+ if(FALSE)
···
0
0
0
0
0
0
0
0
0
0
0
0
0
-356
pkgs/applications/graphics/rawtherapee/fix-6324.patch
···
1
-
See:
2
-
https://github.com/Beep6581/RawTherapee/issues/6324
3
-
https://github.com/Beep6581/RawTherapee/commit/2e0137d54243eb729d4a5f939c4320ec8f8f415d
4
-
5
-
diff --git a/rtengine/canon_cr3_decoder.cc b/rtengine/canon_cr3_decoder.cc
6
-
index 6274154cb..98c743dad 100644
7
-
--- a/rtengine/canon_cr3_decoder.cc
8
-
+++ b/rtengine/canon_cr3_decoder.cc
9
-
@@ -662,7 +662,7 @@ std::uint32_t _byteswap_ulong(std::uint32_t x)
10
-
#endif
11
-
12
-
struct LibRaw_abstract_datastream {
13
-
- IMFILE* ifp;
14
-
+ rtengine::IMFILE* ifp;
15
-
16
-
void lock()
17
-
{
18
-
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
19
-
index 812f122b3..5da696af2 100644
20
-
--- a/rtengine/dcraw.cc
21
-
+++ b/rtengine/dcraw.cc
22
-
@@ -2025,7 +2025,7 @@ void CLASS phase_one_load_raw_c()
23
-
#endif
24
-
{
25
-
int len[2], pred[2];
26
-
- IMFILE ifpthr = *ifp;
27
-
+ rtengine::IMFILE ifpthr = *ifp;
28
-
ifpthr.plistener = nullptr;
29
-
30
-
#ifdef _OPENMP
31
-
@@ -3380,7 +3380,7 @@ void CLASS sony_arw2_load_raw()
32
-
{
33
-
uchar *data = new (std::nothrow) uchar[raw_width + 1];
34
-
merror(data, "sony_arw2_load_raw()");
35
-
- IMFILE ifpthr = *ifp;
36
-
+ rtengine::IMFILE ifpthr = *ifp;
37
-
int pos = ifpthr.pos;
38
-
ushort pix[16];
39
-
40
-
@@ -6394,7 +6394,7 @@ int CLASS parse_tiff_ifd (int base)
41
-
unsigned sony_curve[] = { 0,0,0,0,0,4095 };
42
-
unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
43
-
struct jhead jh;
44
-
-/*RT*/ IMFILE *sfp;
45
-
+/*RT*/ rtengine::IMFILE *sfp;
46
-
/*RT*/ int pana_raw = 0;
47
-
48
-
if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
49
-
@@ -6958,7 +6958,7 @@ it under the terms of the one of two licenses as you choose:
50
-
fread (buf, sony_length, 1, ifp);
51
-
sony_decrypt (buf, sony_length/4, 1, sony_key);
52
-
sfp = ifp;
53
-
-/*RT*/ ifp = fopen (buf, sony_length);
54
-
+/*RT*/ ifp = rtengine::fopen (buf, sony_length);
55
-
// if ((ifp = tmpfile())) {
56
-
// fwrite (buf, sony_length, 1, ifp);
57
-
// fseek (ifp, 0, SEEK_SET);
58
-
@@ -7264,7 +7264,7 @@ void CLASS parse_external_jpeg()
59
-
{
60
-
const char *file, *ext;
61
-
char *jname, *jfile, *jext;
62
-
-/*RT*/ IMFILE *save=ifp;
63
-
+/*RT*/ rtengine::IMFILE *save=ifp;
64
-
65
-
ext = strrchr (ifname, '.');
66
-
file = strrchr (ifname, '/');
67
-
@@ -7292,7 +7292,7 @@ void CLASS parse_external_jpeg()
68
-
*jext = '0';
69
-
}
70
-
if (strcmp (jname, ifname)) {
71
-
-/*RT*/ if ((ifp = fopen (jname))) {
72
-
+/*RT*/ if ((ifp = rtengine::fopen (jname))) {
73
-
// if ((ifp = fopen (jname, "rb"))) {
74
-
if (verbose)
75
-
fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
76
-
diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h
77
-
index 89c1fcaff..f25157088 100644
78
-
--- a/rtengine/dcraw.h
79
-
+++ b/rtengine/dcraw.h
80
-
@@ -73,7 +73,7 @@ public:
81
-
82
-
protected:
83
-
int exif_base, ciff_base, ciff_len;
84
-
- IMFILE *ifp;
85
-
+ rtengine::IMFILE *ifp;
86
-
FILE *ofp;
87
-
short order;
88
-
const char *ifname;
89
-
@@ -125,7 +125,7 @@ protected:
90
-
int cur_buf_size; // buffer size
91
-
uchar *cur_buf; // currently read block
92
-
int fillbytes; // Counter to add extra byte for block size N*16
93
-
- IMFILE *input;
94
-
+ rtengine::IMFILE *input;
95
-
struct int_pair grad_even[3][41]; // tables of gradients
96
-
struct int_pair grad_odd[3][41];
97
-
ushort *linealloc;
98
-
@@ -278,7 +278,7 @@ void parse_redcine();
99
-
class getbithuff_t
100
-
{
101
-
public:
102
-
- getbithuff_t(DCraw *p,IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){}
103
-
+ getbithuff_t(DCraw *p,rtengine::IMFILE *&i, unsigned &z):parent(p),bitbuf(0),vbits(0),reset(0),ifp(i),zero_after_ff(z){}
104
-
unsigned operator()(int nbits, ushort *huff);
105
-
106
-
private:
107
-
@@ -288,7 +288,7 @@ private:
108
-
DCraw *parent;
109
-
unsigned bitbuf;
110
-
int vbits, reset;
111
-
- IMFILE *&ifp;
112
-
+ rtengine::IMFILE *&ifp;
113
-
unsigned &zero_after_ff;
114
-
};
115
-
getbithuff_t getbithuff;
116
-
@@ -296,7 +296,7 @@ getbithuff_t getbithuff;
117
-
class nikbithuff_t
118
-
{
119
-
public:
120
-
- explicit nikbithuff_t(IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){}
121
-
+ explicit nikbithuff_t(rtengine::IMFILE *&i):bitbuf(0),errors(0),vbits(0),ifp(i){}
122
-
void operator()() {bitbuf = vbits = 0;};
123
-
unsigned operator()(int nbits, ushort *huff);
124
-
unsigned errorCount() { return errors; }
125
-
@@ -309,7 +309,7 @@ private:
126
-
}
127
-
unsigned bitbuf, errors;
128
-
int vbits;
129
-
- IMFILE *&ifp;
130
-
+ rtengine::IMFILE *&ifp;
131
-
};
132
-
nikbithuff_t nikbithuff;
133
-
134
-
@@ -378,7 +378,7 @@ void parse_qt (int end);
135
-
// ph1_bithuff(int nbits, ushort *huff);
136
-
class ph1_bithuff_t {
137
-
public:
138
-
- ph1_bithuff_t(DCraw *p, IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){}
139
-
+ ph1_bithuff_t(DCraw *p, rtengine::IMFILE *i, short &o):order(o),ifp(i),bitbuf(0),vbits(0){}
140
-
unsigned operator()(int nbits, ushort *huff);
141
-
unsigned operator()(int nbits);
142
-
unsigned operator()();
143
-
@@ -412,7 +412,7 @@ private:
144
-
}
145
-
146
-
short ℴ
147
-
- IMFILE* const ifp;
148
-
+ rtengine::IMFILE* const ifp;
149
-
UINT64 bitbuf;
150
-
int vbits;
151
-
};
152
-
@@ -430,11 +430,11 @@ void nokia_load_raw();
153
-
154
-
class pana_bits_t{
155
-
public:
156
-
- pana_bits_t(IMFILE *i, unsigned &u, unsigned enc):
157
-
+ pana_bits_t(rtengine::IMFILE *i, unsigned &u, unsigned enc):
158
-
ifp(i), load_flags(u), vbits(0), encoding(enc) {}
159
-
unsigned operator()(int nbits, unsigned *bytes=nullptr);
160
-
private:
161
-
- IMFILE *ifp;
162
-
+ rtengine::IMFILE *ifp;
163
-
unsigned &load_flags;
164
-
uchar buf[0x4000];
165
-
int vbits;
166
-
diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
167
-
index 1fb1d2e1b..951df2248 100644
168
-
--- a/rtengine/dfmanager.cc
169
-
+++ b/rtengine/dfmanager.cc
170
-
@@ -540,7 +540,7 @@ std::vector<badPix> *DFManager::getHotPixels ( const std::string &mak, const std
171
-
172
-
int DFManager::scanBadPixelsFile( Glib::ustring filename )
173
-
{
174
-
- FILE *file = fopen( filename.c_str(), "r" );
175
-
+ FILE *file = ::fopen( filename.c_str(), "r" );
176
-
177
-
if( !file ) {
178
-
return false;
179
-
diff --git a/rtengine/myfile.cc b/rtengine/myfile.cc
180
-
index 842766dcf..2321d18bb 100644
181
-
--- a/rtengine/myfile.cc
182
-
+++ b/rtengine/myfile.cc
183
-
@@ -70,7 +70,7 @@ int munmap(void *start, size_t length)
184
-
185
-
#ifdef MYFILE_MMAP
186
-
187
-
-IMFILE* fopen (const char* fname)
188
-
+rtengine::IMFILE* rtengine::fopen (const char* fname)
189
-
{
190
-
int fd;
191
-
192
-
@@ -123,13 +123,13 @@ IMFILE* fopen (const char* fname)
193
-
return mf;
194
-
}
195
-
196
-
-IMFILE* gfopen (const char* fname)
197
-
+rtengine::IMFILE* rtengine::gfopen (const char* fname)
198
-
{
199
-
return fopen(fname);
200
-
}
201
-
#else
202
-
203
-
-IMFILE* fopen (const char* fname)
204
-
+rtengine::IMFILE* rtengine::fopen (const char* fname)
205
-
{
206
-
207
-
FILE* f = g_fopen (fname, "rb");
208
-
@@ -152,7 +152,7 @@ IMFILE* fopen (const char* fname)
209
-
return mf;
210
-
}
211
-
212
-
-IMFILE* gfopen (const char* fname)
213
-
+rtengine::IMFILE* rtengine::gfopen (const char* fname)
214
-
{
215
-
216
-
FILE* f = g_fopen (fname, "rb");
217
-
@@ -176,7 +176,7 @@ IMFILE* gfopen (const char* fname)
218
-
}
219
-
#endif //MYFILE_MMAP
220
-
221
-
-IMFILE* fopen (unsigned* buf, int size)
222
-
+rtengine::IMFILE* rtengine::fopen (unsigned* buf, int size)
223
-
{
224
-
225
-
IMFILE* mf = new IMFILE;
226
-
@@ -190,7 +190,7 @@ IMFILE* fopen (unsigned* buf, int size)
227
-
return mf;
228
-
}
229
-
230
-
-void fclose (IMFILE* f)
231
-
+void rtengine::fclose (IMFILE* f)
232
-
{
233
-
#ifdef MYFILE_MMAP
234
-
235
-
@@ -207,7 +207,7 @@ void fclose (IMFILE* f)
236
-
delete f;
237
-
}
238
-
239
-
-int fscanf (IMFILE* f, const char* s ...)
240
-
+int rtengine::fscanf (IMFILE* f, const char* s ...)
241
-
{
242
-
// fscanf not easily wrapped since we have no terminating \0 at end
243
-
// of file data and vsscanf() won't tell us how many characters that
244
-
@@ -253,7 +253,7 @@ int fscanf (IMFILE* f, const char* s ...)
245
-
}
246
-
247
-
248
-
-char* fgets (char* s, int n, IMFILE* f)
249
-
+char* rtengine::fgets (char* s, int n, IMFILE* f)
250
-
{
251
-
252
-
if (f->pos >= f->size) {
253
-
@@ -270,7 +270,7 @@ char* fgets (char* s, int n, IMFILE* f)
254
-
return s;
255
-
}
256
-
257
-
-void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range)
258
-
+void rtengine::imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range)
259
-
{
260
-
f->plistener = plistener;
261
-
f->progress_range = progress_range;
262
-
@@ -278,7 +278,7 @@ void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, doub
263
-
f->progress_current = 0;
264
-
}
265
-
266
-
-void imfile_update_progress(IMFILE *f)
267
-
+void rtengine::imfile_update_progress(IMFILE *f)
268
-
{
269
-
if (!f->plistener || f->progress_current < f->progress_next) {
270
-
return;
271
-
diff --git a/rtengine/myfile.h b/rtengine/myfile.h
272
-
index 423edea9a..c655696e6 100644
273
-
--- a/rtengine/myfile.h
274
-
+++ b/rtengine/myfile.h
275
-
@@ -30,8 +30,6 @@ namespace rtengine
276
-
277
-
class ProgressListener;
278
-
279
-
-}
280
-
-
281
-
struct IMFILE {
282
-
int fd;
283
-
ssize_t pos;
284
-
@@ -141,3 +139,5 @@ inline unsigned char* fdata(int offset, IMFILE* f)
285
-
286
-
int fscanf (IMFILE* f, const char* s ...);
287
-
char* fgets (char* s, int n, IMFILE* f);
288
-
+
289
-
+}
290
-
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
291
-
index 9da601e2a..097b9e711 100644
292
-
--- a/rtengine/rtthumbnail.cc
293
-
+++ b/rtengine/rtthumbnail.cc
294
-
@@ -1922,7 +1922,7 @@ bool Thumbnail::writeImage (const Glib::ustring& fname)
295
-
296
-
Glib::ustring fullFName = fname + ".rtti";
297
-
298
-
- FILE* f = g_fopen (fullFName.c_str (), "wb");
299
-
+ FILE* f = ::g_fopen (fullFName.c_str (), "wb");
300
-
301
-
if (!f) {
302
-
return false;
303
-
@@ -1965,7 +1965,7 @@ bool Thumbnail::readImage (const Glib::ustring& fname)
304
-
return false;
305
-
}
306
-
307
-
- FILE* f = g_fopen(fullFName.c_str (), "rb");
308
-
+ FILE* f = ::g_fopen(fullFName.c_str (), "rb");
309
-
310
-
if (!f) {
311
-
return false;
312
-
@@ -2191,7 +2191,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname)
313
-
return false;
314
-
}
315
-
316
-
- FILE *f = g_fopen (fname.c_str (), "wt");
317
-
+ FILE *f = ::g_fopen (fname.c_str (), "wt");
318
-
319
-
if (!f) {
320
-
if (settings->verbose) {
321
-
@@ -2214,7 +2214,7 @@ bool Thumbnail::readEmbProfile (const Glib::ustring& fname)
322
-
embProfile = nullptr;
323
-
embProfileLength = 0;
324
-
325
-
- FILE* f = g_fopen (fname.c_str (), "rb");
326
-
+ FILE* f = ::g_fopen (fname.c_str (), "rb");
327
-
328
-
if (f) {
329
-
if (!fseek (f, 0, SEEK_END)) {
330
-
@@ -2242,7 +2242,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname)
331
-
{
332
-
333
-
if (embProfileData) {
334
-
- FILE* f = g_fopen (fname.c_str (), "wb");
335
-
+ FILE* f = ::g_fopen (fname.c_str (), "wb");
336
-
337
-
if (f) {
338
-
fwrite (embProfileData, 1, embProfileLength, f);
339
-
@@ -2257,7 +2257,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname)
340
-
bool Thumbnail::readAEHistogram (const Glib::ustring& fname)
341
-
{
342
-
343
-
- FILE* f = g_fopen(fname.c_str(), "rb");
344
-
+ FILE* f = ::g_fopen(fname.c_str(), "rb");
345
-
346
-
if (!f) {
347
-
aeHistogram.reset();
348
-
@@ -2280,7 +2280,7 @@ bool Thumbnail::writeAEHistogram (const Glib::ustring& fname)
349
-
{
350
-
351
-
if (aeHistogram) {
352
-
- FILE* f = g_fopen (fname.c_str (), "wb");
353
-
+ FILE* f = ::g_fopen (fname.c_str (), "wb");
354
-
355
-
if (f) {
356
-
fwrite (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof (aeHistogram[0]), f);
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0