Add Flex to views::BoxLayout.
[chromium-blink-merge.git] / third_party / qcms / google.patch
blobaa20bc5f32faae64dae71a1e7150e390f80d02a2
1 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
2 index 36b7011..5876f96 100644
3 --- a/third_party/qcms/src/iccread.c
4 +++ b/third_party/qcms/src/iccread.c
5 @@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
6 if (profile->color_space != RGB_SIGNATURE)
7 return false;
9 - if (profile->A2B0 || profile->B2A0)
10 + if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0))
11 return false;
13 rX = s15Fixed16Number_to_float(profile->redColorant.X);
14 @@ -297,6 +297,11 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
15 sum[1] = rY + gY + bY;
16 sum[2] = rZ + gZ + bZ;
18 +#if defined (_MSC_VER)
19 +#pragma warning(push)
20 +/* Disable double to float truncation warning 4305 */
21 +#pragma warning(disable:4305)
22 +#endif
23 // Build our target vector (see mozilla bug 460629)
24 target[0] = 0.96420;
25 target[1] = 1.00000;
26 @@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
27 tolerance[1] = 0.02;
28 tolerance[2] = 0.04;
30 +#if defined (_MSC_VER)
31 +/* Restore warnings */
32 +#pragma warning(pop)
33 +#endif
34 // Compare with our tolerance
35 for (i = 0; i < 3; ++i) {
36 if (!(((sum[i] - tolerance[i]) <= target[i]) &&
37 @@ -402,7 +411,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde
38 // present that are not part of the tag_index.
39 static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len)
41 - static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
42 + static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
43 struct curveType *curve = NULL;
44 uint32_t type = read_u32(src, offset);
45 uint32_t count;
46 @@ -484,19 +493,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
47 uint32_t channel_offset = 0;
48 int i;
49 for (i = 0; i < num_channels; i++) {
50 - uint32_t tag_len;
51 + uint32_t tag_len = ~0;
53 (*curveArray)[i] = read_curveType(src, curve_offset + channel_offset, &tag_len);
54 if (!(*curveArray)[i]) {
55 invalid_source(src, "invalid nested curveType curve");
58 + if (tag_len == ~0) {
59 + invalid_source(src, "invalid nested curveType tag length");
60 + return;
61 + }
63 channel_offset += tag_len;
64 // 4 byte aligned
65 if ((tag_len % 4) != 0)
66 channel_offset += 4 - (tag_len % 4);
71 static void mAB_release(struct lutmABType *lut)
72 @@ -657,7 +670,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
73 uint16_t num_input_table_entries;
74 uint16_t num_output_table_entries;
75 uint8_t in_chan, grid_points, out_chan;
76 - uint32_t clut_offset, output_offset;
77 + size_t clut_offset, output_offset;
78 uint32_t clut_size;
79 size_t entry_size;
80 struct lutType *lut;
81 @@ -997,6 +1010,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
82 source.size = size;
83 source.valid = true;
85 + if (size < 4)
86 + return INVALID_PROFILE;
88 length = read_u32(src, 0);
89 if (length <= size) {
90 // shrink the area that we can read if appropriate
91 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h
92 index 7d83623..11fe222 100644
93 --- a/third_party/qcms/src/qcms.h
94 +++ b/third_party/qcms/src/qcms.h
95 @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written
96 authorization from SunSoft Inc.
97 ******************************************************************/
99 +/*
100 + * QCMS, in general, is not threadsafe. However, it should be safe to create
101 + * profile and transformation objects on different threads, so long as you
102 + * don't use the same objects on different threads at the same time.
103 + */
106 * Color Space Signatures
107 * Note that only icSigXYZData and icSigLabData are valid
108 @@ -102,6 +108,12 @@ typedef enum {
109 QCMS_DATA_GRAYA_8
110 } qcms_data_type;
112 +/* Format of the output data for qcms_transform_data_type() */
113 +typedef enum {
114 + QCMS_OUTPUT_RGBX,
115 + QCMS_OUTPUT_BGRX
116 +} qcms_output_type;
118 /* the names for the following two types are sort of ugly */
119 typedef struct
121 @@ -146,6 +158,7 @@ qcms_transform* qcms_transform_create(
122 void qcms_transform_release(qcms_transform *);
124 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length);
125 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type);
127 void qcms_enable_iccv4();
129 diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h
130 index 53a3420..fb53e96 100644
131 --- a/third_party/qcms/src/qcmsint.h
132 +++ b/third_party/qcms/src/qcmsint.h
133 @@ -45,6 +45,11 @@ struct precache_output
134 #define ALIGN __attribute__(( aligned (16) ))
135 #endif
137 +typedef struct _qcms_format_type {
138 + int r;
139 + int b;
140 +} qcms_format_type;
142 struct _qcms_transform {
143 float ALIGN matrix[3][4];
144 float *input_gamma_table_r;
145 @@ -88,7 +93,7 @@ struct _qcms_transform {
146 struct precache_output *output_table_g;
147 struct precache_output *output_table_b;
149 - void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length);
150 + void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, struct _qcms_format_type output_format);
153 struct matrix {
154 @@ -280,18 +285,40 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm
155 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
156 unsigned char *src,
157 unsigned char *dest,
158 - size_t length);
159 + size_t length,
160 + qcms_format_type output_format);
161 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
162 unsigned char *src,
163 unsigned char *dest,
164 - size_t length);
165 + size_t length,
166 + qcms_format_type output_format);
167 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
168 unsigned char *src,
169 unsigned char *dest,
170 - size_t length);
171 + size_t length,
172 + qcms_format_type output_format);
173 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
174 unsigned char *src,
175 unsigned char *dest,
176 - size_t length);
177 + size_t length,
178 + qcms_format_type output_format);
180 extern qcms_bool qcms_supports_iccv4;
183 +#ifdef _MSC_VER
185 +long __cdecl _InterlockedIncrement(long volatile *);
186 +long __cdecl _InterlockedDecrement(long volatile *);
187 +#pragma intrinsic(_InterlockedIncrement)
188 +#pragma intrinsic(_InterlockedDecrement)
190 +#define qcms_atomic_increment(x) _InterlockedIncrement((long volatile *)&x)
191 +#define qcms_atomic_decrement(x) _InterlockedDecrement((long volatile*)&x)
193 +#else
195 +#define qcms_atomic_increment(x) __sync_add_and_fetch(&x, 1)
196 +#define qcms_atomic_decrement(x) __sync_sub_and_fetch(&x, 1)
198 +#endif
199 diff --git a/third_party/qcms/src/qcmstypes.h b/third_party/qcms/src/qcmstypes.h
200 index 56d8de3..d58f691 100644
201 --- a/third_party/qcms/src/qcmstypes.h
202 +++ b/third_party/qcms/src/qcmstypes.h
203 @@ -22,37 +22,6 @@
204 #ifndef QCMS_TYPES_H
205 #define QCMS_TYPES_H
207 -#ifdef MOZ_QCMS
209 -#include "prtypes.h"
211 -/* prtypes.h defines IS_LITTLE_ENDIAN and IS_BIG ENDIAN */
213 -#if defined (__SVR4) && defined (__sun)
214 -/* int_types.h gets included somehow, so avoid redefining the types differently */
215 -#include <sys/int_types.h>
216 -#elif defined (_AIX)
217 -#include <sys/types.h>
218 -#elif !defined(ANDROID) && !defined(__OpenBSD__)
219 -typedef PRInt8 int8_t;
220 -typedef PRUint8 uint8_t;
221 -typedef PRInt16 int16_t;
222 -typedef PRUint16 uint16_t;
223 -typedef PRInt32 int32_t;
224 -typedef PRUint32 uint32_t;
225 -typedef PRInt64 int64_t;
226 -typedef PRUint64 uint64_t;
228 -#ifdef __OS2__
229 -/* OS/2's stdlib typdefs uintptr_t. So we'll just include that so we don't collide */
230 -#include <stdlib.h>
231 -#elif !defined(__intptr_t_defined) && !defined(_UINTPTR_T_DEFINED)
232 -typedef PRUptrdiff uintptr_t;
233 -#endif
234 -#endif
236 -#else // MOZ_QCMS
238 #if BYTE_ORDER == LITTLE_ENDIAN
239 #define IS_LITTLE_ENDIAN
240 #elif BYTE_ORDER == BIG_ENDIAN
241 @@ -75,7 +44,7 @@ typedef PRUptrdiff uintptr_t;
243 #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__)
244 # include <inttypes.h>
245 -#elif defined (_MSC_VER)
246 +#elif defined (_MSC_VER) && _MSC_VER < 1600
247 typedef __int8 int8_t;
248 typedef unsigned __int8 uint8_t;
249 typedef __int16 int16_t;
250 @@ -87,7 +56,12 @@ typedef unsigned __int64 uint64_t;
251 #ifdef _WIN64
252 typedef unsigned __int64 uintptr_t;
253 #else
254 +#pragma warning(push)
255 +/* Disable benign redefinition of type warning 4142 */
256 +#pragma warning(disable:4142)
257 typedef unsigned long uintptr_t;
258 +/* Restore warnings */
259 +#pragma warning(pop)
260 #endif
262 #elif defined (_AIX)
263 @@ -96,8 +70,6 @@ typedef unsigned long uintptr_t;
264 # include <stdint.h>
265 #endif
267 -#endif
269 typedef qcms_bool bool;
270 #define true 1
271 #define false 0
272 diff --git a/third_party/qcms/src/transform-sse1.c b/third_party/qcms/src/transform-sse1.c
273 index 2f34db5..aaee1bf 100644
274 --- a/third_party/qcms/src/transform-sse1.c
275 +++ b/third_party/qcms/src/transform-sse1.c
276 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
277 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
278 unsigned char *src,
279 unsigned char *dest,
280 - size_t length)
281 + size_t length,
282 + qcms_format_type output_format)
284 unsigned int i;
285 float (*mat)[4] = transform->matrix;
286 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
288 /* working variables */
289 __m128 vec_r, vec_g, vec_b, result;
290 + const int r_out = output_format.r;
291 + const int b_out = output_format.b;
293 /* CYA */
294 if (!length)
295 @@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
296 src += 3;
298 /* use calc'd indices to output RGB values */
299 - dest[0] = otdata_r[output[0]];
300 - dest[1] = otdata_g[output[1]];
301 - dest[2] = otdata_b[output[2]];
302 + dest[r_out] = otdata_r[output[0]];
303 + dest[1] = otdata_g[output[1]];
304 + dest[b_out] = otdata_b[output[2]];
305 dest += 3;
308 @@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
309 result = _mm_movehl_ps(result, result);
310 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
312 - dest[0] = otdata_r[output[0]];
313 - dest[1] = otdata_g[output[1]];
314 - dest[2] = otdata_b[output[2]];
315 + dest[r_out] = otdata_r[output[0]];
316 + dest[1] = otdata_g[output[1]];
317 + dest[b_out] = otdata_b[output[2]];
319 _mm_empty();
321 @@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
322 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
323 unsigned char *src,
324 unsigned char *dest,
325 - size_t length)
326 + size_t length,
327 + qcms_format_type output_format)
329 unsigned int i;
330 float (*mat)[4] = transform->matrix;
331 @@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
333 /* working variables */
334 __m128 vec_r, vec_g, vec_b, result;
335 + const int r_out = output_format.r;
336 + const int b_out = output_format.b;
337 unsigned char alpha;
339 /* CYA */
340 @@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
341 src += 4;
343 /* use calc'd indices to output RGB values */
344 - dest[0] = otdata_r[output[0]];
345 - dest[1] = otdata_g[output[1]];
346 - dest[2] = otdata_b[output[2]];
347 + dest[r_out] = otdata_r[output[0]];
348 + dest[1] = otdata_g[output[1]];
349 + dest[b_out] = otdata_b[output[2]];
350 dest += 4;
353 @@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
354 result = _mm_movehl_ps(result, result);
355 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
357 - dest[0] = otdata_r[output[0]];
358 - dest[1] = otdata_g[output[1]];
359 - dest[2] = otdata_b[output[2]];
360 + dest[r_out] = otdata_r[output[0]];
361 + dest[1] = otdata_g[output[1]];
362 + dest[b_out] = otdata_b[output[2]];
364 _mm_empty();
366 diff --git a/third_party/qcms/src/transform-sse2.c b/third_party/qcms/src/transform-sse2.c
367 index 6a5faf9..fa7f2d1 100644
368 --- a/third_party/qcms/src/transform-sse2.c
369 +++ b/third_party/qcms/src/transform-sse2.c
370 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
371 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
372 unsigned char *src,
373 unsigned char *dest,
374 - size_t length)
375 + size_t length,
376 + qcms_format_type output_format)
378 unsigned int i;
379 float (*mat)[4] = transform->matrix;
380 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
382 /* working variables */
383 __m128 vec_r, vec_g, vec_b, result;
384 + const int r_out = output_format.r;
385 + const int b_out = output_format.b;
387 /* CYA */
388 if (!length)
389 @@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
390 src += 3;
392 /* use calc'd indices to output RGB values */
393 - dest[0] = otdata_r[output[0]];
394 - dest[1] = otdata_g[output[1]];
395 - dest[2] = otdata_b[output[2]];
396 + dest[r_out] = otdata_r[output[0]];
397 + dest[1] = otdata_g[output[1]];
398 + dest[b_out] = otdata_b[output[2]];
399 dest += 3;
402 @@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
404 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
406 - dest[0] = otdata_r[output[0]];
407 - dest[1] = otdata_g[output[1]];
408 - dest[2] = otdata_b[output[2]];
409 + dest[r_out] = otdata_r[output[0]];
410 + dest[1] = otdata_g[output[1]];
411 + dest[b_out] = otdata_b[output[2]];
414 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
415 unsigned char *src,
416 unsigned char *dest,
417 - size_t length)
418 + size_t length,
419 + qcms_format_type output_format)
421 unsigned int i;
422 float (*mat)[4] = transform->matrix;
423 @@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
425 /* working variables */
426 __m128 vec_r, vec_g, vec_b, result;
427 + const int r_out = output_format.r;
428 + const int b_out = output_format.b;
429 unsigned char alpha;
431 /* CYA */
432 @@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
433 src += 4;
435 /* use calc'd indices to output RGB values */
436 - dest[0] = otdata_r[output[0]];
437 - dest[1] = otdata_g[output[1]];
438 - dest[2] = otdata_b[output[2]];
439 + dest[r_out] = otdata_r[output[0]];
440 + dest[1] = otdata_g[output[1]];
441 + dest[b_out] = otdata_b[output[2]];
442 dest += 4;
445 @@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
447 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
449 - dest[0] = otdata_r[output[0]];
450 - dest[1] = otdata_g[output[1]];
451 - dest[2] = otdata_b[output[2]];
452 + dest[r_out] = otdata_r[output[0]];
453 + dest[1] = otdata_g[output[1]];
454 + dest[b_out] = otdata_b[output[2]];
456 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
457 index 9a6562b..08db142 100644
458 --- a/third_party/qcms/src/transform.c
459 +++ b/third_party/qcms/src/transform.c
460 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point,
461 static struct matrix
462 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination)
464 +#if defined (_MSC_VER)
465 +#pragma warning(push)
466 +/* Disable double to float truncation warning 4305 */
467 +#pragma warning(disable:4305)
468 +#endif
469 struct matrix lam_rigg = {{ // Bradford matrix
470 { 0.8951, 0.2664, -0.1614 },
471 { -0.7502, 1.7135, 0.0367 },
472 { 0.0389, -0.0685, 1.0296 }
474 +#if defined (_MSC_VER)
475 +/* Restore warnings */
476 +#pragma warning(pop)
477 +#endif
478 return compute_chromatic_adaption(source_illumination, target_illumination, lam_rigg);
481 @@ -230,8 +239,11 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm
484 #if 0
485 -static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
486 +static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
488 + const int r_out = output_format.r;
489 + const int b_out = output_format.b;
491 int i;
492 float (*mat)[4] = transform->matrix;
493 for (i=0; i<length; i++) {
494 @@ -251,15 +263,19 @@ static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
495 float out_device_g = pow(out_linear_g, transform->out_gamma_g);
496 float out_device_b = pow(out_linear_b, transform->out_gamma_b);
498 - *dest++ = clamp_u8(255*out_device_r);
499 - *dest++ = clamp_u8(255*out_device_g);
500 - *dest++ = clamp_u8(255*out_device_b);
501 + dest[r_out] = clamp_u8(out_device_r*255);
502 + dest[1] = clamp_u8(out_device_g*255);
503 + dest[b_out] = clamp_u8(out_device_b*255);
504 + dest += 3;
507 #endif
509 -static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
510 +static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
512 + const int r_out = output_format.r;
513 + const int b_out = output_format.b;
515 unsigned int i;
516 for (i = 0; i < length; i++) {
517 float out_device_r, out_device_g, out_device_b;
518 @@ -267,13 +283,14 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
520 float linear = transform->input_gamma_table_gray[device];
522 - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
523 + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
524 out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
525 out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
527 - *dest++ = clamp_u8(out_device_r*255);
528 - *dest++ = clamp_u8(out_device_g*255);
529 - *dest++ = clamp_u8(out_device_b*255);
530 + dest[r_out] = clamp_u8(out_device_r*255);
531 + dest[1] = clamp_u8(out_device_g*255);
532 + dest[b_out] = clamp_u8(out_device_b*255);
533 + dest += 3;
537 @@ -283,8 +300,11 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
538 See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf
541 -static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
542 +static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
544 + const int r_out = output_format.r;
545 + const int b_out = output_format.b;
547 unsigned int i;
548 for (i = 0; i < length; i++) {
549 float out_device_r, out_device_g, out_device_b;
550 @@ -293,20 +313,24 @@ static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne
552 float linear = transform->input_gamma_table_gray[device];
554 - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
555 + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
556 out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
557 out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
559 - *dest++ = clamp_u8(out_device_r*255);
560 - *dest++ = clamp_u8(out_device_g*255);
561 - *dest++ = clamp_u8(out_device_b*255);
562 - *dest++ = alpha;
563 + dest[r_out] = clamp_u8(out_device_r*255);
564 + dest[1] = clamp_u8(out_device_g*255);
565 + dest[b_out] = clamp_u8(out_device_b*255);
566 + dest[3] = alpha;
567 + dest += 4;
572 -static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
573 +static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
575 + const int r_out = output_format.r;
576 + const int b_out = output_format.b;
578 unsigned int i;
579 for (i = 0; i < length; i++) {
580 unsigned char device = *src++;
581 @@ -317,14 +341,19 @@ static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns
582 /* we could round here... */
583 gray = linear * PRECACHE_OUTPUT_MAX;
585 - *dest++ = transform->output_table_r->data[gray];
586 - *dest++ = transform->output_table_g->data[gray];
587 - *dest++ = transform->output_table_b->data[gray];
588 + dest[r_out] = transform->output_table_r->data[gray];
589 + dest[1] = transform->output_table_g->data[gray];
590 + dest[b_out] = transform->output_table_b->data[gray];
591 + dest += 3;
595 -static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
597 +static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
599 + const int r_out = output_format.r;
600 + const int b_out = output_format.b;
602 unsigned int i;
603 for (i = 0; i < length; i++) {
604 unsigned char device = *src++;
605 @@ -336,15 +365,19 @@ static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un
606 /* we could round here... */
607 gray = linear * PRECACHE_OUTPUT_MAX;
609 - *dest++ = transform->output_table_r->data[gray];
610 - *dest++ = transform->output_table_g->data[gray];
611 - *dest++ = transform->output_table_b->data[gray];
612 - *dest++ = alpha;
613 + dest[r_out] = transform->output_table_r->data[gray];
614 + dest[1] = transform->output_table_g->data[gray];
615 + dest[b_out] = transform->output_table_b->data[gray];
616 + dest[3] = alpha;
617 + dest += 4;
621 -static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
622 +static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
624 + const int r_out = output_format.r;
625 + const int b_out = output_format.b;
627 unsigned int i;
628 float (*mat)[4] = transform->matrix;
629 for (i = 0; i < length; i++) {
630 @@ -370,14 +403,18 @@ static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform,
631 g = out_linear_g * PRECACHE_OUTPUT_MAX;
632 b = out_linear_b * PRECACHE_OUTPUT_MAX;
634 - *dest++ = transform->output_table_r->data[r];
635 - *dest++ = transform->output_table_g->data[g];
636 - *dest++ = transform->output_table_b->data[b];
637 + dest[r_out] = transform->output_table_r->data[r];
638 + dest[1] = transform->output_table_g->data[g];
639 + dest[b_out] = transform->output_table_b->data[b];
640 + dest += 3;
644 -static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
645 +static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
647 + const int r_out = output_format.r;
648 + const int b_out = output_format.b;
650 unsigned int i;
651 float (*mat)[4] = transform->matrix;
652 for (i = 0; i < length; i++) {
653 @@ -404,16 +441,21 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
654 g = out_linear_g * PRECACHE_OUTPUT_MAX;
655 b = out_linear_b * PRECACHE_OUTPUT_MAX;
657 - *dest++ = transform->output_table_r->data[r];
658 - *dest++ = transform->output_table_g->data[g];
659 - *dest++ = transform->output_table_b->data[b];
660 - *dest++ = alpha;
661 + dest[r_out] = transform->output_table_r->data[r];
662 + dest[1] = transform->output_table_g->data[g];
663 + dest[b_out] = transform->output_table_b->data[b];
664 + dest[3] = alpha;
665 + dest += 4;
669 // Not used
671 -static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
672 +static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
674 + const int r_out = output_format.r;
675 + const int b_out = output_format.b;
677 unsigned int i;
678 int xy_len = 1;
679 int x_len = transform->grid_size;
680 @@ -462,15 +504,20 @@ static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s
681 float b_y2 = lerp(b_x3, b_x4, y_d);
682 float clut_b = lerp(b_y1, b_y2, z_d);
684 - *dest++ = clamp_u8(clut_r*255.0f);
685 - *dest++ = clamp_u8(clut_g*255.0f);
686 - *dest++ = clamp_u8(clut_b*255.0f);
687 - }
688 + dest[r_out] = clamp_u8(clut_r*255.0f);
689 + dest[1] = clamp_u8(clut_g*255.0f);
690 + dest[b_out] = clamp_u8(clut_b*255.0f);
691 + dest += 3;
696 // Using lcms' tetra interpolation algorithm.
697 -static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
698 +static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
700 + const int r_out = output_format.r;
701 + const int b_out = output_format.b;
703 unsigned int i;
704 int xy_len = 1;
705 int x_len = transform->grid_size;
706 @@ -577,15 +624,20 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
707 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
708 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
710 - *dest++ = clamp_u8(clut_r*255.0f);
711 - *dest++ = clamp_u8(clut_g*255.0f);
712 - *dest++ = clamp_u8(clut_b*255.0f);
713 - *dest++ = in_a;
714 - }
715 + dest[r_out] = clamp_u8(clut_r*255.0f);
716 + dest[1] = clamp_u8(clut_g*255.0f);
717 + dest[b_out] = clamp_u8(clut_b*255.0f);
718 + dest[3] = in_a;
719 + dest += 4;
723 // Using lcms' tetra interpolation code.
724 -static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
725 +static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
727 + const int r_out = output_format.r;
728 + const int b_out = output_format.b;
730 unsigned int i;
731 int xy_len = 1;
732 int x_len = transform->grid_size;
733 @@ -691,14 +743,18 @@ static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
734 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
735 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
737 - *dest++ = clamp_u8(clut_r*255.0f);
738 - *dest++ = clamp_u8(clut_g*255.0f);
739 - *dest++ = clamp_u8(clut_b*255.0f);
740 - }
741 + dest[r_out] = clamp_u8(clut_r*255.0f);
742 + dest[1] = clamp_u8(clut_g*255.0f);
743 + dest[b_out] = clamp_u8(clut_b*255.0f);
744 + dest += 3;
748 -static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
749 +static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
751 + const int r_out = output_format.r;
752 + const int b_out = output_format.b;
754 unsigned int i;
755 float (*mat)[4] = transform->matrix;
756 for (i = 0; i < length; i++) {
757 @@ -726,14 +782,18 @@ static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
758 out_device_b = lut_interp_linear(out_linear_b,
759 transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
761 - *dest++ = clamp_u8(out_device_r*255);
762 - *dest++ = clamp_u8(out_device_g*255);
763 - *dest++ = clamp_u8(out_device_b*255);
764 + dest[r_out] = clamp_u8(out_device_r*255);
765 + dest[1] = clamp_u8(out_device_g*255);
766 + dest[b_out] = clamp_u8(out_device_b*255);
767 + dest += 3;
771 -static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
772 +static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
774 + const int r_out = output_format.r;
775 + const int b_out = output_format.b;
777 unsigned int i;
778 float (*mat)[4] = transform->matrix;
779 for (i = 0; i < length; i++) {
780 @@ -762,16 +822,20 @@ static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
781 out_device_b = lut_interp_linear(out_linear_b,
782 transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
784 - *dest++ = clamp_u8(out_device_r*255);
785 - *dest++ = clamp_u8(out_device_g*255);
786 - *dest++ = clamp_u8(out_device_b*255);
787 - *dest++ = alpha;
788 + dest[r_out] = clamp_u8(out_device_r*255);
789 + dest[1] = clamp_u8(out_device_g*255);
790 + dest[b_out] = clamp_u8(out_device_b*255);
791 + dest[3] = alpha;
792 + dest += 4;
796 #if 0
797 -static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
798 +static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
800 + const int r_out = output_format.r;
801 + const int b_out = output_format.b;
803 int i;
804 float (*mat)[4] = transform->matrix;
805 for (i = 0; i < length; i++) {
806 @@ -787,16 +851,25 @@ static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign
807 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
808 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
810 - *dest++ = clamp_u8(out_linear_r*255);
811 - *dest++ = clamp_u8(out_linear_g*255);
812 - *dest++ = clamp_u8(out_linear_b*255);
813 + dest[r_out] = clamp_u8(out_linear_r*255);
814 + dest[1] = clamp_u8(out_linear_g*255);
815 + dest[b_out] = clamp_u8(out_linear_b*255);
816 + dest += 3;
819 #endif
822 + * If users create and destroy objects on different threads, even if the same
823 + * objects aren't used on different threads at the same time, we can still run
824 + * in to trouble with refcounts if they aren't atomic.
826 + * This can lead to us prematurely deleting the precache if threads get unlucky
827 + * and write the wrong value to the ref count.
828 + */
829 static struct precache_output *precache_reference(struct precache_output *p)
831 - p->ref_count++;
832 + qcms_atomic_increment(p->ref_count);
833 return p;
836 @@ -810,12 +883,12 @@ static struct precache_output *precache_create()
838 void precache_release(struct precache_output *p)
840 - if (--p->ref_count == 0) {
841 + if (qcms_atomic_decrement(p->ref_count) == 0) {
842 free(p);
846 -#ifdef HAS_POSIX_MEMALIGN
847 +#ifdef HAVE_POSIX_MEMALIGN
848 static qcms_transform *transform_alloc(void)
850 qcms_transform *t;
851 @@ -994,13 +1067,15 @@ void qcms_profile_precache_output_transform(qcms_profile *profile)
852 if (profile->color_space != RGB_SIGNATURE)
853 return;
855 - /* don't precache since we will use the B2A LUT */
856 - if (profile->B2A0)
857 - return;
858 + if (qcms_supports_iccv4) {
859 + /* don't precache since we will use the B2A LUT */
860 + if (profile->B2A0)
861 + return;
863 - /* don't precache since we will use the mBA LUT */
864 - if (profile->mBA)
865 - return;
866 + /* don't precache since we will use the mBA LUT */
867 + if (profile->mBA)
868 + return;
871 /* don't precache if we do not have the TRC curves */
872 if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC)
873 @@ -1078,7 +1153,8 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
874 //XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed
875 if (src && lut != src) {
876 free(src);
877 - } else if (dest && lut != src) {
879 + if (dest && lut != dest) {
880 free(dest);
883 @@ -1157,14 +1233,14 @@ qcms_transform* qcms_transform_create(
884 return NULL;
886 if (precache) {
887 -#ifdef X86
888 +#if defined(SSE2_ENABLE) && defined(X86)
889 if (sse_version_available() >= 2) {
890 if (in_type == QCMS_DATA_RGB_8)
891 transform->transform_fn = qcms_transform_data_rgb_out_lut_sse2;
892 else
893 transform->transform_fn = qcms_transform_data_rgba_out_lut_sse2;
895 -#if !(defined(_MSC_VER) && defined(_M_AMD64))
896 +#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64))
897 /* Microsoft Compiler for x64 doesn't support MMX.
898 * SSE code uses MMX so that we disable on x64 */
899 } else
900 @@ -1256,13 +1332,34 @@ qcms_transform* qcms_transform_create(
901 return transform;
904 -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
905 +/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on unused
906 + * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the presence
907 + * of the attribute but is currently only supported by clang */
908 +#if defined(__has_attribute)
909 +#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__)
910 +#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defined(__arm__) && !defined(__mips__)
911 +#define HAS_FORCE_ALIGN_ARG_POINTER 1
912 +#else
913 +#define HAS_FORCE_ALIGN_ARG_POINTER 0
914 +#endif
916 +#if HAS_FORCE_ALIGN_ARG_POINTER
917 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */
918 __attribute__((__force_align_arg_pointer__))
919 #endif
920 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length)
922 - transform->transform_fn(transform, src, dest, length);
923 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
925 + transform->transform_fn(transform, src, dest, length, output_rgbx);
928 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type)
930 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
931 + static const struct _qcms_format_type output_bgrx = { 2, 0 };
933 + transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPUT_BGRX ? output_bgrx : output_rgbx);
936 qcms_bool qcms_supports_iccv4;
937 diff --git a/third_party/qcms/src/transform_util.c b/third_party/qcms/src/transform_util.c
938 index e8447e5..f4338b2 100644
939 --- a/third_party/qcms/src/transform_util.c
940 +++ b/third_party/qcms/src/transform_util.c
941 @@ -36,7 +36,7 @@
943 /* value must be a value between 0 and 1 */
944 //XXX: is the above a good restriction to have?
945 -float lut_interp_linear(double value, uint16_t *table, int length)
946 +float lut_interp_linear(double value, uint16_t *table, size_t length)
948 int upper, lower;
949 value = value * (length - 1); // scale to length of the array
950 @@ -49,11 +49,11 @@ float lut_interp_linear(double value, uint16_t *table, int length)
953 /* same as above but takes and returns a uint16_t value representing a range from 0..1 */
954 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
955 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length)
957 /* Start scaling input_value to the length of the array: 65535*(length-1).
958 * We'll divide out the 65535 next */
959 - uint32_t value = (input_value * (length - 1));
960 + uintptr_t value = (input_value * (length - 1));
961 uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65535) */
962 uint32_t lower = value / 65535; /* equivalent to floor(value/65535) */
963 /* interp is the distance from upper to value scaled to 0..65535 */
964 @@ -67,11 +67,11 @@ uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
965 /* same as above but takes an input_value from 0..PRECACHE_OUTPUT_MAX
966 * and returns a uint8_t value representing a range from 0..1 */
967 static
968 -uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, int length)
969 +uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, size_t length)
971 /* Start scaling input_value to the length of the array: PRECACHE_OUTPUT_MAX*(length-1).
972 * We'll divide out the PRECACHE_OUTPUT_MAX next */
973 - uint32_t value = (input_value * (length - 1));
974 + uintptr_t value = (input_value * (length - 1));
976 /* equivalent to ceil(value/PRECACHE_OUTPUT_MAX) */
977 uint32_t upper = (value + PRECACHE_OUTPUT_MAX-1) / PRECACHE_OUTPUT_MAX;
978 @@ -91,7 +91,7 @@ uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table,
980 /* value must be a value between 0 and 1 */
981 //XXX: is the above a good restriction to have?
982 -float lut_interp_linear_float(float value, float *table, int length)
983 +float lut_interp_linear_float(float value, float *table, size_t length)
985 int upper, lower;
986 value = value * (length - 1);
987 @@ -235,6 +235,21 @@ float u8Fixed8Number_to_float(uint16_t x)
988 return x/256.;
991 +/* The SSE2 code uses min & max which let NaNs pass through.
992 + We want to try to prevent that here by ensuring that
993 + gamma table is within expected values. */
994 +void validate_gamma_table(float gamma_table[256])
996 + int i;
997 + for (i = 0; i < 256; i++) {
998 + // Note: we check that the gamma is not in range
999 + // instead of out of range so that we catch NaNs
1000 + if (!(gamma_table[i] >= 0.f && gamma_table[i] <= 1.f)) {
1001 + gamma_table[i] = 0.f;
1006 float *build_input_gamma_table(struct curveType *TRC)
1008 float *gamma_table;
1009 @@ -254,7 +269,10 @@ float *build_input_gamma_table(struct curveType *TRC)
1013 - return gamma_table;
1015 + validate_gamma_table(gamma_table);
1017 + return gamma_table;
1020 struct matrix build_colorant_matrix(qcms_profile *p)
1021 @@ -390,7 +408,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len
1022 which has an maximum error of about 9855 (pixel difference of ~38.346)
1024 For now, we punt the decision of output size to the caller. */
1025 -static uint16_t *invert_lut(uint16_t *table, int length, int out_length)
1026 +static uint16_t *invert_lut(uint16_t *table, int length, size_t out_length)
1028 int i;
1029 /* for now we invert the lut by creating a lut of size out_length
1030 diff --git a/third_party/qcms/src/transform_util.h b/third_party/qcms/src/transform_util.h
1031 index 8f358a8..de465f4 100644
1032 --- a/third_party/qcms/src/transform_util.h
1033 +++ b/third_party/qcms/src/transform_util.h
1034 @@ -31,9 +31,9 @@
1035 //XXX: could use a bettername
1036 typedef uint16_t uint16_fract_t;
1038 -float lut_interp_linear(double value, uint16_t *table, int length);
1039 -float lut_interp_linear_float(float value, float *table, int length);
1040 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length);
1041 +float lut_interp_linear(double value, uint16_t *table, size_t length);
1042 +float lut_interp_linear_float(float value, float *table, size_t length);
1043 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length);
1046 static inline float lerp(float a, float b, float t)