lazarus/components/fpvectorial/tests/vtmain.pas
2016-09-01 17:30:47 +00:00

1234 lines
44 KiB
ObjectPascal

{ Current issues:
- Radial gradient not rendered correctly (position, colors), saving to svg ok.
- Save polygon to svg empty
- Nonzero/even-odd winding rule not working
}
unit vtmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls, ComCtrls, EditBtn, fpimage, fpvectorial, Types;
type
TRenderEvent = procedure(APage: TvVectorialPage;
AIntParam: Integer = MaxInt) of object;
TRenderParams = class
RefFile: String;
IntParam: Integer;
OnRender: TRenderEvent;
constructor Create(ARenderEvent: TRenderEvent; ARefFilename: String;
AIntParam: Integer = MaxInt);
end;
TRenderCoords = (rcBottomLeftCoords, rcTopLeftCoords);
{ TMainForm }
TMainForm = class(TForm)
BtnSaveAsRef: TButton;
BtnSaveToFiles: TButton;
BtnViewBottomLeft: TButton;
BtnViewTopLeft: TButton;
CbFileFormat: TComboBox;
gbWRBottomLeft: TGroupBox;
gbRenderTest: TGroupBox;
gbBottomLeft: TGroupBox;
gbWRTopLeft: TGroupBox;
gbTopLeft: TGroupBox;
gbReferenceImageTest: TGroupBox;
GroupBox1: TGroupBox;
gbReadWriteTest: TGroupBox;
GbTree: TGroupBox;
Label1: TLabel;
Label14: TLabel;
LblBothImagesMustMatch1: TLabel;
RefImage: TImage;
Label10: TLabel;
Label11: TLabel;
Label13: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
LblBothImagesMustMatch: TLabel;
LblRefImgMustMatch: TLabel;
LblReadWriteInstructions: TLabel;
BottomLeftPaintbox: TPaintBox;
ScrollBox1: TScrollBox;
WRTopLeftPaintbox: TPaintBox;
TopLeftPaintbox: TPaintBox;
WRBottomLeftPaintbox: TPaintBox;
AllTestsPanel: TPanel;
Tree: TTreeView;
procedure BtnSaveToFilesClick(Sender: TObject);
procedure BtnSaveAsRefClick(Sender: TObject);
procedure BtnViewImageClick(Sender: TObject);
procedure CbFileFormatChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure PaintBoxPaint(Sender: TObject);
procedure TreeCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
procedure TreeSelectionChanged(Sender: TObject);
private
{ private declarations }
FDoc: array[TRenderCoords] of TvVectorialDocument;
FDocFromWMF: array[TRenderCoords] of TvVectorialDocument;
FDocFromSVG: array[TRenderCoords] of TvVectorialDocument;
function GetFileFormat: TvVectorialFormat;
function GetFileFormatExt: String;
procedure Populate;
procedure PrepareDoc(var ADoc: TvVectorialDocument; var APage: TvVectorialPage;
AUseTopLeftCoords: boolean);
procedure ReadIni;
procedure ShowFileImage(AFilename: String; AUseTopLeftCoords: Boolean;
APaintbox: TPaintbox);
procedure ShowRefImageTest;
procedure ShowRenderTestImages;
procedure ShowWriteReadTestImages;
procedure UpdateCmdStates;
procedure WriteIni;
// Simple shapes, solid fills and gradients
procedure Render_Shape(APage: TvVectorialPage; AIntParam: Integer);
// Complex shapes
procedure Render_Path_Hole_SolidFill(APage: TvVectorialPage;
AIntParam: Integer);
procedure Render_Path_Hole_GradientFill(APage: TvVectorialPage;
AIntParam: Integer);
procedure Render_SelfIntersectingPoly_SolidFill_EvenOdd(APage: TvVectorialPage;
AIntParam: Integer);
procedure Render_SelfIntersectingPoly_GradientFill_EvenOdd(APage: TvVectorialPage;
AIntParam: Integer);
procedure Render_SelfIntersectingPoly_SolidFill_NonZeroWinding(APage: TvVectorialPage;
AIntParam: Integer);
procedure Render_SelfIntersectingPoly_GradientFill_NonZeroWinding(APage: TvVectorialPage;
AIntParam: Integer);
// Arcs
procedure Render_Arc(APage: TvVectorialPage; AIntParam: Integer);
// Bezier
procedure Render_Bezier(Apage: TvVectorialPage; AIntParam: Integer);
// Text
procedure Render_Text(APage: TvVectorialpage; AIntParam: Integer);
procedure Render_Text_Fonts(APage: TvVectorialPage; AIntParam: Integer);
procedure Render_Text_Colors(APage: TvVectorialPage; AIntParam: Integer);
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.lfm}
uses
Math, FPCanvas, IniFiles, LazFileUtils, LCLIntf,
fpvutils, vtprimitives;
const
IMG_FOLDER = 'images' + PathDelim;
NOT_SAVED = '(not saved)';
{ TRenderParams }
constructor TRenderParams.Create(ARenderEvent: TRenderEvent;
ARefFilename: String; AIntParam: Integer = MaxInt);
begin
OnRender := ARenderEvent;
RefFile := ARefFileName;
IntParam := AIntParam;
end;
{ TMainForm }
procedure TMainForm.BtnSaveAsRefClick(Sender: TObject);
var
bmp: TBitmap;
png: TPortableNetworkGraphic;
fn: String;
renderParams: TRenderParams;
page: TvVectorialPage;
begin
renderParams := TRenderParams(Tree.Selected.Data);
if RenderParams = nil then
exit;
if FDoc[rcBottomLeftCoords] = nil then
exit;
page := FDoc[rcBottomLeftCoords].GetPageAsVectorial(0);
bmp := TBitmap.Create;
try
bmp.SetSize(BottomLeftPaintbox.Width, BottomLeftPaintbox.Height);
bmp.Canvas.GetUpdatedHandle([csHandleValid]); // create the Handle needed by next line
page.DrawBackground(bmp.Canvas);
// bmp canvas has origin at top/left
page.Render(bmp.Canvas, 0, bmp.Height, 1.0, -1.0);
png := TPortableNetworkGraphic.Create;
try
png.Assign(bmp);
// renderParams := TRenderParams(Tree.Selected.Data);
ForceDirectory(IMG_FOLDER);
fn := IncludeTrailingPathDelimiter(IMG_FOLDER) + renderParams.RefFile;
png.SaveToFile(fn);
finally
png.Free;
end;
RefImage.Picture.Assign(bmp);
RefImage.Hint := fn;
finally
bmp.Free;
end;
end;
procedure TMainForm.BtnSaveToFilesClick(Sender: TObject);
var
fn: String;
renderParams: TRenderParams;
folder: String;
fmt: TvVectorialFormat;
ext: String;
begin
renderParams := TRenderParams(Tree.Selected.Data);
if RenderParams = nil then
exit;
fmt := GetFileFormat;
ext := GetFileFormatExt;
folder := IMG_FOLDER + ext + PathDelim;
ForceDirectory(folder);
if FDoc[rcBottomLeftCoords] <> nil then begin
fn := folder + 'bl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
FDoc[rcBottomLeftCoords].WriteToFile(fn, fmt);
ShowFileImage(fn, false, WRBottomLeftPaintbox);
end;
if FDoc[rcTopLeftCoords] <> nil then begin
fn := folder + 'tl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
FDoc[rcTopLeftCoords].WriteToFile(fn, fmt);
ShowFileImage(fn, true, WRTopLeftPaintbox);
end;
UpdateCmdStates;
end;
procedure TMainForm.BtnViewImageClick(Sender: TObject);
var
fn: String;
ext: String;
folder: String;
renderParams: TRenderParams;
begin
BtnSaveToFilesClick(nil);
renderParams := TRenderParams(Tree.Selected.Data);
if renderParams = nil then
exit;
ext := GetFileFormatExt;
folder := IMG_FOLDER + ext + PathDelim;
if Sender = BtnViewBottomLeft then
fn := folder + 'bl_' + ChangeFileExt(renderParams.RefFile, '.' + ext)
else if Sender = BtnViewTopLeft then
fn := folder + 'tl_' + ChangeFileExt(renderParams.RefFile, '.' + ext)
else
raise Exception.Create('BtnViewImageClick: this sender is not supported.');
if FileExists(fn) then
OpenDocument(fn);
end;
procedure TMainForm.CbFileFormatChange(Sender: TObject);
begin
ShowWriteReadTestImages;
UpdateCmdStates;
end;
procedure TMainForm.PrepareDoc(var ADoc: TvVectorialDocument;
var APage: TvVectorialPage; AUseTopLeftCoords: boolean);
var
r: TvRectangle;
begin
FreeAndNil(ADoc);
ADoc := TvVectorialDocument.Create;
APage := ADoc.AddPage;
APage.BackgroundColor := colWhite;
APage.Width := PAGE_SIZE;
APage.Height := PAGE_SIZE;
ADoc.Width := PAGE_SIZE;
ADoc.Height := PAGE_SIZE;
APage.UseTopLeftCoordinates := AUseTopLeftCoords;
// Add a frame around the page
r := TvRectangle.Create(APage);
r.X := 0;
if AUseTopLeftCoords then
r.Y := 0
else
r.Y := APage.Height;
r.CX := APage.Width - 1;
r.CY := APage.Height - 1;
r.Brush := CreateSimpleBrush(bsClear);
r.Pen := CreatePen(psSolid, 1, colSilver);
APage.AddEntity(r);
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
RefImage.Hint := NOT_SAVED;
WRBottomLeftPaintbox.Hint := NOT_SAVED;
WRTopLeftPaintbox.Hint := NOT_SAVED;
ReadIni;
Populate;
TreeSelectionChanged(nil);
end;
procedure TMainForm.FormDestroy(Sender: TObject);
var
parentnode, node: TTreeNode;
rc: TRenderCoords;
begin
parentnode := Tree.Items.GetFirstNode;
while parentnode <> nil do begin
node := parentnode.GetFirstChild;
while node <> nil do begin
TObject(node.Data).Free;
node := node.GetNextSibling;
end;
parentnode := parentnode.GetNextSibling;
end;
for rc in TRenderCoords do begin
FreeAndNil(FDoc[rc]);
FreeAndNil(FDocFromSVG[rc]);
FreeAndNil(FDocFromWMF[rc]);
end;
WriteIni;
end;
function TMainForm.GetFileFormat: TvVectorialFormat;
begin
case CbFileFormat.ItemIndex of
0: Result := vfSVG;
1: Result := vfWindowsMetafileWMF;
else raise Exception.Create('Format not supported');
end;
end;
function TMainForm.GetFileFormatExt: String;
begin
case CbFileFormat.ItemIndex of
0: Result := 'svg';
1: Result := 'wmf';
else raise Exception.Create('Format not supported');
end;
end;
procedure TMainForm.PaintBoxPaint(Sender: TObject);
var
doc: TvVectorialDocument;
page: TvVectorialPage;
w, h: Integer;
fmt: TvVectorialFormat;
rc: TRenderCoords;
begin
fmt := GetFileFormat;
if (Sender = BottomLeftPaintbox) or (Sender = WRBottomLeftPaintbox) then
rc := rcBottomLeftCoords
else
if (Sender = TopLeftPaintbox) or (Sender = WRTopLeftPaintbox) then
rc := rcTopLeftCoords
else
raise Exception.Create('This sender is not supported here.');
doc := nil;
if (Sender = BottomLeftPaintbox) or (Sender = TopLeftPaintbox) then
doc := FDoc[rc]
else
if (Sender = WRBottomLeftPaintbox) or (Sender = WRTopLeftPaintbox) then
case GetFileFormat of
vfSVG:
doc := FDocFromSVG[rc];
vfWindowsMetafileWMF:
doc := FDocFromWMF[rc];
else
raise Exception.Create('File format not supported.');
end;
w := TPaintbox(Sender).Width;
h := TPaintbox(Sender).Height;
if doc = nil then begin
TPaintbox(Sender).Canvas.Brush.Color := clDefault;
TPaintbox(Sender).Canvas.Brush.Style := bsSolid;
TPaintbox(Sender).Canvas.FillRect(0, 0, w, h);
exit;
end;
page := doc.GetPageAsVectorial(0);
page.DrawBackground(TPaintbox(Sender).Canvas);
if page.UseTopLeftCoordinates then
page.Render(TPaintbox(Sender).Canvas, 0, 0, 1.0, 1.0)
else
page.Render(TPaintbox(Sender).Canvas, 0, h, 1.0, -1.0);
end;
procedure TMainForm.Populate;
var
node, node0, node1: TTreeNode;
begin
Tree.Items.Clear;
{ --------------------------------------------------}
node := Tree.Items.AddChild(nil, 'Simple shapes');
{ --------------------------------------------------}
Tree.Items.AddChildObject(node, 'Circle (solid) - move up',
TRenderParams.Create(@Render_Shape, 'circle_solid.png', $0100));
Tree.Items.AddChildObject(node, 'Ellipse (solid) - moved up',
TRenderParams.Create(@Render_Shape, 'ellipse_solid.png', $0200));
Tree.Items.AddChildObject(node, 'Rectangle(solid) - moved up',
TRenderParams.Create(@Render_Shape, 'rect_solid.png', $0300));
Tree.Items.AddChildObject(node, 'Rounded rectangle (solid) - moved up',
TRenderParams.Create(@Render_Shape, 'rounded_rect_solid.png', $0400));
Tree.Items.AddChildObject(node, 'Polygon (solid) - moved up',
TRenderParams.Create(@Render_Shape, 'polygon_solid.png', $0500));
{ --------------------------------------------------}
node := Tree.Items.AddChild(nil, 'Complex shapes');
{ --------------------------------------------------}
Tree.Items.AddChildObject(node, 'Path with hole (solid fill)',
TRenderParams.Create(@Render_Path_Hole_SolidFill, 'path_hole_solid.png'));
Tree.Items.AddChildObject(node, 'Path with hole (gradient fill)',
TRenderParams.Create(@Render_Path_Hole_GradientFill, 'path_hole_gradient.png'));
Tree.Items.AddChildObject(node, 'Self-intersecting polygon (solid fill, even-odd rule) - tip at bottom',
TRenderParams.Create(@Render_SelfIntersectingPoly_SolidFill_EvenOdd, 'selfintersecting_poly_solid_eo.png'));
Tree.Items.AddChildObject(node, 'Self-intersecting polygon (gradient fill, even-odd rule) - tip at bottom',
TRenderParams.Create(@Render_SelfIntersectingPoly_GradientFill_EvenOdd, 'selfintersecting_poly_gradient_eo.png'));
Tree.Items.AddChildObject(node, 'Self-intersecting polygon (solid fill, nonzero winding rule) - tip at bottom',
TRenderParams.Create(@Render_SelfIntersectingPoly_SolidFill_NonZeroWinding, 'selfintersecting_poly_solid_nzw.png'));
Tree.Items.AddChildObject(node, 'Self-intersecting polygon (gradient fill, nonzero winding rule) - tip at bottom',
TRenderParams.Create(@Render_SelfIntersectingPoly_GradientFill_NonZeroWinding, 'selfintersecting_poly_gradient_nzw.png'));
{ -----------------------------------------}
node0 := Tree.Items.AddChild(nil, 'Arcs');
{ -----------------------------------------}
node1 := Tree.Items.AddChild(node0, 'circular');
node := Tree.Items.AddChild(node1, 'clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_cw_q1.png', $0200));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_cw_q12.png', $0201));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_cw_q2.png', $0202));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_cw_q23.png', $0203));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_cw_q3.png', $0204));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_cw_q34.png', $0205));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_cw_q4.png', $0206));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_cw_q41.png', $0207));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q1r.png', $0300));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q12r.png', $0301));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q2r.png', $0302));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q23r.png', $0303));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q3r.png', $0304));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q34r.png', $0305));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q4r.png', $0306));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_cw_q41r.png', $0307));
node := Tree.Items.AddChild(node1, 'counter-clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q1.png', $0000));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q12.png', $0001));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q2.png', $0002));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q23.png', $0003));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q3.png', $0004));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q34.png', $0005));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q4.png', $0006));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q41.png', $0007));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q1r.png', $0100));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q12r.png', $0101));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q2r.png', $0102));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q23r.png', $0103));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q3r.png', $0104));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q34r.png', $0105));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q4r.png', $0106));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ccw_q41r.png', $0107));
node1 := Tree.Items.AddChild(node0, 'elliptical');
node := Tree.Items.AddChild(node1, 'clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q1.png', $1200));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q12.png', $1201));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q2.png', $1202));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q23.png', $1203));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q3.png', $1204));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q34.png', $1205));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q4.png', $1206));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q41.png', $1207));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q1r.png', $1300));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q12r.png', $1301));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q2r.png', $1302));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q23r.png', $1303));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q3r.png', $1304));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q34r.png', $1305));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q4r.png', $1306));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_cw_q41r.png', $1307));
node := Tree.Items.AddChild(node1, 'counter-clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q1.png', $1000));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q12.png', $1001));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q2.png', $1002));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q23.png', $1003));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q3.png', $1004));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q34.png', $1005));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q4.png', $1006));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q41.png', $1007));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q1r.png', $1100));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q12r.png', $1101));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q2r.png', $1102));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q23r.png', $1103));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q3r.png', $1104));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q34r.png', $1105));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q4r.png', $1106));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ell_ccw_q41r.png', $1107));
node1 := Tree.Items.AddChild(node0, 'elliptical, rotated 30deg');
node := Tree.Items.AddChild(node1, 'clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q1.png', $2200));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q12.png', $2201));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q2.png', $2202));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q23.png', $2203));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q3.png', $2204));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q34.png', $2205));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q4.png', $2206));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q41.png', $2207));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q1r.png', $2300));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q12r.png', $2301));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q2r.png', $2302));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q23r.png', $2303));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q3r.png', $2304));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q34r.png', $2305));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q4r.png', $2306));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_cw_q41r.png', $2307));
node := Tree.Items.AddChild(node1, 'counter-clockwise from point 1 to point 2');
Tree.Items.AddChildObject(node, 'Quadrant I',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q1.png', $2000));
Tree.Items.AddChildObject(node, 'Quadrant I+II',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q12.png', $2001));
Tree.Items.AddChildObject(node, 'Quadrant II',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q2.png', $2002));
Tree.Items.AddChildObject(node, 'Quadrant II+III',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q23.png', $2003));
Tree.Items.AddChildObject(node, 'Quadrant III',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q3.png', $2004));
Tree.Items.AddChildObject(node, 'Quadrant III+IV',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q34.png', $2005));
Tree.Items.AddChildObject(node, 'Quadrant IV',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q4.png', $2006));
Tree.Items.AddChildObject(node, 'Quadrant IV+I',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q41.png', $2007));
Tree.Items.AddChildObject(node, 'Quadrant I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q1r.png', $2100));
Tree.Items.AddChildObject(node, 'Quadrant I+II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q12r.png', $2101));
Tree.Items.AddChildObject(node, 'Quadrant II, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q2r.png', $2102));
Tree.Items.AddChildObject(node, 'Quadrant II+III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q23r.png', $2103));
Tree.Items.AddChildObject(node, 'Quadrant III, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q3r.png', $2104));
Tree.Items.AddChildObject(node, 'Quadrant III+IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q34r.png', $2105));
Tree.Items.AddChildObject(node, 'Quadrant IV, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q4r.png', $2106));
Tree.Items.AddChildObject(node, 'Quadrant IV+I, reverse',
TRenderParams.Create(@Render_Arc, 'arc_ellrot_ccw_q41r.png', $2107));
{ -----------------------------------------------}
node := Tree.Items.AddChild(nil, 'Bezier');
{ -----------------------------------------------}
Tree.Items.AddChildObject(node, 'Single segment',
TRenderParams.Create(@Render_Bezier, 'bezier.png'));
{ -----------------------------------------------}
node0 := Tree.Items.AddChild(nil, 'Gradients');
{ -----------------------------------------------}
node := Tree.Items.AddChild(node0, 'horizontal');
Tree.Items.AddChildObject(node, 'Circle',
TRenderParams.Create(@Render_Shape, 'circle_gradienthor.png', $0101));
Tree.Items.AddChildObject(node, 'Ellipse',
TRenderParams.Create(@Render_Shape, 'ellipse_gradienthor.png', $0201));
Tree.Items.AddChildObject(node, 'Rectangle',
TRenderParams.Create(@Render_Shape, 'rect_gradienthor.png', $0301));
Tree.Items.AddChildObject(node, 'Rounded rectangle',
TRenderParams.Create(@Render_Shape, 'rounded_rect_gradienthor.png', $0401));
Tree.Items.AddChildObject(node, 'Polygon',
TRenderParams.Create(@Render_Shape, 'polygon_gradienthor.png', $0501));
node := Tree.Items.AddChild(node0, 'vertical');
Tree.Items.AddChildObject(node, 'Circle',
TRenderParams.Create(@Render_Shape, 'circle_gradientvert.png', $0102));
Tree.Items.AddChildObject(node, 'Ellipse',
TRenderParams.Create(@Render_Shape, 'ellipse_gradientvert.png', $0202));
Tree.Items.AddChildObject(node, 'Rectangle',
TRenderParams.Create(@Render_Shape, 'rect_gradientvert.png', $0302));
Tree.Items.AddChildObject(node, 'Rounded rectangle',
TRenderParams.Create(@Render_Shape, 'rounded_rect_gradientvert.png', $0402));
Tree.Items.AddChildObject(node, 'Polygon',
TRenderParams.Create(@Render_Shape, 'polygon_gradientvert.png', $0502));
node := Tree.Items.AddChild(node0, 'linear');
Tree.Items.AddChildObject(node, 'Circle',
TRenderParams.Create(@Render_Shape, 'circle_gradientlinear.png', $0103));
Tree.Items.AddChildObject(node, 'Ellipse',
TRenderParams.Create(@Render_Shape, 'ellipse_gradientlinear.png', $0203));
Tree.Items.AddChildObject(node, 'Rectangle',
TRenderParams.Create(@Render_Shape, 'rect_gradientlinear.png', $0303));
Tree.Items.AddChildObject(node, 'Rounded rectangle',
TRenderParams.Create(@Render_Shape, 'rounded_rect_gradientlinear.png', $0403));
Tree.Items.AddChildObject(node, 'Polygon',
TRenderParams.Create(@Render_Shape, 'polygon_gradientlinear.png', $0503));
node := Tree.Items.AddChild(node0, 'radial');
Tree.Items.AddChildObject(node, 'Circle',
TRenderParams.Create(@Render_Shape, 'circle_gradientradial.png', $0104));
Tree.Items.AddChildObject(node, 'Ellipse',
TRenderParams.Create(@Render_Shape, 'ellipse_gradientradial.png', $0204));
Tree.Items.AddChildObject(node, 'Rectangle',
TRenderParams.Create(@Render_Shape, 'rect_gradientradial.png', $0304));
Tree.Items.AddChildObject(node, 'Rounded rectangle',
TRenderParams.Create(@Render_Shape, 'rounded_rect_gradientradial.png', $0404));
Tree.Items.AddChildObject(node, 'Polygon',
TRenderParams.Create(@Render_Shape, 'polygon_gradientradial.png', $0504));
{ -----------------------------------------------}
node0 := Tree.Items.AddChild(nil, 'Text');
{ -----------------------------------------------}
node := Tree.Items.AddChild(node0, 'horizontal');
Tree.Items.AddChildObject(node, 'left aligned',
TRenderParams.Create(@Render_Text, 'text_left.png', $0000));
Tree.Items.AddChildObject(node, 'centered',
TRenderParams.Create(@Render_Text, 'text_center.png', $0001));
Tree.Items.AddChildObject(node, 'right aligned',
TRenderParams.Create(@Render_Text, 'text_right.png', $0002));
node := Tree.Items.AddChild(node0, 'rotated by 30 deg');
Tree.Items.AddChildObject(node, 'left aligned',
TRenderParams.Create(@Render_Text, 'text_left_30.png', $1000));
Tree.Items.AddChildObject(node, 'centered',
TRenderParams.Create(@Render_Text, 'text_center_30.png', $1001));
Tree.Items.AddChildObject(node, 'right aligned',
TRenderParams.Create(@Render_Text, 'text_right_30.png', $1002));
node := Tree.Items.AddChild(node0, 'vertical (90 deg, upward)');
Tree.Items.AddChildObject(node, 'left aligned',
TRenderParams.Create(@Render_Text, 'text_left_90.png', $2000));
Tree.Items.AddChildObject(node, 'centered',
TRenderParams.Create(@Render_Text, 'text_center_90.png', $2001));
Tree.Items.AddChildObject(node, 'right aligned',
TRenderParams.Create(@Render_Text, 'text_right_90.png', $2002));
node := Tree.Items.AddChild(node0, 'vertical (-90 deg, downward)');
Tree.Items.AddChildObject(node, 'left aligned',
TRenderParams.Create(@Render_Text, 'text_left_m90.png', $3000));
Tree.Items.AddChildObject(node, 'centered',
TRenderParams.Create(@Render_Text, 'text_center_m90.png', $3001));
Tree.Items.AddChildObject(node, 'right aligned',
TRenderParams.Create(@Render_Text, 'text_right_m90.png', $3002));
node := Tree.Items.AddChild(node0, 'Fonts');
Tree.Items.AddChildObject(node, 'Times New Roman + Courier New',
TRenderParams.Create(@Render_Text_Fonts, 'text_fonts.png'));
Tree.Items.AddChildObject(node0, 'Text colors',
TRenderParams.Create(@Render_Text_Colors, 'text_colors.png'));
end;
procedure TMainForm.Render_Shape(APage: TvVectorialPage;
AIntParam: Integer);
{ AIntParam and $00FF = 0 --> solid fill
1 --> horizontal gradient
2 --> vertical gradient
3 --> linear gradient
4 --> radial gradient
AIntParam and $FF00 = $0100 --> circle
$0200 --> ellipse
$0300 --> rectangle
$0400 --> rounded rect
$0500 --> polygon (triangle) }
var
ent: TvEntityWithPenAndBrush;
begin
case AIntParam and $FF00 of
$0100: ent := CreateStdCircle(APage);
$0200: ent := CreateStdEllipse(APage);
$0300: ent := CreateStdRect(APage);
$0400: ent := CreateStdRoundedRect(APage);
$0500: ent := CreateStdPolygon(APage);
else raise Exception.Create('Shape not supported.');
end;
case AIntParam and $00FF of
$0000: ent.Brush := StdSolidBrush;
$0001: ent.Brush := StdHorizGradientBrush;
$0002: ent.Brush := StdVertGradientBrush;
$0003: ent.Brush := StdLinearGradientBrush;
$0004: ent.Brush := StdRadialGradientBrush;
else raise Exception.Create('Brush not supported');
end;
APage.AddEntity(ent);
end;
procedure TMainForm.Render_Arc(APage: TvVectorialPage; AIntParam: Integer);
//
// AIntParam and $000F = $0000 --> circular arc
// $1000 --> elliptical arc
// $2000 --> elliptical arc, rotated
// AIntParam and $000F = $0000 --> quarter 1
// $0001 --> quarter 1 + 2
// $0002 --> quarter 2
// $0003 --> quarter 2 + 3
// $0004 --> quarter 3
// $0005 --> quarter 3+4
// $0006 --> quarter 4
// $0007 --> quarter 4+1
// AIntParam and $0100 = $0100 --> start and end points exchanged
// AIntParan and $0200 = $0200 --> clockwise
const
ROT_ANGLE = 30;
RY_MULT = 0.6;
CX = 50;
CY = 55;
R = 30;
var
isReversed, isClockwise, isEllipse, isRotated: Boolean;
p: T3dPoint;
x1, y1, x2, y2, rx, ry: Double;
startAngle, endAngle, phi: Double;
begin
isReversed := AIntParam and $0100 <> 0;
isClockwise := AIntParam and $0200 <> 0;
isEllipse := AIntParam and $F000 <> 0;
isRotated := AIntParam and $F000 = $2000;
rx := R;
ry := IfThen(isEllipse, R * RY_MULT, R);
phi := IfThen(isRotated, DegToRad(ROT_ANGLE), 0.0);
startAngle := DegToRad((AIntParam and $000F) * 45); // 0°, 45°, 90°, ...
endAngle := startAngle + pi/2; // 90°, 135°, 180°, ...
x1 := CX + rx * cos(startAngle);
y1 := CY + ry * sin(startAngle);
x2 := CX + rx * cos(endAngle);
y2 := CY + ry * sin(endAngle);
if isRotated then begin
p := Rotate3DPointInXY(Make3DPoint(x1, y1), Make3DPoint(CX, CY), -phi);
// See comment at Rotate3DPointInXY regarding the negative sign of phi
x1 := p.x;
y1 := p.y;
p := Rotate3DPointInXY(Make3DPoint(x2, y2), Make3DPoint(CX, CY), -phi);
x2 := p.x;
y2 := p.y;
end;
if isReversed then
CreateArc(APage, x2, y2, x1, y1, CX, CY, rx, ry, phi, isClockwise)
else
CreateArc(APage, x1, y1, x2, y2, CX, CY, rx, ry, phi, isClockwise);
end;
procedure TMainForm.Render_Bezier(APage: TvVectorialpage; AIntParam: Integer);
const
X1 = 10;
Y1 = 25;
X2 = 30;
Y2 = 80;
X3 = 50;
Y3 = 70;
X4 = 90;
Y4 = 25;
begin
CreateBezier(APage, X1,Y1, X2,Y2, X3,Y3, X4,Y4);
end;
procedure TMainForm.Render_Path_Hole_SolidFill(APage: TvVectorialPage;
AIntParam: Integer);
var
obj: TPath;
begin
obj := CreatePathWithHole(APage); // no need to AddEntity!
obj.Brush.Color := colYellow;
obj.Brush.Style := bsSolid;
obj.Pen.Width := 3;
obj.Pen.Color := colBlue;
end;
procedure TMainForm.Render_Path_Hole_GradientFill(APage: TvVectorialPage;
AIntParam: Integer);
var
obj: TPath;
begin
obj := CreatePathWithHole(APage); // No need to AddEntity!
obj.Brush := StdLinearGradientBrush;
obj.Pen.Width := 3;
obj.Pen.Color := colBlue;
end;
procedure TMainForm.Render_SelfIntersectingPoly_SolidFill_EvenOdd(
APage: TvVectorialPage; AIntParam: Integer);
var
obj: TvPolygon;
begin
obj := CreateStdSelfIntersectingPolygon(APage);
obj.WindingRule := vcmEvenOddRule;
obj.Brush := StdSolidBrush;
APage.AddEntity(obj);
end;
procedure TMainForm.Render_SelfIntersectingPoly_GradientFill_EvenOdd(
APage: TvVectorialPage; AIntParam: Integer);
var
obj: TvPolygon;
begin
obj := CreateStdSelfIntersectingPolygon(APage);
obj.Brush := StdHorizGradientBrush;
obj.WindingRule := vcmEvenOddRule;
APage.AddEntity(obj);
end;
procedure TMainForm.Render_SelfIntersectingPoly_SolidFill_NonZeroWinding(
APage: TvVectorialPage; AIntParam: Integer);
var
obj: TvPolygon;
begin
obj := CreateStdSelfIntersectingPolygon(APage);
obj.WindingRule := vcmNonZeroWindingRule;
obj.Brush := StdSolidBrush;
APage.AddEntity(obj);
end;
procedure TMainForm.Render_SelfIntersectingPoly_GradientFill_NonZeroWinding(
APage: TvVectorialPage; AIntParam: Integer);
var
obj: TvPolygon;
begin
obj := CreateStdSelfIntersectingPolygon(APage);
obj.Brush := StdHorizGradientBrush;
obj.WindingRule := vcmNonzeroWindingRule;
APage.AddEntity(obj);
end;
procedure TMainForm.Render_Text(APage: TvVectorialPage; AIntParam: Integer);
{ AIntParam and $000F = $0000 --> anchor at left
$0001 --> anchor at center
$0002 --> anchor at right
AIntParam and $F000 = $0000 --> horizontal
$1000 --> rotated 30deg
$2000 --> rotated 90deg
$3000 --> rotated -90deg }
const
XTEXT = 50;
YTEXT = 40; // we assume that y points up
L = 10;
var
txt: TvText;
p: TPath;
angle: double;
anchor: TvTextAnchor;
begin
case AIntParam and $000F of
$0000 : anchor := vtaStart;
$0001 : anchor := vtaMiddle;
$0002 : anchor := vtaEnd;
else raise Exception.Create('Text anchor not supported');
end;
case AIntParam and $F000 of
$0000 : angle := 0;
$1000 : angle := 30;
$2000 : angle := 90;
$3000 : angle := -90;
else raise Exception.Create('Text angle not supported.');
end;
// Draw "+" at the origin of the text
if APage.UseTopLeftCoordinates then begin
APage.StartPath (XTEXT - L, PAGE_SIZE - YTEXT);
APage.AddLineToPath(XTEXT + L, PAGE_SIZE - YTEXT);
APage.AddMoveToPath(XTEXT, PAGE_SIZE - YTEXT - L);
APage.AddLineToPath(XTEXT, PAGE_SIZE - YTEXT + L);
end else begin
APage.StartPath (XTEXT - L, YTEXT);
APage.AddLineToPath(XTEXT + L, YTEXT);
APage.AddMoveToPath(XTEXT, YTEXT - L);
APage.AddLineToPath(XTEXT, YTEXT + L);
end;
p := APage.EndPath;
p.Pen.Width := 1;
p.Pen.Color := colRed;
// Draw text
txt := TvText.Create(APage);
txt.X := XTEXT;
if APage.UseTopLeftCoordinates then
txt.Y := PAGE_SIZE - YTEXT else
txt.Y := YTEXT;
txt.Value.Add('ABC');
txt.Font.Size := 14;
txt.TextAnchor := anchor;
txt.Font.Orientation := angle;
APage.AddEntity(txt);
end;
procedure TMainForm.Render_Text_Fonts(APage: TvVectorialPage;
AIntParam: Integer);
var
txt: TvText;
begin
txt := TvText.Create(APage);
txt.X := 10;
txt.Y := 80;
txt.Font.Name := 'Times New Roman';
txt.Font.Size := 10;
txt.Value.Add('Times');
APage.AddEntity(txt);
txt := TvText.Create(APage);
txt.X := 10;
txt.Y := 60;
txt.Font.Name := 'Courier New';
txt.Font.Size := 12;
txt.Value.Add('Courier');
APage.AddEntity(txt);
end;
procedure TMainForm.Render_Text_Colors(APage: TvVectorialPage;
AIntParam: Integer);
var
txt: TvText;
begin
txt := TvText.Create(APage);
txt.X := 10;
txt.Y := 80;
txt.Font.Name := 'Times New Roman';
txt.Font.Size := 14;
txt.Font.Color := colRed;
txt.Value.Add('Text');
txt.Brush.Style := bsSolid;
txt.Brush.Color := colYellow;
txt.Brush.Kind := bkSimpleBrush;
APage.AddEntity(txt);
end;
procedure TMainForm.ReadIni;
var
ini: TCustomIniFile;
L, T, W, H: Integer;
rct: TRect;
begin
ini := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
try
L := ini.ReadInteger('MainForm', 'Left', Left);
T := ini.ReadInteger('MainForm', 'Top', Top);
W := ini.ReadInteger('MainForm', 'Width', Width);
H := ini.ReadInteger('MainForm', 'Height', Height);
rct := Screen.DesktopRect;
if L + W > rct.Right - rct.Left then L := rct.Right - W;
if L < 0 then L := rct.Left;
if T + H > rct.Bottom - rct.Top then T := rct.Bottom - H;
if T < 0 then T := rct.Top;
SetBounds(L, T, W, H);
finally
ini.Free;
end;
end;
procedure TMainForm.WriteIni;
var
ini: TCustomIniFile;
begin
ini := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
try
if WindowState = wsNormal then
begin
ini.WriteInteger('MainForm', 'Left', Left);
ini.WriteInteger('MainForm', 'Top', Top);
ini.WriteInteger('MainForm', 'Width', Width);
ini.WriteInteger('MainForm', 'Height', Height);
end;
finally
ini.Free;
end;
end;
procedure TMainForm.ShowFileImage(AFilename: String; AUseTopLeftCoords: Boolean;
APaintbox: TPaintbox);
var
ext: String;
rc: TRenderCoords;
begin
if AUseTopLeftCoords then
rc := rcTopLeftCoords else
rc := rcBottomLeftCoords;
ext := Lowercase(ExtractFileExt(AFileName));
if not FileExists(AFileName) then begin
case ext of
'.svg': FreeAndNil(FDocFromSVG[rc]);
'.wmf': FreeAndNil(FDocFromWMF[rc]);
else raise Exception.Create('File type not supported');
end;
APaintbox.Hint := NOT_SAVED;
APaintbox.Invalidate;
exit;
end;
if ext = '.svg' then begin
FreeAndNil(FDocFromSVG[rc]);
FDocFromSVG[rc] := TvVectorialDocument.Create;
FDocFromSVG[rc].ReadFromFile(AFileName);
end else
if ext = '.wmf' then begin
FreeAndNil(FDocFromWMF[rc]);
FDocFromWMF[rc] := TvVectorialDocument.Create;
FDocFromWMF[rc].ReadFromFile(AFilename);
end;
APaintbox.Hint := AFileName;
APaintBox.Invalidate;
end;
procedure TMainForm.ShowRefImageTest;
var
renderParams: TRenderParams;
fn: String;
begin
if Tree.Selected = nil then
exit;
renderParams := TRenderParams(Tree.Selected.Data);
if renderParams = nil then
begin
RefImage.Picture := nil;
exit;
end;
fn := IncludeTrailingPathDelimiter(IMG_FOLDER) + renderParams.RefFile;
if FileExists(fn) then begin
RefImage.Picture.LoadFromFile(fn);
RefImage.Hint := fn;
end else begin
RefImage.Picture := nil;
RefImage.Hint := NOT_SAVED;
end;
end;
procedure TMainForm.ShowRenderTestImages;
var
renderParams: TRenderParams;
page: TvVectorialPage = nil;
begin
if Tree.Selected = nil then
exit;
renderParams := TRenderParams(Tree.Selected.Data);
if renderParams = nil then
begin
BottomLeftPaintbox.Invalidate;
TopLeftPaintbox.Invalidate;
exit;
end;
// Render document with bottom/left origin
PrepareDoc(FDoc[rcBottomLeftCoords], page, false);
renderParams.OnRender(page, renderParams.IntParam);
BottomLeftPaintbox.Invalidate;
// Render document with top/left origin
PrepareDoc(FDoc[rcTopLeftCoords], page, true);
renderParams.OnRender(page, renderParams.IntParam);
TopLeftPaintbox.Invalidate;
end;
procedure TMainForm.ShowWriteReadTestImages;
var
renderParams: TRenderParams;
folder: String;
fn: String;
ext: String;
rc: TRenderCoords;
begin
for rc in TRenderCoords do begin
FreeAndNil(FDocFromSVG[rc]);
FreeAndNil(FDocFromWMF[rc]);
end;
if Tree.Selected = nil then
exit;
renderParams := TRenderParams(Tree.Selected.Data);
if renderParams = nil then
begin
WRBottomLeftPaintbox.Invalidate;
WRTopLeftPaintbox.Invalidate;
exit;
end;
ext := GetFileFormatExt;
folder := IMG_FOLDER + ext + PathDelim;
fn := folder + 'bl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
ShowFileImage(fn, false, WRBottomLeftPaintbox);
fn := folder + 'tl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
ShowFileImage(fn, true, WRTopLeftPaintbox);
end;
procedure TMainForm.TreeSelectionChanged(Sender: TObject);
begin
ShowRenderTestImages;
ShowRefImageTest;
ShowWriteReadTestImages;
UpdateCmdStates;
end;
procedure TMainForm.TreeCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if Node.HasChildren then
Sender.Canvas.Font.Style := [fsBold] else
Sender.Canvas.Font.Style := [];
end;
procedure TMainForm.UpdateCmdStates;
var
fn: String;
folder: string;
renderParams: TRenderParams;
ext: String;
rc: TRenderCoords;
rcOK: array[TRenderCoords] of boolean = (false, false);
begin
BtnSaveAsRef.Enabled := Tree.Selected <> nil;
BtnSaveToFiles.Enabled := Tree.Selected <> nil;
BtnViewBottomLeft.Enabled := Tree.Selected <> nil;
BtnViewTopLeft.Enabled := Tree.Selected <> nil;
if Tree.Selected <> nil then begin
renderParams := TRenderParams(Tree.Selected.Data);
if renderParams <> nil then begin
ext := GetFileFormatExt;
folder := IMG_FOLDER + ext + PathDelim;
fn := folder + 'bl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
rcOK[rcBottomLeftCoords] := FileExists(fn);
fn := folder + 'tl_' + ChangeFileExt(renderParams.RefFile, '.' + ext);
rcOK[rcTopLeftCoords] := FileExists(fn);
end;
end;
BtnViewBottomLeft.Enabled := rcOK[rcBottomLeftcoords];
BtnViewTopLeft.Enabled := rcOK[rcTopLeftCoords];
end;
end.