How can I drawing text with outline on a canvas? lazarus / 39-Graphics ---------------------------------------------------------------------- HudchewMan · 2018-01-22 18:49 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. This is example of my code. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormPaint(Sender: TObject);var  textarea: TRect;  mytext: string;  mytextstyle: TTextStyle; begin  Canvas.GradientFill(Self.ClientRect, clNavy, clGreen, gdHorizontal);   mytext      := 'Hello the world, Who am I.';  textarea    := Rect(20, Self.Height - 80, Self.Width - 20, Self.Height - 10);  mytextstyle := Canvas.TextStyle;  mytextstyle.Wordbreak  := False;  mytextstyle.SingleLine := True;   Canvas.Font.Size  := 16;   // Border  Canvas.Font.Color := clWhite;  Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 - 0, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 + 0, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 0, Self.Height - 80 - 3, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 - 0, Self.Height - 80 + 3, mytext, mytextstyle);   Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 - 3, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 + 3, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 3, Self.Height - 80 - 3, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 - 3, Self.Height - 80 + 3, mytext, mytextstyle);   // Text  Canvas.Font.Color := clBlue;  Canvas.TextRect(textarea, 20, Self.Height - 80, mytext, mytextstyle); end;  The result is here. 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) ---------------------------------------------------------------------- Handoko · 2018-01-22 19:15 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 ---------------------------------------------------------------------- Eugene Loza · 2018-01-22 19:20 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Canvas.TextRect(textarea, 20 - 1, Self.Height - 80 - 1, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 1, Self.Height - 80 + 1, mytext, mytextstyle);  Canvas.TextRect(textarea, 20 + 1, Self.Height - 80 - 1, mytext, mytextstyle);  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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i for i := -5 to 5 do  for j := -5 to 5 do  begin     Canvas.TextRect(textarea, 20 - i, Self.Height - 80 - j, mytext, mytextstyle);     Canvas.TextRect(textarea, 20 + i, Self.Height - 80 + j, mytext, mytextstyle);     Canvas.TextRect(textarea, 20 + i, Self.Height - 80 - j, mytext, mytextstyle);     Canvas.TextRect(textarea, 20 - i, Self.Height - 80 + j, mytext, mytextstyle);  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. Quoteyou won't get it by simply repeat the writingI always do outline and shadow by repeat writing, because I'm lazy to make complex calculations ---------------------------------------------------------------------- Handoko · 2018-01-22 19:27 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. ---------------------------------------------------------------------- HudchewMan · 2018-01-22 19:45 Thank you and thank you very much. ---------------------------------------------------------------------- taazz · 2018-01-22 20:05 a faster windows only solution Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses windows; {$R *.lfm} { TForm1 } procedure TForm1.FormPaint(Sender: TObject);var  textarea: TRect;  mytext: string;  mytextstyle: TTextStyle; begin  canvas.Lock;  try    Canvas.GradientFill(Self.ClientRect, clNavy, clGreen, gdHorizontal);     mytext      := 'Hello the world, Who am I.';    textarea    := Classes.Rect(20, Self.Height - 80, Self.Width - 20, Self.Height - 10);    mytextstyle := Canvas.TextStyle;    mytextstyle.Wordbreak  := False;    mytextstyle.SingleLine := True;     Canvas.Pen.Style := psClear;    Canvas.Brush.Style := bsClear;     Canvas.Font.Size  := 22;    Canvas.Font.Style := [fsBold];     windows.BeginPath(Canvas.Handle);    //Canvas.TextRect(textarea, 20, Self.Height - 80, mytext, mytextstyle);    Canvas.TextOut(20,Height-80, mytext);    EndPath(Canvas.Handle);    Canvas.Brush.Color := clBlue;    Canvas.Brush.Style := bsSolid;    Canvas.Pen.Color   := clWhite;    Canvas.Pen.Style   := psSolid;     windows.StrokeAndFillPath(canvas.Handle);   finally    Canvas.Unlock;  end;end; ---------------------------------------------------------------------- RAW · 2018-01-23 00:39 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... ---------------------------------------------------------------------- HudchewMan · 2018-01-23 15:47 Thank you very much. ---------------------------------------------------------------------- circular · 2018-01-23 19:10 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 ---------------------------------------------------------------------- HudchewMan · 2018-01-24 06:57 Thank you ---------------------------------------------------------------------- Awesome Programmer · 2019-04-01 17:58 Quote from: circular on January 23, 2018, 08:10:29 pmIn 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? ---------------------------------------------------------------------- circular · 2019-04-02 13:35 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.