Get smoother fonts using AlphaBlend

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

Get smoother fonts using AlphaBlend

Post by Michael Vogel »

I've started another thread sometime ago about some quality issues when using drawtext and alphablend and wrote a workaround by just creating a larger image in the background and shrinking it to the needed size.
So larger font sizes can be used and the resulting output looks smooth, but when many text has to be used, the creation of the images takes quite a while. This method can be seen below in the CreateButtonText procedure (you have to change the 'smooth' constant to '1' or '2' to see its effect).

So I am searching for a possibility to get smoother text without creating to much stress for the cpu. A have another simple approach (only for black text for now) which could speed up the whole thing, it could be seen in the NicerButtonText function below (which is active, while smooth=0). You can set the binary 'nicebutton' constant to '%1111' if you want to affect all text boxes.

Code: Select all

#Smooth=0;            set to 1 (or 2) to get smoother text

#NiceButton=%0100;      set '1' for all buttons to get nicer (while smooth=0)

#ButtonText="ABCD"
#Button=64

Procedure NicerButtonText(n,size,Text.s);   new attempt to get a finer text

	Protected x,y,z

	CreateImage(n,size,size,32)
	StartDrawing(ImageOutput(n))
	DrawingFont(FontID(0))
	DrawText((size-TextWidth(Text))>>1,(size-TextHeight("Wg"))>>1,Text,$ffffffff,0)

	DrawingMode(#PB_2DDrawing_AllChannels)
	For y=0 To size-1
		For x=0 To size-1
			z=Red(Point(x,y))
			Plot(x,y,z*$1000000+(255-z)*$10101)
			; something like Plot(x,y,z&$FFFFFF|$1000000*(Red(z)+Blue(z)+Green(z))/3) for keeping the color
		Next x
	Next y
	StopDrawing()

EndProcedure
Procedure CreateButtonText(n,size,Text.s);   my "traditional" method

	size<<#Smooth
	CreateImage(n,size,size,32|#PB_Image_Transparent)

	StartDrawing(ImageOutput(n))
	DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
	DrawingFont(FontID(0))
	DrawText((size-TextWidth(Text))>>1,(size-TextHeight("Wg"))>>1,Text,$ff000000)
	StopDrawing()

	size>>#Smooth
	ResizeImage(n,size,size)

EndProcedure
Procedure Main()

	Protected c.s
	WinID=OpenWindow(0,0,0,#Button<<2,#Button,"ABCD",#PB_Window_ScreenCentered|#PB_Window_Invisible|#PB_Window_SystemMenu)
	LoadFont(0,"Trebuchet MS",MulDiv_(#Button<<#Smooth,4,5))

	For i=0 To 3
		c=Mid(#ButtonText,i+1,1)
		If #Smooth=0 And (8>>i)&#NiceButton<>0
			NicerButtonText(i,#Button,c)
		Else
			CreateButtonText(i,#Button,c)
		EndIf
		ButtonImageGadget(i,i*#Button,0,#Button,#Button,ImageID(i))
	Next i

	HideWindow(0,0)

	quit=0
	Repeat
		Select WaitWindowEvent()
		Case #PB_Event_Gadget
			i=EventGadget()
			NicerButtonText(i,#Button,Mid(#ButtonText,i+1,1))
			ButtonImageGadget(i,i*#Button,0,#Button,#Button,ImageID(i))
		Case #WM_CHAR,#PB_Event_CloseWindow
			quit=1
		EndSelect
	Until quit

EndProcedure
Main()
So where are my coding questions? How to improve (the speed of) NicerButtonText? Would there be a fast solution for colored text as well? Or will there be a combination of PB_2DDrawing constants which could do the same result?
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Get smoother fonts using AlphaBlend

Post by IdeasVacuum »

If using Windows, try Danilo's GDI+ Lib.

http://www.purebasic.fr/english/viewtop ... 12&t=46987
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get smoother fonts using AlphaBlend

Post by Michael Vogel »

IdeasVacuum wrote:If using Windows, try Danilo's GDI+ Lib.
http://www.purebasic.fr/english/viewtop ... 12&t=46987
It's a great library, but I don't want to use it in this case, because I fear, that some PC's won't support GDI+ and all I need is to fill 12 buttons with text in the "standard" font.

In the example above I have used a larger font for demonstration only, depending on your system settings you may easily see the quality issues using drawtext. In my program I would have to replace FontID(0) by GetGadgetFont(#PB_Default), where the difference can also be seen on certain machines.

Actually, I tried to remove the pixel loops in the NicerButtonText procedure and use a custom filter (test code below), but it seems, that I make something wrong, because I never can read the characters and only get a box. What's wrong here?

BTW: the help pages for DrawingMode show some pictures (which could also be cropped a little bit), but one is missing for Drawing_Gradient.

Code: Select all

Procedure FilterCallback(x,y,Source,Target)
	ProcedureReturn RGBA($80,Red(Source),Red(Target),$FF)
EndProcedure

If OpenWindow(0,0,0,400,200,"2DDrawing Beispiel",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	If CreateImage(0,400,200,32|#PB_Image_Transparent) And StartDrawing(ImageOutput(0))
	
		;DrawingMode(#PB_2DDrawing_CustomFilter|#PB_2DDrawing_Transparent)
		DrawingMode(#PB_2DDrawing_CustomFilter)
		
		CustomFilterCallback(@FilterCallback())
		
		Circle(100,100,100,$F0)
		Circle(300,100,100,$40)
		DrawText(0,0,"HELLO",$80,$20)
		StopDrawing()
		
		ImageGadget(0,0,0,400,200,ImageID(0))
		
	EndIf

	Repeat
		Event = WaitWindowEvent()
	Until Event = #PB_Event_CloseWindow
	
EndIf
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get smoother fonts using AlphaBlend

Post by Michael Vogel »

Couldn't solve the DrawText issue (blurred characters on some graphic cards) by using a custom filter. Maybe when implementing image functions like CopyImageLayer(#PB_Image_LayerRed,#PB_Image_LayerAlpha) and InvertImageLayer(#PB_Image_AllLayers) a simplier workaround could be found.

So I still copying pixel by pixel, which could be done faster when copying only the data within the text area. The DrawTextSmooth function in the example below will work fine until the text is wider than the image (any tips here to get the image dimensions within the procedure?).

Code: Select all

#Text="ABCD"

Procedure StandardText()

	DrawingMode(#PB_2DDrawing_AlphaBlend)
	DrawText((300-TextWidth(#Text))>>1,(100-TextHeight("Wg"))>>1,#Text,$FF000000,0)

EndProcedure
Procedure SmoothImage()

	DrawingMode(#PB_2DDrawing_Default)
	Box(0,0,300,100,#White)
	DrawText((300-TextWidth(#Text))>>1,(100-TextHeight("Wg"))>>1,#Text,#Black,#White)

	DrawingMode(#PB_2DDrawing_AllChannels)

	y=100
	w=300
	While y
		y-1
		x=w
		While x
			x-1
			z=Point(x,y)&$FF
			; If z
			; z=85+MulDiv_(z,2,3);    lighter
			; EndIf
			Plot(x,y,(255-z)<<24+z*$10101)
		Wend
	Wend

EndProcedure
Procedure DrawTextSmooth(x,y,text.s)

	Protected x0,xo,yo
	x0=x
	DrawingMode(#PB_2DDrawing_Default)
	DrawText(x,y,#Text,#Black,#White)

	xo=x+TextWidth(#Text)
	yo=y+TextHeight("Ip")

	DrawingMode(#PB_2DDrawing_AllChannels)
	While y<yo
		x=x0
		While x<xo
			z=Point(x,y)&$FF
			Plot(x,y,(255-z)<<24+z*$10101)
			x+1
		Wend
		y+1
	Wend

EndProcedure

Procedure Main()

	WinID=OpenWindow(0,0,0,300,300,"ABCD",#PB_Window_ScreenCentered|#PB_Window_Invisible|#PB_Window_SystemMenu)

	; LoadFont(0,"Trebuchet MS",15);					[ 1 ]
	; LoadFont(0,"Calibri",18);						[ 2 ]

	For i=1 To 3
		CreateImage(i,300,100,32|#PB_Image_Transparent)

		StartDrawing(ImageOutput(i))
		; DrawingFont(FontID(0));						[ 1, 2 ]
		
		DrawingFont(GetGadgetFont(#PB_Default));	[ 3 ]

		Select i

		Case 1
			StandardText()

		Case 2
			SmoothImage()

		Case 3
			DrawTextSmooth((300-TextWidth(#Text))>>1,(100-TextHeight("Wg"))>>1,#Text)

		EndSelect

		StopDrawing()
		ButtonImageGadget(i,0,(i-1)*100,300,100,ImageID(i))

	Next i

	HideWindow(0,0)

	quit=0
	Repeat
		Select WaitWindowEvent()
		Case #WM_CHAR,#PB_Event_CloseWindow
			quit=1
		EndSelect
	Until quit

EndProcedure
Main()
Post Reply