mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-04 06:24:04 +02:00
1234 lines
44 KiB
ObjectPascal
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.
|
|
|