Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2
/*
3
 * Copyright © 2010, 2012 Soren Sandmann Pedersen
4
 * Copyright © 2010, 2012 Red Hat, Inc.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice (including the next
14
 * paragraph) shall be included in all copies or substantial portions of the
15
 * Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
 * DEALINGS IN THE SOFTWARE.
24
 *
25
 * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk)
26
 */
27
 
28
#ifdef HAVE_CONFIG_H
29
#include 
30
#endif
31
 
32
#include 
33
#include 
34
#include 
35
 
36
#include "pixman-private.h"
37
 
38
/* Workaround for http://gcc.gnu.org/PR54965 */
39
/* GCC 4.6 has problems with force_inline, so just use normal inline instead */
40
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 6)
41
#undef force_inline
42
#define force_inline __inline__
43
#endif
44
 
45
typedef float (* combine_channel_t) (float sa, float s, float da, float d);
46
 
47
static force_inline void
48
combine_inner (pixman_bool_t component,
49
	       float *dest, const float *src, const float *mask, int n_pixels,
50
	       combine_channel_t combine_a, combine_channel_t combine_c)
51
{
52
    int i;
53
 
54
    if (!mask)
55
    {
56
	for (i = 0; i < 4 * n_pixels; i += 4)
57
	{
58
	    float sa = src[i + 0];
59
	    float sr = src[i + 1];
60
	    float sg = src[i + 2];
61
	    float sb = src[i + 3];
62
 
63
	    float da = dest[i + 0];
64
	    float dr = dest[i + 1];
65
	    float dg = dest[i + 2];
66
	    float db = dest[i + 3];
67
 
68
	    dest[i + 0] = combine_a (sa, sa, da, da);
69
	    dest[i + 1] = combine_c (sa, sr, da, dr);
70
	    dest[i + 2] = combine_c (sa, sg, da, dg);
71
	    dest[i + 3] = combine_c (sa, sb, da, db);
72
	}
73
    }
74
    else
75
    {
76
	for (i = 0; i < 4 * n_pixels; i += 4)
77
	{
78
	    float sa, sr, sg, sb;
79
	    float ma, mr, mg, mb;
80
	    float da, dr, dg, db;
81
 
82
	    sa = src[i + 0];
83
	    sr = src[i + 1];
84
	    sg = src[i + 2];
85
	    sb = src[i + 3];
86
 
87
	    if (component)
88
	    {
89
		ma = mask[i + 0];
90
		mr = mask[i + 1];
91
		mg = mask[i + 2];
92
		mb = mask[i + 3];
93
 
94
		sr *= mr;
95
		sg *= mg;
96
		sb *= mb;
97
 
98
		ma *= sa;
99
		mr *= sa;
100
		mg *= sa;
101
		mb *= sa;
102
 
103
		sa = ma;
104
	    }
105
	    else
106
	    {
107
		ma = mask[i + 0];
108
 
109
		sa *= ma;
110
		sr *= ma;
111
		sg *= ma;
112
		sb *= ma;
113
 
114
		ma = mr = mg = mb = sa;
115
	    }
116
 
117
	    da = dest[i + 0];
118
	    dr = dest[i + 1];
119
	    dg = dest[i + 2];
120
	    db = dest[i + 3];
121
 
122
	    dest[i + 0] = combine_a (ma, sa, da, da);
123
	    dest[i + 1] = combine_c (mr, sr, da, dr);
124
	    dest[i + 2] = combine_c (mg, sg, da, dg);
125
	    dest[i + 3] = combine_c (mb, sb, da, db);
126
	}
127
    }
128
}
129
 
130
#define MAKE_COMBINER(name, component, combine_a, combine_c)		\
131
    static void								\
132
    combine_ ## name ## _float (pixman_implementation_t *imp,		\
133
				pixman_op_t              op,		\
134
				float                   *dest,		\
135
				const float             *src,		\
136
				const float             *mask,		\
137
				int		         n_pixels)	\
138
    {									\
139
	combine_inner (component, dest, src, mask, n_pixels,		\
140
		       combine_a, combine_c);				\
141
    }
142
 
143
#define MAKE_COMBINERS(name, combine_a, combine_c)			\
144
    MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c)		\
145
    MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c)
146
 
147
 
148
/*
149
 * Porter/Duff operators
150
 */
151
typedef enum
152
{
153
    ZERO,
154
    ONE,
155
    SRC_ALPHA,
156
    DEST_ALPHA,
157
    INV_SA,
158
    INV_DA,
159
    SA_OVER_DA,
160
    DA_OVER_SA,
161
    INV_SA_OVER_DA,
162
    INV_DA_OVER_SA,
163
    ONE_MINUS_SA_OVER_DA,
164
    ONE_MINUS_DA_OVER_SA,
165
    ONE_MINUS_INV_DA_OVER_SA,
166
    ONE_MINUS_INV_SA_OVER_DA
167
} combine_factor_t;
168
 
169
#define CLAMP(f)					\
170
    (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f)))
171
 
172
static force_inline float
173
get_factor (combine_factor_t factor, float sa, float da)
174
{
175
    float f = -1;
176
 
177
    switch (factor)
178
    {
179
    case ZERO:
180
	f = 0.0f;
181
	break;
182
 
183
    case ONE:
184
	f = 1.0f;
185
	break;
186
 
187
    case SRC_ALPHA:
188
	f = sa;
189
	break;
190
 
191
    case DEST_ALPHA:
192
	f = da;
193
	break;
194
 
195
    case INV_SA:
196
	f = 1 - sa;
197
	break;
198
 
199
    case INV_DA:
200
	f = 1 - da;
201
	break;
202
 
203
    case SA_OVER_DA:
204
	if (FLOAT_IS_ZERO (da))
205
	    f = 1.0f;
206
	else
207
	    f = CLAMP (sa / da);
208
	break;
209
 
210
    case DA_OVER_SA:
211
	if (FLOAT_IS_ZERO (sa))
212
	    f = 1.0f;
213
	else
214
	    f = CLAMP (da / sa);
215
	break;
216
 
217
    case INV_SA_OVER_DA:
218
	if (FLOAT_IS_ZERO (da))
219
	    f = 1.0f;
220
	else
221
	    f = CLAMP ((1.0f - sa) / da);
222
	break;
223
 
224
    case INV_DA_OVER_SA:
225
	if (FLOAT_IS_ZERO (sa))
226
	    f = 1.0f;
227
	else
228
	    f = CLAMP ((1.0f - da) / sa);
229
	break;
230
 
231
    case ONE_MINUS_SA_OVER_DA:
232
	if (FLOAT_IS_ZERO (da))
233
	    f = 0.0f;
234
	else
235
	    f = CLAMP (1.0f - sa / da);
236
	break;
237
 
238
    case ONE_MINUS_DA_OVER_SA:
239
	if (FLOAT_IS_ZERO (sa))
240
	    f = 0.0f;
241
	else
242
	    f = CLAMP (1.0f - da / sa);
243
	break;
244
 
245
    case ONE_MINUS_INV_DA_OVER_SA:
246
	if (FLOAT_IS_ZERO (sa))
247
	    f = 0.0f;
248
	else
249
	    f = CLAMP (1.0f - (1.0f - da) / sa);
250
	break;
251
 
252
    case ONE_MINUS_INV_SA_OVER_DA:
253
	if (FLOAT_IS_ZERO (da))
254
	    f = 0.0f;
255
	else
256
	    f = CLAMP (1.0f - (1.0f - sa) / da);
257
	break;
258
    }
259
 
260
    return f;
261
}
262
 
263
#define MAKE_PD_COMBINERS(name, a, b)					\
264
    static float force_inline						\
265
    pd_combine_ ## name (float sa, float s, float da, float d)		\
266
    {									\
267
	const float fa = get_factor (a, sa, da);			\
268
	const float fb = get_factor (b, sa, da);			\
269
									\
270
	return MIN (1.0f, s * fa + d * fb);				\
271
    }									\
272
    									\
273
    MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name)
274
 
275
MAKE_PD_COMBINERS (clear,			ZERO,				ZERO)
276
MAKE_PD_COMBINERS (src,				ONE,				ZERO)
277
MAKE_PD_COMBINERS (dst,				ZERO,				ONE)
278
MAKE_PD_COMBINERS (over,			ONE,				INV_SA)
279
MAKE_PD_COMBINERS (over_reverse,		INV_DA,				ONE)
280
MAKE_PD_COMBINERS (in,				DEST_ALPHA,			ZERO)
281
MAKE_PD_COMBINERS (in_reverse,			ZERO,				SRC_ALPHA)
282
MAKE_PD_COMBINERS (out,				INV_DA,				ZERO)
283
MAKE_PD_COMBINERS (out_reverse,			ZERO,				INV_SA)
284
MAKE_PD_COMBINERS (atop,			DEST_ALPHA,			INV_SA)
285
MAKE_PD_COMBINERS (atop_reverse,		INV_DA,				SRC_ALPHA)
286
MAKE_PD_COMBINERS (xor,				INV_DA,				INV_SA)
287
MAKE_PD_COMBINERS (add,				ONE,				ONE)
288
 
289
MAKE_PD_COMBINERS (saturate,			INV_DA_OVER_SA,			ONE)
290
 
291
MAKE_PD_COMBINERS (disjoint_clear,		ZERO,				ZERO)
292
MAKE_PD_COMBINERS (disjoint_src,		ONE,				ZERO)
293
MAKE_PD_COMBINERS (disjoint_dst,		ZERO,				ONE)
294
MAKE_PD_COMBINERS (disjoint_over,		ONE,				INV_SA_OVER_DA)
295
MAKE_PD_COMBINERS (disjoint_over_reverse,	INV_DA_OVER_SA,			ONE)
296
MAKE_PD_COMBINERS (disjoint_in,			ONE_MINUS_INV_DA_OVER_SA,	ZERO)
297
MAKE_PD_COMBINERS (disjoint_in_reverse,		ZERO,				ONE_MINUS_INV_SA_OVER_DA)
298
MAKE_PD_COMBINERS (disjoint_out,		INV_DA_OVER_SA,			ZERO)
299
MAKE_PD_COMBINERS (disjoint_out_reverse,	ZERO,				INV_SA_OVER_DA)
300
MAKE_PD_COMBINERS (disjoint_atop,		ONE_MINUS_INV_DA_OVER_SA,	INV_SA_OVER_DA)
301
MAKE_PD_COMBINERS (disjoint_atop_reverse,	INV_DA_OVER_SA,			ONE_MINUS_INV_SA_OVER_DA)
302
MAKE_PD_COMBINERS (disjoint_xor,		INV_DA_OVER_SA,			INV_SA_OVER_DA)
303
 
304
MAKE_PD_COMBINERS (conjoint_clear,		ZERO,				ZERO)
305
MAKE_PD_COMBINERS (conjoint_src,		ONE,				ZERO)
306
MAKE_PD_COMBINERS (conjoint_dst,		ZERO,				ONE)
307
MAKE_PD_COMBINERS (conjoint_over,		ONE,				ONE_MINUS_SA_OVER_DA)
308
MAKE_PD_COMBINERS (conjoint_over_reverse,	ONE_MINUS_DA_OVER_SA,		ONE)
309
MAKE_PD_COMBINERS (conjoint_in,			DA_OVER_SA,			ZERO)
310
MAKE_PD_COMBINERS (conjoint_in_reverse,		ZERO,				SA_OVER_DA)
311
MAKE_PD_COMBINERS (conjoint_out,		ONE_MINUS_DA_OVER_SA,		ZERO)
312
MAKE_PD_COMBINERS (conjoint_out_reverse,	ZERO,				ONE_MINUS_SA_OVER_DA)
313
MAKE_PD_COMBINERS (conjoint_atop,		DA_OVER_SA,			ONE_MINUS_SA_OVER_DA)
314
MAKE_PD_COMBINERS (conjoint_atop_reverse,	ONE_MINUS_DA_OVER_SA,		SA_OVER_DA)
315
MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
316
 
317
/*
318
 * PDF blend modes:
319
 *
320
 * The following blend modes have been taken from the PDF ISO 32000
321
 * specification, which at this point in time is available from
322
 * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
323
 * The relevant chapters are 11.3.5 and 11.3.6.
324
 * The formula for computing the final pixel color given in 11.3.6 is:
325
 * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
326
 * with B() being the blend function.
327
 * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
328
 *
329
 * These blend modes should match the SVG filter draft specification, as
330
 * it has been designed to mirror ISO 32000. Note that at the current point
331
 * no released draft exists that shows this, as the formulas have not been
332
 * updated yet after the release of ISO 32000.
333
 *
334
 * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
335
 * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
336
 * argument. Note that this implementation operates on premultiplied colors,
337
 * while the PDF specification does not. Therefore the code uses the formula
338
 * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
339
 */
340
 
341
#define MAKE_SEPARABLE_PDF_COMBINERS(name)				\
342
    static force_inline float						\
343
    combine_ ## name ## _a (float sa, float s, float da, float d)	\
344
    {									\
345
	return da + sa - da * sa;					\
346
    }									\
347
    									\
348
    static force_inline float						\
349
    combine_ ## name ## _c (float sa, float s, float da, float d)	\
350
    {									\
351
	float f = (1 - sa) * d + (1 - da) * s;				\
352
									\
353
	return f + blend_ ## name (sa, s, da, d);			\
354
    }									\
355
    									\
356
    MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
357
 
358
static force_inline float
359
blend_multiply (float sa, float s, float da, float d)
360
{
361
    return d * s;
362
}
363
 
364
static force_inline float
365
blend_screen (float sa, float s, float da, float d)
366
{
367
    return d * sa + s * da - s * d;
368
}
369
 
370
static force_inline float
371
blend_overlay (float sa, float s, float da, float d)
372
{
373
    if (2 * d < da)
374
	return 2 * s * d;
375
    else
376
	return sa * da - 2 * (da - d) * (sa - s);
377
}
378
 
379
static force_inline float
380
blend_darken (float sa, float s, float da, float d)
381
{
382
    s = s * da;
383
    d = d * sa;
384
 
385
    if (s > d)
386
	return d;
387
    else
388
	return s;
389
}
390
 
391
static force_inline float
392
blend_lighten (float sa, float s, float da, float d)
393
{
394
    s = s * da;
395
    d = d * sa;
396
 
397
    if (s > d)
398
	return s;
399
    else
400
	return d;
401
}
402
 
403
static force_inline float
404
blend_color_dodge (float sa, float s, float da, float d)
405
{
406
    if (FLOAT_IS_ZERO (d))
407
	return 0.0f;
408
    else if (d * sa >= sa * da - s * da)
409
	return sa * da;
410
    else if (FLOAT_IS_ZERO (sa - s))
411
	return sa * da;
412
    else
413
	return sa * sa * d / (sa - s);
414
}
415
 
416
static force_inline float
417
blend_color_burn (float sa, float s, float da, float d)
418
{
419
    if (d >= da)
420
	return sa * da;
421
    else if (sa * (da - d) >= s * da)
422
	return 0.0f;
423
    else if (FLOAT_IS_ZERO (s))
424
	return 0.0f;
425
    else
426
	return sa * (da - sa * (da - d) / s);
427
}
428
 
429
static force_inline float
430
blend_hard_light (float sa, float s, float da, float d)
431
{
432
    if (2 * s < sa)
433
	return 2 * s * d;
434
    else
435
	return sa * da - 2 * (da - d) * (sa - s);
436
}
437
 
438
static force_inline float
439
blend_soft_light (float sa, float s, float da, float d)
440
{
441
    if (2 * s < sa)
442
    {
443
	if (FLOAT_IS_ZERO (da))
444
	    return d * sa;
445
	else
446
	    return d * sa - d * (da - d) * (sa - 2 * s) / da;
447
    }
448
    else
449
    {
450
	if (FLOAT_IS_ZERO (da))
451
	{
452
	    return 0.0f;
453
	}
454
	else
455
	{
456
	    if (4 * d <= da)
457
		return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
458
	    else
459
		return d * sa + (sqrtf (d * da) - d) * (2 * s - sa);
460
	}
461
    }
462
}
463
 
464
static force_inline float
465
blend_difference (float sa, float s, float da, float d)
466
{
467
    float dsa = d * sa;
468
    float sda = s * da;
469
 
470
    if (sda < dsa)
471
	return dsa - sda;
472
    else
473
	return sda - dsa;
474
}
475
 
476
static force_inline float
477
blend_exclusion (float sa, float s, float da, float d)
478
{
479
    return s * da + d * sa - 2 * d * s;
480
}
481
 
482
MAKE_SEPARABLE_PDF_COMBINERS (multiply)
483
MAKE_SEPARABLE_PDF_COMBINERS (screen)
484
MAKE_SEPARABLE_PDF_COMBINERS (overlay)
485
MAKE_SEPARABLE_PDF_COMBINERS (darken)
486
MAKE_SEPARABLE_PDF_COMBINERS (lighten)
487
MAKE_SEPARABLE_PDF_COMBINERS (color_dodge)
488
MAKE_SEPARABLE_PDF_COMBINERS (color_burn)
489
MAKE_SEPARABLE_PDF_COMBINERS (hard_light)
490
MAKE_SEPARABLE_PDF_COMBINERS (soft_light)
491
MAKE_SEPARABLE_PDF_COMBINERS (difference)
492
MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
493
 
494
/*
495
 * PDF nonseperable blend modes.
496
 *
497
 * These are implemented using the following functions to operate in Hsl
498
 * space, with Cmax, Cmid, Cmin referring to the max, mid and min value
499
 * of the red, green and blue components.
500
 *
501
 * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
502
 *
503
 * clip_color (C):
504
 *   l = LUM (C)
505
 *   min = Cmin
506
 *   max = Cmax
507
 *   if n < 0.0
508
 *     C = l + (((C – l) × l) ⁄     (l – min))
509
 *   if x > 1.0
510
 *     C = l + (((C – l) × (1 – l)) (max – l))
511
 *   return C
512
 *
513
 * set_lum (C, l):
514
 *   d = l – LUM (C)
515
 *   C += d
516
 *   return clip_color (C)
517
 *
518
 * SAT (C) = CH_MAX (C) - CH_MIN (C)
519
 *
520
 * set_sat (C, s):
521
 *  if Cmax > Cmin
522
 *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
523
 *    Cmax = s
524
 *  else
525
 *    Cmid = Cmax = 0.0
526
 *  Cmin = 0.0
527
 *  return C
528
 */
529
 
530
/* For premultiplied colors, we need to know what happens when C is
531
 * multiplied by a real number. LUM and SAT are linear:
532
 *
533
 *    LUM (r × C) = r × LUM (C)		SAT (r × C) = r × SAT (C)
534
 *
535
 * If we extend clip_color with an extra argument a and change
536
 *
537
 *        if x >= 1.0
538
 *
539
 * into
540
 *
541
 *        if x >= a
542
 *
543
 * then clip_color is also linear:
544
 *
545
 *     r * clip_color (C, a) = clip_color (r_c, ra);
546
 *
547
 * for positive r.
548
 *
549
 * Similarly, we can extend set_lum with an extra argument that is just passed
550
 * on to clip_color:
551
 *
552
 *     r × set_lum ( C, l, a)
553
 *
554
 *   = r × clip_color ( C + l - LUM (C), a)
555
 *
556
 *   = clip_color ( r * C + r × l - LUM (r × C), r * a)
557
 *
558
 *   = set_lum ( r * C, r * l, r * a)
559
 *
560
 * Finally, set_sat:
561
 *
562
 *     r * set_sat (C, s) = set_sat (x * C, r * s)
563
 *
564
 * The above holds for all non-zero x because they x'es in the fraction for
565
 * C_mid cancel out. Specifically, it holds for x = r:
566
 *
567
 *     r * set_sat (C, s) = set_sat (r_c, rs)
568
 *
569
 *
570
 *
571
 *
572
 * So, for the non-separable PDF blend modes, we have (using s, d for
573
 * non-premultiplied colors, and S, D for premultiplied:
574
 *
575
 *   Color:
576
 *
577
 *     a_s * a_d * B(s, d)
578
 *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
579
 *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
580
 *
581
 *
582
 *   Luminosity:
583
 *
584
 *     a_s * a_d * B(s, d)
585
 *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
586
 *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
587
 *
588
 *
589
 *   Saturation:
590
 *
591
 *     a_s * a_d * B(s, d)
592
 *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
593
 *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
594
 *                                        a_s * LUM (D), a_s * a_d)
595
 *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
596
 *
597
 *   Hue:
598
 *
599
 *     a_s * a_d * B(s, d)
600
 *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
601
 *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
602
 *
603
 */
604
 
605
typedef struct
606
{
607
    float	r;
608
    float	g;
609
    float	b;
610
} rgb_t;
611
 
612
static force_inline float
613
minf (float a, float b)
614
{
615
    return a < b? a : b;
616
}
617
 
618
static force_inline float
619
maxf (float a, float b)
620
{
621
    return a > b? a : b;
622
}
623
 
624
static force_inline float
625
channel_min (const rgb_t *c)
626
{
627
    return minf (minf (c->r, c->g), c->b);
628
}
629
 
630
static force_inline float
631
channel_max (const rgb_t *c)
632
{
633
    return maxf (maxf (c->r, c->g), c->b);
634
}
635
 
636
static force_inline float
637
get_lum (const rgb_t *c)
638
{
639
    return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f;
640
}
641
 
642
static force_inline float
643
get_sat (const rgb_t *c)
644
{
645
    return channel_max (c) - channel_min (c);
646
}
647
 
648
static void
649
clip_color (rgb_t *color, float a)
650
{
651
    float l = get_lum (color);
652
    float n = channel_min (color);
653
    float x = channel_max (color);
654
    float t;
655
 
656
    if (n < 0.0f)
657
    {
658
	t = l - n;
659
	if (FLOAT_IS_ZERO (t))
660
	{
661
	    color->r = 0.0f;
662
	    color->g = 0.0f;
663
	    color->b = 0.0f;
664
	}
665
	else
666
	{
667
	    color->r = l + (((color->r - l) * l) / t);
668
	    color->g = l + (((color->g - l) * l) / t);
669
	    color->b = l + (((color->b - l) * l) / t);
670
	}
671
    }
672
    if (x > a)
673
    {
674
	t = x - l;
675
	if (FLOAT_IS_ZERO (t))
676
	{
677
	    color->r = a;
678
	    color->g = a;
679
	    color->b = a;
680
	}
681
	else
682
	{
683
	    color->r = l + (((color->r - l) * (a - l) / t));
684
	    color->g = l + (((color->g - l) * (a - l) / t));
685
	    color->b = l + (((color->b - l) * (a - l) / t));
686
	}
687
    }
688
}
689
 
690
static void
691
set_lum (rgb_t *color, float sa, float l)
692
{
693
    float d = l - get_lum (color);
694
 
695
    color->r = color->r + d;
696
    color->g = color->g + d;
697
    color->b = color->b + d;
698
 
699
    clip_color (color, sa);
700
}
701
 
702
static void
703
set_sat (rgb_t *src, float sat)
704
{
705
    float *max, *mid, *min;
706
    float t;
707
 
708
    if (src->r > src->g)
709
    {
710
	if (src->r > src->b)
711
	{
712
	    max = &(src->r);
713
 
714
	    if (src->g > src->b)
715
	    {
716
		mid = &(src->g);
717
		min = &(src->b);
718
	    }
719
	    else
720
	    {
721
		mid = &(src->b);
722
		min = &(src->g);
723
	    }
724
	}
725
	else
726
	{
727
	    max = &(src->b);
728
	    mid = &(src->r);
729
	    min = &(src->g);
730
	}
731
    }
732
    else
733
    {
734
	if (src->r > src->b)
735
	{
736
	    max = &(src->g);
737
	    mid = &(src->r);
738
	    min = &(src->b);
739
	}
740
	else
741
	{
742
	    min = &(src->r);
743
 
744
	    if (src->g > src->b)
745
	    {
746
		max = &(src->g);
747
		mid = &(src->b);
748
	    }
749
	    else
750
	    {
751
		max = &(src->b);
752
		mid = &(src->g);
753
	    }
754
	}
755
    }
756
 
757
    t = *max - *min;
758
 
759
    if (FLOAT_IS_ZERO (t))
760
    {
761
	*mid = *max = 0.0f;
762
    }
763
    else
764
    {
765
	*mid = ((*mid - *min) * sat) / t;
766
	*max = sat;
767
    }
768
 
769
    *min = 0.0f;
770
}
771
 
772
/*
773
 * Hue:
774
 * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
775
 */
776
static force_inline void
777
blend_hsl_hue (rgb_t *res,
778
	       const rgb_t *dest, float da,
779
	       const rgb_t *src, float sa)
780
{
781
    res->r = src->r * da;
782
    res->g = src->g * da;
783
    res->b = src->b * da;
784
 
785
    set_sat (res, get_sat (dest) * sa);
786
    set_lum (res, sa * da, get_lum (dest) * sa);
787
}
788
 
789
/*
790
 * Saturation:
791
 * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
792
 */
793
static force_inline void
794
blend_hsl_saturation (rgb_t *res,
795
		      const rgb_t *dest, float da,
796
		      const rgb_t *src, float sa)
797
{
798
    res->r = dest->r * sa;
799
    res->g = dest->g * sa;
800
    res->b = dest->b * sa;
801
 
802
    set_sat (res, get_sat (src) * da);
803
    set_lum (res, sa * da, get_lum (dest) * sa);
804
}
805
 
806
/*
807
 * Color:
808
 * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
809
 */
810
static force_inline void
811
blend_hsl_color (rgb_t *res,
812
		 const rgb_t *dest, float da,
813
		 const rgb_t *src, float sa)
814
{
815
    res->r = src->r * da;
816
    res->g = src->g * da;
817
    res->b = src->b * da;
818
 
819
    set_lum (res, sa * da, get_lum (dest) * sa);
820
}
821
 
822
/*
823
 * Luminosity:
824
 * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
825
 */
826
static force_inline void
827
blend_hsl_luminosity (rgb_t *res,
828
		      const rgb_t *dest, float da,
829
		      const rgb_t *src, float sa)
830
{
831
    res->r = dest->r * sa;
832
    res->g = dest->g * sa;
833
    res->b = dest->b * sa;
834
 
835
    set_lum (res, sa * da, get_lum (src) * da);
836
}
837
 
838
#define MAKE_NON_SEPARABLE_PDF_COMBINERS(name)				\
839
    static void								\
840
    combine_ ## name ## _u_float (pixman_implementation_t *imp,		\
841
				  pixman_op_t              op,		\
842
				  float                   *dest,	\
843
				  const float             *src,		\
844
				  const float             *mask,	\
845
				  int		           n_pixels)	\
846
    {									\
847
    	int i;								\
848
									\
849
	for (i = 0; i < 4 * n_pixels; i += 4)				\
850
	{								\
851
	    float sa, da;						\
852
	    rgb_t sc, dc, rc;						\
853
									\
854
	    sa = src[i + 0];						\
855
	    sc.r = src[i + 1];						\
856
	    sc.g = src[i + 2];						\
857
	    sc.b = src[i + 3];						\
858
									\
859
	    da = dest[i + 0];						\
860
	    dc.r = dest[i + 1];						\
861
	    dc.g = dest[i + 2];						\
862
	    dc.b = dest[i + 3];						\
863
									\
864
	    if (mask)							\
865
	    {								\
866
		float ma = mask[i + 0];					\
867
									\
868
		/* Component alpha is not supported for HSL modes */	\
869
		sa *= ma;						\
870
		sc.r *= ma;						\
871
		sc.g *= ma;						\
872
		sc.g *= ma;						\
873
	    }								\
874
									\
875
	    blend_ ## name (&rc, &dc, da, &sc, sa);			\
876
									\
877
	    dest[i + 0] = sa + da - sa * da;				\
878
	    dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r;	\
879
	    dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g;	\
880
	    dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b;	\
881
	}								\
882
    }
883
 
884
MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue)
885
MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation)
886
MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color)
887
MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity)
888
 
889
void
890
_pixman_setup_combiner_functions_float (pixman_implementation_t *imp)
891
{
892
    /* Unified alpha */
893
    imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float;
894
    imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float;
895
    imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float;
896
    imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float;
897
    imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float;
898
    imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float;
899
    imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float;
900
    imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float;
901
    imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float;
902
    imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float;
903
    imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float;
904
    imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float;
905
    imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float;
906
    imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float;
907
 
908
    /* Disjoint, unified */
909
    imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float;
910
    imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float;
911
    imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float;
912
    imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float;
913
    imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float;
914
    imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float;
915
    imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float;
916
    imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float;
917
    imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float;
918
    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float;
919
    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float;
920
    imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float;
921
 
922
    /* Conjoint, unified */
923
    imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float;
924
    imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float;
925
    imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float;
926
    imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float;
927
    imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float;
928
    imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float;
929
    imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float;
930
    imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float;
931
    imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float;
932
    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float;
933
    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float;
934
    imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float;
935
 
936
    /* PDF operators, unified */
937
    imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float;
938
    imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float;
939
    imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float;
940
    imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float;
941
    imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float;
942
    imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float;
943
    imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float;
944
    imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float;
945
    imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float;
946
    imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float;
947
    imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float;
948
 
949
    imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float;
950
    imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float;
951
    imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float;
952
    imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float;
953
 
954
    /* Component alpha combiners */
955
    imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float;
956
    imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float;
957
    imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float;
958
    imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float;
959
    imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float;
960
    imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float;
961
    imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float;
962
    imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float;
963
    imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float;
964
    imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float;
965
    imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float;
966
    imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float;
967
    imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float;
968
    imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float;
969
 
970
    /* Disjoint CA */
971
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float;
972
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float;
973
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float;
974
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float;
975
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float;
976
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float;
977
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float;
978
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float;
979
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float;
980
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float;
981
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float;
982
    imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float;
983
 
984
    /* Conjoint CA */
985
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float;
986
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float;
987
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float;
988
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float;
989
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float;
990
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float;
991
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float;
992
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float;
993
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float;
994
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float;
995
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float;
996
    imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float;
997
 
998
    /* PDF operators CA */
999
    imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float;
1000
    imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float;
1001
    imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float;
1002
    imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float;
1003
    imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float;
1004
    imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float;
1005
    imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float;
1006
    imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float;
1007
    imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float;
1008
    imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float;
1009
    imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float;
1010
 
1011
    /* It is not clear that these make sense, so make them noops for now */
1012
    imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float;
1013
    imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float;
1014
    imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float;
1015
    imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float;
1016
}