Beveled edges on a rectangle

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Beveled edges on a rectangle

Post by Keya »

my google for "bevel site:purebasic.fr" yielded only half a dozen results! :( and none particularly on target lol

Anyway here is my attempt. I only need it for rectangles, which is good as the thought of doing it with other shapes scares me :) I find it interesting how easy this is to do with rectangles, yet how its a bit trickier if it's a triangle or pentagon. Wonders of the universe!

First is a manual one-box-at-a-time, which looks good but its currently just black-to-white (anyone know how to do a fade from color-to-shadowcolor instead?). Also I discovered PB's gradient functions for a proper color-to-color transition (shown here) which is what id like the first one to do instead of black-to-white:
Image

Code: Select all

Procedure CreateBevelBoxBW(color, bevelwidth, width, height)
  Protected hImg, w, h, pct.f
  hImg = CreateImage(#PB_Any, width, height, 24, color) 
  If hImg
    If StartDrawing(ImageOutput(hImg))
      If bevelwidth > 0        
        DrawingMode(#PB_2DDrawing_Outlined)
        For i = 0 To bevelwidth-1
          pct = (i / bevelwidth-1) * 255
          FrontColor(RGB(pct,pct,pct))
          Box(0+i, 0+i, width-(i*2),height-(i*2))
        Next i        
      EndIf
      StopDrawing() 
    EndIf
    ProcedureReturn hImg
  EndIf
EndProcedure



Procedure CreateBevelBox(color, shadowcolor, bevelwidth, width, height)
  Protected hImg, w, h, pct.f
  hImg = CreateImage(#PB_Any, width, height, 24, color) 
  If hImg
    If StartDrawing(ImageOutput(hImg))
      If bevelwidth > 0        
        DrawingMode(#PB_2DDrawing_Gradient)
        GradientColor(0.0, color)
        GradientColor(1.0 - (bevelwidth*0.01), color)
        GradientColor(1.0, shadowcolor)
        BoxedGradient(0,0,width,height)
        Box(0,0,width,height)        
      EndIf
      StopDrawing() 
    EndIf
    ProcedureReturn hImg
  EndIf
EndProcedure



width = 400:  height = 200
color = RGB(0,200,200)
shadowcolor = RGB(0,0,50)
bevelwidth = 10

If OpenWindow(0, 0, 0, width, height, "Bevel box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  hImg = CreateBevelBox(color, shadowcolor, bevelwidth, width, height)
  
  ;hImg = CreateBevelBoxBW(color, bevelwidth, width, height)
  
  
  If IsImage(hImg):  ImageGadget(0, 0, 0, width, height, ImageID(hImg)): EndIf
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Beveled edges on a rectangle

Post by Samuel »

Keya wrote: First is a manual one-box-at-a-time, which looks good but its currently just black-to-white (anyone know how to do a fade from color-to-shadowcolor instead?).
You can calculate it by finding the difference between the inner and outer colors, and then divide those RGB values by the bevel length.

Here's a quick example.

Code: Select all

Procedure CreateBevelBox2(InnerColor.i, OuterColor.i, BevelWidth.i, Width.i, Height.i)
  
  Define.i Image
  Define.i CTR
  Define.i StartR, StartG, StartB
  Define.i R, G, B
  Define.i DifR, DifG, DifB
  Define.d PctR, PctG, PctB
  
  Image = CreateImage(#PB_Any, Width, Height, 24)
  
  R = Red(OuterColor)
  G = Green(OuterColor)
  B = Blue(OuterColor)
  
  DifR = Red(InnerColor) - Red(OuterColor)
  DifG = Green(InnerColor) - Green(OuterColor)
  DifB = Blue(InnerColor) - Blue(OuterColor)
  
  PctR = DifR / BevelWidth
  PctG = DifG / BevelWidth
  PctB = DifB / BevelWidth
  
  StartDrawing(ImageOutput(Image))
    For CTR = 0 To BevelWidth - 1
      R + PctR
      G + PctG
      B + PctB
      Box(CTR, CTR, Width-CTR*2, Height-CTR*2, RGB(R,G,B))
    Next
    Box(BevelWidth-1, BevelWidth-1, Width+2-BevelWidth*2, Height+2-BevelWidth*2, InnerColor)
  StopDrawing()
  
  ProcedureReturn Image
  
EndProcedure

width = 400
height = 200
bevelwidth = 10

If OpenWindow(0, 0, 0, width, height, "Bevel box", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  hImg = CreateBevelBox2(RGB(255,0,0), RGB(0,50,50), bevelwidth, width, height)
 
  If IsImage(hImg)
    ImageGadget(0, 0, 0, width, height, ImageID(hImg))
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Beveled edges on a rectangle

Post by BasicallyPure »

Hi Samuel,

I like your example.
I think it works better if you define R G B as double rather than integer. :)
Change bevelwidth to 30 to see the difference.

Code: Select all

;Define.i R, G, B
Define.d R, G, B
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Beveled edges on a rectangle

Post by Keya »

ahhh, thanks Samuel! :)
Also i just found this neat little procedure by thyphoon which he uses in a password strength meter to indicate from green-to-red http://www.purebasic.fr/english/viewtopic.php?p=254452

Code: Select all

Procedure GetColor(ColorA.l, ColorB.l, Min.l, Max.l, Cursor.l)
  Protected R.l, G.l, B.l
  Max = Max-Min
  Cursor = Cursor-Min
  R = Red(ColorB)-Red(ColorA)
  R = Red(ColorA) + (R*Cursor/Max)
  G = Green(ColorB)-Green(ColorA)
  G = Green(ColorA) + (G*Cursor/Max)
  B = Blue(ColorB)-Blue(ColorA)
  B = Blue(ColorA) + (B*Cursor/Max)
  ProcedureReturn RGB(R, G, B)
EndProcedure
eg. MiddleColor = GetColor(RGB(255,0,0), RGB(0,255,0), 0, 255, 128)
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Beveled edges on a rectangle

Post by PureLust »

Hi Keya,

maybe you want to bevel some images sometime, or want to create sharper or softener bevel
or even buttons with flipping bevel, so this little routine might be helpful.


Image

Code: Select all

EnableExplicit

Procedure BevelImage(ImageNr, BevelSize, HighlightColor=#White, ShadowColor=#Black, MinOpacity=30, MaxOpacity=180)
	Protected Alpha.c, n
	Protected r1=Red(HighlightColor), g1=Green(HighlightColor), b1=Blue(HighlightColor)
	Protected r2=Red(ShadowColor), g2=Green(ShadowColor), b2=Blue(ShadowColor)
	
	If IsImage(ImageNr)
		
		Protected Width  = ImageWidth(ImageNr)
		Protected Height = ImageHeight(ImageNr)
		
		Protected Dummy = CreateImage(#PB_Any, Width, Height, 32, #PB_Image_Transparent)
		
		If BevelSize > 0 And Width > 2 * BevelSize And Height > 2 * BevelSize
			If Dummy And StartDrawing(ImageOutput(Dummy))
				
				DrawingMode(#PB_2DDrawing_AllChannels)
				
				For n = 0 To BevelSize-1
					
					Alpha = MaxOpacity - (((MaxOpacity-MinOpacity) * n) / (BevelSize-1))
					
					Line(n,n, Width-2*n, 1, RGBA(r1,g1,b1,Alpha))
					Line(n,n, 1, Height-2*n, RGBA(r1,g1,b1,Alpha))
					Line(n+1,Height-n-1, Width-2*n, 1, RGBA(r2,g2,b2,Alpha))
					Line(Width-n-1,n+1, 1, Height-2*n, RGBA(r2,g2,b2,Alpha))
					
				Next
				
				StopDrawing()
				
				If StartDrawing(ImageOutput(ImageNr))
					DrawingMode(#PB_2DDrawing_AlphaBlend)
					DrawImage(ImageID(Dummy),0,0)
					StopDrawing()
					ProcedureReturn #True
				EndIf
				
			EndIf
		EndIf
	EndIf
EndProcedure



Define Width = 200,  Height = 150, n, Event

; ----- creating some rectangular Images -----

Define Img1 = CreateImage(#PB_Any, Width, Height, 24, $ff6666)
Define Img2 = CreateImage(#PB_Any, Width, Height, 24, $66ff66)
Define Img3 = CreateImage(#PB_Any, Width, Height, 24, $6666ff)
Define Img4 = CreateImage(#PB_Any, Width, Height, 24, $008888)

If StartDrawing(ImageOutput(Img4))			; ----- let's paint some circles ...
	For n = 1 To 200
		Circle(Random(Width), Random(Height), 30, Random($ffffff))
	Next
	StopDrawing()
EndIf

Define Img5 = CopyImage(Img1, #PB_Any)	; ----- clone the Images for click-beveling
Define Img6 = CopyImage(Img2, #PB_Any)
Define Img7 = CopyImage(Img3, #PB_Any)
Define Img8 = CopyImage(Img4, #PB_Any)

; -----  beveling Button-Images -----

BevelImage(Img1, 10)
BevelImage(Img2, 30, #Yellow, $008800, 0, 255)
BevelImage(Img3, 15, #White, #Black, 50, 90)
BevelImage(Img4, 20, #White, #Black, 0, 255)

; -----  beveling clicked Button-Images -----

BevelImage(Img5, 10, #Black, #White)
BevelImage(Img6, 20, #Yellow, $008800, 0, 160)
BevelImage(Img7, 15, #Black, #White,90,90)
BevelImage(Img8, 20, #Black, #White, 0, 190)

Width + 8
Height + 8

If OpenWindow(0, 0, 0, Width * 2 + 30, Height * 2 + 30, "BevelImage() - Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	ButtonImageGadget(0, 10,10,Width,Height, ImageID(Img1))
	ButtonImageGadget(1, 20+Width,10,Width,Height, ImageID(Img2))
	ButtonImageGadget(2, 10,20+Height,Width,Height, ImageID(Img3))
	ButtonImageGadget(3, 20+Width,20+Height,Width,Height, ImageID(Img4))
	
	SetGadgetAttribute(0, #PB_Button_PressedImage, ImageID(Img5))
	SetGadgetAttribute(1, #PB_Button_PressedImage, ImageID(Img6))
	SetGadgetAttribute(2, #PB_Button_PressedImage, ImageID(Img7))
	SetGadgetAttribute(3, #PB_Button_PressedImage, ImageID(Img8))
	
	Repeat
		Event = WaitWindowEvent()
	Until Event = #PB_Event_CloseWindow
EndIf
Last edited by PureLust on Fri Jan 22, 2016 3:28 pm, edited 1 time in total.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Beveled edges on a rectangle

Post by Keya »

PureLust, really nice! thankyou :) you're off by 1 pixel in the lower-left corner however! Easiest seen in your green-yellow button example. I had a quick go at fixing it but just kept making it worse lol
Image
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: Beveled edges on a rectangle

Post by PureLust »

Keya wrote:PureLust, really nice! thankyou :) you're off by 1 pixel in the lower-left corner however!
Hey Keya, ... yes, you were right.

Just corrected the code in my post above. :wink:
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Beveled edges on a rectangle

Post by walbus »

Very nice idea !
Post Reply