AggPas not working lazarus / 39-Graphics ---------------------------------------------------------------------- Blue_Painted · 2016-07-04 18:10 I'm re-implementing a Delphi project in Lazarus. The original project used AggPass successfully (XE2 I think) but in Lazarus I'm just getting nothing: No output at all. I've built this MDC -- mostly from the AggPas documentation but it's the same general arrangement as my Delphi app -- and this doesn't work either. 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.TestBtnClick(Sender: TObject);begin     FBitmap:= TBitmap.Create;     FBitmap.PixelFormat:= pf32bit;     FBitmap.SetSize(256,256);     FBitmap.Canvas.FillRect(0,0,254,254); // otherwise FBitmap is empty      FAgg2D:= TAgg2D.Create;     if FAgg2D.Attach(FBitmap)      then begin           FAgg2d.ClearAll(255,255,155);           FAgg2d.LineWidth(10);         FAgg2d.LineColor($32,$CD,$32);           FAgg2d.FillColor($CD,$CD,$10);            FAgg2D.Rectangle(20,60,120,160);            FAgg2d.Text(32,32,'Hello world');        end        else FBitmap.Canvas.TextOut(5,5,'Didnt attach');     PaintBox.Refresh;end; procedure TForm1.PaintBoxPaint(Sender: TObject);begin     if Assigned(FBitmap)    then PaintBox.Canvas.Draw(0,0,FBitmap);end;  I've checked that TForm1.PaintBoxPaint() gets called - and it does -- and I've stepped through Agg2D.attach() which is how I found that I had to for the bitmap to be non-Empty. I'm using Lazarus 1.6 with FPC 3.0.0 and AggPas 2.4 -rm3(freshly downloaded today) I'm pretty sure it's me doing something stupid but I can't see it. Many thanks in advance. Ed ---------------------------------------------------------------------- Graeme · 2016-07-05 05:37 The original AggPas from the AggPas website is rather old and with a few bug. You could also try the AggPas included with Lazarus (see the components directory, but that too is buggy, but has better LCL support. The most well maintained AggPas I know, is the one used by fpGUI and maintained by myself.   https://github.com/graemeg/fpGUI/tree/maint/src/corelib/render/softw are Anyway, here is slightly improved drawing code. Note the additional 2 lines highlighted. 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   FAgg2d.ClearAll(255,255,155);  FAgg2d.LineWidth(10);  FAgg2d.LineColor($32,$CD,$32);  FAgg2d.FillColor($CD,$CD,$10);   FAgg2D.Rectangle(20,60,120,160);   FAgg2D.NoLine;  FAgg2D.Font('/usr/local/share/fonts/Liberation/LiberationSans- Regular.ttf', 20);  FAgg2d.Text(32,32,'Hello world');  The output can be seen via the attached screenshot. I used fpGUI and its own AggPas code. Other than that, I don't see any obvious errors in your code. But maybe try the Agg2D included with Lazarus - never the original AggPas (which doesn't even support 64-bit platforms). ---------------------------------------------------------------------- Blue_Painted · 2016-07-05 05:57 Thanks very much for this. I've tried the included version but saw no improvement. I'll look at the version included with your fpGUI when I have the time. In the meantime I've found that BGRABitmap provides everything I need. Thanks again. Ed ---------------------------------------------------------------------- engkin · 2016-07-05 06:45 If you don't change the bitmap through its canvas then enclose the changes between BeginUpdate and EndUpdate (Windows issue?): 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      if FAgg2D.Attach(FBitmap)      then begin           FBitmap.BeginUpdate();           FAgg2d.ClearAll(255,255,155);...         FAgg2d.Text(32,32,'Hello world');           FBitmap.EndUpdate();        end... Using the aggpas in components produced the attached image. ---------------------------------------------------------------------- vfclists · 2016-07-05 06:59 Is there something wrong with the web configuration on the lazarus- ide.org domain? I  can 't see the images at  http://forum.lazarus- ide.org/index.php?action=post;topic=33232 but I can see them at http://forum.lazarus.freepascal.org/index.php?action=post;topic=33232. Do any of you have the same issue? ---------------------------------------------------------------------- engkin · 2016-07-05 07:08 Quote from: vfclists on July 05, 2016, 08:59:22 amDo any of you have the same issue? I don't see images using http://forum.lazarus- ide.org/index.php?topic=33232 No thumbnails using http://forum.lazarus.freepascal.org only full size images (after changing the host?) ---------------------------------------------------------------------- Graeme · 2016-07-05 07:56 Quote from: vfclists on July 05, 2016, 08:59:22 amDo any of you have the same issue? Yup, same issue here. The forum.lazarus-ide.org domain doesn't produce any images in posts. Using the original forum.lazarus.freepascal.org it does. Where and to whom do we report this issue? ps:   Thanks for spotting the issue with LCL+AggPas. ---------------------------------------------------------------------- Blue_Painted · 2016-07-05 08:38 Quote from: engkin on July 05, 2016, 08:45:17 amIf you don't change the bitmap through its canvas then enclose the changes between BeginUpdate and EndUpdate (Windows issue?): 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      if FAgg2D.Attach(FBitmap)      then begin           FBitmap.BeginUpdate();           FAgg2d.ClearAll(255,255,155);...         FAgg2d.Text(32,32,'Hello world');           FBitmap.EndUpdate();        end... Using the aggpas in components produced the attached image. Thanks very much - that's what I was missing .. and yes, this IS on Windows. Now I don't know whether to go back to AggPas or use BGRABitmap ....! ---------------------------------------------------------------------- Graeme · 2016-07-05 09:38 Quote from: Blue_Painted on July 05, 2016, 10:38:11 amNow I don't know whether to go back to AggPas or use BGRABitmap ....! Both are pretty similar, but my preference would be AggPas for its high quality sub-pixel rendering and flexible rendering pipeline support. Also you did mention your Delphi application already uses AggPas, so obviously it will be much easier to move that code to Lazarus (rendering code will not need any changes). ---------------------------------------------------------------------- circular · 2016-07-05 10:12 It is a bit a matter of taste. AggPas is a bit faster however if you want to do something that is not already defined in Agg2D, that's too complicated to my taste. There is a package that contains a modernized version of AggPas, that seems to make it a bit simpler. I don't know how much it is compatible with Lazarus though. Link: https://github.com/CWBudde/AggPasMod Drawing joined shapes: https://github.com/bgrabitmap/lazpaint/blob/master/bgraaggtest/gouraud _main.pas (BGRABitmap) https://github.com/CWBudde/AggPasMod/blob/master/Examples/Simple/Goura ud.dpr (modernized AggPas) https://github.com/graemeg/fpGUI/blob/maint/src/corelib/render/softwar e/agg-demos/gouraud.dpr (classic AggPas) http://antigrain.com/demo/gouraud.png (screenshot) Doing a custom gradient and applying a mask to it: https://github.com/bgrabitmap/lazpaint/blob/master/bgraaggtest/alpha_g radient_main.pas (BGRABitmap) https://github.com/CWBudde/AggPasMod/blob/master/Examples/Simple/Alpha Gradient.dpr (modernized AggPas) https://github.com/graemeg/fpGUI/blob/maint/src/corelib/render/softwar e/agg-demos/alpha_gradient.dpr (classic AggPas) http://antigrain.com/demo/alpha_gradient.png (approximate screenshot but you can see a bit the shapes and mask) @Graeme: I would agre about the flexibility of the pipeline, however not about the quality as I find that AggPas and BGRABitmap have the same quality. ---------------------------------------------------------------------- Thaddy · 2016-07-05 10:22 Doesn't aggPas require {$mode delphi}? ---------------------------------------------------------------------- circular · 2016-07-05 10:35 Can you be more specific? ---------------------------------------------------------------------- Thaddy · 2016-07-05 10:52 Well the last version I tried is here: http://www.crossgl.com/aggpas/ and that needs mode delphi There are more recent ones that need mode delphiunicode. I am not aware of a version for FPC that works w/o those defines. I may be wrong. But OTOH it often happens nowadays that the original code has a better chance of compiling than some half-baked and old FPC translations! ---------------------------------------------------------------------- Graeme · 2016-07-05 11:09 Quote from: circular on July 05, 2016, 12:12:49 pmIt is a bit a matter of taste. AggPas is a bit faster however if you want to do something that is not already defined in Agg2D, that's too complicated to my taste. It's more about what you want to accomplish. Some would say "too complicated", others would say "more flexible". The custom rendering pipeline plays a huge roll here. The whole point of AGG (and thus AggPas) is to have independent functionality [graphics features] that you can arrange in any order to produce infinite results. As the original AGG website also mentions. The idea is not to have a "black box" design, and to easy place whatever functionality you want or need for a specific purpose into a function or class, thus making it reusable when needed. The TAgg2D class is exactly one such example, where many independent features were put together will a simpler interface to mimic the Delphi style TCanvas functionality. Once you understand AGG (the tutorials do wonders here ), it is easy to build other similar "easy to use" classes for your exact needs. QuoteThere is a package that contains a modernized version of AggPas, that seems to make it a bit simpler. The usage of "modernized" is a bit deceiving. The only reason that fork of AggPas was created, is because Delphi dropped support for the Object data type. Free Pascal has no such problem. Also, I found some bugs in AggPasMod that doesn't exist in the AggPas included with fpGUI. I've also extended my fork of AggPas beyond the original AggPas -RM3 release, or the one included with Lazarus. QuoteDrawing joined shapes: ...snip... https://github.com/graemeg/fpGUI/blob/maint/src/corelib/render/softwar e/agg-demos/alpha_gradient.dpr (classic AggPas) You referenced the wrong project file there by the way. All your comparison shows is that you implemented "easier to use interfaces" or wrapper functions for functionality you wanted. Nothing stops me or others from doing the same for AggPas. Quote@Graeme: I would agre about the flexibility of the pipeline, however not about the quality as I find that AggPas and BGRABitmap have the same quality. The custom rendering pipeline is probably the feature I use the most - so that is a big deal to me. For others, their mileage my vary. As for the rendering quality... I did comparison tests some 6 years ago, and then the font and anti-aliased renderings of complex graphics produced better results with AggPas. I believe at that point BGRABitmap was also closely tied to LCL (limiting its usefulness) - I assume that has changed now? To be honest, I haven't used or tried BGRABitmap since. To be fair, in my earlier reply, I did mention BGRABitmap and AggPas are similar. ---------------------------------------------------------------------- Graeme · 2016-07-05 11:13 Quote from: Thaddy on July 05, 2016, 12:22:05 pmDoesn't aggPas require {$mode delphi}? So, I don't see that as a negative. It simply means AggPas can also be compiled with a Delphi compiler (*) out of the box. To some, that is a plus point. (*) - those Delphi compiler versions that still have support for the Object data type. ---------------------------------------------------------------------- Graeme · 2016-07-05 11:16 Quote from: Thaddy on July 05, 2016, 12:52:10 pmWell the last version I tried is here: http://www.crossgl.com/aggpas/ Please don't use that version. It is seriously old, doesn't support 64-bit and not being maintained by anybody. ---------------------------------------------------------------------- Thaddy · 2016-07-05 11:28 Quote from: Graeme on July 05, 2016, 01:16:14 pmPlease don't use that version. It is seriously old, doesn't support 64-bit and not being maintained by anybody. I wrote I could be wrong. I am testing something more recent. For Delphi, that is. Under {$MODE DELPHIUNICODE} that is. ---------------------------------------------------------------------- circular · 2016-07-05 13:02 Quote from: Graeme on July 05, 2016, 01:09:18 pmIt's more about what you want to accomplish. Some would say "too complicated", others would say "more flexible".Well I specify that I am talking about my taste. I find that if struggle understanding what's written, I achieve less. I achieve more when the code is easy for me to read. So it is important to you to have the ability to customize the pipeline? QuoteThe whole point of AGG (and thus AggPas) is to have independent functionality [graphics features] that you can arrange in any order to produce infinite results. As the original AGG website also mentions.Infinity is theoretical by definition. Do you have examples of things you've done with AggPas that cannot be done with BGRABitmap, except using other pixelformats? QuoteThe idea is not to have a "black box" designYou can look at the code of BGRABitmap, it is not opaque. You can derive classes for example. You can also suggest modifications or new functions that can be added to the library. QuoteQuoteThere is a package that contains a modernized version of AggPas, that seems to make it a bit simpler. The usage of "modernized" is a bit deceiving. The only reason that fork of AggPas was created, is because Delphi dropped support for the Object data type. Free Pascal has no such problem. Also, I found some bugs in AggPasMod that doesn't exist in the AggPas included with fpGUI. I've also extended my fork of AggPas beyond the original AggPas -RM3 release, or the one included with Lazarus.Do you think the author of the library wanted to deceive people when calling it "modernized"? I am ok with the term "modernized" in the sense that using real classes is easier to understand for me and more in line with object oriented programming design used in Free Pascal and Lazarus. QuoteYou referenced the wrong project file there by the way. Thanks for poining it out. QuoteAll your comparison shows is that you implemented "easier to use interfaces" or wrapper functions for functionality you wanted. Nothing stops me or others from doing the same for AggPas.Maybe. Then I would suggest to write such wrappers to make AggPas available to a wider public. QuoteAs for the rendering quality... I did comparison tests some 6 years ago, and then the font and anti-aliased renderings of complex graphics produced better results with AggPas. I believe at that point BGRABitmap was also closely tied to LCL (limiting its usefulness) - I assume that has changed now? To be honest, I haven't used or tried BGRABitmap since.Regarding the font rendering, BGRABitmap by default relies on the system canvas to render font and as a result, it does not handle much font hinting. You can however use other font renderers like TBGRAFreeTypeFontRenderer to have font hinting. It uses LazFreeType that is not perfect yet though. Apart from the font, do you have examples of complex graphics? QuoteTo be fair, in my earlier reply, I did mention BGRABitmap and AggPas are similar.  Yes. It is ok, I don't see it as a problem to discuss differences. ---------------------------------------------------------------------- Graeme · 2016-07-05 15:31 Quote from: circular on July 05, 2016, 03:02:23 pmSo it is important to you to have the ability to customize the pipeline? Yes, very much so. It allows you to greatly optimise rendering functions performance. The rendering pipeline will only contain what is really needed. QuoteInfinity is theoretical by definition. Do you have examples of things you've done with AggPas that cannot be done with BGRABitmap, except using other pixelformats? As I mentioned, I don't use BGRABitmap and definitely don't know it well. So I'm the wrong person to make deep technical comparisons. Here is a very good AGG tutorial. http://www.antigrain.com/articles/ddj1.agdoc.html What is nice is that it shows the power of the customisable rendering pipeline. It starts off with a basic vertex source. That vertex source doesn't change between the tutorial steps, but the rendering pipeline is changed instead, resulting in completely different rendered output after each step. Steps 5 (example_pipeline5.cpp) & 6 (example_pipeline6.cpp) show how powerful a custom rendering pipeline can be. The text explains that part well. I've ported the tutorial's examples to AggPas source code too. I just realised I never placed it in the fpGUI repository. I'll do so tonight. QuoteI am ok with the term "modernized" in the sense that using real classes is easier to understand for me and more in line with object oriented programming design used in Free Pascal and Lazarus. Using the Object data structure is also "object oriented programming". The Class data structure has simply extended it somewhat in recent years, but honestly not by much. There is also nothing wrong with writing new programs that are procedure based instead of object oriented - though like you, I wouldn't go that route any more. Just a small point of interest.... the most popular operating system is the world, the Linux kernel, is procedure based. So OOP is not the only way to code. QuoteApart from the font, do you have examples of complex graphics? My previous work with AggPas was commercial projects - I don't have code or screenshots of that work unfortunately. One project was mathematics and science related. Another project was map rendering in various formats (map layers). Another nice feature I like using in AggPas is hooking up multiple rendering pipelines (eg: TAgg2D as well) to the same render buffer, but each instance only has access to a certain region of the rendering buffer. But I need to underline, I made a choice 6 years ago with what was available then. At that time AggPas was the better choice for me, and I still use it to date. Somebody with deep technical knowledge of both AggPas and BGRAGraphics can do a more in-depth comparison, but that person is not me. ---------------------------------------------------------------------- circular · 2016-07-05 23:14 There is no right or wrong. Simply different ways. Quote from: Graeme on July 05, 2016, 05:31:02 pmWhat is nice is that it shows the power of the customisable rendering pipeline. It starts off with a basic vertex source. That vertex source doesn't change between the tutorial steps, but the rendering pipeline is changed instead, resulting in completely different rendered output after each step. Steps 5 (example_pipeline5.cpp) & 6 (example_pipeline6.cpp) show how powerful a custom rendering pipeline can be. The text explains that part well.Ah an example, ok I see what you're saying. You can do that as well in BGRABitmap. If you want to transform the pen like that, you can first call ComputeWidePolygon and then apply a transform to the result, instead of first applying the transform and then calling ComputeWidePolygon (or simply calling the DrawPolygon function). It would not be really a pipeline structure though I suppose. QuoteUsing the Object data structure is also "object oriented programming". The Class data structure has simply extended it somewhat in recent years, but honestly not by much.Yes and no. You cannot override virtual functions without a class. That's important. QuoteThere is also nothing wrong with writing new programs that are procedure based instead of object oriented - though like you, I wouldn't go that route any more. Just a small point of interest.... the most popular operating system is the world, the Linux kernel, is procedure based. So OOP is not the only way to code. Well if you go deep in BGRABitmap, you will find some procedure based programming. Though most of it is encapsulated in classes. QuoteAnother nice feature I like using in AggPas is hooking up multiple rendering pipelines (eg: TAgg2D as well) to the same render buffer, but each instance only has access to a certain region of the rendering buffer.For multithreading? QuoteBut I need to underline, I made a choice 6 years ago with what was available then. At that time AggPas was the better choice for me, and I still use it to date. Somebody with deep technical knowledge of both AggPas and BGRAGraphics can do a more in-depth comparison, but that person is not me.That's ok. It is still helpful for me when you show examples wth AggPas and what you find interesting in them. What about changing the title of this topic, because AggPas is working, isn't it? ---------------------------------------------------------------------- circular · 2016-07-05 23:43 For example 6, here is how to do it with BGRABitmap. By the way, i've just added the operator * for an array of pixel on Git. So you would not have to define it anymore in next version of the lib. Using this operator avoids having to write a for loop each time. 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 BGRATransform, BGRABitmapTypes, BGRAPath; operator*(M: TAffineMatrix; A: ArrayOfTPointF): ArrayOfTPointF;var  i: NativeInt;begin  setlength(result, length(A));  for i := 0 to high(A) do    result[i] := M*A[i];end; procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);var matrix: TAffineMatrix;  path: TBGRAPath;  outline, border: ArrayOfTPointF;begin    matrix := AffineMatrixIdentity;    matrix *= AffineMatrixTranslation(Bitmap.Width div 2, Bitmap.Height div 2);    matrix *= AffineMatrixScale(0.4,0.75);    matrix *= AffineMatrixRotationDeg(35.0);    matrix *= AffineMatrixTranslation(-Bitmap.Width div 2, -Bitmap.Height div 2);   path := TBGRAPath.Create;    path.moveTo(10, 10);    path.lineTo(Bitmap.Width-10, 10);    path.lineTo(Bitmap.Width-10, Bitmap.Height-10);    path.lineTo(10, Bitmap.Height-10);    path.lineTo(10, Bitmap.Height-20);    path.bezierCurveTo(Bitmap.Width-20, Bitmap.Height-20,                     Bitmap.Width-20, 20,                       10, 20);     outline := path.ToPoints;    path.Free;     Bitmap.FillPolyAntialias(matrix*outline, BGRA(160,180,80));     Bitmap.JoinStyle := pjsMiter;    border := Bitmap.ComputeWidePolygon(outline, 6);    Bitmap.FillPolyAntialias(matrix*border, BGRA(120,100,0));end; ---------------------------------------------------------------------- Thaddy · 2016-07-06 08:27 @Circular: Hm, I have to try -Sv  (vector math) instead of the operator overload. Something to do today Did you try that already? ---------------------------------------------------------------------- circular · 2016-07-06 12:51 @Thaddy: That's a good point, that's probably a case where some SSE optimization would be possible. I haven't tried.