How to fill holes within the outlined text?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2819
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

How to fill holes within the outlined text?

Post 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
pjay
Enthusiast
Enthusiast
Posts: 277
Joined: Thu Mar 30, 2006 11:14 am

Re: How to fill holes within the outlined text?

Post 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
User avatar
Michael Vogel
Addict
Addict
Posts: 2819
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How to fill holes within the outlined text?

Post 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
pjay
Enthusiast
Enthusiast
Posts: 277
Joined: Thu Mar 30, 2006 11:14 am

Re: How to fill holes within the outlined text?

Post 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
#NULL
Addict
Addict
Posts: 1499
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: How to fill holes within the outlined text?

Post 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
User avatar
Michael Vogel
Addict
Addict
Posts: 2819
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How to fill holes within the outlined text?

Post 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
User avatar
Michael Vogel
Addict
Addict
Posts: 2819
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How to fill holes within the outlined text?

Post 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
User avatar
Michael Vogel
Addict
Addict
Posts: 2819
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How to fill holes within the outlined text?

Post 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
Post Reply