I looking for a way to draw a rounded rect given the radius and the thickness of the lines. Here is my code. I could have just done a circlefill instead of putpixels, but I want the rectangle to be contained in x1y1-x2y2. So the thicker I increase the thickness, the rectangle stays the same size. Just the thickness of the lines changes.
Here is a screenshot with radius=16, thickness=12,color=black
http://www.dharmon.cc/misc/sshot.png
1 | #pragma warning( disable: 4311 ) |
2 | #pragma warning( disable: 4312 ) |
3 | |
4 | #include <allegro.h> |
5 | |
6 | typedef struct _tc_struct |
7 | { |
8 | int color; |
9 | int thickness; |
10 | } _tc_struct; |
11 | |
12 | #define tc_to_i( x ) ((int)(void*)(_tc_struct*)(x)) |
13 | #define i_to_tc( x ) ((_tc_struct*)(void*)(int)(x)) |
14 | |
15 | |
16 | // draws a 1 width rect from top |
17 | void thickputpixel_t( BITMAP *bmp, int x, int y, int color ) |
18 | { |
19 | rectfill( bmp, x, y, x, y + i_to_tc( color )->thickness, i_to_tc( color )->color ); |
20 | } |
21 | |
22 | // draws a 1 width rect from bottom |
23 | void thickputpixel_b( BITMAP *bmp, int x, int y, int color ) |
24 | { |
25 | rectfill( bmp, x, y, x, y - i_to_tc( color )->thickness, i_to_tc( color )->color ); |
26 | } |
27 | |
28 | // draws a 1 height rect from right |
29 | void thickputpixel_r( BITMAP *bmp, int x, int y, int color ) |
30 | { |
31 | rectfill( bmp, x, y, x - i_to_tc( color )->thickness, y, i_to_tc( color )->color ); |
32 | } |
33 | |
34 | void thickputpixel_l( BITMAP *bmp, int x, int y, int color ) |
35 | { |
36 | rectfill( bmp, x, y, x + i_to_tc( color )->thickness, y, i_to_tc( color )->color ); |
37 | } |
38 | |
39 | void thickputpixel_tl( BITMAP *bmp, int x, int y, int color ) |
40 | { |
41 | rectfill( bmp, x, y, x + i_to_tc( color )->thickness, y + i_to_tc( color )->thickness, i_to_tc( color )->color ); |
42 | } |
43 | |
44 | void thickputpixel_tr( BITMAP *bmp, int x, int y, int color ) |
45 | { |
46 | rectfill( bmp, x, y, x - i_to_tc( color )->thickness, y + i_to_tc( color )->thickness, i_to_tc( color )->color ); |
47 | } |
48 | |
49 | void thickputpixel_bl( BITMAP *bmp, int x, int y, int color ) |
50 | { |
51 | rectfill( bmp, x, y, x + i_to_tc( color )->thickness, y - i_to_tc( color )->thickness, i_to_tc( color )->color ); |
52 | } |
53 | |
54 | void thickputpixel_br( BITMAP *bmp, int x, int y, int color ) |
55 | { |
56 | rectfill( bmp, x, y, x - i_to_tc( color )->thickness, y - i_to_tc( color )->thickness, i_to_tc( color )->color ); |
57 | } |
58 | |
59 | /******************************************************************************/ |
60 | |
61 | void thickline_t( BITMAP *bmp, int x1, int y1, int x2, int y2, int color ) |
62 | { |
63 | do_line( bmp, x1, y1, x2, y2, color, thickputpixel_t ); |
64 | } |
65 | |
66 | void thickline_b( BITMAP *bmp, int x1, int y1, int x2, int y2, int color ) |
67 | { |
68 | do_line( bmp, x1, y1, x2, y2, color, thickputpixel_b ); |
69 | } |
70 | void thickline_r( BITMAP *bmp, int x1, int y1, int x2, int y2, int color ) |
71 | { |
72 | do_line( bmp, x1, y1, x2, y2, color, thickputpixel_r ); |
73 | } |
74 | |
75 | void thickline_l( BITMAP *bmp, int x1, int y1, int x2, int y2, int color ) |
76 | { |
77 | do_line( bmp, x1, y1, x2, y2, color, thickputpixel_l ); |
78 | } |
79 | |
80 | /******************************************************************************/ |
81 | |
82 | void thickarc_tl( BITMAP *bmp, int x, int y, fixed angle1, fixed angle2, int r, int color ) |
83 | { |
84 | do_arc( bmp, x, y, angle1, angle2, r, color, thickputpixel_tl ); |
85 | } |
86 | |
87 | void thickarc_tr( BITMAP *bmp, int x, int y, fixed angle1, fixed angle2, int r, int color ) |
88 | { |
89 | do_arc( bmp, x, y, angle1, angle2, r, color, thickputpixel_tr ); |
90 | } |
91 | |
92 | void thickarc_bl( BITMAP *bmp, int x, int y, fixed angle1, fixed angle2, int r, int color ) |
93 | { |
94 | do_arc( bmp, x, y, angle1, angle2, r, color, thickputpixel_bl ); |
95 | } |
96 | |
97 | void thickarc_br( BITMAP *bmp, int x, int y, fixed angle1, fixed angle2, int r, int color ) |
98 | { |
99 | do_arc( bmp, x, y, angle1, angle2, r, color, thickputpixel_br ); |
100 | } |
101 | |
102 | /******************************************************************************/ |
103 | |
104 | void drawRoundedRect( BITMAP *bitmap, int x1, int y1, int x2, int y2, int radius, int thickness, int color ) |
105 | { |
106 | _tc_struct tc; |
107 | |
108 | tc.thickness = thickness - 1; |
109 | tc.color = color; |
110 | |
111 | |
112 | thickarc_tl( bitmap, x1 + radius, y1 + radius, itofix( 64 ), itofix( 128 ), radius, tc_to_i( &tc ) ); |
113 | thickarc_tr( bitmap, x2 - radius, y1 + radius, itofix( 0 ), itofix( 64 ), radius, tc_to_i( &tc ) ); |
114 | thickarc_br( bitmap, x2 - radius, y2 - radius, itofix( 192 ), itofix( 0 ), radius, tc_to_i( &tc ) ); |
115 | thickarc_bl( bitmap, x1 + radius, y2 - radius, itofix( 128 ), itofix( 192 ), radius, tc_to_i( &tc ) ); |
116 | |
117 | thickline_t( bitmap, x1 + radius, y1, x2 - radius, y1, tc_to_i( &tc ) ); |
118 | thickline_b( bitmap, x1 + radius, y2, x2 - radius, y2, tc_to_i( &tc) ); |
119 | thickline_l( bitmap, x1, y1 + radius, x1, y2 - radius, tc_to_i( &tc )); |
120 | thickline_r( bitmap, x2, y1 + radius, x2, y2 - radius, tc_to_i( &tc ) ); |
121 | } |
I wanted to give more than just the color to do_line and do_arc. I wanted to add a thickness. So I created a struct and sent the struct instead.
Does anyone have a better way to do this?
Your inner radius is same as outer radius. The arches have different middle points. So the thickness is not constant. It doesn't look bad, but I'd draw them with same center point.
Guess my approach would to draw four rectangles forming the straight edges. Then I'd use quadratic bitmaps for the corners. I'd start with magic pink for the quadrates, then I'd draw a black larger circle and a magenta smaller circle, both with centre in the corner of the quadrate. Then I'd transparent blit the quadrate to the right place.
I thought about using one bitmap for the corners, but wouldn't creating it, drawing to it, and blitting it be more time consuming?
Does anyone have a better way to do this?
ol::Rect( x, y, w, h, thickness, roundness ).Draw( color );
Seriously though...
I thought about using one bitmap for the corners, but wouldn't creating it, drawing to it, and blitting it be more time consuming?
You mean, more time-consuming than to call rectfill per each pixel through a function pointer? The best way would be to rip Allegro's circle code and modify that to draw your thick edges - all 4 at the same time as they're mirror images of each other.