Rounded Corner

BlitzPlus Forums/BlitzPlus Programming/Rounded Corner

WillKoh2(Posted 2004) [#1]
I want to create a piece of code to create a rounded corner that changes color from outside to inside. The upperleft corner will get darker from outside to in.. To draw the next pixel of an angle from -90 to 0 i use cos and sin, but the multiplicator needs to decrease in a proper way the more towards the inner of the corner i get (smaller and smaller arcs with darker color, but all going from angle -90 to 0)


Rob Farley(Posted 2004) [#2]
Graphics 640,480,16,2
For x=0 To 128
For y=0 To 128
i=255-(Sqr((x*x)+(y*y))*2)
If i>0 Then Color i,i,i:Plot x+320,y+240
Next
Next
WaitKey
modify the i= line to
i=Sqr((x*x)+(y*y)) where i is the radius. This way you can do what you like with it! If you do a for x =-128 to 128 and the same on the y you'll get a circle.


WillKoh2(Posted 2004) [#3]
Hrm.. interesting. That would be the down-right corner though.. but i might figure it out for the others too. i tried to plot along arcs but you did a rectangular plotting with circular color change.. seems better..


Andy_A(Posted 2004) [#4]
Found some code in the archives
http://www.blitzbasic.com/codearcs/codearcs.php?code=402

Modified it to work as you described.

Andy

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 
; Rounded Rectangles
;
; Stephen C. Demuth -- sdemuth@...
; August 22, 2002
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Modified for smooth shading by Andy Amaya
; February 12, 2004
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

sw = 800
sh = 600

Graphics sw, sh
SetBuffer BackBuffer()

SeedRnd(MilliSecs())

While KeyHit(1) = 0

	Cls()
	Color 255,255,255
	Text 0,0,"Press a key for random rectangle"
	Text 0,20,"Press ESC to exit"

	r = 255
	g = 255
	b = 255
	wide = Rand(100,350)*2
	high = Rand(100,150)*2
	
	x = (sw - wide)/2
	y = (sh - high)/2	
	
	For rad = 50 To 10 Step -1
		Color r,g,b
		RRect (x, y, wide, high, rad)
		r = r - 6
		g = g - 6
		b = b - 6
		x = x + 1
		y = y + 1
		wide = wide - 2
		high = high - 2
	Next

	Flip()
	WaitKey
Wend

End



;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; RRect(x,y,width,height,radius=5)
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function RRect(x,y,width,height,radius=5)

	If radius > width/2 Then radius = width/2
	If radius > height/2 Then radius = height/2

	;---DRAW BORDERS
	Line x+radius,y,x+width-radius,y			   ;Top
	Line x+radius,y+height,x+width-radius,y+height ;Bottom	
	Line x,y+radius,x,y+height-radius			   ;Left
	Line x+width,y+radius,x+width,y+height-radius  ;Right	


	;---DRAW CORNERS

	;Upper Left
	For deg = 90 To 180
		yp = Sin(deg) * radius * -1 + y + radius
		xp = Cos(deg) * radius + x + radius		
		Oval xp-1,yp-1,2,2,1
;		Plot xp,yp
	Next

	;Lower Left
	For deg = 180 To 270
		yp = Sin(deg) * radius * -1 + y + height - radius
		xp = Cos(deg) * radius + x + radius		
		Oval xp-1,yp-1,2,2,1
;		Plot xp,yp
	Next

	;Upper Right
	For deg = 0 To 90
		yp = Sin(deg) * radius * -1 + y + radius
		xp = Cos(deg) * radius + x + width - radius		
		Oval xp-1,yp-1,2,2,1
;		Plot xp,yp
	Next

	;Lower Right
	For deg = 270 To 359
		yp = Sin(deg) * radius * -1 + y + height - radius
		xp = Cos(deg) * radius + x + width - radius		
		Oval xp-1,yp-1,2,2,1
;		Plot xp,yp
	Next

;Adjustment
	Line x+radius,y-1,x+width-radius,y-1			   ;Top
	Line x+radius,y+height+1,x+width-radius,y+height+1 ;Bottom	
	Line x-1,y+radius,x-1,y+height-radius			   ;Left
	Line x+width+1,y+radius,x+width+1,y+height-radius  ;Right

End Function



WillKoh(Posted 2004) [#5]
I am not sure about the rounding (which is diffrent for each) of the corners to create a button. If one looks at a W95 square (not rounded) button you see that the basics is to make the under and right-side edges dark and the upper and left side bright. When corners are rounded, transition in those corners caught between the bright and dark edge is needed, in addition to the transition of each corner that makes it be rounded... I am thinking of creating images that can be saved and reused: the 4 corners, a tile-image for the space between upper & down right corners, another tile image for space between upper & down left corners, and a tile between left upper corner and right upper corner and a tile between left down corner and right down corner.. and then a tile in the inside space. The tiling is to create buttons of different size but with the same corners. No unique transitions depending on button size should be done; it's all in the pre-made images that make up the buttons parts.

Your first code created a good right-down corner, that in smaller size could be saved and used as that part in buttons. The image-system would enable one to manually create the pieces in an editor or create them with another algo should one want too...

The new code is more complicated without beeing of much use to me I think, but the first one is really on the right track. Could you make code for the other corners (thinking of how buttons are basically construced)?


WillKoh(Posted 2004) [#6]
Well, with the help of the first example I'll have to persue(sp?) this matter on my own...


Andy_A(Posted 2004) [#7]
If you look at the new code it does exactly what you need.
Take the time and effort to see how it works.

Since all you want are thin lines, get rid of the four "Line" statements after the remark ";Adustment" in the RRect() function.

Call the function twice like so:

x = 100
y = 100
wide = 400
high = 300

color 128,128,255 ;(light blue)
rad = 15
Rect (x, y, wide, high, rad)

color 0,0,255 ;(blue)
rad = 14
RRect (x, y, wide, high, rad)

Done!

It doesn't get any easier than that, the rest is up to you.

Suggest testing and studying before making judgements.


WillKoh(Posted 2004) [#8]
To [Rob Farley]: When I use your technique to create a func that builds surch a corner (to an image) it suddenly won't work anymore..

Function MkCornDnRt(Size,Mask)

   CornDnRt = CreateImage(Size,Size)
  SetBuffer ImageBuffer(CornDnRt)
   SetRGB Mask: Rect 0, 0, Size, Size, 1
   LockBuffer()
  For X = 0 To Size - 1
   For Y = 0 To Size - 1
    C = 255 - (Sqr((X*X)+(Y*Y))*2)
    If C > 0 Then WritePixelFast X, Y, OneRGB(C,C,C)
   Next
  Next
   UnlockBuffer()
  MaskImage CornDnRt, Red(Mask), Green(Mask), Blue(Mask)
   Return CornDnRt

End Function


What's wrong? Have I changed something fundamental?


WillKoh(Posted 2004) [#9]
...supposing the OneRGB func is

Function OneRGB(R,G,B)
 Return $FF000000 Or R Shl 16 Or G Shl 8 Or B
End Function



WillKoh(Posted 2004) [#10]
If anyone else than rob farley is also welcome of course..


WillKoh(Posted 2004) [#11]
The point is to create the corners as separate images (too store and use to build buttons

later), and that the upper-left corner will be quite bright (but have nuances) whereas the

down-right corner will be quite dark (but also have nuances).

The upper and left edges of a button is bright but the down and right edges are dark.
This is very sharply seen on a simple non-rounded W95 button.

Two corners, the upper-right and down-left, are in conflict zones so to speak. These two

corners require a special color transition because they are between the bright/dark portions

of the button's edge. This is in addition to the 'regular' color transition that makes them

be round...

See?