📄 uvectorgraphics.pas
字号:
constructor Create(const FileName: String; CanContainLinks: Boolean);
//Closes the SVG file and frees the object.
destructor Destroy; override;
//Sets the link target for the next box to be drawn.
procedure SetNextTextBoxesLinkTarget(const Target: String); override;
//Called before ~[link GetTextExtent] is called to allow the set-up for the
//measurement. GetTextExtent may be called several times.
procedure PrepareTextMeasuring; override;
//Measures the size of a text in the diagram in the format.
function GetTextExtent(const Text: String): TSize; override;
//Called after ~[link GetTextExtent] has been called to allow the tear down
//after the measurement.
procedure EndTextMeasuring; override;
//Called before the actual image is being drawn.
procedure InitImageObjects(ImageWidth, ImageHeight: Integer;
const ImageTitle: String); override;
//Called after the actual image has been drawn.
procedure FinalizeImageObjects; override;
//Draws a text and a rectangle behind it.
procedure DrawBoxedText(const Text: String; X, Y: Integer; BoxSize: TSize);
override;
//Draws an arrow.
procedure DrawArrow(Src, Dest, Arr1, Arr2: TPoint; BoldArrow: Boolean);
override;
//Draws a line.
procedure DrawLine(Xs, Ys, Xe, Ye: Integer); override;
end;
{$IFNDEF LINUX}
{Draws a string and a rectangle behind it into an EMF file.
~param Canvas the canvas of a Windows Meta File to draw the boxed string on
~param Name the name of the class or file to be drawn
~param X,Y the position to draw it at
~param BoxSize the size of the rectangle behind the text }
procedure EMFDrawBoxedString(Canvas: TCanvas; const Name: String;
X, Y: Integer; BoxSize: TSize);
var TextSize :TSize; //size of the text
begin
Canvas.RoundRect(X, Y, X + BoxSize.cx, Y + BoxSize.cy, //draw box around
RoundRectRadix, RoundRectRadix); //the name
TextSize := Canvas.TextExtent(Name); //get size of the name
Canvas.TextOut(X + (BoxSize.cx - TextSize.cx) div 2, //draw it centered
Y + (BoxSize.cy - TextSize.cy) div 2 - 2, Name); //in the box
end;
{Draws an arrow inside an EMF file.
~param Canvas the canvas of a Windows Meta File to draw the arrow on
~param Src the starting point of the arrow
~param Dest the ending point of the arrow
~param Arr1, Arr2 the positions of both sides of the head of the arrow
~param BoldArrow whether the arrow should be "bold", the head filled }
procedure EMFDrawArrow(Canvas: TCanvas; Src, Dest, Arr1, Arr2: TPoint;
BoldArrow: Boolean);
begin
Canvas.Polyline([Src, Dest]); //draw arrow (main line)
if BoldArrow then //if bold arrows should be used
Canvas.Polygon([Arr1, Dest, Arr2]) //fill arrowhead
else
Canvas.Polyline([Arr1, Dest, Arr2]); //just draw its sides
end;
{Draws a line in an EMV file.
~param Canvas the canvas of a Windows Meta File to draw the line on
~param Xs, Ys starting position of the line
~param Xe, Ye end point of the line }
procedure EMFDrawLine(Canvas: TCanvas; Xs, Ys, Xe, Ye: Integer);
begin
Canvas.MoveTo(Xs, Ys); //go to the start of the line
Canvas.LineTo(Xe, Ye); //and draw it to its end
end;
{$ENDIF}
{Starts an SVG file by writing its document type and so on.
~param SVGFile the stream to write the SVG file to
~param Title the title of the SVG file
~param ImageWidth, ImageHeight the dimensions of the image in the file
~param CanContainLinks whether the image can (will) contain links }
procedure SVGStartFile(SVGFile: TBufferStream; const Title: String;
ImageWidth, ImageHeight: Integer;
CanContainLinks: Boolean);
begin
//start the SVG file
SVGFile.WriteString('<?xml version="1.0" encoding="UTF-8"?>');
// ISO-8859-1
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"');
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">');
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString('<svg xmlns="http://www.w3.org/2000/svg"');
SVGFile.WriteString(XMLNewLine);
if CanContainLinks then
begin
SVGFile.WriteString(' xmlns:xlink="http://www.w3.org/1999/xlink"');
SVGFile.WriteString(XMLNewLine);
end;
//and set the size of the image
{
SVGFile.WriteFormatted(' viewBox="0 0 %d %d"',
[ImageWidth, ImageHeight]);
SVGFile.WriteFormatted(' width="%d" height="%d">',
[ImageWidth, ImageHeight]);
}
SVGFile.WriteString('>');
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(' <title>'); //write its title
SVGFile.WriteString(Title);
SVGFile.WriteString('</title>');
SVGFile.WriteString(XMLNewLine);
// SVGFile.WriteStrings(' <desc>', Title, '</desc>');
// SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(XMLNewLine);
(* // a CSS fragment to highlight boxes when the mouse pointer is moved on them
<defs>
<style type="text/css"><![CDATA[
rect:hover {
fill: #FFF0D0;
stroke-width: 4;
}
]]></style>
</defs>
*)
//set the default font
SVGFile.WriteFormatted(' <g font-family="%s, Verdana, Helvetica, Arial, sans-serif" font-size="%dpt">',
//font-size-adjust="0.58"
[SVGFontName, SVGFontSize]);
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(XMLNewLine);
end;
{Ends an SVG file by closing any tags opened in ~[link SVGStartFile].
~param SVGFile the stream to write the SVG file to }
procedure SVGEndFile(SVGFile: TBufferStream);
begin
SVGFile.WriteString(' </g>'); //end the definition of the font
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString('</svg>'); //end the SVG file
SVGFile.WriteString(XMLNewLine);
end;
{Draws a string and a rectangle behind it into an SVG file.
~param SVGFile the stream of the SVG file to draw the boxed string in
~param Name the name of the class or file to be drawn
~param X, Y the position to draw it at
~param BoxSize the size of the rectangle behind the text
~param LinkTarget the target of a link that should be generated for the box,
if '', no link will be generated }
procedure SVGDrawBoxedString(SVGFile: TBufferStream; const Name: String;
X, Y: Integer; BoxSize: TSize;
const LinkTarget: String);
begin
SVGFile.WriteString(' <g>'); //group box and name together
SVGFile.WriteString(XMLNewLine);
//draw box around the name
if LinkTarget <> '' then //link is available?
begin //start it
SVGFile.WriteFormatted(' <a xlink:href="%s">', [LinkTarget]);
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(' ');
end;
//draw the background rectangle
SVGFile.WriteFormatted(' <rect x="%d" y="%d" width="%d" height="%d" rx="%d" fill="white" stroke="black" stroke-width="2" />',
[X, Y, BoxSize.cx, BoxSize.cy, RoundRectRadix]);
SVGFile.WriteString(XMLNewLine);
if LinkTarget <> '' then //link has been started?
begin
SVGFile.WriteString(' </a>'); //end it now
SVGFile.WriteString(XMLNewLine);
end;
//draw the name
SVGFile.WriteFormatted(' <text x="%d" y="%d" text-anchor="middle">%s</text>',
[X + BoxSize.cx div 2,
Y + SVGFontSize + SVGFontSize * 4 div 5, Name]);
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(' </g>'); //end group for box and name
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(XMLNewLine);
end;
{Draws an arrow inside an SVG file.
~param SVGFile the stream of the SVG file to draw the arrow in
~param Src the starting point of the arrow
~param Dest the ending point of the arrow
~param Arr1, Arr2 the positions of both sides of the head of the arrow
~param BoldArrow whether the arrow should be "bold", the head filled }
procedure SVGDrawArrow(SVGFile: TBufferStream; Src, Dest, Arr1, Arr2: TPoint;
BoldArrow: Boolean);
begin
SVGFile.WriteString(' <g>'); //group line and head of arrow together
SVGFile.WriteString(XMLNewLine);
//draw arrow (main line)
SVGFile.WriteFormatted(' <line x1="%d" y1="%d" x2="%d" y2="%d" stroke="black" stroke-width="2" />',
[Src.x, Src.y, Dest.x, Dest.y]);
SVGFile.WriteString(XMLNewLine);
if BoldArrow then //if a bold arrow should be drawn
//fill arrowhead
SVGFile.WriteFormatted(' <polygon points="%d,%d %d,%d %d,%d" stroke="black" fill="black" />',
[Arr1.x, Arr1.y, Dest.x, Dest.y, Arr2.x, Arr2.y])
else
//just draw both sides of the arrow head
SVGFile.WriteFormatted(' <polyline points="%d,%d %d,%d %d,%d" stroke="black" stroke-width="2" fill="none" />',
[Arr1.x, Arr1.y, Dest.x, Dest.y,
Arr2.x, Arr2.y]);
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(' </g>'); //end the group
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(XMLNewLine);
end;
{Draws a line in an SVG file.
~param SVGFile the stream of the SVG file to draw the line in
~param Xs, Ys starting position of the line
~param Xe, Ye end point of the line }
procedure SVGDrawLine(SVGFile: TBufferStream; Xs, Ys, Xe, Ye: Integer);
begin //simply draw the line
SVGFile.WriteFormatted(' <line x1="%d" y1="%d" x2="%d" y2="%d" stroke="black" stroke-width="2" />',
[Xs, Ys, Xe, Ye]);
SVGFile.WriteString(XMLNewLine);
SVGFile.WriteString(XMLNewLine);
end;
{Creates the object and saves the name of the file.
~param FileName the name of the file the diagram should be saved as }
constructor TVectorFormatHandler.Create(const FileName: String);
begin
inherited Create; //create the object
FFileName := FileName; //save the name of the file
end;
{Sets the link target for the next box to be drawn. Should only be called once
for each box, if not called or with an empty string no link will be generated
on the box.
~param Target the target the box should link to }
procedure TVectorFormatHandler.SetNextTextBoxesLinkTarget(const Target:
String);
begin
//nothing to do in this abstract class
end;
{Creates the drawer of diagrams and saves the parameters.
~param Files the list of files to be written
~param FormatHandler the object used to do the actual drawing
~param URLCallBack if not nil, determines the URL to link each file to }
constructor TVectorFileDrawer.Create(Files: TFileList;
FormatHandler: TVectorFormatHandler;
URLCallBack: TGetFileURLCallBack);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -