Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: HudchewMan on January 22, 2018, 07:49:40 pm

Title: How can I drawing text with outline on a canvas?
Post by: HudchewMan on January 22, 2018, 07:49:40 pm
Help me please.

I try to find the way to drawing text with outline on a canvas. But not found. :(
(Google with keyword 'Lazarus draw text outline' and another similar this.)

so I try to repeat write text around it but it's look very ugly. :o :'(

This is example of my code.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormPaint(Sender: TObject);
  2. var
  3.   textarea: TRect;
  4.   mytext: string;
  5.   mytextstyle: TTextStyle;
  6.  
  7. begin
  8.   Canvas.GradientFill(Self.ClientRect, clNavy, clGreen, gdHorizontal);
  9.  
  10.   mytext      := 'Hello the world, Who am I.';
  11.   textarea    := Rect(20, Self.Height - 80, Self.Width - 20, Self.Height - 10);
  12.   mytextstyle := Canvas.TextStyle;
  13.   mytextstyle.Wordbreak  := False;
  14.   mytextstyle.SingleLine := True;
  15.  
  16.   Canvas.Font.Size  := 16;
  17.  
  18.   // Border
  19.   Canvas.Font.Color := clWhite;
  20.   Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 - 0, mytext, mytextstyle);
  21.   Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 + 0, mytext, mytextstyle);
  22.   Canvas.TextRect(textarea, 20 + 0, Self.Height - 80 - 3, mytext, mytextstyle);
  23.   Canvas.TextRect(textarea, 20 - 0, Self.Height - 80 + 3, mytext, mytextstyle);
  24.  
  25.   Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 - 3, mytext, mytextstyle);
  26.   Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 + 3, mytext, mytextstyle);
  27.   Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 - 3, mytext, mytextstyle);
  28.   Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 + 3, mytext, mytextstyle);
  29.  
  30.   // Text
  31.   Canvas.Font.Color := clBlue;
  32.   Canvas.TextRect(textarea, 20, Self.Height - 80, mytext, mytextstyle);
  33.  
  34. end;
  35.  

The result is here.

https://photos.app.goo.gl/uwNcFZ9KZsg7WXYV2 (https://photos.app.goo.gl/uwNcFZ9KZsg7WXYV2)

How should I do?

Thank you very much and sorry for my poor English.

* * * * *
My system:
Lazarus 1.8.0 + FPC 3.0.4
Linux elementary OS 0.4 Loki (base on Ubuntu 16.04)
Title: Re: How can I drawing text with outline on a canvas?
Post by: Handoko on January 22, 2018, 08:15:04 pm
Hello HudchewMan,
Welcome to the forum.

Doing text outline requires complex calculation, you won't get it by simply repeat the writing.

Instead of reinventing the wheel, I recommend you to try BGRABitmap:
http://wiki.freepascal.org/Sample_Graphics#Text_Outline (http://wiki.freepascal.org/Sample_Graphics#Text_Outline)
Title: Re: How can I drawing text with outline on a canvas?
Post by: Eugene Loza on January 22, 2018, 08:20:40 pm
The problem you have is that the "outline" images you draw have smaller elements than 3 pixels you shift them.
This should be enough for 1 pixel outline.
Code: Pascal  [Select][+][-]
  1.   Canvas.TextRect(textarea, 20 - 1, Self.Height - 80 - 1, mytext, mytextstyle);
  2.   Canvas.TextRect(textarea, 20 + 1, Self.Height - 80 + 1, mytext, mytextstyle);
  3.   Canvas.TextRect(textarea, 20 + 1, Self.Height - 80 - 1, mytext, mytextstyle);
  4.   Canvas.TextRect(textarea, 20 - 1, Self.Height - 80 + 1, mytext, mytextstyle);
If you need a larger outline, but you may do it by
Code: Pascal  [Select][+][-]
  1. for i := -5 to 5 do
  2.   for j := -5 to 5 do
  3.   begin
  4.      Canvas.TextRect(textarea, 20 - i, Self.Height - 80 - j, mytext, mytextstyle);
  5.      Canvas.TextRect(textarea, 20 + i, Self.Height - 80 + j, mytext, mytextstyle);
  6.      Canvas.TextRect(textarea, 20 + i, Self.Height - 80 - j, mytext, mytextstyle);
  7.      Canvas.TextRect(textarea, 20 - i, Self.Height - 80 + j, mytext, mytextstyle);
  8.   end;
This is extremely inefficient, but will get you to the place you want simple and dirty :)

If you want to make it "Better" then you might want to look into gauss blur, make an clear image with gauss blur of several pixels, process it and then copyrect it into your main canvas. It'll be much more efficient and beautiful, but will require you to carefully work pixel-by-pixel.

Quote
you won't get it by simply repeat the writing
I always do outline and shadow by repeat writing, because I'm lazy to make complex calculations :D
Title: Re: How can I drawing text with outline on a canvas?
Post by: Handoko on January 22, 2018, 08:27:58 pm
Well, actually yes we can but the result is not good. I never do it programmatically but I ever tried it using GIMP and Inkspace. The result looked ugly on large text.
Title: Re: How can I drawing text with outline on a canvas?
Post by: HudchewMan on January 22, 2018, 08:45:09 pm
Thank you and thank you very much. :)
Title: Re: How can I drawing text with outline on a canvas?
Post by: taazz on January 22, 2018, 09:05:07 pm
a faster windows only solution
Code: Pascal  [Select][+][-]
  1. uses windows;
  2.  
  3. {$R *.lfm}
  4.  
  5. { TForm1 }
  6.  
  7. procedure TForm1.FormPaint(Sender: TObject);
  8. var
  9.   textarea: TRect;
  10.   mytext: string;
  11.   mytextstyle: TTextStyle;
  12.  
  13. begin
  14.   canvas.Lock;
  15.   try
  16.     Canvas.GradientFill(Self.ClientRect, clNavy, clGreen, gdHorizontal);
  17.  
  18.     mytext      := 'Hello the world, Who am I.';
  19.     textarea    := Classes.Rect(20, Self.Height - 80, Self.Width - 20, Self.Height - 10);
  20.     mytextstyle := Canvas.TextStyle;
  21.     mytextstyle.Wordbreak  := False;
  22.     mytextstyle.SingleLine := True;
  23.  
  24.     Canvas.Pen.Style := psClear;
  25.     Canvas.Brush.Style := bsClear;
  26.  
  27.     Canvas.Font.Size  := 22;
  28.     Canvas.Font.Style := [fsBold];
  29.  
  30.     windows.BeginPath(Canvas.Handle);
  31.     //Canvas.TextRect(textarea, 20, Self.Height - 80, mytext, mytextstyle);
  32.     Canvas.TextOut(20,Height-80, mytext);
  33.     EndPath(Canvas.Handle);
  34.     Canvas.Brush.Color := clBlue;
  35.     Canvas.Brush.Style := bsSolid;
  36.     Canvas.Pen.Color   := clWhite;
  37.     Canvas.Pen.Style   := psSolid;
  38.  
  39.     windows.StrokeAndFillPath(canvas.Handle);
  40.  
  41.   finally
  42.     Canvas.Unlock;
  43.   end;
  44. end;                
  45.  
Title: Re: How can I drawing text with outline on a canvas?
Post by: RAW on January 23, 2018, 01:39:16 am
If you like you can try...

Graphics32 // +GR32_LINES and GR32_Text
BGRABitmap // as Handoko already said...
VampyreImaging Lib
GDI+ (Windows)
...

Then you can use semitransparent pixel and you'll get a lot of ready to use functions/procedures... really nice...
Title: Re: How can I drawing text with outline on a canvas?
Post by: HudchewMan on January 23, 2018, 04:47:17 pm
Thank you very much. :)
Title: Re: How can I drawing text with outline on a canvas?
Post by: circular on January 23, 2018, 08:10:29 pm
In BGRABitmap, as mentioned Handoko you can use the Contour filter to draw an outline with BGRABitmap. You can also use the Outline* properties of the Font renderer:
http://wiki.freepascal.org/BGRABitmap_tutorial_Font_rendering
Title: Re: How can I drawing text with outline on a canvas?
Post by: HudchewMan on January 24, 2018, 07:57:58 am
Thank you :)
Title: Re: How can I drawing text with outline on a canvas?
Post by: Awesome Programmer on April 01, 2019, 07:58:26 pm
In BGRABitmap, as mentioned Handoko you can use the Contour filter to draw an outline with BGRABitmap. You can also use the Outline* properties of the Font renderer:
http://wiki.freepascal.org/BGRABitmap_tutorial_Font_rendering

Hi circular link,

That's true Fontrenderer has Outline features and others like shadow. However, If you use Fontrenderer to apply font special effects like shadow, you can't use TextRect to word wrap your text and still have shadow, unless I am wrong.
It seems you can ONLY use TextOut with Fontrenderer for shadows and outline if you don't want to word wrap. If you do want to word wrap your text using TextRect, then you can't use Fontrenderer. Correct me if I am wrong.

Currently, that's what I am fighting with and can't seem to figure out a solution. I simply want to word wrap my text and still have the outline and shadow that I enabled or applied with Fontrenderer.  Is there any way to do that, circular link?
Title: Re: How can I drawing text with outline on a canvas?
Post by: circular on April 02, 2019, 03:35:09 pm
Sorry Awesome programmer, I did not see your post.

You're right I forgot to implement TextRect/TextWordWrap in TBGRATextEffectFontRenderer.

In the meantime you can use the function TextMultiline of TBGRABitmap. Also, it handles better Unicode and supports tabs.

EDIT: I fixed the FX with TextRect on the dev branch.
TinyPortal © 2005-2018