Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Drawing Rounded Rects

This thread is locked; no one can reply to it. rss feed Print
Drawing Rounded Rects
DanielH
Member #934
January 2001
avatar

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 
6typedef 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
17void 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
23void 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
29void 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 
34void 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 
39void 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 
44void 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 
49void 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 
54void 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 
61void 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 
66void 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}
70void 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 
75void 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 
82void 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 
87void 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 
92void 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 
97void 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 
104void 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?

Johan Halmén
Member #1,550
September 2001

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.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

DanielH
Member #934
January 2001
avatar

I thought about using one bitmap for the corners, but wouldn't creating it, drawing to it, and blitting it be more time consuming?

Fladimir da Gorf
Member #1,565
October 2001
avatar

Quote:

Does anyone have a better way to do this?

ol::Rect( x, y, w, h, thickness, roundness ).Draw( color );

;)

Seriously though...

Quote:

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.

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Go to: