Rounded Rectangles

Post Reply
matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Rounded Rectangles

Post by matt7 »

These are some simple functions for drawing rectangles with rounded corners. They are designed to match the built-in DRAW RECT and FILL RECT functions but have an additional parameter for the rectangle's corner radius. These functions work as you would expect with DRAW COLOR, DRAW ALPHA, DRAW SIZE, and FILL COLOR.

Note: If you want to fill a rounded rectangle with transparency (FILL ALPHA < 1) or using a graphics mode other than NORMAL, you will need to do the following:
  • Create a new sprite and begin editing it / drawing to it with SPRITE BEGIN
  • Make sure FILL APHA is set to 1 and GRAPHICS MODE is set to NORMAL
  • Call FILL_ROUNDRECT to draw the rounded rectangle at full opacity
  • Finish drawing to the sprite with SPRITE END
  • Move the sprite to the desired location and set the desired graphics settings (using SPRITE ALPHA and GRAPHICS MODE)
  • Stamp the sprite to the main graphics layer (or to another sprite)
This is because to fill in the rounded rectangle the function makes several different fills that overlap one another.

For examples, see the screenshots on my Gradient Editor and MSGBOX library forum posts.

Code: Select all

'==============================================================

'g'
/*
    DRAW_ROUNDRECT (x1, y1, x2, y2, r)
    FILL_ROUNDRECT (x1, y1, x2, y2, r)


Functions for drawing rectangles with rounded corners.

Both functions take an input of the rectangle's top-left x,y coordinates and bottom-right x,y coordinates, and the corner radius.

  Inputs
  ------

    x1, y1    x,y-coordinates of the top-left corner
    x2, y2    x,y-coordinates of the bottom-right corner
    r         corner radius

DRAW_ROUNDRECT draws a rectangle with rounded corners. This function uses only DRAW LINE and DRAW ARC commands.

FILL_ROUNDRECT fills a rectangle with rounded corners. This function uses only FILL CIRCLE and FILL RECT commands. Note: This function uses multiple fill commands that overlap in some areas. For alpha values that are less than one and non-normal graphics modes, run this command with FILL ALPHA 1 and GRAPHICS MODE NORMAL in a sprite and then stamp the sprite to the final destination with the desired graphics settings.

'==============================================================
*/
''

DEF DRAW_ROUNDRECT (x1, y1, x2, y2, r)

  pi = 2*ACOS(0)    ' depends on OPTION ANGLE

  DRAW LINE x1+r, y1   TO x2-r, y1          ' top
  DRAW LINE x2-r, y2   TO x1+r, y2          ' bottom
  DRAW LINE x2  , y1+r TO x2  , y2-r        ' right
  DRAW LINE x1  , y2-r TO x1  , y1+r        ' left

  DRAW ARC x1+r, y1+r, r, pi    , pi*3/2    ' top-left
  DRAW ARC x2-r, y1+r, r, pi*3/2,  0        ' top-right
  DRAW ARC x2-r, y2-r, r, 0     , pi/2      ' bottom-right
  DRAW ARC x1+r, y2-r, r, pi/2  , pi        ' bottom-left

END DEF

'==============================================================

DEF FILL_ROUNDRECT (x1, y1, x2, y2, r)

  FILL CIRCLE x1+r, y1+r SIZE r         ' top-left
  FILL CIRCLE x2-r, y1+r SIZE r         ' top-right
  FILL CIRCLE x2-r, y2-r SIZE r         ' bottom-right
  FILL CIRCLE x1+r, y2-r SIZE r         ' bottom-left

  FILL RECT x1+r, y1   TO x2-r, y2      ' vertical
  FILL RECT x1  , y1+r TO x2  , y2-r    ' horizontal

END DEF

'==============================================================

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Rounded Rectangles

Post by rbytes »

This is a handy tool. Thanks, matt7.

The topic has actually come up twice before in Basic Programs. I posted a variation in 2015, not realizing that Dutchman had posted one a year earlier. The Libraries folder didn't come on line until last year, I believe, so you would not know about these posts by searching Libraries.

viewtopic.php?f=20&t=1169&p=6899&hilit= ... gles#p6899

viewtopic.php?f=20&t=449&p=1470&hilit=R ... gles#p1470

Each post offers some useful variations, and gives SB programmers more resources for their toolboxes.

Yours has a solution to a question I had been stuck on back then - how to create a rounded rectangle with an alpha less than 1. I tried it, but of course the partial transparency revealed the rectangle and circles. Copying it into a sprite first and then stamping it at a fractional alpha is a very elegant solution. 8-)
The only thing that gets me down is gravity...

User avatar
Dutchman
Posts: 848
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: Rounded Rectangles

Post by Dutchman »

old alternative solution: viewtopic.php?f=20&t=449&p=1470 :D
Last edited by Dutchman on Thu Jan 19, 2023 3:50 pm, edited 1 time in total.

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Rounded Rectangles

Post by Henko »

Dutchman wrote:
Thu Mar 07, 2019 9:35 am
old alternative solution: viewtopic.php?f=20&t=449&p=1470 :D
But it is not fool proof (said the fool :mrgreen: )
A45FC47D-DA3D-4665-B18E-DCEA5D2DF628.png
A45FC47D-DA3D-4665-B18E-DCEA5D2DF628.png (278.8 KiB) Viewed 6239 times

User avatar
Dutchman
Posts: 848
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: Rounded Rectangles

Post by Dutchman »

Game, set match! :lol:

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Rounded Rectangles

Post by rbytes »

It could be a logo if you put some letters on it! :lol:
The only thing that gets me down is gravity...

matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Re: Rounded Rectangles

Post by matt7 »

I didn't see those earlier posts! After looking back at them, I suppose what my functions provide is the most minimalistic version possible. Any draw and fill settings (including color, alpha, dash, and shadow) must be set before calling one of the functions, just like normal DRAW and FILL commands.

Here is an enhanced version that some might prefer:
  • You can now specify any two opposite corners (you no longer have to give the top-left and bottom-right corners, the functions will sort that out)
  • The corner radius is now automatically capped at half the distance of the shortest side

Code: Select all

'==============================================================

'g'
/*
    DRAW_ROUNDRECT (x1, y1, x2, y2, r)
    FILL_ROUNDRECT (x1, y1, x2, y2, r)


Functions for drawing rectangles with rounded corners.

Both functions take the same inputs.

  Inputs
  ------

    x1, y1    x,y-coordinates of first corner
    x2, y2    x,y-coordinates of second corner
    r         corner radius

DRAW_ROUNDRECT draws a rectangle with rounded corners. This function uses only DRAW LINE and DRAW ARC commands.

FILL_ROUNDRECT fills a rectangle with rounded corners. This function uses only FILL CIRCLE and FILL RECT commands. Note: This function uses multiple fill commands that overlap in some areas. For alpha values that are less than one and non-normal graphics modes, run this command with FILL ALPHA 1 and GRAPHICS MODE NORMAL in a sprite and then stamp the sprite to the final destination with the desired graphics settings.

'==============================================================
*/
''

DEF DRAW_ROUNDRECT (x1, y1, x2, y2, r)

  ' Swap coordinates so that x1,y1 is top-left
  ' corner and x2,y2 is bottom-right corner
  IF x1 > x2 THEN
    xtemp = x1  !  x1 = x2  !  x2 = xtemp
  END IF
  IF y1 > y2 THEN
    ytemp = y1  !  y1 = y2  !  y2 = ytemp
  END IF
  
  ' Cap radius at half of the shortest edge length
  r = MIN(r, MIN(x2-x1, y2-y1)/2)

  pi = 2*ACOS(0)    ' depends on OPTION ANGLE

  DRAW LINE x1+r, y1   TO x2-r, y1          ' top
  DRAW LINE x2-r, y2   TO x1+r, y2          ' bottom
  DRAW LINE x2  , y1+r TO x2  , y2-r        ' right
  DRAW LINE x1  , y2-r TO x1  , y1+r        ' left

  DRAW ARC x1+r, y1+r, r, pi    , pi*3/2    ' top-left
  DRAW ARC x2-r, y1+r, r, pi*3/2,  0        ' top-right
  DRAW ARC x2-r, y2-r, r, 0     , pi/2      ' bottom-right
  DRAW ARC x1+r, y2-r, r, pi/2  , pi        ' bottom-left

END DEF

'==============================================================

DEF FILL_ROUNDRECT (x1, y1, x2, y2, r)

  ' Swap coordinates so that x1,y1 is top-left
  ' corner and x2,y2 is bottom-right corner
  IF x1 > x2 THEN
    xtemp = x1  !  x1 = x2  !  x2 = xtemp
  END IF
  IF y1 > y2 THEN
    ytemp = y1  !  y1 = y2  !  y2 = ytemp
  END IF
  
  ' Cap radius at half of the shortest edge length
  r = MIN(r, MIN(x2-x1, y2-y1)/2)

  FILL CIRCLE x1+r, y1+r SIZE r         ' top-left
  FILL CIRCLE x2-r, y1+r SIZE r         ' top-right
  FILL CIRCLE x2-r, y2-r SIZE r         ' bottom-right
  FILL CIRCLE x1+r, y2-r SIZE r         ' bottom-left

  FILL RECT x1+r, y1   TO x2-r, y2      ' vertical
  FILL RECT x1  , y1+r TO x2  , y2-r    ' horizontal

END DEF

'==============================================================

And if someone preferred to avoid the hassle of drawing to and stamping a sprite when FILL ALPHA is less than 1 and/or GRAPHICS MODE is not NORMAL, you could even enhance it further doing the sprite drawing and stamping inside FILL_ROUNDRECT itself. This would require using my GET_GRAPHICS_MODE$ function (Save/Restore the GRAPHICS MODE) to detect the graphics mode and Joel's save_graphic_params function (Joel's utilities) to detect the fill alpha setting.

User avatar
Dutchman
Posts: 848
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: Rounded Rectangles

Post by Dutchman »

matt7 wrote:
Thu Mar 07, 2019 9:12 pm
… Any draw and fill settings (including color, alpha, dash, and shadow) must be set before calling one of the functions, just like normal DRAW and FILL commands.
… snip
You do not have to be a fool to forget that :P

Post Reply