Page 1 of 1

Rounded Rectangles

Posted: Wed Mar 06, 2019 7:29 pm
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

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

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 2:42 am
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-)

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 9:35 am
by Dutchman
old alternative solution: viewtopic.php?f=20&t=449&p=1470 :D

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 9:48 am
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 6497 times

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 11:36 am
by Dutchman
Game, set match! :lol:

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 2:46 pm
by rbytes
It could be a logo if you put some letters on it! :lol:

Re: Rounded Rectangles

Posted: Thu Mar 07, 2019 9:12 pm
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.

Re: Rounded Rectangles

Posted: Fri Mar 08, 2019 10:00 am
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