Draw round corners with different colors

Just starting out? Need help? Post your questions and find answers here.
Justin
Addict
Addict
Posts: 956
Joined: Sat Apr 26, 2003 2:49 pm

Draw round corners with different colors

Post by Justin »

I'm trying to draw a box with rounded corners but with each half corner drawn with a different color. I adapted this great code from eddy:
https://www.purebasic.fr/english/viewto ... t=roundbox
With big corner radius it seems to work but not with small ones, this is how it looks:
Image
I'm pretty bad at drawing, i spent a lot of time with this with no success! :evil:
Can someone help?, here's the code:

Code: Select all

EnableExplicit

Structure BORDER_RADIUS
	topLeft.d
	topRight.d
	bottomLeft.d
	bottomRight.d
EndStructure

Procedure.l drawRoundBox(x.d, y.d, width.d, height.d, lineWidth.d, *bRadius.BORDER_RADIUS)
	Protected.d px, py
	Protected.l xColor, yColor
	
	xColor = RGBA(255, 0, 0, 255)
	yColor = RGBA(0, 0, 255, 255)

	;TOP BORDER
	MovePathCursor(x + *bRadius\topLeft, y, #PB_Path_Relative)
	
	;Top Left half corner
	VectorSourceColor(xColor)
	AddPathEllipse(0, *bRadius\topLeft, *bRadius\topLeft, *bRadius\topLeft, 225, -90, #PB_Path_Relative) 
		
	;Border top line
	AddPathLine(width - *bRadius\topLeft - *bRadius\topRight, 0, #PB_Path_Relative) 
	px = PathCursorX() : py = PathCursorY()

	;Top right half corner
	AddPathEllipse(0, *bRadius\topRight, *bRadius\topRight, *bRadius\topRight, -90, -45, #PB_Path_Connected | #PB_Path_Relative)
	StrokePath(lineWidth)
	
	;RIGHT BORDER
	;Top right half corner
	MovePathCursor(px, py)
	VectorSourceColor(yColor)
	AddPathEllipse(0, *bRadius\topRight, *bRadius\topRight, *bRadius\topRight, -45, 0, #PB_Path_Relative)
			
	;Border right line
	AddPathLine(0, Height-*bRadius\topRight-*bRadius\bottomRight, #PB_Path_Relative) 
	px = PathCursorX() : py = PathCursorY()
			
	;Bottom right half corner
	AddPathEllipse(-*bRadius\bottomRight, 0, *bRadius\bottomRight, *bRadius\bottomRight, 0, 45, #PB_Path_Connected | #PB_Path_Relative) 
	StrokePath(lineWidth)
	
	;BOTTOM BORDER
	;Bottom down half corner
	MovePathCursor(px, py)
	AddPathEllipse(-*bRadius\bottomRight, 0, *bRadius\bottomRight, *bRadius\bottomRight, 45, 90, #PB_Path_Relative)
	VectorSourceColor(xColor)
		
	;bottom border line
	AddPathLine(*bRadius\bottomRight + *bRadius\bottomLeft - width, 0, #PB_Path_Relative) 
	px = PathCursorX() : py = PathCursorY()
			
	;Bottom left half corner
	AddPathEllipse(0, -*bRadius\bottomLeft, *bRadius\bottomLeft, *bRadius\bottomLeft, 90, 135, #PB_Path_Connected | #PB_Path_Relative) 
	StrokePath(lineWidth)
	
	;LEFT BORDER
	;Bottom left half corner
	MovePathCursor(px, py)
	VectorSourceColor(yColor)
	AddPathEllipse(0, -*bRadius\bottomLeft, *bRadius\bottomLeft, *bRadius\bottomLeft, 135, 180, #PB_Path_Relative) 
	
	;Left border line
	AddPathLine(x, y + *bRadius\topLeft) 
	px = PathCursorX() : py = PathCursorY()
	
	;Top left half border
	AddPathEllipse(*bRadius\topLeft, 0, *bRadius\topLeft, *bRadius\topLeft, 180, -135, #PB_Path_Relative) ;180, -135
	StrokePath(lineWidth)
	
	ProcedureReturn #True
EndProcedure

Procedure AddPathRoundBox(x.d, y.d, Width.d, Height.d, lineWidth.d, *bRadius.BORDER_RADIUS)	
	;Clockwise
	MovePathCursor(x + *bRadius\topLeft, y, #PB_Path_Relative)
	
	;top left corner
	AddPathEllipse(0, *bRadius\topLeft, *bRadius\topLeft, *bRadius\topLeft, 180, -90, #PB_Path_Relative) 

 	;Border top
	AddPathLine(Width - *bRadius\topLeft - *bRadius\topRight, 0, #PB_Path_Relative) 
; 
; 	;Top right corner
	AddPathEllipse(0, *bRadius\topRight, *bRadius\topRight, *bRadius\topRight, -90, 0, #PB_Path_Connected | #PB_Path_Relative)
; 
; 	;border right
	AddPathLine(0, Height-*bRadius\topRight-*bRadius\bottomRight, #PB_Path_Relative) 
; 
; 	;bottom right corner
	AddPathEllipse(-*bRadius\bottomRight, 0, *bRadius\bottomRight, *bRadius\bottomRight, 0, 90, #PB_Path_Connected | #PB_Path_Relative) 
; 
; 	;bottom border
	AddPathLine(*bRadius\bottomRight + *bRadius\bottomLeft - Width, 0, #PB_Path_Relative) 
; 	
; 	;bottom left corner
	AddPathEllipse(0, -*bRadius\bottomLeft, *bRadius\bottomLeft, *bRadius\bottomLeft, 90, 180, #PB_Path_Connected | #PB_Path_Relative) 
; 	
	ClosePath() ;border left
	
	StrokePath(lineWidth, #PB_Path_RoundEnd)

	MovePathCursor(0, -*bRadius\topLeft, #PB_Path_Relative)
EndProcedure

Procedure main()
	Protected.l ev
	Protected.BORDER_RADIUS bRadius
	Protected.d lineWidth

	OpenWindow(0, 0, 0, 800, 600, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(0, 0, 0, 800, 600)
	
	If StartVectorDrawing(CanvasVectorOutput(0))
		bRadius\topLeft = 6
		bRadius\topRight = 6
		bRadius\bottomLeft = 6
		bRadius\bottomRight = 6
		lineWidth = 8

		drawRoundBox(DesktopScaledX(10), DesktopScaledY(10), DesktopScaledX(350), DesktopScaledY(350), lineWidth, @bRadius)

		AddPathRoundBox(DesktopScaledX(400), DesktopScaledY(10), DesktopScaledX(350), DesktopScaledY(350), lineWidth, @bRadius)

		StopVectorDrawing()
	EndIf
	
	Repeat
		ev = WaitWindowEvent()
	Until ev = #PB_Event_CloseWindow
EndProcedure

main()
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Draw round corners with different colors

Post by moulder61 »

Hi Justin,
It looks pretty good to me, not pixelated like your example.
I'm using PB 6.04 LTS x64 on Void Linux.
Here's a link to what it looks like on my machine.

https://u.pcloud.link/publink/show?code ... 8BymyOvbo7

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
User avatar
mk-soft
Always Here
Always Here
Posts: 6320
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Draw round corners with different colors

Post by mk-soft »

Must be a bug under Windows. The angles are not correct.
It is ok under macOS and Linux.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Justin
Addict
Addict
Posts: 956
Joined: Sat Apr 26, 2003 2:49 pm

Re: Draw round corners with different colors

Post by Justin »

Hi, thanks both for testing.

After spending a ridicously amount of time It seems that applying an offset to the angles degree fixes the issue, i used a default of 2 or the difference between the line width and radius if the line width is bigger.

But not sure if only works with my set up, would you mind to test in in mac / linux if you can?
You can enable / disable the correction with the applyCorrection variable.

If this is a bug it could be moved to that section, but i asked chatgpt to do it in c and gdiplus and showed the same issue but i did not checked the angles.
PB:

Code: Select all

EnableExplicit

Macro __IF(condition)
	If (condition)
EndMacro

Macro __END_IF()
	EndIf
EndMacro

Macro __IIF(condition, expIfTrue, expIfFalse, ret)
	If (condition)
		ret = expIfTrue
	Else
		ret = expIfFalse
EndMacro	

Macro __IIF_ENDIF(condition, expIfTrue, expIfFalse, ret)
	__IIF(condition, expIfTrue, expIfFalse, ret)
	EndIf 
EndMacro		

Macro __ELSE_IIF(condition, expIfTrue, expIfFalse, ret)
	ElseIf (condition)
		ret = expIfTrue
		
	Else
		ret = expIfFalse
EndMacro

Macro __ELSE_IIF_ENDIF(condition, expIfTrue, expIfFalse, ret)
	__ELSE_IIF(condition, expIfTrue, expIfFalse, ret)
	EndIf
EndMacro

Structure BORDER_RADIUS
	topLeft.d
	topRight.d
	bottomLeft.d
	bottomRight.d
EndStructure

Procedure.l drawRoundBox(x.d, y.d, width.d, height.d, lineWidth.d, *bRadius.BORDER_RADIUS)
	Protected.l applyCorrection
	Protected.d color1, color2, angleOffset
	
	applyCorrection = #True
	
	;Offset corrdinates to make inner border
	x + (lineWidth) / 2
	y + (lineWidth) / 2
	width - ((lineWidth) / 2) - ((lineWidth) / 2)
	height - ((lineWidth) / 2) - ((lineWidth) / 2)

	color1 = RGBA(255, 0, 0, 255)
	color2 = RGBA(0, 0, 255, 255)
	
	If applyCorrection
		angleOffset = 2 ;default angle offset
	EndIf 
	
	;TOP BORDER
	;Move to top left corner ellipse center
	MovePathCursor(x + *bRadius\topLeft, y + *bRadius\topLeft)

	;Top left corner up
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\topLeft, Round(lineWidth - *bRadius\topLeft, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(0, 0, *bRadius\topLeft, *bRadius\topLeft, 225 - angleOffset, -90, #PB_Path_Relative) 
	
 	;Border line
	AddPathLine(width - *bRadius\topLeft - *bRadius\topRight, 0, #PB_Path_Relative) 

	;Top right corner up
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\topRight, Round(lineWidth - *bRadius\topRight, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(0, *bRadius\topRight, *bRadius\topRight, *bRadius\topRight, -90, -45 + angleOffset, #PB_Path_Connected | #PB_Path_Relative)
	
	VectorSourceColor(color1)
	StrokePath(lineWidth)
	
	;RIGHT BORDER
	;Move to top right corner ellipse center
	MovePathCursor(x + width - *bRadius\topRight, y + *bRadius\topRight)

	;Top right corner down
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\topRight, Round(lineWidth - *bRadius\topRight, #PB_Round_Up), angleOffset, angleOffset)
	EndIf
	AddPathEllipse(0, 0, *bRadius\topRight, *bRadius\topRight, -45 - angleOffset, 0, #PB_Path_Relative)
	
	;Border line
	AddPathLine(0, height-*bRadius\topRight-*bRadius\bottomRight, #PB_Path_Relative)

	;Bottom right corner up
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\bottomRight, Round(lineWidth - *bRadius\bottomRight, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(-*bRadius\bottomRight, 0, *bRadius\bottomRight, *bRadius\bottomRight, 0, 45 + angleOffset, #PB_Path_Connected | #PB_Path_Relative) 

	VectorSourceColor(color2)
	StrokePath(lineWidth)
	
	;BOTTOM BORDER
	;Move to bottom right corner ellipse center
	MovePathCursor(x + width - *bRadius\bottomRight, y + height - *bRadius\bottomRight)
	
	;Bottom right corner down
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\bottomRight, Round(lineWidth - *bRadius\bottomRight, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(0, 0, *bRadius\bottomRight, *bRadius\bottomRight, 45 - angleOffset, 90,  #PB_Path_Relative)

	;Border line
	AddPathLine(*bRadius\bottomRight + *bRadius\bottomLeft - width, 0, #PB_Path_Relative) 

	;Bottom left corner down
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\bottomLeft, Round(lineWidth - *bRadius\bottomLeft, #PB_Round_Up), angleOffset, angleOffset)
	EndIf
	AddPathEllipse(0, -*bRadius\bottomLeft, *bRadius\bottomLeft, *bRadius\bottomLeft, 90, 135 + angleOffset, #PB_Path_Connected | #PB_Path_Relative) 
	VectorSourceColor(color1)
	StrokePath(lineWidth)
	
	;LEFT BORDER
	;Move to bottom left corner ellipse center
	MovePathCursor(x + *bRadius\bottomLeft, y + height - *bRadius\bottomLeft)
	
	;Bottom left corner up
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\bottomLeft, Round(lineWidth - *bRadius\bottomLeft, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(0, 0, *bRadius\bottomLeft, *bRadius\bottomLeft, 135 - angleOffset, 180, #PB_Path_Relative) 

	;Border line
	AddPathLine(0, *bRadius\bottomLeft + *bRadius\topLeft - height, #PB_Path_Relative)
	
	;Top left corner down
	;angleOffset
	If applyCorrection
		__IIF_ENDIF(lineWidth > *bRadius\topLeft, Round(lineWidth - *bRadius\topLeft, #PB_Round_Up), angleOffset, angleOffset)
	EndIf 
	AddPathEllipse(*bRadius\topLeft, 0, *bRadius\topLeft, *bRadius\topLeft, 180, 225 + angleOffset, #PB_Path_Connected | #PB_Path_Relative) 
	VectorSourceColor(color2)
	StrokePath(lineWidth)
	
	ProcedureReturn #True
EndProcedure


Procedure main()
	Protected.l ev
	Protected.BORDER_RADIUS bRadius
	Protected.d lineWidth

	OpenWindow(0, 0, 0, 800, 600, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(0, 0, 0, 800, 600)
	
	If StartVectorDrawing(CanvasVectorOutput(0))
		bRadius\topLeft = 6
		bRadius\topRight = 6
		bRadius\bottomLeft = 6
		bRadius\bottomRight = 6
		lineWidth = 8

		AddPathBox(DesktopScaledX(10), DesktopScaledY(10), DesktopScaledX(350), DesktopScaledY(350))
		StrokePath(1)
		drawRoundBox(DesktopScaledX(10), DesktopScaledY(10), DesktopScaledX(350), DesktopScaledY(350), lineWidth, @bRadius)

		StopVectorDrawing()
	EndIf
	
	Repeat
		ev = WaitWindowEvent()
	Until ev = #PB_Event_CloseWindow
EndProcedure

main()
chatgpt c / gdiplus

Code: Select all

void DrawRoundedRectWithColoredCorners(HDC hdc, int x, int y, int width, int height, int radius, int borderWidth, Gdiplus::Color color1, Gdiplus::Color color2) {
	Gdiplus::Graphics graphics(hdc);
	graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
	
	Gdiplus::Pen pen1(color1, borderWidth);
	Gdiplus::Pen pen2(color2, borderWidth);

	// Adjust coordinates to account for pen width
	int adjustedX = x + borderWidth / 2;
	int adjustedY = y + borderWidth / 2;
	int adjustedWidth = width - borderWidth;
	int adjustedHeight = height - borderWidth;
	int adjustedRadius = radius;

	// Top-left corner
	graphics.DrawArc(&pen1, adjustedX, adjustedY, adjustedRadius * 2, adjustedRadius * 2, 180, 45);
	graphics.DrawArc(&pen2, adjustedX, adjustedY, adjustedRadius * 2, adjustedRadius * 2, 225, 45);
	//return;
	// Top-right corner
	graphics.DrawArc(&pen2, adjustedX + adjustedWidth - adjustedRadius * 2, adjustedY, adjustedRadius * 2, adjustedRadius * 2, 270, 45);
	graphics.DrawArc(&pen1, adjustedX + adjustedWidth - adjustedRadius * 2, adjustedY, adjustedRadius * 2, adjustedRadius * 2, 315, 45);
	
	// Bottom-right corner
	graphics.DrawArc(&pen1, adjustedX + adjustedWidth - adjustedRadius * 2, adjustedY + adjustedHeight - adjustedRadius * 2, adjustedRadius * 2, adjustedRadius * 2, 0, 45);
	graphics.DrawArc(&pen2, adjustedX + adjustedWidth - adjustedRadius * 2, adjustedY + adjustedHeight - adjustedRadius * 2, adjustedRadius * 2, adjustedRadius * 2, 45, 45);
	
	// Bottom-left corner
	graphics.DrawArc(&pen2, adjustedX, adjustedY + adjustedHeight - adjustedRadius * 2, adjustedRadius * 2, adjustedRadius * 2, 90, 45);
	graphics.DrawArc(&pen1, adjustedX, adjustedY + adjustedHeight - adjustedRadius * 2, adjustedRadius * 2, adjustedRadius * 2, 135, 45);
	
	// Draw the straight lines connecting the corners
	//graphics.DrawLine(&pen1, adjustedX + adjustedRadius, adjustedY, adjustedX + adjustedWidth - adjustedRadius, adjustedY); // Top edge
	graphics.DrawLine(&pen2, adjustedX + adjustedRadius, adjustedY, adjustedX + adjustedWidth - adjustedRadius, adjustedY); // Top edge
	
	//graphics.DrawLine(&pen1, adjustedX + adjustedRadius, adjustedY + adjustedHeight, adjustedX + adjustedWidth - adjustedRadius, adjustedY + adjustedHeight); // Bottom edge
	graphics.DrawLine(&pen2, adjustedX + adjustedRadius, adjustedY + adjustedHeight, adjustedX + adjustedWidth - adjustedRadius, adjustedY + adjustedHeight); // Bottom edge
	
	graphics.DrawLine(&pen1, adjustedX, adjustedY + adjustedRadius, adjustedX, adjustedY + adjustedHeight - adjustedRadius); // Left edge
	//graphics.DrawLine(&pen2, adjustedX, adjustedY + adjustedRadius, adjustedX, adjustedY + adjustedHeight - adjustedRadius); // Left edge
	
	graphics.DrawLine(&pen1, adjustedX + adjustedWidth, adjustedY + adjustedRadius, adjustedX + adjustedWidth, adjustedY + adjustedHeight - adjustedRadius); // Right edge
	//graphics.DrawLine(&pen2, adjustedX + adjustedWidth, adjustedY + adjustedRadius, adjustedX + adjustedWidth, adjustedY + adjustedHeight - adjustedRadius); // Right edge
}
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Draw round corners with different colors

Post by moulder61 »

Hi Justin,
First example works the same except there is a grey box around the drawing. Not sure if that's intentional because I haven't looked closely at the code.
I assume the second example isn't supposed to work in PB? I tried it anyway but get a syntax error on line 1.

If you know how to add an image to a post can you enlighten me?
Meanwhile, a picture of the grey box around the drawing:

https://u.pcloud.link/publink/show?code ... GSifWgr0Jy

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
Post Reply