1+ static uint32_t tmpicon [ICONSIZE * ICONSIZE ];
2+
3+ static uint32_t prealpha (uint32_t p ) {
4+ uint8_t a = p >> 24u ;
5+ uint32_t rb = (a * (p & 0xFF00FFu )) >> 8u ;
6+ uint32_t g = (a * (p & 0x00FF00u )) >> 8u ;
7+ return (rb & 0xFF00FFu ) | (g & 0x00FF00u ) | ((~a ) << 24u );
8+ }
9+
10+ #if BAR_ALPHA_PATCH
11+ static uint8_t div255 (uint16_t x ) { return (x * 0x8081u ) >> 23u ; }
12+ static uint32_t blend (uint32_t p1rb , uint32_t p1g , uint8_t p1a , uint32_t p2 ) {
13+ uint8_t a = p2 >> 24u ;
14+ uint32_t rb = (p2 & 0xFF00FFu ) + ( (a * p1rb ) >> 8u );
15+ uint32_t g = (p2 & 0x00FF00u ) + ( (a * p1g ) >> 8u );
16+ return (rb & 0xFF00FFu ) | (g & 0x00FF00u ) | div255 (~a * 255u + a * p1a ) << 24u ;
17+ }
18+
19+ void
20+ drw_img (Drw * drw , int x , int y , XImage * img , uint32_t * tmp )
21+ {
22+ if (!drw || !drw -> scheme )
23+ return ;
24+ uint32_t * data = (uint32_t * )img -> data , p = drw -> scheme [ColBg ].pixel ,
25+ prb = p & 0xFF00FFu , pg = p & 0x00FF00u ;
26+ uint8_t pa = p >> 24u ;
27+ int icsz = img -> width * img -> height , i ;
28+ for (i = 0 ; i < icsz ; ++ i ) tmp [i ] = blend (prb , pg , pa , data [i ]);
29+
30+ img -> data = (char * ) tmp ;
31+ XPutImage (drw -> dpy , drw -> drawable , drw -> gc , img , 0 , 0 , x , y , img -> width , img -> height );
32+ img -> data = (char * ) data ;
33+ }
34+ #else
35+ static uint32_t blend (uint32_t p1rb , uint32_t p1g , uint32_t p2 ) {
36+ uint8_t a = p2 >> 24u ;
37+ uint32_t rb = (p2 & 0xFF00FFu ) + ( (a * p1rb ) >> 8u );
38+ uint32_t g = (p2 & 0x00FF00u ) + ( (a * p1g ) >> 8u );
39+ return (rb & 0xFF00FFu ) | (g & 0x00FF00u ) | ((~a ) << 24u );
40+ }
41+
42+ void
43+ drw_img (Drw * drw , int x , int y , XImage * img , uint32_t * tmp )
44+ {
45+ if (!drw || !drw -> scheme )
46+ return ;
47+ uint32_t * data = (uint32_t * )img -> data , p = drw -> scheme [ColBg ].pixel , prb = p & 0xFF00FFu , pg = p & 0x00FF00u ;
48+ int icsz = img -> width * img -> height , i ;
49+ for (i = 0 ; i < icsz ; ++ i ) tmp [i ] = blend (prb , pg , data [i ]);
50+ img -> data = (char * ) tmp ;
51+ XPutImage (drw -> dpy , drw -> drawable , drw -> gc , img , 0 , 0 , x , y , img -> width , img -> height );
52+ img -> data = (char * ) data ;
53+ }
54+ #endif // BAR_ALPHA_PATCH
55+
56+ XImage *
57+ geticonprop (Window win )
58+ {
59+ int format ;
60+ unsigned long n , extra , * p = NULL ;
61+ Atom real ;
62+
63+ if (XGetWindowProperty (dpy , win , netatom [NetWMIcon ], 0L , LONG_MAX , False , AnyPropertyType ,
64+ & real , & format , & n , & extra , (unsigned char * * )& p ) != Success )
65+ return NULL ;
66+ if (n == 0 || format != 32 ) { XFree (p ); return NULL ; }
67+
68+ unsigned long * bstp = NULL ;
69+ uint32_t w , h , sz ;
70+
71+ {
72+ const unsigned long * end = p + n ;
73+ unsigned long * i ;
74+ uint32_t bstd = UINT32_MAX , d , m ;
75+ for (i = p ; i < end - 1 ; i += sz ) {
76+ if ((w = * i ++ ) > UINT16_MAX || (h = * i ++ ) > UINT16_MAX ) { XFree (p ); return NULL ; }
77+ if ((sz = w * h ) > end - i ) break ;
78+ if ((m = w > h ? w : h ) >= ICONSIZE && (d = m - ICONSIZE ) < bstd ) { bstd = d ; bstp = i ; }
79+ }
80+ if (!bstp ) {
81+ for (i = p ; i < end - 1 ; i += sz ) {
82+ if ((w = * i ++ ) > UINT16_MAX || (h = * i ++ ) > UINT16_MAX ) { XFree (p ); return NULL ; }
83+ if ((sz = w * h ) > end - i ) break ;
84+ if ((d = ICONSIZE - (w > h ? w : h )) < bstd ) { bstd = d ; bstp = i ; }
85+ }
86+ }
87+ if (!bstp ) { XFree (p ); return NULL ; }
88+ }
89+
90+ if ((w = * (bstp - 2 )) == 0 || (h = * (bstp - 1 )) == 0 ) { XFree (p ); return NULL ; }
91+
92+ uint32_t icw , ich , icsz ;
93+ if (w <= h ) {
94+ ich = ICONSIZE ; icw = w * ICONSIZE / h ;
95+ if (icw == 0 ) icw = 1 ;
96+ }
97+ else {
98+ icw = ICONSIZE ; ich = h * ICONSIZE / w ;
99+ if (ich == 0 ) ich = 1 ;
100+ }
101+ icsz = icw * ich ;
102+
103+ uint32_t i ;
104+ #if ULONG_MAX > UINT32_MAX
105+ uint32_t * bstp32 = (uint32_t * )bstp ;
106+ for (sz = w * h , i = 0 ; i < sz ; ++ i ) bstp32 [i ] = bstp [i ];
107+ #endif
108+ uint32_t * icbuf = malloc (icsz << 2 ); if (!icbuf ) { XFree (p ); return NULL ; }
109+ if (w == icw && h == ich ) memcpy (icbuf , bstp , icsz << 2 );
110+ else {
111+ Imlib_Image origin = imlib_create_image_using_data (w , h , (DATA32 * )bstp );
112+ if (!origin ) { XFree (p ); free (icbuf ); return NULL ; }
113+ imlib_context_set_image (origin );
114+ imlib_image_set_has_alpha (1 );
115+ Imlib_Image scaled = imlib_create_cropped_scaled_image (0 , 0 , w , h , icw , ich );
116+ imlib_free_image_and_decache ();
117+ if (!scaled ) { XFree (p ); free (icbuf ); return NULL ; }
118+ imlib_context_set_image (scaled );
119+ imlib_image_set_has_alpha (1 );
120+ memcpy (icbuf , imlib_image_get_data_for_reading_only (), icsz << 2 );
121+ imlib_free_image_and_decache ();
122+ }
123+ XFree (p );
124+ for (i = 0 ; i < icsz ; ++ i ) icbuf [i ] = prealpha (icbuf [i ]);
125+ #if BAR_ALPHA_PATCH
126+ return XCreateImage (dpy , drw -> visual , drw -> depth , ZPixmap , 0 , (char * )icbuf , icw , ich , 32 , 0 );
127+ #else
128+ return XCreateImage (dpy , DefaultVisual (dpy , screen ), DefaultDepth (dpy , screen ), ZPixmap , 0 , (char * )icbuf , icw , ich , 32 , 0 );
129+ #endif // BAR_ALPHA_PATCH
130+ }
131+
132+ void
133+ freeicon (Client * c )
134+ {
135+ if (c -> icon ) {
136+ XDestroyImage (c -> icon );
137+ c -> icon = NULL ;
138+ }
139+ }
140+
141+ void
142+ updateicon (Client * c )
143+ {
144+ freeicon (c );
145+ c -> icon = geticonprop (c -> win );
146+ }
0 commit comments