wiki.freepascal code shows nothing. lazarus / 39-Graphics ---------------------------------------------------------------------- jipété · 2023-09-11 10:30 Hello, Starting with this page (https://wiki.freepascal.org/fcl- image#Drawing_text) and using 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.Button1Click(Sender: TObject);var  // https://wiki.freepascal.org/fcl-image//  Img: TFPMemoryImage; // original  Img: TFPCustomImage;   // essay, same poorly result  Writer: TFPWriterPNG;  ms: TMemoryStream;  ImgCanvas: TFPImageCanvas;  fs: TFileStream;  AFont: TFreeTypeFont;begin  Img:=nil;  ImgCanvas:=nil;  Writer:=nil;  ms:=nil;  fs:=nil;  AFont:=nil;  try    // initialize free type font manager    ftfont.InitEngine;    FontMgr.SearchPath:='/usr/share/fonts/truetype/dejavu/';    AFont:=TFreeTypeFont.Create;     // create an image of width 200, height 100    Img:=TFPMemoryImage.Create(200,100);    Img.UsePalette:=false;    // create the canvas with the drawing operations    ImgCanvas:=TFPImageCanvas.create(Img);     // paint white background    ImgCanvas.Brush.FPColor:=colYellow; //colWhite; -- better like that    ImgCanvas.Brush.Style:=bsSolid;    ImgCanvas.Rectangle(0,0,Img.Width,Img.Height);     // paint text    ImgCanvas.Font:=AFont;    ImgCanvas.Font.Name:='DejaVuSans';    ImgCanvas.Font.Size:=20;    ImgCanvas.TextOut(10,30,'Test');     // write image as png to memory stream    Writer:=TFPWriterPNG.create;  ms:=TMemoryStream.Create;    writer.ImageWrite(ms,Img);    // write memory stream to file    ms.Position:=0;    fs:=TFileStream.Create('testfont.png',fmCreate); // img written in prog's folder    fs.CopyFrom(ms,ms.Size);  finally    AFont.Free;    ftfont.DoneEngine; // needed or not ?    ms.Free;    Writer.Free;    ImgCanvas.Free;    Img.Free;    fs.Free;  end;end;absolutly nothing is displayed on form, while the saved file is correct. What's wrong in that code ? Thanks, Debian Bullseye 11.7 64bits Gtk2 and FPC 3.2.2 Laz 2.2.6 ---------------------------------------------------------------------- rvk · 2023-09-11 10:59 Maybe I'm overlooking something but where in that code do you paint to your form? The example is also not for painting to a form but to a file (which seems to work correctly). ---------------------------------------------------------------------- jipété · 2023-09-11 11:37 You're right ! I've misunderstood the simple line from the wiki : Here is an example, how to create a 200x100 image, painting a white background and some text and saving it as .png: When I read the word "painting", I think "painting where ? On the form ?" There is nothing else to receive paint, so it must be on form so I expected to see the background and the text on the form, but maybe I'm wrong... ---------------------------------------------------------------------- rvk · 2023-09-11 12:23 Quote from: jipété on September 11, 2023, 01:37:35 pmWhen I read the word "painting", I think "painting where ? On the form ?" There is nothing else to receive paint, so it must be on form so I expected to see the background and the text on the form, but maybe I'm wrong... It's "painting" on a (virtual) canvas (that's the virtual TFPImageCanvas). After that it is saved to a file. And if you are going to save something to a file, you might not even want it to show on a form at all. (That's where a canvas comes in. A canvas can be visible but doesn't need to be.) ---------------------------------------------------------------------- wp · 2023-09-11 12:41 The following code paints the image onto a TImage component (which you must drop on the form): 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.Button1Click(Sender: TObject);var  // https://wiki.freepascal.org/fcl-image//  Img: TFPMemoryImage; // original  Img: TFPCustomImage;   // essay, same poorly result  Writer: TFPWriterPNG;  ImgCanvas: TFPImageCanvas;  AFont: TFreeTypeFont;begin  Img:=nil;  ImgCanvas:=nil;  Writer:=nil;  AFont:=nil;  try    // initialize free type font manager    ftfont.InitEngine;    // FontMgr.SearchPath not needed on Windows//    FontMgr.SearchPath:='c:\windows\fonts\';//    FontMgr.SearchPath:='/usr/share/fonts/truetype/dejavu/';    AFont:=TFreeTypeFont.Create;     // create an image of width 200, height 100    Img:=TFPMemoryImage.Create(200,100);    Img.UsePalette:=false;    // create the canvas with the drawing operations    ImgCanvas:=TFPImageCanvas.create(Img);     // paint white background    ImgCanvas.Brush.FPColor:=colYellow; //colWhite; -- better like that    ImgCanvas.Brush.Style:=bsSolid;    ImgCanvas.Rectangle(0,0,Img.Width-1,Img.Height-1);     // paint text  ImgCanvas.Font:=AFont;    ImgCanvas.Font.Name:='DejaVuSerif';    ImgCanvas.Font.Size:=20;    ImgCanvas.TextOut(10,30,'Test');     // load image into TImage component    Image1.Picture.Bitmap.Assign(Img);  finally    AFont.Free;    ftfont.DoneEngine; // needed or not ?    Writer.Free;    ImgCanvas.Free;    Img.Free;  end;end; ---------------------------------------------------------------------- jipété · 2023-09-11 14:08 Quote from: wp on September 11, 2023, 02:41:20 pmThe following code paints the image onto a TImage component (which you must drop on the form): Thanks a lot ! Anyway, using 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 ImgCanvas.TextOut(10,30,'Test'); I don't understand why the "T" start at 10,10 : img rect-10x10 On previous picture, width of big black lines is 6, so, if I ask ImgCanvas.Rectangle(5,5,... it means ImgCanvas.Rectangle(0to5=6px,0to5=6px ? If I write 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 ImgCanvas.Rectangle(0,0,Img.Width,Img.Height); I notice strong left and top borders ; to have clean, nice and free border, I need to write 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 ImgCanvas.Rectangle(-1,-1,Img.Width,Img.Height); : like that, The Gimp tells that the rectangle is 200 x 100... If I select the yellow rect with right+1 and bottom+1, one can see one-pixel skyblue lines on bottom and right yellow sides, meaning the width is really 200 and the height really 100, so, what's wrong with 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 ImgCanvas.Rectangle(0,0,Img.Width,Img.Height); ? img 201x101 Thx again, ---------------------------------------------------------------------- wp · 2023-09-11 16:33 Quote from: jipété on September 11, 2023, 04:08:00 pmAnyway, using 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 ImgCanvas.TextOut(10,30,'Test'); I don't understand why the "T" start at 10,10 Text output is done here by the FTFont unit which is based on FreeType where Text is drawn relative to the base line. In the LCL's TCanvas, on the other hand, text is drawn relative to the top. Just two worlds... You can bring them together by evaluating the FontMetric parameters. Unfortunately, they are not readily accessible in the FTFont unit, but you could use this procedure: 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 GetFontMetric(AFont: TFreeTypeFont; var Ascender, Descender: Integer);var  fontID: Integer;  face: PFT_Face;  h: Double;begin  fontID := FontMgr.RequestFont(AFont.Name, AFont.FontIndex);  face := FontMgr.GetFreeTypeFont(fontID);  h := AFont.GetTextHeight('Tg');  Ascender := round(face^.ascender / face^.height * h);  Descender := round(face^.descender / face^.height * h);end; Ascender is the distance between baseline and top-most pixel of a font, and descender is the difference to the bottom-most pixel. (descender < 0). Subtracting the ascender from the baseline position yields the top position of the character cells. Quote from: jipété on September 11, 2023, 04:08:00 pmOn previous picture, width of big black lines is 6, so, if I ask ImgCanvas.Rectangle(5,5,... it means ImgCanvas.Rectangle(0to5=6px,0to5=6px ? Again two worlds... In one world (yours), each pixel is a box and if you want to draw a line between x=0 and x=5 you draw the pixels 0, 1, 2, 3, 4, 5 - and these are 6 pixels. In the other world, a pixel is a mathematical coordinate, an infintely small point, and now the distance between 0 and 5 is 5 (this is the same as saying that there are 5 years between jan 1 2000 and jan 1 2005). I know there was an article somewhere explaining it better but I cannot find it at the moment. And there are cases in which it is not clear to which world they belong... I gave up to try to memorize these differences, a simple test quickly shows the differences. ---------------------------------------------------------------------- jipété · 2023-09-11 18:13 Hi ! It's the first time in my life that I see the way you compute font's data and of course, your results are not the same as what I can find here and there. For example, have a look at the page https://www.developpez.net/forums/d2121853/autres- langages/pascal/lazarus/telechargez/font-inspector/, this program gives other values than yours. fontinspector.png So, where is the truth ? Linux doesn't retrieve the same values as Windows does, see here (it's french, but no matter) : https://www.developpez.net/forums/d2155453/autres- langages/pascal/lazarus/laz-2-2-6-fpc-3-2-2-tmemo-incapable-rendre- correctement-fonte/#post11969332 And last but not least, some values of TTextMetrics are not available in Linux, OMG, I'm lost... Alas, no help available for FontMgr, Ascender or Descender... ---------------------------------------------------------------------- wp · 2023-09-11 20:28 Interesting that you show me a screenshot similar to my own program (https://github.com/wp- xyz/LazSamples/tree/master/graphics/font%20inspector)... But the calculation is correct. The only problem is that the sample text to measure the text height did not contain the highest characters. Changing this the ascender/descender determined by my procedure and by the LCL yield the same values. ---------------------------------------------------------------------- rvk · 2023-09-11 20:37 Quote from: jipété on September 11, 2023, 08:13:39 pmFor example, have a look at the page https://www.developpez.net/forums/d2121853/autres- langages/pascal/lazarus/telechargez/font-inspector/, this program gives other values than yours. fontinspector.png Is that forum only accessible to subscribers? I get an error message "Cette discussion n'existe plus". ---------------------------------------------------------------------- jipété · 2023-09-11 22:23 Quote from: wp on September 11, 2023, 10:28:19 pmInteresting that you show me a screenshot similar to my own program (https://github.com/wp- xyz/LazSamples/tree/master/graphics/font%20inspector)... Before now, I didn't know your code. Quote from: wp on September 11, 2023, 10:28:19 pmBut the calculation is correct.Things are not so simple : there is a bigger glyph than Ä, it's Ê. So the results are now different : 25 <> 26 ! different_values.png To have a better view, I've changed 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 ImgCanvas.Line(0, 30-asc, 400, 30-asc); to 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 ImgCanvas.Line(0, 28-asc, 400, 28-asc); and zoomed the resulting image, see 2nd attachment : big-letters_and_1px-red-line.png And maybe there are some other letters more bigger... This problem is a nightmare. Your code looks like better than the one I knew, so Quote from: rvk on September 11, 2023, 10:37:57 pmIs that forum only accessible to subscribers? I get an error message "Cette discussion n'existe plus". for rvk, forget mine and use the wp's code. ---------------------------------------------------------------------- wp · 2023-09-11 22:45 Quote from: jipété on September 12, 2023, 12:23:02 amthere is a bigger glyph than Ä, it's Ê. Probably this is the reason why the LCL/VCL's Canvas.TextHeight reports the height including some white space above and below the character cells (internal/external leading)? To do it correctly you should iterate over all characters of the font file and determine the maximum of the ascender/descender values. Or maybe there are better ways? There are several freetype libraries in FPC and in Lazarus. Maybe there are ones which provider better support. But sincerly: Why are you doing it in the hard way? Why don't you use the standard TCanvas when you only draw on a bitmap to display it in a TImage? ---------------------------------------------------------------------- jipété · 2023-09-12 09:57 Hello, One physical machine running Linux Debian 11 and VirtualBox, one virtual machine running Seven. Starting Lazarus 2.2.6 in Debian, Project / New Project / Application, 1 TButton, 1 TMemo, 5 lines of 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.Button1Click(Sender: TObject);begin  Memo1.Clear;  Memo1.Font.Name:='Bonita';  Memo1.Font.Size:=60; // 60 to nicely see the problem  Memo1.Append('Bonita');  Memo1.Append('Bonita');end;and F9, then opening the project (shared folder) in Seven and voilà : Debian-Seven.png Why the Seven window bigger than the Debian window ? If same size, the Seven TMemo looks like empty ! The caret is 77 px height in Debian and 100 px in Seven, heavy in Debian and light in Seven, and there are 22 px between the 2 "B" in Debian and 47 in Seven. Cross-platform, Lazarus, really ? I expected the same results, so I loose my time trying to understand what is happening, but I haven't the skills. I'm just a fonts' lover. Quote from: wp on September 12, 2023, 12:45:03 amBut sincerly: Why are you doing it in the hard way? Why don't you use the standard TCanvas when you only draw on a bitmap to display it in a TImage? with something like that ? 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.Button2Click(Sender: TObject);var  Bitmap: TBitmap;  Metric: TLCLTextMetric;begin  Bitmap := TBitmap.Create;  Bitmap.Height := 50;  Bitmap.Width := 500;   Bitmap.Canvas.Font.Name:='Palatino Linotype';  Bitmap.Canvas.Font.Height:=20;  Bitmap.Canvas.GetTextMetrics(Metric);  Bitmap.Canvas.TextOut(0, 1, 'Test JjgÄÉÊ ' + IntToStr(Metric.Height) + ' = ' + IntToStr(Metric.Ascender) + ' + ' + IntToStr(Metric.Descender));   Image2.Picture.Assign(Bitmap);  Bitmap.Free;end; I loose accents (Basic button) : img_3tries 3 tries, 3 different values ! A nightmare I've said, yesterday... Also discovered the following (read comments) : 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  tm: TLCLTextMetric;begin// regarding Font.name, both commented out so prog uses ide params and shows ÄÉÊ// but the font is NOT the good one I need !// if one is activated, prog looses accents and shows AEE...  Label1.Font.Name:='Palatino Linotype'; // new, jpt//  Label1.Font.Name:='Bonita'; // new, jpt   Label1.Font.Size:=20; // new, jpt  Label1.Canvas.GetTextMetrics(tm);  Label2.Caption := Format('Font metrics from Canvas.GetTextMetrics: ' + LineEnding +    'Ascender  = %d' + LineEnding +    'Descender = %d' + LineEnding +    'Height = %d', [tm.Ascender, tm.Descender, tm.Height]);end; (no image) And look at the yellow result, below, made with the TFPCustomImage, TFPImageCanvas and TFreeTypeFont, and use the red lines to compare. I don't understand why the accent on the E between the A and the other E is smaller on the left than on the right, it's a mystery. But noticed one hour ago that the font is wrong, re-read previous text. And below, in skyblue, a try with LO Writer, which is better than the yellow and lightgray tries. 3tries-with-lowriter Regards, (not available from this afternoon to late tomorrow morning, see you later, alligator !) -- jp