@@ -22,6 +22,7 @@ static Visual *visual;
2222static Window rootwin ;
2323static Colormap colormap ;
2424static XrmDatabase xdb ;
25+ static XRenderPictFormat * xformat ;
2526static char * xrm ;
2627static int screen ;
2728static int depth ;
@@ -173,6 +174,7 @@ static void
173174initdc (void )
174175{
175176 XGCValues values ;
177+ Pixmap pbg , pselbg , separator ;
176178 unsigned long valuemask ;
177179
178180 /* get color pixels */
@@ -191,6 +193,22 @@ initdc(void)
191193 values .line_width = config .separator_pixels ;
192194 valuemask = GCLineWidth | GCArcMode ;
193195 dc .gc = XCreateGC (dpy , rootwin , valuemask , & values );
196+
197+ /* create color source Pictures */
198+ dc .pictattr .repeat = 1 ;
199+ dc .pictattr .poly_edge = PolyEdgeSmooth ;
200+ pbg = XCreatePixmap (dpy , rootwin , 1 , 1 , depth );
201+ pselbg = XCreatePixmap (dpy , rootwin , 1 , 1 , depth );
202+ separator = XCreatePixmap (dpy , rootwin , 1 , 1 , depth );
203+ pie .bg = XRenderCreatePicture (dpy , pbg , xformat , CPRepeat , & dc .pictattr );
204+ pie .selbg = XRenderCreatePicture (dpy , pselbg , xformat , CPRepeat , & dc .pictattr );
205+ pie .separator = XRenderCreatePicture (dpy , separator , xformat , CPRepeat , & dc .pictattr );
206+ XRenderFillRectangle (dpy , PictOpOver , pie .bg , & dc .normal [ColorBG ].color , 0 , 0 , 1 , 1 );
207+ XRenderFillRectangle (dpy , PictOpOver , pie .selbg , & dc .selected [ColorBG ].color , 0 , 0 , 1 , 1 );
208+ XRenderFillRectangle (dpy , PictOpOver , pie .separator , & dc .separator .color , 0 , 0 , 1 , 1 );
209+ XFreePixmap (dpy , pbg );
210+ XFreePixmap (dpy , pselbg );
211+ XFreePixmap (dpy , separator );
194212}
195213
196214/* setup pie */
@@ -207,12 +225,10 @@ initpie(void)
207225 pie .fulldiameter = pie .diameter + (pie .border * 2 );
208226
209227 /* set the separator beginning and end */
210- pie .separatorbeg = config .separatorbeg ;
211- pie .separatorend = config .separatorend ;
212-
213- /* set the inner circle position */
214- pie .innercircley = pie .innercirclex = pie .radius - pie .radius * pie .separatorbeg ;
215- pie .innercirclediameter = (pie .radius * pie .separatorbeg ) * 2 ;
228+ pie .separatorbeg = pie .radius * config .separatorbeg ;
229+ pie .separatorend = pie .radius * config .separatorend ;
230+ pie .innerangle = atan (config .separator_pixels / (2.0 * pie .separatorbeg ));
231+ pie .outerangle = atan (config .separator_pixels / (2.0 * pie .separatorend ));
216232
217233 /* Create a simple bitmap mask (depth = 1) */
218234 pie .clip = XCreatePixmap (dpy , rootwin , pie .diameter , pie .diameter , 1 );
@@ -320,7 +336,10 @@ allocmenu(struct Menu *parent, struct Slice *list, unsigned level)
320336 menu -> x = 0 ; /* calculated by setupmenu() */
321337 menu -> y = 0 ; /* calculated by setupmenu() */
322338 menu -> level = level ;
339+
340+ /* create pixmap and picture */
323341 menu -> pixmap = XCreatePixmap (dpy , menu -> win , pie .diameter , pie .diameter , depth );
342+ menu -> picture = XRenderCreatePicture (dpy , menu -> pixmap , xformat , CPPolyEdge | CPRepeat , & dc .pictattr );
324343 menu -> drawn = 0 ;
325344
326345 return menu ;
@@ -640,78 +659,58 @@ static void
640659setslices (struct Menu * menu )
641660{
642661 struct Slice * slice ;
643- double anglerad ; /* angle in radians */
662+ double a = 0.0 ;
644663 unsigned n = 0 ;
645- int angle = 0 ;
646664 int textwidth ;
647665
648- menu -> halfslice = ( 360 * 64 ) / ( menu -> nslices * 2 ) ;
666+ menu -> half = M_PI / menu -> nslices ;
649667 for (slice = menu -> list ; slice ; slice = slice -> next ) {
650- n ++ ;
668+ slice -> slicen = n ++ ;
651669
652- slice -> angle1 = angle - menu -> halfslice ;
653- if (slice -> angle1 < 0 )
654- slice -> angle1 += 360 * 64 ;
655- slice -> angle2 = menu -> halfslice * 2 ;
670+ slice -> anglea = a - menu -> half ;
671+ slice -> angleb = a + menu -> half ;
656672
657673 /* get length of slice->label rendered in the font */
658674 textwidth = (slice -> label ) ? drawtext (NULL , NULL , 0 , 0 , slice -> label ): 0 ;
659675
660- /* anglerad is now the angle in radians of the middle of the slice */
661- anglerad = (angle * M_PI ) / (180 * 64 );
662-
663676 /* get position of slice's label */
664- slice -> labelx = pie .radius + ((pie .radius * 2 )/3 * cos (anglerad )) - (textwidth / 2 );
665- slice -> labely = pie .radius - ((pie .radius * 2 )/3 * sin (anglerad ));
677+ slice -> labelx = pie .radius + ((pie .radius * 2 )/3 * cos (a )) - (textwidth / 2 );
678+ slice -> labely = pie .radius - ((pie .radius * 2 )/3 * sin (a ));
666679
667680 /* get position of submenu */
668- slice -> x = pie .radius + (pie .diameter * (cos (anglerad ) * 0.9 ));
669- slice -> y = pie .radius - (pie .diameter * (sin (anglerad ) * 0.9 ));
681+ slice -> x = pie .radius + (pie .diameter * (cos (a ) * 0.9 ));
682+ slice -> y = pie .radius - (pie .diameter * (sin (a ) * 0.9 ));
670683
671684 /* create icon */
672685 if (slice -> file != NULL ) {
673686 int maxiconsize = (pie .radius + 1 ) / 2 ;
674- double sliceanglerad ; /* inner angle of a slice */
675687 int iconw , iconh ; /* icon width and height */
676688 int iconsize ; /* requested icon size */
677689 int xdiff , ydiff ;
678690
679- sliceanglerad = (slice -> angle2 * M_PI ) / (180 * 64 );
680-
681- xdiff = pie .radius * 0.5 - (pie .radius * (cos (sliceanglerad ) * 0.5 ));
682- ydiff = pie .radius * (sin (sliceanglerad ) * 0.5 );
691+ xdiff = pie .radius * 0.5 - (pie .radius * (cos (menu -> half ) * 0.75 ));
692+ ydiff = pie .radius * (sin (menu -> half ) * 0.75 );
683693
684694 iconsize = sqrt (xdiff * xdiff + ydiff * ydiff );
685695 iconsize = MIN (maxiconsize , iconsize );
686696
687697 slice -> icon = loadicon (slice -> file , iconsize , & iconw , & iconh );
688698
689- slice -> iconx = pie .radius + (pie .radius * (cos (anglerad ) * 0.6 )) - iconw / 2 ;
690- slice -> icony = pie .radius - (pie .radius * (sin (anglerad ) * 0.6 )) - iconh / 2 ;
699+ slice -> iconx = pie .radius + (pie .radius * (cos (a ) * 0.6 )) - iconw / 2 ;
700+ slice -> icony = pie .radius - (pie .radius * (sin (a ) * 0.6 )) - iconh / 2 ;
691701 }
692702
693- /* anglerad is now the angle in radians of angle1 */
694- anglerad = (slice -> angle1 * M_PI ) / (180 * 64 );
695-
696- /* set position of the line segment separating slices */
697- slice -> linexi = pie .radius + pie .radius * (cos (anglerad ) * pie .separatorbeg );
698- slice -> lineyi = pie .radius + pie .radius * (sin (anglerad ) * pie .separatorbeg );
699- slice -> linexo = pie .radius + pie .radius * (cos (anglerad ) * pie .separatorend );
700- slice -> lineyo = pie .radius + pie .radius * (sin (anglerad ) * pie .separatorend );
701- if (abs (slice -> linexo - slice -> linexi ) <= 2 )
702- slice -> linexo = slice -> linexi ;
703-
704- /* set position of the icon */
705- angle = (360 * 64 * n ) / menu -> nslices ;
706-
707703 /* create and draw pixmap */
708704 slice -> pixmap = XCreatePixmap (dpy , menu -> win , pie .diameter , pie .diameter , depth );
705+ slice -> picture = XRenderCreatePicture (dpy , slice -> pixmap , xformat , CPPolyEdge | CPRepeat , & dc .pictattr );
709706 slice -> drawn = 0 ;
710707
711708 /* call recursivelly */
712709 if (slice -> submenu != NULL ) {
713710 setslices (slice -> submenu );
714711 }
712+
713+ a += menu -> half * 2 ;
715714 }
716715}
717716
@@ -847,8 +846,7 @@ static struct Slice *
847846getslice (struct Menu * menu , int x , int y )
848847{
849848 struct Slice * slice ;
850- double phi ;
851- int angle ;
849+ double angle ;
852850 int r ;
853851
854852 if (menu == NULL )
@@ -860,18 +858,17 @@ getslice(struct Menu *menu, int x, int y)
860858
861859 /* if the cursor is in the middle circle, it is in no slice */
862860 r = sqrt (x * x + y * y );
863- if (r <= pie .radius * pie . separatorbeg )
861+ if (r <= pie .separatorbeg )
864862 return NULL ;
865863
866- phi = atan2 (y , x );
867- if (y < 0 )
868- phi += 2 * M_PI ;
869- angle = ((phi * 180 * 64 ) / M_PI );
870-
871- if (angle < menu -> halfslice )
872- return menu -> list ;
873- for (slice = menu -> list ; slice != NULL ; slice = slice -> next )
874- if (angle >= slice -> angle1 && angle < slice -> angle1 + slice -> angle2 )
864+ angle = atan2 (y , x );
865+ if (angle < 0.0 ) {
866+ if (angle > - menu -> half )
867+ return menu -> list ;
868+ angle = (2 * M_PI ) + angle ;
869+ }
870+ for (slice = menu -> list ; slice ; slice = slice -> next )
871+ if (angle >= slice -> anglea && angle < slice -> angleb )
875872 return slice ;
876873
877874 return NULL ;
@@ -941,6 +938,92 @@ unmapmenu(struct Menu *currmenu)
941938 }
942939}
943940
941+ /* draw background of selected slice */
942+ static void
943+ drawslice (struct Menu * menu , struct Slice * slice )
944+ {
945+ XPointDouble * p ;
946+ int i , n ;
947+ double hd , a , b , c ;
948+
949+ if (slice == NULL )
950+ return ;
951+
952+ /* determine number of segments to draw */
953+ hd = hypot (pie .radius , pie .radius )/2 ;
954+ n = ((2 * M_PI ) / (menu -> nslices * acos (hd /(hd + 1.0 )))) + 0.5 ;
955+
956+ /* angles */
957+ a = ((2 * M_PI ) / (menu -> nslices * n ));
958+ b = ((2 * M_PI ) / menu -> nslices );
959+ c = b * slice -> slicen ;
960+
961+ p = emalloc ((n + 2 ) * sizeof * p );
962+ p [0 ].x = pie .radius ;
963+ p [0 ].y = pie .radius ;
964+ for (i = 0 ; i < n + 1 ; i ++ ) {
965+ p [i + 1 ].x = pie .radius + (pie .radius + 1 ) * cos ((i - (n / 2.0 )) * a - c );
966+ p [i + 1 ].y = pie .radius + (pie .radius + 1 ) * sin ((i - (n / 2.0 )) * a - c );
967+ }
968+
969+ XRenderCompositeDoublePoly (dpy , PictOpOver , pie .selbg , slice -> picture ,
970+ XRenderFindStandardFormat (dpy , PictStandardA8 ),
971+ 0 , 0 , 0 , 0 , p , n + 2 , 0 );
972+
973+ free (p );
974+ }
975+
976+ /* draw circle */
977+ static void
978+ drawcircle (Picture picture , int radius )
979+ {
980+ XPointDouble * p ;
981+ int i , n ;
982+ double hd , a ;
983+
984+ /* determine number of segments to draw */
985+ hd = hypot (radius , radius )/2 ;
986+ n = ((2 * M_PI ) / (acos (hd /(hd + 1.0 )))) + 0.5 ;
987+
988+ /* angles */
989+ a = ((2 * M_PI ) / n );
990+
991+ p = emalloc ((n + 2 ) * sizeof * p );
992+ p [0 ].x = pie .radius ;
993+ p [0 ].y = pie .radius ;
994+ for (i = 0 ; i < n + 1 ; i ++ ) {
995+ p [i + 1 ].x = pie .radius + (radius + 1 ) * cos (i * a );
996+ p [i + 1 ].y = pie .radius + (radius + 1 ) * sin (i * a );
997+ }
998+
999+ XRenderCompositeDoublePoly (dpy , PictOpOver , pie .bg , picture ,
1000+ XRenderFindStandardFormat (dpy , PictStandardA8 ),
1001+ 0 , 0 , 0 , 0 , p , n + 2 , 0 );
1002+
1003+ free (p );
1004+ }
1005+
1006+ /* draw separator before slice */
1007+ static void
1008+ drawseparator (Picture picture , struct Menu * menu , struct Slice * slice )
1009+ {
1010+ XPointDouble p [4 ];
1011+ double a ;
1012+
1013+ a = (M_PI / menu -> nslices ) + ((2 * M_PI ) / menu -> nslices ) * slice -> slicen ;
1014+ p [0 ].x = pie .radius + pie .separatorbeg * cos (a - pie .innerangle );
1015+ p [0 ].y = pie .radius + pie .separatorbeg * sin (a - pie .innerangle );
1016+ p [1 ].x = pie .radius + pie .separatorbeg * cos (a + pie .innerangle );
1017+ p [1 ].y = pie .radius + pie .separatorbeg * sin (a + pie .innerangle );
1018+ p [2 ].x = pie .radius + pie .separatorend * cos (a + pie .outerangle );
1019+ p [2 ].y = pie .radius + pie .separatorend * sin (a + pie .outerangle );
1020+ p [3 ].x = pie .radius + pie .separatorend * cos (a - pie .outerangle );
1021+ p [3 ].y = pie .radius + pie .separatorend * sin (a - pie .outerangle );
1022+ XRenderCompositeDoublePoly (dpy , PictOpOver , pie .separator , picture ,
1023+ XRenderFindStandardFormat (dpy , PictStandardA8 ),
1024+ 0 , 0 , 0 , 0 , p , 4 , 0 );
1025+ }
1026+
9441027/* draw regular slice */
9451028static void
9461029drawmenu (struct Menu * menu , struct Slice * selected )
@@ -949,27 +1032,22 @@ drawmenu(struct Menu *menu, struct Slice *selected)
9491032 XftColor * color ;
9501033 XftDraw * draw ;
9511034 Drawable pixmap ;
1035+ Picture picture ;
9521036
9531037 if (selected ) {
9541038 pixmap = selected -> pixmap ;
1039+ picture = selected -> picture ;
9551040 selected -> drawn = 1 ;
9561041 } else {
9571042 pixmap = menu -> pixmap ;
1043+ picture = menu -> picture ;
9581044 menu -> drawn = 1 ;
9591045 }
9601046
961- /* draw slice background */
962- for (slice = menu -> list ; slice ; slice = slice -> next ) {
963- if (slice == selected )
964- color = dc .selected ;
965- else
966- color = dc .normal ;
967-
968- XSetForeground (dpy , dc .gc , color [ColorBG ].pixel );
969- XFillArc (dpy , pixmap , dc .gc , 0 , 0 ,
970- pie .diameter , pie .diameter ,
971- slice -> angle1 , slice -> angle2 );
972- }
1047+ /* draw background */
1048+ XSetForeground (dpy , dc .gc , dc .normal [ColorBG ].pixel );
1049+ XFillRectangle (dpy , pixmap , dc .gc , 0 , 0 , pie .diameter , pie .diameter );
1050+ drawslice (menu , selected );
9731051
9741052 /* draw slice foreground */
9751053 for (slice = menu -> list ; slice ; slice = slice -> next ) {
@@ -991,18 +1069,11 @@ drawmenu(struct Menu *menu, struct Slice *selected)
9911069 }
9921070
9931071 /* draw separator */
994- XSetForeground (dpy , dc .gc , dc .separator .pixel );
995- XDrawLine (dpy , pixmap , dc .gc ,
996- slice -> linexi , slice -> lineyi ,
997- slice -> linexo , slice -> lineyo );
1072+ drawseparator (picture , menu , slice );
9981073 }
9991074
10001075 /* draw inner circle */
1001- XSetForeground (dpy , dc .gc , dc .normal [ColorBG ].pixel );
1002- XFillArc (dpy , pixmap , dc .gc ,
1003- pie .innercirclex , pie .innercircley ,
1004- pie .innercirclediameter , pie .innercirclediameter ,
1005- 0 , 360 * 64 );
1076+ drawcircle (picture , pie .separatorbeg );
10061077}
10071078
10081079/* draw slices of the current menu and of its ancestors */
@@ -1273,6 +1344,7 @@ main(int argc, char *argv[])
12731344 rootwin = RootWindow (dpy , screen );
12741345 colormap = DefaultColormap (dpy , screen );
12751346 depth = DefaultDepth (dpy , screen );
1347+ xformat = XRenderFindVisualFormat (dpy , visual );
12761348 if ((xrm = XResourceManagerString (dpy )) != NULL )
12771349 xdb = XrmGetStringDatabase (xrm );
12781350
0 commit comments