@@ -302,6 +302,141 @@ static const twin_src_msk_op comp3[2][4][4][3] = {
302
302
#define operand_index (o ) \
303
303
((o)->source_kind == TWIN_SOLID ? 3 : o->u.pixmap->format)
304
304
305
+ #define _twin_add_ARGB (s , d , i , t ) (((t) = (s) + twin_get_8(d, i)))
306
+ #define _twin_add (s , d , t ) (((t) = (s) + (d)))
307
+ #define _twin_div (d , i , t ) \
308
+ (((t) = (d) / 9), (t) = twin_get_8((t), 0), \
309
+ (twin_argb32_t) twin_sat(t) << (i))
310
+ #define _twin_sub_ARGB (s , d , i , t ) (((t) = (s) - twin_get_8(d, i)))
311
+ #define _twin_sub (s , d , t ) (((t) = (s) - (d)))
312
+ #define twin_put_8 (d , i , t ) (((t) = (d) << (i)))
313
+
314
+ #define min (x , y ) \
315
+ ({ \
316
+ typeof(x) _x = (x); \
317
+ typeof(y) _y = (y); \
318
+ (void) (&_x == &_y); \
319
+ _x < _y ? _x : _y; \
320
+ })
321
+ #define max (x , y ) \
322
+ ({ \
323
+ typeof(x) _x = (x); \
324
+ typeof(y) _y = (y); \
325
+ (void) (&_x == &_y); \
326
+ _x > _y ? _x : _y; \
327
+ })
328
+
329
+ void twin_stack (twin_pixmap_t * trg_px , twin_pixmap_t * src_px , bool horiz_span )
330
+ {
331
+ int first_num , second_num , radius = 2 ;
332
+ twin_pointer_t src_ptr , trg_ptr , old_ptr , new_ptr ;
333
+ twin_argb32_t sumInR , sumOutR , sumR , sumInG , sumOutG , sumG , sumInB , sumOutB ,
334
+ sumB , _cur , _old , _new , _src ;
335
+ uint16_t t1 , t2 , t3 , t4 ;
336
+ first_num = src_px -> height , second_num = src_px -> width ;
337
+ for (int first = 0 ; first < first_num ; first ++ ) {
338
+ /* padding sum_out */
339
+ sumInR = sumOutR = sumR = sumInG = sumOutG = sumG = sumInB = sumOutB =
340
+ sumB = 0x00000000 ;
341
+
342
+ for (int i = 0 ; i < radius ; i ++ ) {
343
+ if (horiz_span )
344
+ src_ptr = twin_pixmap_pointer (src_px , 0 , first );
345
+ else
346
+ src_ptr = twin_pixmap_pointer (src_px , first , 0 );
347
+ _src = * src_ptr .argb32 ;
348
+ sumOutR = _twin_add_ARGB (sumOutR , _src , 0 , t1 );
349
+ sumOutG = _twin_add_ARGB (sumOutG , _src , 8 , t2 );
350
+ sumOutB = _twin_add_ARGB (sumOutB , _src , 16 , t3 );
351
+ for (int j = 0 ; j < i + 1 ; j ++ ) {
352
+ sumR = _twin_add_ARGB (sumR , _src , 0 , t1 );
353
+ sumG = _twin_add_ARGB (sumG , _src , 8 , t2 );
354
+ sumB = _twin_add_ARGB (sumB , _src , 16 , t3 );
355
+ }
356
+ }
357
+
358
+ for (int i = 0 ; i < radius ; i ++ ) {
359
+ if (horiz_span )
360
+ src_ptr = twin_pixmap_pointer (src_px , i , first );
361
+ else
362
+ src_ptr = twin_pixmap_pointer (src_px , first , i );
363
+ _src = * src_ptr .argb32 ;
364
+ sumInR = _twin_add_ARGB (sumInR , _src , 0 , t1 );
365
+ sumInG = _twin_add_ARGB (sumInG , _src , 8 , t2 );
366
+ sumInB = _twin_add_ARGB (sumInB , _src , 16 , t3 );
367
+ for (int j = 0 ; j < radius - i ; j ++ ) {
368
+ sumR = _twin_add_ARGB (sumR , _src , 0 , t1 );
369
+ sumG = _twin_add_ARGB (sumG , _src , 8 , t2 );
370
+ sumB = _twin_add_ARGB (sumB , _src , 16 , t3 );
371
+ }
372
+ }
373
+
374
+ for (int cur = 0 ; cur < second_num ; cur ++ ) {
375
+ if (horiz_span ) {
376
+ src_ptr = twin_pixmap_pointer (src_px , cur , first );
377
+ trg_ptr = twin_pixmap_pointer (trg_px , cur , first );
378
+ old_ptr =
379
+ twin_pixmap_pointer (src_px , max (cur - radius , 0 ), first );
380
+ new_ptr = twin_pixmap_pointer (
381
+ src_px , min (cur + radius , second_num - 1 ), first );
382
+ } else {
383
+ src_ptr = twin_pixmap_pointer (src_px , first , cur );
384
+ trg_ptr = twin_pixmap_pointer (trg_px , first , cur );
385
+ old_ptr =
386
+ twin_pixmap_pointer (src_px , first , max (cur - radius , 0 ));
387
+ new_ptr = twin_pixmap_pointer (
388
+ src_px , first , min (cur + radius , second_num - 1 ));
389
+ }
390
+ _cur = * src_ptr .argb32 ;
391
+ _old = * old_ptr .argb32 ;
392
+ _new = * new_ptr .argb32 ;
393
+ /* STEP 1 : sum_out + current */
394
+ sumOutR = _twin_add_ARGB (sumOutR , _cur , 0 , t1 );
395
+ sumOutG = _twin_add_ARGB (sumOutG , _cur , 8 , t2 );
396
+ sumOutB = _twin_add_ARGB (sumOutB , _cur , 16 , t3 );
397
+ /* STEP 2 : sum_in + new */
398
+ sumInR = _twin_add_ARGB (sumInR , _new , 0 , t1 );
399
+ sumInG = _twin_add_ARGB (sumInG , _new , 8 , t2 );
400
+ sumInB = _twin_add_ARGB (sumInB , _new , 16 , t3 );
401
+ /* STEP 3: sum + sum_in */
402
+ sumR = _twin_add (sumR , sumInR , t1 );
403
+ sumG = _twin_add (sumG , sumInG , t2 );
404
+ sumB = _twin_add (sumB , sumInB , t3 );
405
+ /* STEP 4 : sum / 9 */
406
+ * trg_ptr .argb32 =
407
+ (_twin_div (sumR , 0 , t1 ) | _twin_div (sumG , 8 , t2 ) |
408
+ _twin_div (sumB , 16 , t3 ) | (* src_ptr .argb32 & 0xff000000 ));
409
+ /* STEP 5 : sum - sum_out */
410
+ sumR = _twin_sub (sumR , sumOutR , t1 );
411
+ sumG = _twin_sub (sumG , sumOutG , t2 );
412
+ sumB = _twin_sub (sumB , sumOutB , t3 );
413
+ /* STEP 6 : sum_out - old */
414
+ sumOutR = _twin_sub_ARGB (sumOutR , _old , 0 , t1 );
415
+ sumOutG = _twin_sub_ARGB (sumOutG , _old , 8 , t2 );
416
+ sumOutB = _twin_sub_ARGB (sumOutB , _old , 16 , t3 );
417
+ /* STEP 7 : sum_in - source_current */
418
+ sumInR = _twin_sub_ARGB (sumInR , _cur , 0 , t1 );
419
+ sumInG = _twin_sub_ARGB (sumInG , _cur , 8 , t2 );
420
+ sumInB = _twin_sub_ARGB (sumInB , _cur , 16 , t3 );
421
+ }
422
+ }
423
+ }
424
+
425
+ void twin_stack_blur (twin_pixmap_t * px )
426
+ {
427
+ if (px -> format != TWIN_ARGB32 )
428
+ return ;
429
+ twin_pixmap_t * tmp_px =
430
+ twin_pixmap_create (px -> format , px -> width , px -> height );
431
+ memcpy (tmp_px -> p .v , px -> p .v ,
432
+ px -> width * px -> height * twin_bytes_per_pixel (px -> format ));
433
+
434
+ twin_stack (tmp_px , px , true);
435
+ twin_stack (px , tmp_px , false);
436
+ twin_pixmap_destroy (tmp_px );
437
+ return ;
438
+ }
439
+
305
440
/* FIXME: source clipping is busted */
306
441
static void _twin_composite_simple (twin_pixmap_t * dst ,
307
442
twin_coord_t dst_x ,
@@ -777,3 +912,41 @@ void twin_fill(twin_pixmap_t *dst,
777
912
(* op )(twin_pixmap_pointer (dst , left , iy ), src , right - left );
778
913
twin_pixmap_damage (dst , left , top , right , bottom );
779
914
}
915
+
916
+ void twin_glass_fill (twin_pixmap_t * dst ,
917
+ twin_argb32_t pixel ,
918
+ twin_operator_t operator ,
919
+ twin_coord_t left ,
920
+ twin_coord_t top ,
921
+ twin_coord_t right ,
922
+ twin_coord_t bottom )
923
+ {
924
+ twin_src_op op ;
925
+ twin_source_u src ;
926
+ twin_coord_t iy , ix ;
927
+
928
+ /* offset */
929
+ left += dst -> origin_x ;
930
+ top += dst -> origin_y ;
931
+ right += dst -> origin_x ;
932
+ bottom += dst -> origin_y ;
933
+
934
+ /* clip */
935
+ if (left < dst -> clip .left )
936
+ left = dst -> clip .left ;
937
+ if (right > dst -> clip .right )
938
+ right = dst -> clip .right ;
939
+ if (top < dst -> clip .top )
940
+ top = dst -> clip .top ;
941
+ if (bottom > dst -> clip .bottom )
942
+ bottom = dst -> clip .bottom ;
943
+ if (left >= right || top >= bottom )
944
+ return ;
945
+
946
+ src .c = pixel ;
947
+ op = fill [operator ][dst -> format ];
948
+
949
+ for (iy = 0 ; iy < dst -> height ; iy ++ )
950
+ for (ix = 0 ; ix < dst -> width ; ix ++ )
951
+ (* op )(twin_pixmap_pointer (dst , ix , iy ), src , 1 );
952
+ }
0 commit comments