📄 uicpdfdoc.pas
字号:
{ * * * *** * * * *** TICPDFVisitor *** * * * *** * * * }
{Creates the visitor and saves the reference on its generator.
~param Generator the generator for which the COM should be written }
constructor TICPDFVisitor.Create(Generator: TICPDFDoc);
begin
inherited Create(Generator); //create the object
FGenerator := Generator; //save the reference
end;
{Resets the attributes to ready the visitor for a new generation. }
procedure TICPDFVisitor.ResetForNewGeneration;
begin
inherited ResetForNewGeneration; //reset inherited state
FPreformattedDepth := 0; //reset to initial state
FDrawingDiagram := False;
end;
{Has to be called before visiting a COM to prepare the visitor. }
procedure TICPDFVisitor.StartVisit;
begin
//currently nothing has to be done
Assert(FPreformattedDepth = 0); //just check the initial state is correct
{
Assert(FFontSettingCount = 0);
PushFont(FGenerator.CurrentFont, FGenerator.CurrentStyle,
FGenerator.CurrentColor);
Assert(EAX = 1);
}
end;
{Has to be called after visiting a COM to perform follow-up operations.
~param EndLine whether the COM should be flushed to the PDF file and the line
be ended }
procedure TICPDFVisitor.EndVisit(EndLine: Boolean);
begin
if EndLine then //if the text should be written now
FTextWriter.EndLine; //write it
Assert(FPreformattedDepth = 0); //make sure everything has been closed
{
Assert((FLinkCount = 0) or
((FLinkCount = 1) and (FLinks[0].EndIndex <> -1)));
Assert(FFontSettingCount = 1);
PopFont(1);
}
end;
{Draws the created diagram on a bitmap and writes it with the generator.
~param Diagram the created diagram to save as an image
~param DiagramIndex the number of diagrams generated so far, used to create a
unique (file) name for the diagram }
procedure TICPDFVisitor.DrawDiagram(Diagram: TDiagram; DiagramIndex: Integer);
var Drawer :TPDFDiagramDrawer; //the drawer of the diagram
begin
if FGenerator.DiagramsDirectlyAsPDF then //diagrams should be drawn in PDF?
begin
FTextWriter.EndLine; //end the current paragraph
Drawer := TPDFDiagramDrawer.Create; //create object drawing the diagram
try
Drawer.Writer := FWriter; //assign the PDF file to draw it in
Drawer.Textwriter := FTextWriter; //and the manager of the content
//and a function to set the scaling of the diagram
Drawer.ScaleCallBack := CenteredImageScale;
FDrawingDiagram := True; //start drawing the diagram
Diagram.DrawWholeDiagramWith(Drawer); //draw diagram in the PDF file
Drawer.Finish; //let the drawer finish (clean up)
FCurrentDiagramSize := Diagram.Size; //save the size of the diagram
//let the links inside the image be added
Assert(Assigned(FTextWriter.OnImageLinks));
FTextWriter.OnImageLinks('', DiagramLinks,
Drawer.Size.x, Drawer.Size.y,
Drawer.Offset.x, Drawer.Offset.y);
//move below the image, the page is filled with the image?
if FTextWriter.MoveBelowImage(Drawer.Offset.y, Drawer.Size.y) then
FTextWriter.NewPage //start a new one
else
begin
//set the new position absolutely
FWriter.SetTextPoint(FTextWriter.LeftLineStart, FTextWriter.YPos);
FTextWriter.EndLine; //just start a new paragraph
end;
finally
Drawer.Free; //free the drawer object
end;
FDrawingDiagram := False; //diagram has been drawn
end
else
//draw the diagram as a PNG image and include that pixel data
inherited DrawDiagram(Diagram, DiagramIndex);
end;
{Writes the created diagram.
~param DiagramCode the code as returned by ~[link FGenerator].~[link
FGenerator.WriteImage WriteImage]
~param ImageSize the dimensions of the diagram in pixels }
procedure TICPDFVisitor.WriteDiagram(const DiagramCode: String;
ImageSize: TPoint);
begin
Assert(ImageSize.x > 0);
Assert(ImageSize.y > 0);
if DiagramCode <> '' then
begin
FTextWriter.EndLine; //end the current paragraph
DrawCenteredImage(DiagramCode, ImageSize, DiagramLinks); //draw the diagram
FTextWriter.EndLine; //and start a new paragraph
end;
end;
{Called for each manual link to an identifier or file with a not empty text.
~param Node the node of a link to an identifier or file with some text }
procedure TICPDFVisitor.LinkIdentifierWithText(Node: TICNLinkIdentifier);
var Ignore :Boolean; //whether the link should be ignored
begin
//get whether the target of the link is documented
Ignore := FGenerator.DoNotDocumentIdentifier(Node.Identifier, Node.TheFile);
if not Ignore then //link target documented?
//start the link on the identifier or file
FTextWriter.StartLink(ltThisDoc,
FGenerator.GetURIOf(Node.Identifier, Node.TheFile));
Node.VisitChildren(Self); //write the text
if not Ignore then //if not ignored
FTextWriter.EndLink; //end the link
end;
{Calculates the scaling factor for a centered image.
~param ImageSize the original size of the image in pixels
~result the scaling factor to be used when drawing the image }
function TICPDFVisitor.CenteredImageScale(ImageSize: TPoint): Single;
begin
//calculate scale factor for maximum size of the image
if ImageSize.y * (FTextWriter.LineWidth / ImageSize.x) >
FTextWriter.PageRect.Top - FTextWriter.PageRect.Bottom then
Result := (FTextWriter.PageRect.Top - FTextWriter.PageRect.Bottom) /
ImageSize.y
else
Result := FTextWriter.LineWidth / ImageSize.x;
if Result > FGenerator.MaxImageScale then //don't zoom the images too much
Result := FGenerator.MaxImageScale;
end;
{Draws a centered image.
~param ImageName the internal name of the image with which it has already been
registered in the PDF file
~param ImageSize the original size of the image in pixels
~param Links the list of links inside the image }
procedure TICPDFVisitor.DrawCenteredImage(const ImageName: String;
ImageSize: TPoint;
Links: TImageLinkList);
var ImageScale :Double; //value to the scale the image by
Position :TPDFPoint; //position of the image on the page
NewPage :Boolean; //whether a new page is needed
begin
Assert(ImageSize.x > 0);
Assert(ImageSize.y > 0);
FTextWriter.FlushLine; //end last paragraph/line
//calculate scale factor for maximum size of the image
ImageScale := CenteredImageScale(ImageSize);
//show the image on the page (may also be the next page)
NewPage := FTextWriter.ShowCenteredImage(ImageName,
ImageSize.x * ImageScale,
ImageSize.y * ImageScale, Position);
Assert(Assigned(FTextWriter.OnImageLinks));
//let the links inside the image be added
FTextWriter.OnImageLinks(ImageName, Links,
ImageSize.x * ImageScale, ImageSize.y * ImageScale,
Position.x, Position.y);
if NewPage then //the page is filled with the image?
FTextWriter.NewPage; //start a new one
end;
{Writes a heading for some information in the documentation.
~param Text the text of the heading to write
~param AfterParagraph whether the heading should start a new paragraph, it is
always written at least in a new line
~param NewLineAfter whether the heading should be on a line on its own and
the content below the heading, in some cases it may
instead follow directly after the heading }
procedure TICPDFVisitor.AddSmallHeading(const Text: String;
AfterParagraph: Boolean;
NewLineAfter: Boolean = True);
begin
if AfterParagraph then //bigger vertical separation?
FTextWriter.EndParagraph //start a new paragraph
else
FTextWriter.EndLine;
if NewLineAfter then //content on the next line?
FTextWriter.EnsurePageLines(2); //should not break in between
FTextWriter.AddStyledText(Text, pfsBold); //add the text of the heading
if NewLineAfter then //content on the next line?
FTextWriter.EndLine; //write the header
end;
{Writes a localized heading for some information in the documentation.
~param Text the text of the heading to be localized and written
~param AfterParagraph whether the heading should start a new paragraph, it is
always written at least in a new line
~param NewLineAfter whether the heading should be on a line on its own and
the content below the heading, in some cases it may
instead follow directly after the heading }
procedure TICPDFVisitor.AddSmallLocalizedHeading(Text: TDocumentationTexts;
AfterParagraph: Boolean;
NewLineAfter: Boolean = True);
begin //write the localized heading
AddSmallHeading(DocumentationTexts[Text].T, AfterParagraph, NewLineAfter);
end;
{Writes some text into the PDF file.
~param Text the text to be written in the PDF file }
procedure TICPDFVisitor.WriteText(const Text: String);
var Index :Integer; //beginning of current line
EndLine :Integer; //end of the line
begin
if Text <> '' then //text not empty?
begin
//format not relevant?
if (FPreformattedDepth = 0) and not FGenerator.KeepRawLineBreaks then
FTextWriter.AddText(Text) //just add the text
else
begin
Index := 1; //search through whole string
repeat
EndLine := SearchString(#10, Text, Index); //search end of line
if EndLine <> 0 then //next line found?
begin //add text of current line
FTextWriter.AddText(TrimRight(Copy(Text, Index, EndLine - Index)));
FTextWriter.FlushLine; //write the line
Index := EndLine + 1; //resume with next line
end;
until EndLine = 0; //until in last line
//just add the last line
FTextWriter.AddText(Copy(Text, Index, High(Length(Text))));
end; //else not LineBreak
end; //if Text <> ''
end;
{Writes the localized version of the text.
~param Text the text to be written in its localized version }
procedure TICPDFVisitor.Localize(Text: TDocumentationTexts);
begin
FTextWriter.AddText(DocumentationTexts[Text].T); //get and write the text
end;
{Called for all text nodes in the ~[link UICNodes COM].
~param Text the text of the node }
procedure TICPDFVisitor.Text(const Text: String);
begin
WriteText(Text); //just write the text
end;
{Called for all raw text nodes/raw data in the ~[link UICNodes COM]. This is
not supported in PDF.
~param Text the raw data to be inserted unchanged in the documentation }
procedure TICPDFVisitor.RawText(const Text: String);
begin
if TrimLeft(Text) <> '' then
//generate a warning message and just ignore the raw code
FGenerator.AddPositionMessage(FGenerator.MakeDocMessagesID,
Ord(mdmkNotSupported),
DocumentationTexts[dtRawDataNotSupportedInPDF].T);
end;
{Called for all nodes of all kinds of breaks in the ~[link UICNodes COM].
This means line breaks or paragraph breaks.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -