TMS Software. All-Access

TMS MemInsight, Delphi runtime memory inspection: statistics and filters

Using TMS MemInsight is easy: drop a component on your form, set some properties and there you go. Altough the component and UI of TMS MemInsight are currently based on the VCL you can already use it in your FireMonkey (on Windows and without UI), Windows service or console applications or any other headless application, such as a TMX XData server. But in this blog, we dive deeper: TMS MemInsight has a wide API and offers all of its options and features by code. Let’s start by looking at some of the properties of the memory profiler first. To access it, as well as other parts of TMS MemInsight, use the units TMS.MI.Access and TMS.MI.Memory from within your code. These units contain some functions which serve as entry point to gain access to the interfaces needed to control tracing, filters as well as more advanced options like collecting memory statistics as it’s done within the UI. Another handy unit is TMS.MI.Core which offers some ready to use utility functions. You can enable/disable the profiler by setting it’s Active property. You can Suspend/Resume profiling for the current thread by calling the methods of the same name or exclude them completely to control and tune what is being traced. For this, TMS MemInsight also offers filters which allow for even more fine tuning. Filters can also be customized and attached and removed dynamically. The folder “Dev” contains a sample for such a filter which allows tracing of objects contained in certain units only. We will use it in our example below. Another useful method is SuspendMethod which disables tracing for the current thread until the current scope is exited. Usually this is, as the name suggests, the current method, although this has slightly changed in Delphi 11 Alexandria with the introduction of inline variables where the scope might be limited to the current begin/end block. The memory profiler includes three different filters. The Default filter allows to configure, which threads are being traced as well as setting the TraceTypes: mtString, mtObject, mtArray, mtRecord and mtUnknown. Beside of that you can, if your applications is build using run-time packages, select which package classes are shown. The IncludeFilter and ExcludeFilter allow fine grained tracing considering the class name of objects and supports pattern matching. This way you can limit the tracing to certain class names as well as class names matching something like “TYourPrefix*” or exclude class names matching similar patterns. All filters can be activated/deactivated by setting their Active property. You can store and reload these configurations for latter use. Let’s jump right into our first example: collecting memory statistics and dumping them into a file. Working with these statistics is, in almost all cases, my starting point when trying to understand why, where and what the application is consuming. As this is happening during run-time I can use the application, repeat certain functions and observe its behavior to isolate and concentrate on concrete spots. Limiting the tracing on these identified classes by using the above mentioned filters is also helpful. For the sake of this example we create five utility functions: InitializeProfiling, StartProfiling, StopProfiling, ResetStatistics and SaveToFile. InitializeProfiling will set up some default options and attach and configure the filter as well as the memory statistics. We also disable stack traces as […]

Read More

TMS WEB Core for Visual Studio Code 1.9.7.0 released

We’re happy to announce that with the new release of TMS WEB Core for Visual Studio Code, we stepped up the level of web client application development with Object Pascal. The key goals of this new release 1.9.7.0 are: Introduce visual form inheritance Framework synchronization with TMS WEB Core for Delphi Increased robustness, compatibility and stability Improved coding experience thanks to a new OmniPascal update Visual form inheritance Now you can take advantage of the visual form inheritance feature also from the TMS WEB Core Visual Studio Code IDE. This means you can design a form and created an inherited form and use base form class and inherited form live visually in the IDE. Any changes you apply to the base class will be immediately visible in the descending form class and modifications to the descending class are nicely managed and persisted. Using visual form inheritance should significantly increase your productivity when you deal with web application form logic with repeating patterns. See for yourself how this visual form inheritance feature is used in the IDE: Framework synchronization with TMS WEB Core for Delphi In the new release, all latest features & improvements of the TMS WEB Core framework are adopted in TMS WEB Core for Visual Studio Code. This includes: New : geMemo editor type added in TWebStringGrid New : WordWrap property added in TWebStringGrid New : TWebResponsiveGrid.OnGetItemTemplate event added New : Support for custom images added in TWebDBNavigator New : SelectCell() added in TWebTableControl New : ScrollRowInView() added in TWebTableControl New : MultiSelect option added to TWebResponsiveGrid New : Miletus use of USB UART on Raspberry Pi New : Miletus extensibility through libraries New : Hyperlinks clickable with Ctrl key in TWebRichEditToolbar New : Hyperlink button added in TWebRichEditToolbar New : FindCellFindNext functions added in TWebTableControl New : Filtering capability added in TWebTableControl TWebDBTableControl       + various smaller improvements and fixes. Given that the TMS WEB Core framework under TMS WEB Core for Visual Studio Code is identical to TMS WEB Core for Delphi, this means you can perfectly continue development projects handled by other team members in Delphi also from Visual Studio Code and vice versa.  Increased robustness, compatibility and stability. While TMS WEB Core for Visual Studio Code is younger than the version for Delphi, it comes with the additional challenge that it has a web technology based form designer. This means that it uses a full WYSIWYG form designer that also uses HTML elements or complete HTML templates live on the form designer. You can understand this brings increased complexities to manage in the designer and we focused on improving the experience at design-time in this new release. Improvements were done to the framework to handle this design-time situation better and we significantly extended the number of tests run from within the IDE itself to guarantee stability & compatibility. This new release should move this a significant step forward. Improved coding experience thanks to a new OmniPascal update Not really a part of this new TMS WEB Core for Visual Studio Code 1.9.7.0 release, but the new OmniPascal version will still improve your coding experience while developing in TMS WEB Core for Visual Studio Code. We worked together with the author of OmniPascal. This Visual Studio Code plugin provides code completion & highlighting […]

Read More

Embarcadero MVP Jens Fudge on FlexCel

TMS FlexCel is one of our flagship products, with well over 20 years of development going into it and meanwhile supporting the near entire Microsoft Excel feature set and as development tools Delphi, C++Builder and .NET via C#, VB.NET or .. actually any Windows language that can use DLL’s via TMS FlexCel DLL.  While FlexCel can be used to read and write .XLS and .XLSX files extremely fast, on-the-fly and most importantly, without the need to have Microsoft Excel installed, it can actually also being used as a reporting tool where it generates Excel, PDF, HTML, SVG, Image files… with  report templates defined in an Excel file and possibly also data coming from an Excel file. Today, we bring you a fantastic opportunity to discover how Jens Fudge, Embarcadero MVP in Denmark, frequent speaker at Delphi conferences uses FlexCel. Jens is not only Delphi expert, he was also Paralympic Champion Archery and still heavily involved with archery and training top sportspeople. And that’s not all, Jens runs his own Delphi development consulting company and published in 2020 also a book “Choose to be a Winner” about adopting a winning mindset for sports people but equally applicable to anyone wanting to get more out of life.  See in this video how Jens Fudge created score cards as reports from archery competition results using FlexCel: If you feel like discovering more of the power of FlexCel, Jens informed us that he was involved in setting up a one hour webinar for the Danish Delphi user group in March. So, stay tuned, as soon as we have the final information on this webinar, we’ll inform so you can also register and attend this webinar! 

Read More

FNC Conversion Components in TMS Analytics & Physics 3.3

From version 3.3, TMS Analytics & Physics library contains several FNC components for converting math formulae and units of measurement to special text formats. In this article, we’ll consider how to do the conversion and how then use the converted strings in Delphi applications.  Let’s begin with formula converters: TFNCFormula2PlainConverter – converts a formula to plain text. TFNCFormula2TeXConverter – converts a formula to TeX format. The TFNCFormula2PlainConverter component has the following published properties: Formula (string) – a formula to convert. PlainFormula (string) – the formula in plain text format (read-only). Valid (boolean) – the formula is valid for conversion (read-only). Error (string) – description of the error if occurred during conversion (read-only). The component provides a very simple functionality: when the ‘Formula’ property changes, the value is converted to plain text format and assigned to the ‘PlainFormula’ property.  What is the plain text format and when it could be useful? Plain text format just presents a formula as a string using special Unicode characters to make it closer to natural math notation. For example, the formula ‘x^2’ can be written with the superscript symbol as ‘x2’. In the following picture, an example of such conversion is presented. Here we should note that not all formulae can be presented in this format. If a formula is not valid for the conversion, an error message will be shown with the ‘Error’ property. Now let’s use this converter to make a fine math application. In one of the previous articles, we explained how to use curve fitting FNC math components. In the following picture, we showed an example of data approximated with a Taylor series.   On the FNC chart, we showed the formula of the fitted curve in the legend. Let’s use the converter and improve the design of the application. We just need to write a small piece of code: procedure TForm1.ShowCurveLegend(const formula: string);begin  FNCFormula2PlainConverter1.Formula:= formula;  TMSFNCChart1.Series[1].LegendText:= FNCFormula2PlainConverter1.PlainFormula;end;procedure TForm1.FNCApproxFunction1D1FormulaChanged(Sender: TObject; const formula: string);begin  ShowCurveLegend(formula);end; When a formula of the approximated function is changed, we convert it to plain text format and show the formula on the chart. The resulting form is presented in the picture below. As one can see, the formula of the fitted curve looks like a natural math expression, without superfluous symbols, like power operator ‘^’ and indexing brackets ‘[]’. One more example of the curve, fitted with a Fourier series, is shown in the following picture.   The full source code of the demo project is available with the latest version of TMS Analytics & Physics library.  We can use the same approach to present units of measurement in the form of natural physics notation with the TFNCUnit2PlainConverter component. An example of such conversion is shown in the picture below.   The next component TFNCFormula2TeXConverter has similar functionality, but it converts formulae to TeX format. This format is not for human reading, so, we need a drawing library to display formulae in natural math notation. We’ll use the MathJax library, as described in this article, together with the TTMSFNCWebBrowser component. Here is a simple code for converting a formula to TeX format and showing it in the browser component: procedure TForm1.DrawFormula(const formula: string);var  texf, htmlcode: string;begin  FNCFormula2TeXConverter1.Formula:= formula;  texf:= FNCFormula2TeXConverter1.TeXFormula;  htmlcode:= GetTeXHTML(texf);  DrawTeXInBrowser(htmlcode);end; Thus, we have a simple application to display math formulae. An example of a […]

Read More

TMS FNC Chart Update 1.8

TMS FNC Chart is designed to display different kinds of data such as financial and marketing data, monthly business sales, graphical and math data and much more as a chart. This chart is almost fully customizable. Updated Editor In this new update the editor was changed to work as the other editors in other FNC products. The editor adapts to your theme, it changes according to the Light or Dark style of the IDE. It now has high DPI aware controls that look crisp in run-time and in design-time on Delphi 11 Alexandria.And the editor is available in Visual Studio Code. Works together with TMS Analytics & Physics The TMS Analytics & Physics library is a set of classes that provide functionality for building powerful math applications with Delphi. And you can visualize the data or formulas with the TMS FNC Chart. More information on TMS FNC Chart can be found on the product page.

Read More

Delphi is 27, happy birthday and welcome to the new generation

Happy Birthday Delphi It is meanwhile a regular. It is again February 14 and it is the birthday of Delphi. We celebrate today 27 years! Not including its predecessor Turbo Pascal, it’s for a whole generation of software developers already well over the half of a career that Delphi gives us professional satisfaction as well as bread on the table. But today, I wanted to devote this birthday of Delphi to the next generation. The new generation that is at the start of a new software development career. The new generation that discovers Delphi and is feeling enthusiasm and the new generation for which Delphi still is a valuable & productive tool to accomplish real-life software development tasks that has an impact on people’s lives. Enough said, read the article Stephanie Bracke, our intern this year at TMS software wrote herself or watch the video she made herself! See or read & be amazed about what Stephanie accomplished for Delphi apps that can change people’s lives, including people with disabilities. Bruno Stephanie.Introduce(‘Hello world’); When I first started my internship at TMS software, I felt overwhelmed and that still feels like an understatement, but luckily my mentor Bruno repeatedly told me ( and I needed to hear that every time as well ) that in order to be able to run, you should learn how to walk. To get started and prepare myself during the summer holidays, I was given a two book, the first by Marco Cantù and another by Holger Flick. to try to get myself familiar with the Delphi IDE and also the Object Pascal language.  My project For my first real assignment I was given an open source library called Annyang! And was the task was to study this library and turn this into an easy to use speech to text component for TMS WEB Core.  I feel like creating the TSpeechToText component with Annyang! Is like entering a rabbit hole, in school we learned the basics, but the deeper you go, the more there is to learn!  In short, I created a web application with TMS WEB Core and only one button that starts Annyang. But of course, you can start the engine automatically at application startup or in different ways, if you don’t like that button. You’re as free as a bird here! Once the button on my webpage is clicked, the device microphone gets activated (see red little icon the caption) in your browser and Annyang starts to listen to your command. I added a few commands, for example:  Start -> starts the camera Snap ->takes a picture Listen -> Annyang starts listening to sentences and adds it to the memo Once you activate the “Listen” command, Annyang will still listen to single word commands and execute those as a priority instead of adding the recognized words in a TWebMemo control, whenever that single word is used in a sentence, the entire sentence will be written down without execution of said command. There are also commands like zoom, reset, pause and resume but those are for you to find out in the demo!   The more time I spend using Annyang as a component the more I can think of ways to enhance it, there are just so many ways and possibilities of using this component that I can’t wait to see what […]

Read More

Check your overflows

This topic has concerned me forever, but an exploit I read about a month ago triggered me to finally write something. The exploit itself is fascinating, so in case you haven’t read about it, I’ll leave the link here: https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html But what can be so fascinating about a vulnerability?, I can hear you say. We find exploits every day in every product, don’t we? To what I have to answer, “yes, we do”. And, while not the focus of this post, that’s exactly the problem. The exploit This was an exploit in a JBIG2 library. JBIG2 is not designed to execute code, so it is not simple to make it execute code. It is not like a flaw in a PDF javascript implementation, where you get access to the javascript engine when you shouldn’t, and once you are in, you just execute commands. There is nothing to execute here. And yet… The exploit starts simple, with an overflow bug. Basically you sum some numbers, say like: MemoryToAllocate := Length(data1) + Length(data2); …AllocatedMemory := AllocateMemory(MemoryToAllocate); FillWithData(AllocatedMemory); But what happens if I maliciously create a file where Length(data1) is near the maximum an integer can hold and then add the length of data2? In most programming languages, what will happen is that the integer will overflow, so 2147483647 + 1 = -2147483648 And of course, since I have control over both lengths, I can create a file that allocates, say 2 bytes, and then tries to write 100 bytes into the allocated memory, corrupting the stack. And now it is where it gets interesting. We want to execute code, not to corrupt the stack, and as mentioned before JBIG2 doesn’t really execute any code. So how do we continue? Simple: We find out a way to emulate a NAND gate with the stack corruption, and then construct our own computer from those NAND gates, where we can execute any code we want. As the article says, it is not as performant as JavaScript, but it gets the job done. Now you can infect a phone just by sending it a message, without the user even having to click on anything.   The takeaway In computing, we always tend to forget about border conditions. Usually, that works fine: I mean, what are the odds that an integer overflows in day-to-day images? The JBIG2 code was probably correct for virtually 100% of naturally occurring JBIG2 files. But when you add someone maliciously trying to break your code, the situation changes. No matter how small a hole you leave on your wall, someone will use it and build a 6-lane highway to enter your place. Give them a small overflow, and they will make a whole computer out of NAND gates. And what can we do about it? First steps first: we should always stay vigilant, not just about how invalid data can break our program, but more important, how maliciously created, completely-unlikely-to-exist-in-the-real-world data can break our apps.  WE NEED TO ALWAYS CONSIDER HOW SOMEONE COULD MALICIOUSLY ATTACK OUR CODE. IT IS NOT ENOUGH WITH JUST MAKING SURE IT WORKS IN THE EXPECTED OR REASONABLE CASES But I firmly believe that staying vigilant is not enough. We are humans, after all, and humans make mistakes. So we need all the extra help we can get, […]

Read More

Add custom controls to your map with TMS FNC Maps for Delphi

ElementContainers is a major new feature in TMS FNC Maps v3.0. With ElementContainers you can add custom controls on top of the map. These custom controls consist of HTML and CSS elements. Interaction with the map and the application can be added by using Actions. At runtime the content of the ElementContainers can be updated dynamically through JavaScript. ElementContainers are independent of the mapping service which means they will look and function identically regardless of your preferred mapping service. A preview is automatically available at design-time to make editing the HTML/CSS elements as straightforward as possible. In this blog post I’ll demonstrate how easy it is to add a custom interactive zoom control to the map. The Basics Position the container anywhere on the map with the Position and Margin properties. We’ll place the container in the bottom left corner of the map: set Position to poBottomLeft. Add an item to the Actions collection of the ElementContainer to interact with the map. Select the ID from the element to interact with from the HTMLElementID dropdown list. In this case pick “customRange1” to interact with the slider control. Set Event to heCustom and CustomEvent to input to catch the input event of the slider control. Set EventReturnValue to rvValue to retrieve the updated value of the slider control. Assign the ElementAction’s OnExecute event to add an event handler. The updated slider control value is returned as a string in the AEventData.CustomData property. We can use this value to update the map’s zoom level with the code below: procedure TForm1.TMSFNCMaps1ElementContainers0Actions0Execute(Sender: TObject; AEventData: TTMSFNCMapsEventData); var f: Double; v: string; begin f := 0; v := StringReplace(AEventData.CustomData, ‘”‘, ”, [rfReplaceAll]); if TryStrToFloatDot(v, f) then TMSFNCMaps1.SetZoomLevel(f); end; Assign the TTMSFNCMaps’s OnZoomChanged event to interact with the ElementContainer. When the map’s zoom level changes, get the new zoom level and update the label and slider control in the ElementContainer. procedure TForm1.TMSFNCMaps1ZoomChanged(Sender: TObject; AEventData: TTMSFNCMapsEventData); begin TMSFNCMaps1.GetZoomLevel; end; procedure TForm1.TMSFNCMaps1GetZoomLevel(Sender: TObject; AZoomLevel: Double); begin TMSFNCMaps1.ExecuteJavaScript(‘document.getElementById(“customRange1”).value = ‘ + FloatToStrDot(AZoomLevel)); TMSFNCMaps1.ExecuteJavaScript(‘document.getElementById(“customZoom1″).innerText = ‘ + FloatToStrDot(Round(AZoomLevel))); end; The custom control is now ready to be used. The Styling Using Bootstrap is a straightforward way to improve the visuals of HTML elements. With a few adjustments Bootstrap styling can be added to ElementContainers. Include the Bootstrap CSS library via the HeadLinks collection.Add an item to the HeadLinks collection; set Kind to mlkLink, URL to “https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css” and Rel to “stylesheet”. Add Bootstrap HTML classes to the ElementContainer’s HTML. Change the HTML value to: Zoom Level 12 Then set HTMLElementClassName to “card” and UseDefaulStyle to “False”. Suddenly the custom control looks a lot prettier. Notice that the ElementContainer’s content with Bootstrap styling is fully visible at design-time as well. Because ElementContainers are completely independent from the mapping service, the result looks exactly the same even when switching to a different service. The screenshot below shows the same ElementContainer with Service set to msHere. The Code Of course, the same result can also be achieved in code. procedure TForm1.FormCreate(Sender: TObject); var ElementContainer: TTMSFNCMapsElementContainer; ElementAction: TTMSFNCMapsElementAction; html: TStringList; begin TMSFNCMaps1.ClearElementContainers; TMSFNCMaps1.ClearHeadLinks; TMSFNCMaps1.BeginUpdate; TMSFNCMaps1.AddHeadLink(‘https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css’, mlkLink, ‘stylesheet’); html := TStringList.Create; html.Add(” + ‘Zoom Level ‘ + ’12’ +’ ‘ +’ ‘ +’ ‘ +”); ElementContainer := TMSFNCMaps1.AddElementContainer(html); ElementContainer.HTMLElementClassName := ‘card’; ElementContainer.Position := poBottomRight; ElementContainer.Margins.Bottom := 15; ElementContainer.UseDefaultStyle := False; ElementAction := ElementContainer.AddAction(‘customRange1’, heCustom); ElementAction.CustomEvent := ‘input’; […]

Read More

FNC Physics Components in TMS Analytics & Physics 3.3

TMS Analytics & Physics library is a set of classes that provide functionality for building powerful math and engineering applications with Delphi IDE. In the new version 3.3 of the library, we introduced special FNC physics components to take advantage of Delphi’s rapid application development. In this article, we’ll consider the base concepts of the FNC physics components and provide information on how to work with units of measurement.  Let’s consider the following FNC physics components: TFNCUnitProvider – creates a physics environment for the application; contains information about registered physics entities and provides units of measurement to other physics components. TFNCUnitConverter – provides properties and functionality to convert physical values measured in two different units. To begin an FNC physics application we first need to put a TFNCUnitProvider component on the form. The component has the following published properties: Quantities (TQuantityCollection) – a collection of registered physical quantities. Prefixes (TPrefixCollection) – a collection of registered prefixes that can be used to create units with multiplier factors (like kilo-, milli-, and so on). Units (TUnitCollection) – a collection of registered units of measurement that can be used to create complicated derived units. When you put a TFNCUnitProvider on the form in design-time, it automatically finds all registered quantities, prefixes, and units. The collections of these items are not editable, they only provide information about available physical entities. When an item is selected in a collection, its properties are shown in the Object Inspector. In the picture below, you can see a collection of physical quantities:   Any quantity has the following properties: Name (string) – the name of the quantity. Symbol (string) – a common symbol for the quantity designation. Dimension (string) – physical dimension of the quantity. As an example, we showed the ‘Area’ quantity. Its physical dimension is ‘L^2’ – squared length. More information about physical dimensions can be found in the documentation for the library. Analogously, you can view information about all registered unit prefixes, as shown in the picture below.   A prefix provides the following properties: Name (string) – the name of the prefix. Symbol (string) – symbol, identifying the prefix in composite units. Value (real) – the multiplier factor of the prefix. And finally, you can view all available units of measurements.   Any unit provides the following properties: Name (string) – the name of the unit. Symbol (string) – the symbol of the unit that is used to identify this unit for conversion algorithm and other manipulations. Dimension (string) – physical dimension of the unit. The unit provider component supplies the physical entities to other components, for example, to the TFNCUnitConverter. This component is intended to convert physical values measured in two different units and has the following properties: Provider (TFNCUnitProvider) – a unit provider. Unit1 (TUnitProperty) – the first unit of measurement for conversion. Unit2 (TUnitProperty) – the second unit of measurement for conversion. Value1 (real) – the first value, measured in the first unit of measurement. Value2 (real) – the second value, measured in the second unit of measurement. Valid (boolean) – read-only value defining if all input items are valid for conversion. Error (string) – read-only text of an error that occurred during conversion. IntervalConversion (boolean) – defines if making the interval conversion or not. First of all, you need to […]

Read More

PDF generation with complex graphics in Delphi

Intro TMS FNC Core is the core foundation of FNC. It offers a solid structure for the other FNC component sets such as TMS FNC UI Pack and TMS FNC Maps. In the past, we have demonstrated the capabilities of TMS FNC Core in various ways. Below are a couple of links to blog posts about functionality available in TMS FNC Core. A browser, JSON persistence, printing, SVG support and many more. Today I want to focus on another “hidden gem”: PDF generation and in particular focusing on drawing complex graphics. Basic drawing  Before going to complex drawing statements, we need to take a look at the basics. Generating a PDF starts by specifying a file name, adding the first page, and then the PDF context is ready to be accessed via the Graphics property. In the sample below, we draw a simple rectangle by setting the properties of the fill & stroke and by calling p.Graphics.DrawRectangle. uses   FMX.TMSFNCPDFLib, FMX.TMSFNCGraphicsTypes; procedure TPDFGenerationForm.GeneratePDF; var   p: TTMSFNCPDFLib; begin   p := TTMSFNCPDFLib.Create;   try     p.BeginDocument(‘MyPDF.pdf’);     p.NewPage;     p.Graphics.Fill.Color := gcYellowgreen;     p.Graphics.Stroke.Color := gcGreen;     p.Graphics.Stroke.Width := 4;     p.Graphics.DrawRectangle(RectF(100, 100, 300, 300));     p.EndDocument(True);   finally     p.Free;   end; end; This generates the following PDF The basic ITMSFNCCustomPDFGraphicsLib interface (p.Graphics property) exposes a lot of basic drawing calls to draw shapes constructed out of simple primitives or more complex paths. On top of that, it’s possible to export images as well. Using these calls gives you the flexibility to enhance your PDF with vector sharp graphics. The way this needs to be done is by calling each draw statement in a specific order. See this sample below to draw a bezier curve. uses   FMX.TMSFNCPDFLib, FMX.TMSFNCGraphicsTypes, FMX.TMSFNCPDFCoreLibBase; procedure TPDFGenerationForm.GeneratePDF; var   p: TTMSFNCPDFLib; begin   p := TTMSFNCPDFLib.Create;   try     p.BeginDocument(‘MyPDF.pdf’);     p.NewPage; p.Graphics.Stroke.Color := gcDarkseagreen; p.Graphics.Stroke.Width := 3; p.Graphics.Stroke.Kind := gskSolid; p.Graphics.DrawPathBegin; p.Graphics.DrawPathMoveToPoint(PointF(350, 40)); p.Graphics.DrawPathAddCurveToPoint(PointF(310, 130), PointF(445, 50), PointF(398, 115)); p.Graphics.DrawPathEnd(dmPathStroke); p.Graphics.Stroke.Width := 0.5; p.Graphics.Stroke.Color := gcBlack; p.Graphics.Fill.Color := gcNull; p.Graphics.Fill.Kind := gfkSolid; p.Graphics.DrawLine(PointF(350, 40), PointF(310, 130)); p.Graphics.DrawLine(PointF(445, 50), PointF(398, 115)); p.Graphics.DrawRectangle(RectF(442.5, 47.5, 447.5, 52.5)); p.Graphics.DrawRectangle(RectF(395.5, 50 + 62.5, 400.5, 50 + 67.5)); p.Graphics.DrawRectangle(RectF(347.5, 50 – 12.5, 352.5, 50 – 7.5)); p.Graphics.DrawRectangle(RectF(307.5, 127.5, 312.5, 132.5));     p.EndDocument(True);   finally     p.Free;   end; end; The result of the above code is a bezier curve with lines and handles mimicking interaction. Mapping FNC Core graphics onto PDF graphics After the initial release, we had some requests on exporting FNC components to PDF. The PDF graphics layer was too limited to export components to PDF, therefore we have created the TTMSFNCGraphicsPDFEngine class, which decends from TTMSFNCGraphics, the core class for all FNC cross-platform drawing. On top of the default PDF graphics, the TTMSFNCGraphicsPDFEngine gives you complex paths, matrix transforms as well as various flexible image drawing options. Together with SVG support we can then load the SVG as a resource and draw the information as vector graphics inside the PDF. Internally, the SVG is parsed, elements are transformed to FNC graphics paths and with that information the PDF graphics engine draws renders the SVG onto the PDF canvas, via the earlier mentioned drawing calls. All in a couple of lines. uses   FMX.TMSFNCPDFLib, FMX.TMSFNCGraphicsTypes,   FMX.TMSFNCGraphicsPDFEngine, FMX.TMSFNCTypes; procedure TPDFGenerationForm.GeneratePDF; var   p: TTMSFNCPDFLib;   g: TTMSFNCGraphicsPDFEngine;   bmp: TTMSFNCBitmap; begin […]

Read More