Sign in Join
Wiki copytemporary

fpvectorial: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: fpvectorial

OldNewLine
1+## Introduction
2+
3+FPVectorial offers support to read, modify and write vectorial images.
4+
5+Its counterpart library is [[fcl-image]], which works with raster images. FPVectorial comes with a unit which allows to draw a vectorial image to a TFPCustomCanvas, but no routines are provided to convert raster images to vectorial images.
6+
7+## Download
8+
9+fpvectorial is distributed along with Lazarus. You can find it in folder *components/fpvectorial* of your Lazarus installation.
10+
11+If you have a release version of Lazarus and want the latest version of fpvectorial you can download it by svn from
12+
13+`svn co `[`http://svn.freepascal.org/svn/lazarus/trunk/components/fpvectorial`](http://svn.freepascal.org/svn/lazarus/trunk/components/fpvectorial)` fpvectorial`
14+
15+Downloading the fpvviewer project:
16+
17+`svn co `[`https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/fpvviewer`](https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/fpvviewer)` fpvviewer`
18+
19+## Current file list
20+
21+FPVectorial is located in the Lazarus directory *components/fpvectorial*.
22+
23+The central unit is *[[doc:fcl/fpvectorial|fpvectorial]]*.
24+
25+**Readers for various image formats**
26+
27+- **pdfvectorialreader** - Read support for PDF files, supports compression, only reads the first page
28+- **avisocncgcodereader** - Read support for the G-Code from the Aviso CNC machine
29+- **cdrvectorialreader** - Initial work of a reader support for Corel Draw CDR files
30+- **dxfvectorialreader** - Read support for DXF, the Drawing eXchange Format utilized by the AutoCAD
31+- **svgvectorialreader** - Read support for SVG
32+- **epsvectorialreader** - Read support for Encapsulated PostScript
33+- **wmfvectorialreader** - Read support for WMF (Windows metafile, cross-platform!)
34+
35+**Writers for various image formats**
36+
37+- **avisocncgcodewriter** - Write support for the G-Code from the Aviso CNC machine
38+- **svgvectorialwriter** - Write support for SVG. The most advanced writer at the moment. Supports lines, curves and text. Supports pen color and width.
39+
40+**Other units**
41+
42+- **fpvtocanvas** - Converts a vectorial document to a TFPCustomCanvas descendent (like TCanvas). Essentially converts the vectorial image to a raster image
43+- **fpvutils** - Utility functions which don't belong to fpvectorial.pas or that would bring unwanted dependencies to it. Color conversion functions.
44+- **pdfvrlexico**, **pdfvrsemantico**, **pdfvrsintatico**, **avisozlib** - Other units from the PDF reader, don't use directly
45+
46+## Formats
47+
48+### PDF
49+
50+The PDF format is developed by Adobe (tm) and it is fully documented. Inside, PDF is simply text, so it is rather easy to parse, but parts of this text are usually can be compressed.
51+
52+Link to the PDF Reference: <http://www.adobe.com/devnet/pdf/pdf_reference.html>
53+
54+### CorelDraw
55+
56+Corel does not release public documentation for its CorelDraw file format. Any information about this format depends on reverse engineering and guessing. The format is binary and consists of a tree of chunks.
57+
58+See also [[fpvectorial|fpvectorial#fpcorelexplorer]]
59+
60+### SVG
61+
62+Scalable Vectorial Graphics (SVG) is a standard from W3C for vectorial graphics. It is the native format of Inkscape and stores its data as a single, uncompressed XML file with the extension ".svg".
63+
64+Link to the specification: <http://www.w3.org/TR/SVG/>
65+
66+A very serious shortcoming in SVG is that it does not allow real world units to be specified in the drawing routines, only pixel values accepted, which makes it impossible to have a document with real world units. This can be worked around by simply hardcoding to a fixed DPI resolution, which is 90 DPI for Inkscape. Read more here:
67+
68+- <http://stackoverflow.com/questions/1346922/svg-and-dpi-absolute-units-and-user-units-inkscape-vs-firefox-vs-imagemagick>
69+- <http://www.inkscapeforum.com/viewtopic.php?f=16&t=5904>
70+- <http://www.inkscapeforum.com/viewtopic.php?f=16&t=3700&p=17179&hilit=units+path#p17179>
71+
72+Following Inkscape and the Opera Browser, FPVectorial also hardcodes to 90 DPI.
73+
74+As of February 2014 support for SVG is partial.
75+
76+### DXF
77+
78+The Drawing eXchange Format from Autodesk AutoCAD. This format is documented, but the quality of the documentation is rather low, lacking adequate explanations.
79+
80+The format itself is rather simple, composed by text. Each unit is composed of two lines, the first one being a number describing the type of data and then another line with the value itself, which might be text or a number.
81+
82+The most common problem in other DXF reading libraries is that they don't support the actual DXF writen by newer versions of AutoCAD. This is not the case with fpvectorial, which was tested with AutoCAD 2000 and also the previous simpler formats.
83+
84+Link to the documentation:
85+
86+- <http://www.autodesk.com/techpubs/autocad/acad2000/dxf/>
87+
88+The software fpvviewer can be utilized to show the internal structure of a DXF file. This software can be found in the lazarus-ccr svn in applications/fpvviewer. More info here: [[fpvectorial|fpvectorial#fpvviewer]]
89+
90+### WMF
91+
92+The Windows Metafile (WMF) format was originally designed for Microsoft Windows in the 1990s. The files can contain both vector graphics and bitmap components and consist of a list of drawing commands with parameters which are originally passed directly to the Windows Graphics Device Interface (GDI); in fpvectorial, however, they are converted to graphics objects which makes the format platform-independent.
93+
94+The file structure is documented at <http://msdn.microsoft.com/en-us/library/cc250370.aspx>
95+
96+### PostScript
97+
98+PostScript is a graphics drawing programming language and fpvectorial has an interpreter which can execute PostScript and convert its commands into its internal format. This is done by reader modules, for example epsvectorialreader. The interpreter is separated into a Tokenizer and an Executer. The tokens are classified into 3 types: Procedures, ExpressionTokens and Comments. Procedures are inside a {..} block in PostScript and in FPVectorial they are not tokenezed in the first pass, but instead on the first usage. The entire document is tokenized in one run, before executing the tokens, except for the procedures. The PostScript interpreter contains a Stack and a lookup Dictionary, as specified in PostScript.
99+
100+PostScript can be embedded into various formats, and the interpreter currently supports the EPS format.
101+
102+**References**:
103+
104+- <http://en.wikipedia.org/wiki/Encapsulated_PostScript>
105+- <http://partners.adobe.com/public/developer/en/ps/PLRM.pdf>
106+
107+### LAS
108+
109+LAS is geospatial data encoded in the ASPRS LASer (LAS) file format, which exists in versions 1.0, 1.1, 1.2, 1.3 and 1.4. Version 2.0 does not yet exist as of December 2011.
110+
111+**References**:
112+
113+- <http://en.wikipedia.org/wiki/LibLAS>
114+- <http://www.asprs.org/a/society/committees/lidar/lidar_format.html>
115+- <http://trac.liblas.org/wiki/Software>
116+- <http://www.cs.unc.edu/~isenburg/lastools/>
117+- <http://www.fugroviewer.com/>
118+- Example las file: www.appliedimagery.com/downloads/sampledata/Serpent%20Mound%20Model%20LAS%20Data.las
119+- Specification docs up to 1.3: <http://www.asprs.org/a/society/committees/standards/lidar_exchange_format.html>
120+- Specification for 1.4: <http://www.asprs.org/Press-Releases/LAS-1-4-Draft-Specification-Released-by-ASPRS.html>
121+
122+## Types of data in FPVectorial
123+
124+FPVectorial holds lists of three types of objects: paths, text and entities.
125+
126+Essentially paths are sequences of points, through which run lines and bezier curves. A path can be a line, a bezier, a polyline, a polybezier or any combination of these elements. The main characteristic of paths is that they can be utilized to guide a milling machine, also known as CNC machine, into physically executing the drawing. Before being able to execute a drawing which contains either text or entities in a CNC machine, these items need to be converted to paths.
127+
128+Text, just like the name says are strings drawn with fonts.
129+
130+Entities are things like circles, arcs, ellipses, rotated ellipses, etc.
131+
132+## Usage examples
133+
134+### Format conversion
135+
136+This example loads a PDF, converts it to G-Code and writes the G-Code to a TStrings descendent
137+
138+``` pascal
139+uses
140+ fpvectorial, pdfvectorialreader, avisocncgcodewriter;
141+
142+var
143+ Vec: TvVectorialDocument;
144+begin
145+ if dialogoAbrir.Execute() then
146+ begin
147+ Vec := TvVectorialDocument.Create;
148+ try
149+ Vec.ReadFromFile(dialogoAbrir.FileName, vfPDF);
150+ Vec.WriteToStrings(synCodigo.Lines, vfGCodeAvisoCNCPrototipoV5);
151+ finally
152+ Vec.Free;
153+ end;
154+ end;
155+end;
156+```
157+
158+### Adding paths, bezier lines and text
159+
160+This example shows how to add various elements.
161+
162+``` pascal
163+{
164+Author: Felipe Monteiro de Carvalho
165+
166+License: Public Domain
167+}
168+program fpvwritetest;
169+
170+{$mode objfpc}{$H+}
171+
172+uses
173+ fpvectorial, svgvectorialwriter;
174+
175+const
176+ cFormat = vfSVG;
177+ cExtension = '.svg';
178+var
179+ VecDoc: TvVectorialDocument;
180+ Vec: TvVectorialPage;
181+ s : String;
182+begin
183+ VecDoc := TvVectorialDocument.Create;
184+ try
185+ // All documents are 10cm x 10cm
186+ VecDoc.Width := 100;
187+ VecDoc.Height := 100;
188+
189+ Vec := VecDoc.AddPage();
190+ Vec.Width := VecDoc.Width;
191+ Vec.Height := VecDoc.Height;
192+
193+ // ...
194+
195+ // multi_test_1 Combines various elements
196+ Vec.Clear;
197+ Vec.StartPath(0, 20);
198+ Vec.AddLineToPath(30, 30);
199+ Vec.EndPath();
200+ Vec.StartPath(0, 0);
201+ Vec.AddLineToPath(100, 0);
202+ Vec.AddLineToPath(100, 100);
203+ Vec.AddLineToPath(0, 100);
204+ Vec.AddLineToPath(0, 0);
205+ Vec.EndPath();
206+ Vec.StartPath(0, 0);
207+ Vec.AddLineToPath(10, 10);
208+ Vec.AddBezierToPath(10, 20, 20, 20, 20, 10);
209+ Vec.AddLineToPath(30, 0);
210+ Vec.EndPath();
211+ Vec.AddText(10, 10, 0, '10,10 Some text in english.');
212+ s := '20, 20 Mówić, cześć, Włosku, Parabéns.';
213+ Vec.AddText(20, 20, 0, s);
214+ s := '30, 30 森林,是一个高密';
215+ Vec.AddText(30, 30, 0, s);
216+ VecDoc.WriteToFile('multi_test_1' + cExtension, cFormat);
217+ finally
218+ VecDoc.Free;
219+ end;
220+end.
221+```
222+
223+And here is the output of this example when rendered by the Opera Browser:
224+
225+![](/wiki-images/9/92/Fpvectorial_svg_output.PNG)
226+
227+### Adding Aligned Coordinates
228+
229+One can either add horizontal coordinates:
230+
231+``` pascal
232+Vec.AddAlignedDimension(Make2DPoint(100, 50), Make2DPoint(200, 100), Make2DPoint(100, 150), Make2DPoint(200, 150));
233+```
234+
235+![](/wiki-images/0/05/Aligned_dimension_horizontal.png)
236+
237+Or add vertical coordinates:
238+
239+``` pascal
240+Vec.AddAlignedDimension(Make2DPoint(50, 250), Make2DPoint(100, 200), Make2DPoint(150, 250), Make2DPoint(150, 200));
241+```
242+
243+![](/wiki-images/6/68/Aligned_dimension_vertical.png)
244+
245+### Rendering the image into a TCanvas
246+
247+To render a vectorial image into a TCanvas or TFPCustomCanvas use the unit fpvtocanvas and its routines:
248+
249+``` pascal
250+unit fpvtocanvas;
251+//..
252+{@@
253+ This function draws a FPVectorial vectorial image to a TFPCustomCanvas
254+ descendent, such as TCanvas from the LCL.
255+
256+ Be careful that by default this routine does not execute coordinate transformations,
257+ and that FPVectorial works with a start point in the bottom-left corner, with
258+ the X growing to the right and the Y growing to the top. This will result in
259+ an image in TFPCustomCanvas mirrored in the Y axis in relation with the document
260+ as seen in a PDF viewer, for example. This can be easily changed with the
261+ provided parameters. To have the standard view of an image viewer one could
262+ use this function like this:
263+
264+ DrawFPVectorialToCanvas(ASource, ADest, 0, ASource.Height, 1.0, -1.0);
265+}
266+procedure DrawFPVectorialToCanvas(ASource: TvVectorialPage;
267+ ADest: TFPCustomCanvas;
268+ ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0);
269+```
270+
271+And below an example taken from lazarus-ccr/application/fpvviewer
272+
273+``` pascal
274+uses fpvtocanvas;
275+
276+procedure TfrmFPVViewer.btnVisualizeClick(Sender: TObject);
277+const
278+ FPVVIEWER_MAX_IMAGE_SIZE = 1000;
279+ FPVVIEWER_MIN_IMAGE_SIZE = 100;
280+ FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS = 100;
281+var
282+ Vec: TvVectorialDocument;
283+ CanvasSize: TPoint;
284+begin
285+ // First check the in input
286+ //if not CheckInput() then Exit;
287+
288+ notebook.PageIndex := 0;
289+
290+ Drawer.Clear;
291+
292+ Vec := TvVectorialDocument.Create;
293+ try
294+ Vec.ReadFromFile(editFileName.FileName);
295+
296+ // We need to be robust, because sometimes the document size won't be given
297+ // also give up drawing everything if we need more then 4MB of RAM for the image
298+ // and also give some space in the image to allow for negative coordinates
299+ if Vec.Width * spinScale.Value > FPVVIEWER_MAX_IMAGE_SIZE then CanvasSize.X := FPVVIEWER_MAX_IMAGE_SIZE
300+ else if Vec.Width < FPVVIEWER_MIN_IMAGE_SIZE then CanvasSize.X := Drawer.Width
301+ else CanvasSize.X := Round(Vec.Width * spinScale.Value);
302+ if CanvasSize.X < Drawer.Width then CanvasSize.X := Drawer.Width;
303+
304+ if Vec.Height * spinScale.Value > FPVVIEWER_MAX_IMAGE_SIZE then CanvasSize.Y := FPVVIEWER_MAX_IMAGE_SIZE
305+ else if Vec.Height < FPVVIEWER_MIN_IMAGE_SIZE then CanvasSize.Y := Drawer.Height
306+ else CanvasSize.Y := Round(Vec.Height * spinScale.Value);
307+ if CanvasSize.Y < Drawer.Height then CanvasSize.Y := Drawer.Height;
308+
309+ Drawer.Drawing.Width := CanvasSize.X;
310+ Drawer.Drawing.Height := CanvasSize.Y;
311+ Drawer.Drawing.Canvas.Brush.Color := clWhite;
312+ Drawer.Drawing.Canvas.Brush.Style := bsSolid;
313+ Drawer.Drawing.Canvas.FillRect(0, 0, Drawer.Drawing.Width, Drawer.Drawing.Height);
314+ DrawFPVectorialToCanvas(
315+ Vec.GetPage(0),
316+ Drawer.Drawing.Canvas,
317+ FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS,
318+ Drawer.Drawing.Height - FPVVIEWER_SPACE_FOR_NEGATIVE_COORDS,
319+ spinScale.Value,
320+ -1 * spinScale.Value);
321+ Drawer.Invalidate;
322+ finally
323+ Vec.Free;
324+ end;
325+end;
326+```
327+
328+### Coordinates in FPVectorial
329+
330+It is important to note that FPVectorial works with two different systems of coordinates: Top-Left Coordinates and Bottom-Left Coordinates. TCanvas uses the coordinates from the Windows API, with the origin in the top-left corner and with the X axis growing to the right and the Y axis growing to the bottom. FPVectorial, besides supporting this system, also supports another one for drawing formats where this system is native such as CAD software, Inkscape, the Mac OS X APIs (Carbon and Cocoa), etc. In FPVectorial the origin is in bottom-left for all vectorial graphics formats except SVG. The X axis grows to the right and the Y axis to the top. The origin is in the top-left for SVG and all text document formats such as DOCX.
331+
332+![](/wiki-images/a/a1/Fpvectorial_coords.png)
333+
334+When the coordinates do not match TCanvas, one should be careful when converting coordinates between TCanvas and FPVectorial. To convert coordinates between TCanvas and FPVectorial, one needs the height of the Canvas. The following routine from the unit **fpvutils** can be used to execute this conversion:
335+
336+``` pascal
337+{@@ Converts the coordinate system from a TCanvas to FPVectorial
338+ The basic difference is that the Y axis is positioned differently and
339+ points upwards in FPVectorial and downwards in TCanvas.
340+ The X axis doesn't change. The fix is trivial and requires only the Height of
341+ the Canvas as extra info.
342+}
343+function CanvasCoordsToFPVectorial(AY: Integer; AHeight: Integer):
344+Integer; inline;
345+begin
346+ Result := AHeight - AY;
347+end;
348+```
349+
350+And there is also a difference regarding the text positioning. In TCanvas.TextOut the text is positioned based on the top-left coordinates of the text area. In fpvectorial it is based on the bottom-left. Again, there is a convenient routine in the unit **fpvutils** to convert between the coordinate systems:
351+
352+``` pascal
353+{@@
354+ LCL Text is positioned based on the top-left corner of the text.
355+ Besides that, one also needs to take the general coordinate change into account too.
356+
357+ @param ACanvasHeight Should receive TCanvas.Height
358+ @param ATextHeight Should receive TFont.Size
359+}
360+function CanvasTextPosToFPVectorial(AY: Integer; ACanvasHeight, ATextHeight: Integer): Integer;
361+begin
362+ Result := CanvasCoordsToFPVectorial(AY, ACanvasHeight) - ATextHeight;
363+end;
364+```
365+
366+### More examples
367+
368+Since fpvectorial is part of the Lazarus distribution, you can find the examples in the folder *components/fpvectorial/examples* of your Lazarus directory.
369+
370+## fpvviewer
371+
372+The Free Pascal Vectorial Viewer is a sample application which implements a simple CAD viewer using fpvectorial.
373+
374+Besides being able to visualize vectorial drawings, this software can also help in exploring the internal structure of DXF file:
375+
376+![](/wiki-images/3/3d/Fpvviewer_EPS.png)![](/wiki-images/7/74/Fpvviewer.png)
377+
378+Its source code can be found in the Lazarus-CCR in the directory application/fpvviewer
379+
380+Link to download the zipped source snapshot of this application: <https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/applications/fpvviewer/>
381+
382+Link to download the entire Lazarus-CCR repository from subversion:
383+
384+`svn co `[`https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr`](https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr)` lazarus-ccr`
385+
386+### Contour line generation
387+
388+fpvviewer can generate contour lines from .raw files. These files can be generated with fpv3dviewer
389+
390+![](/wiki-images/c/cf/Contourlines_las.PNG)
391+
392+![](/wiki-images/5/57/Contourlines_regular.PNG)
393+
394+### FPVectorial Debug Tokens
395+
396+FPVViewer can be utilized to see the internal debug tokens from fpvectorial, see:
397+
398+![](/wiki-images/a/ae/Fpvectorial_debug_tokens.png)
399+
400+## fpcorelexplorer
401+
402+An application was developed for helping studying the CDR file format. At the moment this application can identify the version of CorelDraw files. It is located in fpctrunk/packages/fpvectorial/examples/fpcorelexplorer.lpi
403+
404+![](/wiki-images/c/cd/Fpcorelexplorer.png)
405+
406+## fpv3dviewer
407+
408+One of the examples of fpvectorial located in lazarus/components/fpvectorial/examples/fpv3dviewer.lpi is a 3D viewer.
409+
410+![](/wiki-images/1/1f/FPV3DViewer.png)
411+
412+## Articles about fpvectorial
413+
414+- Revista Clube Delphi Edition \#131: <http://www.devmedia.com.br/assgold/listmag.asp?site=3>
415+
416+Go to back [[Package List|Packages List]]
417+
418+---
419+*From the Free Pascal wiki, page "fpvectorial", as it stood on 2024-05-09 after a change by EkkehardDomning, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
420+Category: Data import and export
421+Category: FPVectorial
422+Category: Graphics
423+Category: Lazarus-CCR
424+Category: Packages

Back to history