Page 1 of 1

How to fill holes within the outlined text?

Posted: Thu Jun 06, 2024 9:41 pm
by Michael Vogel
:|

Code: Select all

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0, "Consolas", 20)
CreateImage(0,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(0))
VectorFont(FontID(0), 15)

MovePathCursor(20, 10)
AddPathText("'Simple Text : Errors!'"); or... AddPathText("'Simple ; * : ~ errors!'")

VectorSourceColor($FFffffff)
StrokePath(13,#PB_Path_Preserve|#PB_Path_RoundCorner)
VectorSourceColor($FF0000ff)
FillPath()
StopVectorDrawing()

ResizeImage(0,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200,ImageID(0))

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Thu Jun 06, 2024 10:25 pm
by pjay
If performance isn't a concern:

Code: Select all

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0, "Consolas", 20)
CreateImage(0,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(0))
VectorFont(FontID(0), 15)

MovePathCursor(20, 10)
AddPathText("'Simple Text : Errors!'"); or... AddPathText("'Simple ; * : ~ errors!'")

VectorSourceColor($FFffffff)
For x = 1 To 13
  StrokePath(x,#PB_Path_Preserve|#PB_Path_RoundCorner)
Next
VectorSourceColor($FF0000ff)
FillPath()
StopVectorDrawing()

ResizeImage(0,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200,ImageID(0))

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Fri Jun 07, 2024 6:06 am
by Michael Vogel
Thanks, good idea...

But beside the speed alpha blending is also a point (which I didn't mention before)...

Code: Select all

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0, "Consolas", 20)
CreateImage(0,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(0))
VectorFont(FontID(0), 16.5)

For i=-50 To 250 Step 10
	MovePathCursor(i,50)
	AddPathLine(50,-50,#PB_Path_Relative)
Next i
VectorSourceColor($FF804040)
StrokePath(3)

MovePathCursor(20, 10)
;AddPathText("'Simple Text : Errors!'"); or... 
AddPathText("'Simple ; * : ~ errors!'")

VectorSourceColor($80ffffff)
If 0
	For x = 1 To 13 Step 2
		StrokePath(x,#PB_Path_Preserve|#PB_Path_RoundCorner)
	Next
Else
	StrokePath(13,#PB_Path_Preserve|#PB_Path_RoundCorner)
EndIf

VectorSourceColor($FF0000ff)
FillPath()
StopVectorDrawing()

ResizeImage(0,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200,ImageID(0))

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Fri Jun 07, 2024 7:29 am
by pjay
You could process the alpha channel manually & use a compositing process to display:

Code: Select all

#Img_BG = 0
#Img_FG = 1
#Img_Final = 2

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0, "Consolas", 20)
CreateImage(#Img_FG,250,50,32,#Black)
CreateImage(#Img_BG,250,50,32,#Black)
CreateImage(#Img_Final,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(#Img_BG))
VectorFont(FontID(0), 16.5)
For i=-50 To 250 Step 10
	MovePathCursor(i,50)
	AddPathLine(50,-50,#PB_Path_Relative)
Next i
VectorSourceColor($FF804040)
StrokePath(3)
StopVectorDrawing()

Procedure outlinedText_ToImg_Alpha(img,x,y,text.s, fontID = 0, size.f = 16.5, outlineSize = 13, txtCol = $ff0000ff, outlineCol = $80ffffff)
  Protected ola = Alpha(outlineCol), olc = RGBA(Red(outlineCol),Green(outlineCol),Blue(outlineCol),255),px,py,p,r,g,b,a
  StartVectorDrawing(ImageVectorOutput(img))
  VectorFont(FontID(fontID), size)
  MovePathCursor(x, y)
  AddPathText("'Simple ; * : ~ errors!'")
  For px = 1 To outlineSize Step 2 : VectorSourceColor(olc) : StrokePath(px,#PB_Path_Preserve|#PB_Path_RoundCorner) : Next
  StopVectorDrawing()
  
  StartDrawing(ImageOutput(img))
  DrawingMode(#PB_2DDrawing_AllChannels)

  For px = 0 To OutputWidth()-1
    For py = 0 To OutputHeight()-1
      p = Point(px,py) : r = Red(p) : g = Green(p) : b = Blue(p)
      If r > 0 Or g > 0 Or b > 0 : Plot(px,py,RGBA(r,g,b,ola)) : Else : Plot(px,py,RGBA(0,0,0,0)) : EndIf
    Next
  Next
  StopDrawing()

  StartVectorDrawing(ImageVectorOutput(img))
  VectorFont(FontID(fontID), size) : VectorSourceColor($FF0000ff)
  MovePathCursor(x, y) : AddPathText("'Simple ; * : ~ errors!'") : FillPath()
  StopVectorDrawing()
EndProcedure

txt.s = "'Simple ; * : ~ errors!'"

outlinedText_ToImg_Alpha(#Img_FG,20,10,txt)

; final composition:
StartDrawing(ImageOutput(#Img_Final))
DrawImage(ImageID(#Img_BG),0,0)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(#Img_FG),0,0)
StopDrawing()

ResizeImage(#Img_Final,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200, ImageID(#Img_Final))
SetWindowTitle(0,"Time for process: "+Str(time)+"ms")

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Fri Jun 07, 2024 9:45 am
by #NULL
Dawing with larger font size like 25 (at LoadFont and VectorFont) doesn't seem to have that problem(?)
So maybe draw larger on an Image first and resize it down, then draw the image.
Or use larger font size and scale down the text drawing:

Code: Select all

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0, "Consolas", 25)
CreateImage(0,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(0))
VectorFont(FontID(0), 25)

For i=-50 To 250 Step 10
	MovePathCursor(i,50)
	AddPathLine(50,-50,#PB_Path_Relative)
Next i
VectorSourceColor($FF804040)
StrokePath(3)

MovePathCursor(20, 10)
ScaleCoordinates(0.6, 0.6)
AddPathText("'Simple Text : Errors!'"); or... 
;AddPathText("'Simple ; * : ~ errors!'")

VectorSourceColor($80ffffff)
If 0
	For x = 1 To 13 Step 2
		StrokePath(x,#PB_Path_Preserve|#PB_Path_RoundCorner)
	Next
Else
	StrokePath(13,#PB_Path_Preserve|#PB_Path_RoundCorner)
EndIf

VectorSourceColor($FF0000ff)
FillPath()
StopVectorDrawing()

ResizeImage(0,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200,ImageID(0))

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Fri Jun 14, 2024 4:58 pm
by Michael Vogel
Thanks for helping, the pjay's idea is genius - but can't fix all errors here (one extreme case can be checked by downloading my demo program* or with the simple code below. It uses the font Bahnschrift but there are many more showing the same issues.

#Null's code snippet does still show holey areas here :(

I think, vector font drawing does need a different mode for drawing where overlapping object areas needs to be painted as well.

*) The program is a fully working image filter program but starts with a text example at the first run. Font & Text options are set by using the shortcut Ctrl+Shift+F, Shift+Escape quits the program.

Code: Select all

#Text="HEKTX"
#Size=40
#Font="Bahnschrift"

#Img_BG = 0
#Img_FG = 1
#Img_Final = 2

OpenWindow(0, 0, 0, 1000, 200, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

LoadFont(0,#Font,#Size,#PB_Font_Bold)
CreateImage(#Img_FG,250,50,32,#Black)
CreateImage(#Img_BG,250,50,32,#Black)
CreateImage(#Img_Final,250,50,32,#Black)
StartVectorDrawing(ImageVectorOutput(#Img_BG))
VectorFont(FontID(0),#Size)
For i=-50 To 250 Step 10
	MovePathCursor(i,50)
	AddPathLine(50,-50,#PB_Path_Relative)
Next i
VectorSourceColor($FF804040)
StrokePath(3)
StopVectorDrawing()

Procedure outlinedText_ToImg_Alpha(img,x,y,text.s, fontID = 0, size.f = 16.5, outlineSize = 13, txtCol = $ff0000ff, outlineCol = $80ffffff)
  Protected ola = Alpha(outlineCol), olc = RGBA(Red(outlineCol),Green(outlineCol),Blue(outlineCol),255),px,py,p,r,g,b,a
  StartVectorDrawing(ImageVectorOutput(img))
  VectorFont(FontID(fontID),#Size)
  MovePathCursor(x, y)
  AddPathText(text)
  For px = 1 To outlineSize Step 2 : VectorSourceColor(olc) : StrokePath(px,#PB_Path_Preserve|#PB_Path_RoundCorner) : Next
  StopVectorDrawing()
  
  StartDrawing(ImageOutput(img))
  DrawingMode(#PB_2DDrawing_AllChannels)

  For px = 0 To OutputWidth()-1
    For py = 0 To OutputHeight()-1
      p = Point(px,py) : r = Red(p) : g = Green(p) : b = Blue(p)
      If r > 0 Or g > 0 Or b > 0 : Plot(px,py,RGBA(r,g,b,ola)) : Else : Plot(px,py,RGBA(0,0,0,0)) : EndIf
    Next
  Next
  StopDrawing()

  StartVectorDrawing(ImageVectorOutput(img))
  VectorFont(FontID(fontID),#Size)
  VectorSourceColor($FF0000ff)
  MovePathCursor(x, y)
  AddPathText(text)
  FillPath()
  StopVectorDrawing()
EndProcedure

txt.s = "'Simple ; * : ~ errors!'"

outlinedText_ToImg_Alpha(#Img_FG,20,10,#Text)

; final composition:
StartDrawing(ImageOutput(#Img_Final))
DrawImage(ImageID(#Img_BG),0,0)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawImage(ImageID(#Img_FG),0,0)
StopDrawing()

ResizeImage(#Img_Final,1000,200,#PB_Image_Raw)
ImageGadget(0, 0, 0, 1000, 200, ImageID(#Img_Final))
SetWindowTitle(0,"Time for process: "+Str(time)+"ms")

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Sat Jun 15, 2024 3:36 pm
by Michael Vogel
I am not sure if the StrokePath issues are because of overlapping areas but for me it looks a little bit like that - simiar to the issues seen with Bahnschrift and FillPath.

The later problem can be solved by using #PB_Path_Winding (see code below), would be a similar option helpful for StrokePath?

Code: Select all

size=400

CompilerIf 0
	; the font contains overlapping path segments which leave holes for FillPath(), FillPath(#PB_Path_Winding) works perfectly
	font.s="Bahnschrift"
	pnts.i=400	
	type.i=#PB_Font_Bold
	text.s="HEX"
CompilerElse
	; with this font the outline path may show holes by using wide pens for StrokePath() - DashPath() does show the cause of the problem
	font.s="Consolas"
	pnts.i=340	
	type.i=#Null
	text.s=":;!"
CompilerEndIf

OpenWindow(0, 0,0, size*2,size, "Hole in One", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0,0, size*2,size)

LoadFont(0,font,pnts,type)
Dim dashes.d(1)
dashes(0) = 5
dashes(1) = 5

CreateImage(0,size,50,32,#Black)
StartVectorDrawing(CanvasVectorOutput(0))
VectorFont(FontID(0),pnts)

For i=-size To size*2 Step 20
	MovePathCursor(i,size)
	AddPathLine(size,-size,#PB_Path_Relative)
Next i
VectorSourceColor($FFF0A0B0)
StrokePath(7)

MovePathCursor(80,20)
AddPathText(text)

VectorSourceColor($C0404040)
StrokePath(180,#PB_Path_Preserve|#PB_Path_RoundCorner)
; StrokePath(90,#PB_Path_Preserve|#PB_Path_RoundCorner)
; CustomDashPath(180,dashes(),#PB_Path_Preserve|#PB_Path_RoundCorner)

VectorSourceColor($FF800000)
;FillPath(#PB_Path_Winding)
FillPath()
StopVectorDrawing()

Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

Re: How to fill holes within the outlined text?

Posted: Sun Jun 16, 2024 10:07 pm
by Michael Vogel
Feature Request - #PB_Path_Winding flag for the StrokePath command.

Code: Select all

OpenWindow(0, 0, 0, 1400, 500, "Swiss Cheese", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 1400, 500)

StartVectorDrawing(CanvasVectorOutput(0))

For j=1 To 8
	MovePathCursor(j*(j*10+80)+j*40-40,200)
	AddPathCircle(0,-50,40,0,0,#PB_Path_Relative)
	AddPathBox(-70,250,60,60,#PB_Path_Relative)
	VectorSourceColor(RGBA(255, 0, 0, 255))
	StrokePath(j*20, #PB_Path_RoundCorner)
Next
StopVectorDrawing()

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow