DrawText() with border?
DrawText() with border?
How can draw a text with a border around it (with alpha support)?
Well, I had the idea of loading a relatively bigger font and drawing this one first and then the smaller one in the center of it. But then the padding between each character won't be correct and alpha won't work either.
Can anyone help me out? I already searched in the forum and even the whole internet but didn't found a solution...
Well, I had the idea of loading a relatively bigger font and drawing this one first and then the smaller one in the center of it. But then the padding between each character won't be correct and alpha won't work either.
Can anyone help me out? I already searched in the forum and even the whole internet but didn't found a solution...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
One classic way is to draw the same exact text, in a different color, around it.
This is what I use:
It looks fine. However it can only do a single fixed-width border, and it calls DrawText() 5 times... which has actually caused frame slowdown for me sometimes.
This is what I use:
Code: Select all
Procedure Write(x.l, y.l, Message.s, Color.i, Center.i = #False, Outline.l = -1)
Static dx.l
If (Message)
If (Center)
dx = x - TextWidth(Message)/2
Else
dx = x
EndIf
If (Outline >= 0)
DrawText(dx - 1, y, Message, Outline)
DrawText(dx + 1, y, Message, Outline)
DrawText(dx, y - 1, Message, Outline)
DrawText(dx, y + 1, Message, Outline)
EndIf
DrawText(dx, y, Message, Color)
EndIf
EndProcedure
Re: DrawText() with border?
I'm very rushed and am not sure if the following is what you are after? If it is then you can probably do the same sort of thing using the drawing lib and the alpha channels etc.
Code: Select all
text$ = "Hello Stinky!"
LoadFont(1, "Arial", 60)
pen = CreatePen_(#PS_SOLID, 2, #Blue)
If OpenWindow(0, 100, 100, 440, 300, "PureBasic - Image")
If CreateImage(0, 440, 300)
hdc = StartDrawing(ImageOutput(0))
If hdc
Box(0, 0, 440, 300, #White)
oldPen = SelectObject_(hdc, pen)
SetBkMode_(hdc, #TRANSPARENT)
oldFont = SelectObject_(hdc, FontID(1))
SetTextAlign_(hdc, #TA_LEFT|#TA_TOP)
BeginPath_(hdc)
TextOut_(hdc, 0, 0, text$, Len(text$))
EndPath_(hdc)
SelectObject_(hdc, oldFont)
StrokeAndFillPath_(hdc)
SelectObject_(hdc, oldPen)
StopDrawing() ; This is absolutely needed when the drawing operations are finished !!! Never forget it !
EndIf
EndIf
ImageGadget(1, 0, 0, 0, 0, ImageID(0))
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow ; If the user has pressed on the close button
EndIf
DeleteObject_(pen)
I may look like a mule, but I'm not a complete ass.
Re: DrawText() with border?
@kenmo
I also thought of this but it's a very unpleasant way of doing it. Also it doesn't allow making thicker borders and alpha doesn't work because DrawText() lays over DrawText() etc.
@srod
Kind of. But I don't see where I could change the thickness of the border and the color inside the characters.
I also thought of this but it's a very unpleasant way of doing it. Also it doesn't allow making thicker borders and alpha doesn't work because DrawText() lays over DrawText() etc.
@srod
Kind of. But I don't see where I could change the thickness of the border and the color inside the characters.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
Code: Select all
text$ = "Hello Stinky!"
LoadFont(1, "Arial", 70)
Procedure BorderedText(hdc, x, y, text$, borderWidth, borderColor, fillColor)
Protected pen, oldPen, brush, oldBrush
pen = CreatePen_(#PS_SOLID, borderWidth, borderColor)
oldPen = SelectObject_(hdc, pen)
brush = CreateSolidBrush_(fillColor)
oldBRush = SelectObject_(hdc, brush)
SetBkMode_(hdc, #TRANSPARENT)
SetTextAlign_(hdc, #TA_LEFT|#TA_TOP)
BeginPath_(hdc)
TextOut_(hdc, x, y, text$, Len(text$))
EndPath_(hdc)
StrokeAndFillPath_(hdc)
SelectObject_(hdc, oldBrush)
SelectObject_(hdc, oldPen)
DeleteObject_(brush)
DeleteObject_(pen)
EndProcedure
If OpenWindow(0, 100, 100, 500, 300, "PureBasic - Image")
If CreateImage(0, 500, 300)
hdc = StartDrawing(ImageOutput(0))
If hdc
Box(0, 0, 500, 300, #White)
oldFont = SelectObject_(hdc, FontID(1))
BorderedText(hdc, 0, 0, text$, 1, #Blue, #White)
BorderedText(hdc, 0, 80, text$, 4, #Blue, #Red)
BorderedText(hdc, 0, 160, text$, 2, #Red, #Gray)
SelectObject_(hdc, oldFont)
StopDrawing()
EndIf
EndIf
ImageGadget(1, 0, 0, 0, 0, ImageID(0))
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
I may look like a mule, but I'm not a complete ass.
Re: DrawText() with border?
Too bad there isn't a cross-platform solution. Anyway thank you srod!
Now I'll just have to try to get alpha involved.
Now I'll just have to try to get alpha involved.

If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
Probably best doing this on a pixel by pixel basis (use the drawing buffer). I hacked up some alpha support using a combination of the above code and PB's DrawText() on the alpha-channel, but the effects were relatively poor due to anti-aliasing effects etc.c4s wrote:Now I'll just have to try to get alpha involved.
I may look like a mule, but I'm not a complete ass.
Re: DrawText() with border?
I'm testing again and this stuff seems complicated to me.srod wrote:Probably best doing this on a pixel by pixel basis (use the drawing buffer). I hacked up some alpha support using a combination of the above code and PB's DrawText() on the alpha-channel, but the effects were relatively poor due to anti-aliasing effects etc.
Could you please share your code?
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
I haven't got any code for the pixel by pixel stuff though it should be easy enough.
All I did was test some code using a combination of the above and PB's 2d drawing lib to give some alpha support and whilst it worked, it wasn't good enough because of the text anti-alias.

All I did was test some code using a combination of the above and PB's 2d drawing lib to give some alpha support and whilst it worked, it wasn't good enough because of the text anti-alias.
I may look like a mule, but I'm not a complete ass.
Re: DrawText() with border?
So you would draw the API stuff on a separate 24bit image with a color like $FF00FF as the background, then create a 32bit alpha image containing the API image and replace each $FF00FF pixel with full alpha, then draw the real things (unfortunately the API image creation must be before the actual StartDrawing() block...not cool) and the outlined "text" with DrawAlphaImage()?
This is really complicated to me and yes, I already tried it but didn't work. Looks like I didn't try hard enough though. What makes me think is your comment about anti-alias. Does that mean it could look strange on some systems?
So again I searched through the net using terms like "text border", "draw text outline" but it seems that all I get is something like kenmo's idea and another approach using .NET... This is really disappointing.
This is really complicated to me and yes, I already tried it but didn't work. Looks like I didn't try hard enough though. What makes me think is your comment about anti-alias. Does that mean it could look strange on some systems?
So again I searched through the net using terms like "text border", "draw text outline" but it seems that all I get is something like kenmo's idea and another approach using .NET... This is really disappointing.

If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
This is my current solution and I don't like that I have to create the image before the actual Drawing block also a thickness small than 10 doesn't look good and finally I can't handle it as a normal DrawText() function. 

Code: Select all
EnableExplicit
Enumeration
#Font
#Window
#Image
#ImageGadget
EndEnumeration
Procedure ImageDrawTextBordered(Text.s, TextFontNr, TextColor=$000000, BorderColor=$FFFFFF, BorderThickness=1)
Protected ImageNr, Image1Nr, Image2Nr, hDC
Protected Width, Height, iX, iY
Protected Pen, PenOld, FontOld
; Get width & height of the text+border
ImageNr = CreateImage(#PB_Any, 1, 1)
If ImageNr
If StartDrawing(ImageOutput(ImageNr))
DrawingFont(FontID(TextFontNr))
Width = TextWidth(Text) + (BorderThickness * 2)
Height = TextHeight(Text) + (BorderThickness * 2)
StopDrawing()
EndIf
FreeImage(ImageNr)
EndIf
; Draw bordered text on Image1
Image1Nr = CreateImage(#PB_Any, Width, Height, 24)
If Image1Nr
hDC = StartDrawing(ImageOutput(Image1Nr))
If hDC
Box(0, 0, Width, Height, $FF00FF)
FontOld = SelectObject_(hDC, FontID(TextFontNr))
Pen = CreatePen_(#PS_SOLID, BorderThickness, BorderColor)
PenOld = SelectObject_(hDC, Pen)
SetBkMode_(hDC, #TRANSPARENT)
BeginPath_(hDC)
TextOut_(hDC, BorderThickness, BorderThickness, Text, Len(Text))
EndPath_(hDC)
StrokeAndFillPath_(hDC)
SelectObject_(hDC, PenOld)
DeleteObject_(Pen)
SelectObject_(hDC, FontOld)
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(TextFontNr))
DrawText(BorderThickness, BorderThickness, Text, TextColor)
StopDrawing()
EndIf
; Draw Image1 on Image2, make $FF00FF parts transparent
Image2Nr = CreateImage(#PB_Any, Width, Height, 32)
If Image2Nr
If StartDrawing(ImageOutput(Image2Nr))
DrawImage(ImageID(Image1Nr), 0, 0)
DrawingMode(#PB_2DDrawing_AlphaChannel)
For iY = 0 To Height - 1
For iX = 0 To Width - 1
If Point(iX, iY) & $FFFFFF = $FF00FF
Plot(iX, iY, $00000000)
EndIf
Next
Next
StopDrawing()
EndIf
EndIf
FreeImage(Image1Nr)
EndIf
ProcedureReturn Image2Nr
EndProcedure
Define Text.s, Width, Height
Define ImageNr
Text = "Test"
Width = 330
Height = 150
LoadFont(#Font, "", 90, #PB_Font_HighQuality)
ImageNr = ImageDrawTextBordered(Text, #Font, $F0F0F0, $FFFF00, 10) ; StartDrawing in a Drawing block isn't allowed
If CreateImage(#Image, Width, Height)
If StartDrawing(ImageOutput(#Image))
DrawingMode(#PB_2DDrawing_Gradient)
BackColor($00FFFF) : FrontColor($FF0000)
LinearGradient(0, Height, Width, Height)
Box(0, 0, Width, Height)
DrawAlphaImage(ImageID(ImageNr), 10, 10) ; Draw the text image
FreeImage(ImageNr)
StopDrawing()
EndIf
EndIf
If OpenWindow(#Window, #PB_Any, #PB_Any, Width, Height, "DrawTextBordered() Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(#ImageGadget, 0, 0, Width, Height, ImageID(#Image))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: DrawText() with border?
Well the text itself doesn't have an alpha-channel and that particular example wouldn't require any additional images at all in that you could easily render the bordered text directly onto a window (because you are not using alpha values with the text itself).
Here's my quick hack which renders the text with alpha. I use your gradient filled image from above.
You could easily modify this to simulate a DrawAlphaText() kind of function.
Here's my quick hack which renders the text with alpha. I use your gradient filled image from above.
Code: Select all
text$ = "Heyho!"
LoadFont(1, "Arial", 90)
;Create a background brush.
If CreateImage(1, 450, 400)
If StartDrawing(ImageOutput(1))
DrawingMode(#PB_2DDrawing_Gradient)
BackColor($00FFFF) : FrontColor($FF0000)
LinearGradient(0, 400, 450, 400)
Box(0, 0, 450, 400)
StopDrawing()
EndIf
EndIf
backBrush = CreatePatternBrush_(ImageID(1))
Procedure GetAlphaBorderedText(image, x, y, text$, borderWidth, borderColor, fillColor, alpha)
Protected pen, oldPen, brush, oldBrush, oldFont, *mem.RGBQUAD, pxHeight, pxWidth, i , j
pen = CreatePen_(#PS_SOLID, borderWidth, borderColor)
If IsImage(image)
hdc = StartDrawing(ImageOutput(image))
If hdc
oldFont = SelectObject_(hdc, FontID(1))
oldPen = SelectObject_(hdc, pen)
brush = CreateSolidBrush_(fillColor)
oldBRush = SelectObject_(hdc, brush)
SetBkMode_(hdc, #TRANSPARENT)
SetTextAlign_(hdc, #TA_LEFT|#TA_TOP)
BeginPath_(hdc)
TextOut_(hdc, x, y, text$, Len(text$))
EndPath_(hdc)
StrokeAndFillPath_(hdc)
SelectObject_(hdc, oldBrush)
SelectObject_(hdc, oldPen)
DeleteObject_(brush)
DeleteObject_(pen)
;Apply per-pixel alpha values.
;We change all oqaque pixels to transparent and transparent ones are given the specified alpha value.
*mem = DrawingBuffer()
If DrawingBufferPixelFormat() & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
pxHeight = ImageHeight(image)
pxWidth = ImageWidth(image)
For i = 1 To pxHeight
For j = 1 To pxWidth
If *mem\rgbReserved = 0
*mem\rgbReserved = alpha
Else
*mem\rgbReserved = 0
EndIf
*mem + SizeOf(RGBQUAD)
Next
Next
EndIf
StopDrawing()
EndIf
EndIf
EndProcedure
hWnd = OpenWindow(0, 100, 100, 450, 400, "PureBasic - Image")
If hWnd
SetClassLongPtr_(hWnd, #GCL_HBRBACKGROUND, backBrush)
InvalidateRect_(hWnd, 0, 1)
If CreateImage(0, 450, 140, 32)
GetAlphaBorderedText(0, 20, 0, text$, 6, #Red, #White, 80)
EndIf
ImageGadget(1, 0, 0, 0, 0, ImageID(0))
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
I may look like a mule, but I'm not a complete ass.
Re: DrawText() with border?
Here is code by Trond that outlines text.
Here's the source link where this and related code were presented in relationship to producing a watermark.
Code: Select all
h = 500
w = 500
CreateImage(0, h, w, 24)
LoadFont(0, "Impact", 40)
text.s = "In my pants!"
tcol = #Red
ocol = #White ; can't be the same as tcol!
owidth = 2
StartDrawing(ImageOutput(0))
DrawingFont(FontID(0))
FrontColor(tcol)
DrawRotatedText(100, 350, text, 45)
For y = owidth To h-owidth-1
For x = owidth To w-owidth-1
c1 = Point(x, y)
If c1 <> tcol
For y2 = -owidth To owidth
For x2 = -owidth To owidth
If Point(x+x2, y+y2) = tcol
Plot(x, y, ocol)
Break 2
EndIf
Next
Next
EndIf
Next
Next
StopDrawing()
OpenWindow(0, 0, 0, 500, 500, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
ImageGadget(0, 0, 0, 0, 0, ImageID(0))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
Re: DrawText() with border?
Thank you for that link. I probably was to focused on "border" instead of "outline" when searching the forum.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!