⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 updftextwriter.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:


   { * * *  ***  * * *  ***   TPDFTextColumn   ***  * * *  ***  * * *  }

{$IFDEF DEBUG}
    //just a simple counter as an information how often the code in
    //~[link TPDFTextColumn] is executed
var CreateCounterTPDFTextColumn: Cardinal = 0;
{$ENDIF}



{Creates the object to represent a cell of a table without content.
~param Owner  the manager of the current table row which owns this text object
~param Writer the writer of the PDF file
~param Left   horizontal position of the left border of the column
~param Right  horizontal position of the right border of the column }
constructor TPDFTextColumn.CreateEmptyColumn(Owner: TPDFTextWriterManager;
                                             Writer: TPDFWriter;
                                             Left, Right: TPDFValue);
begin
 Assert(Right > Left);

{$IFDEF DEBUG}
 Inc(CreateCounterTPDFTextColumn);                //count number of instances
{$ENDIF}

 inherited Create;                                //create the object

 FManager := Owner;                               //save the manager

 Owner.AddTextObject(Self);                       //and register itself to it

 FLeftPosition := Left;                           //save position and width
 FColumnWidth := Right - Left;                    //of the table cell

 FAlignment := taLeft;                            //use default alignment
 FVerticalAlignment := vaTop;

 //use the current font and select its color
 FCurrentParagraphFont.Font := Writer.FontType;
 FCurrentParagraphFont.Style := Writer.FontStyle;
 FCurrentParagraphFont.Size := Writer.Size;
 FCurrentParagraphFont.Color := Writer.Color;
end;

{Creates the object to represent the text of a cell of a table.
~param Owner             the manager of the current table row which owns this
                         text object
~param Writer            the writer of the PDF file
~param Left              horizontal position of the left border of the column
~param Right             horizontal position of the right border of the column
~param Alignment         the horizontal alignment of the text in the column
~param VerticalAlignment the vertical alignment of the content of the cell
~param FirstCharacter    the index of the first character in the array that is
                         part of this cell
~param LastCharacter     the index of the last character in the array that is
                         still part of this cell
~param Characters        the characters that are the text of the cell
~param CharWidths        the widths of the characters
~param Breakable         the kinds of the characters in the text, used to
                         determine where to break it
~param Attributes        the attributes of the text or parts of it
~param FirstAttr         the index of the first attribute inside this cell
~param LastAttr          the index of the last attribute inside this cell
~param Links             the links inside the text of this cell
~param FirstLink         the index of the first link inside this cell
~param LastLink          the index of the last link inside this cell }
constructor TPDFTextColumn.CreateColumn(Owner: TPDFTextWriterManager;
                                        Writer: TPDFWriter;
                                        Left, Right: TPDFValue;
                                        Alignment: TTextAlignment;
                                        VerticalAlignment: TVerticalAlignment;
                                        FirstCharacter, LastCharacter: Integer;
                                        const Characters: TCharacterArray;
                                        const CharWidths: TPDFValueArray;
                                        const Breakable: TCharacterBreakables;
                                        const Attributes: TParagraphAttributes;
                                        FirstAttr, LastAttr: Integer;
                                        const Links: TParagraphLinks;
                                        FirstLink, LastLink: Integer);
begin
 //create object and initialize base value
 CreateEmptyColumn(Owner, Writer, Left, Right);

 FAlignment := Alignment;                       //save the alignment
 FVerticalAlignment := VerticalAlignment;

 if LastCharacter >= FirstCharacter then        //cell is really not empty?
  begin
   //copy the characters and the attributes and links on them
   FCharacters := Copy(Characters, FirstCharacter,
                                   LastCharacter - FirstCharacter + 1);
   FAttributes := Copy(Attributes, FirstAttr, LastAttr - FirstAttr + 1);
   FLinks := Copy(Links, FirstLink, LastLink - FirstLink + 1);

   //adjust index to absolute values to the copied characters
   AdjustAttributeIndices(FirstCharacter);
   //calculate meta data of the text needed to write it
   CalculateTextMetaData(CharWidths, Breakable, FirstCharacter);
  end;
end;


{Creates the object to represent the text of a paragraph.
~param Owner          the manager of the paragraph which owns this text object
~param Writer         the writer of the PDF file
~param Left           horizontal position of the left border of the text
~param Right          horizontal position of the right border of the text
~param Alignment      the horizontal alignment of the paragraph
~param CharacterCount the number of valid characters in the array for the
                      paragraph
~param Characters     the characters that are the text of the paragraph
~param CharWidths     the widths of the characters
~param Breakable      the kinds of the characters in the paragraph, used to
                      determine where to break it
~param Attributes     the attributes of the text or parts of it
~param AttrCount      the number of valid attributes in the array
~param Links          the links inside the text of the paragraph
~param LinkCount      the number of valid links in the array
~param InLink         whether the beginning of the paragraph is already in a
                      link, i.e. whether the first link has already be
                      started in the previous paragraph }
constructor TPDFTextColumn.CreateTheText(Owner: TPDFTextWriterManager;
                                         Writer: TPDFWriter;
                                         Left, Right: TPDFValue;
                                         Alignment: TTextAlignment;
                                         CharacterCount: Integer;
                                         const Characters: TCharacterArray;
                                         const CharWidths: TPDFValueArray;
                                         const Breakable: TCharacterBreakables;
                                        const Attributes: TParagraphAttributes;
                                         AttrCount: Integer;
                                         const Links: TParagraphLinks;
                                         LinkCount: Integer;
                                         InLink: Boolean);
begin
 //create object and initialize base value
 CreateEmptyColumn(Owner, Writer, Left, Right);

 FAlignment := Alignment;                       //save the alignment and
 FCharacters := Copy(Characters, 0, CharacterCount); //copy all the data
 FAttributes := Copy(Attributes, 0, AttrCount);
 FLinks := Copy(Links, 0, LinkCount);
 FInLink := InLink;

 Assert(not InLink or (LinkCount > 0));

 //if in a link, set the color of the text to signal the link
 if InLink then
  FCurrentParagraphFont.Color := Owner.FTextWriter.LinkColors[Links[0].
                                                                     LinkType];
 if CharacterCount > 0 then                     //paragraph not empty?
  //calculate meta data of the text needed to write it
  CalculateTextMetaData(CharWidths, Breakable, 0);
end;

{Frees the object and unregisters it from its manager. }
destructor TPDFTextColumn.Destroy;
begin
 if Assigned(FManager) then                //assigned to a manager object?
  FManager.TextObjectFreed(Self);            //unregister it from the manager

 inherited Destroy;                        //free the object
end;







{Adjusts the indices of characters for the attributes and links if only part of
 the text is written with this object.
~param By the value by which the indices have to be adjusted }
procedure TPDFTextColumn.AdjustAttributeIndices(By: Integer);
var       i             :Integer;        //counter through attributes and links
begin
 for i := Low(FAttributes) to High(FAttributes) do //for each attribute
  begin
   Assert(FAttributes[i].StartIndex > By);
   Dec(FAttributes[i].StartIndex, By);              //adjust its starting index
  end;
 for i := Low(FLinks) to High(FLinks) do           //for each link
  begin
   Assert(FLinks[i].StartIndex > By);
   Dec(FLinks[i].StartIndex, By);                    //adjust its indices
   Assert(FLinks[i].EndIndex <> -1);
   Assert((FLinks[i].EndIndex = -1) or (FLinks[i].EndIndex > By));
   Dec(FLinks[i].EndIndex, By);
  end;
end;


{Calculates meta data about the text after the object has been created and the
 text saved.
~param CharWidths an array with the widths of all characters in
                  ~[link FCharacters]
~param Breakable  the kinds of the characters in ~[link FCharacters], used to
                  determine where to break the text
~param FirstIndex the index of the first valid entries in the two arrays }
procedure TPDFTextColumn.CalculateTextMetaData(
                                         const CharWidths: TPDFValueArray;
                                         const Breakable: TCharacterBreakables;
                                         FirstIndex: Integer);
begin
 //create array with the summed-up widths of characters
 SetLength(FSumCharWidths, Length(FCharacters) + 1);
 //and calculate the summed-up widths
 CalculateSumCharWidths(@CharWidths[FirstIndex], FSumCharWidths);
 //calculate the (maximum) font size of the text
 CalculateFontSize(FAttributes);
 //calculate the number of lines needed to show the text and where to break it
 CalculateLines(@Breakable[FirstIndex]);
end;

{Calculates the summed up widths of the characters in the paragraph.
~param CharWidths    the widths of all characters in ~[link FCharacters] to
                     sum up
~param SumCharWidths the array in which to save the summed-up widths }
procedure TPDFTextColumn.CalculateSumCharWidths(
                                          CharWidths: PPDFValue;
                                          const SumCharWidths :TPDFValueArray);
          //type to access the next value in an array of TPDFValues by pointer
type      TPDFValueIndexer = array[0..1] of TPDFValue;
var       i             :Integer;       //counter through the widths
          Sums          :PPDFValue;     //runner through the sums
begin
 SumCharWidths[0] := 0;                 //for no characters the width is 0
 Sums := @SumCharWidths[0];
 //calculate sum of widths of all characters in the paragraph
 for i := 1 to High(SumCharWidths) do
  begin
   //add the width of the character to the last summed-up width
   TPDFValueIndexer(Pointer(Sums)^)[1] := Sums^ + CharWidths^;
   Inc(Sums);
   Inc(CharWidths);
  end;
end;

{Calculates the (maximum) font size used for the text.
~param Attributes the list of attributes that may change the size of the used
                  font, i.e. ~[link FAttributes] }
procedure TPDFTextColumn.CalculateFontSize(Attributes: TParagraphAttributes);
var       Size          :TPDFValue;       //the used maximum font size
          //whether the first font attribute has still to be found
          First         :Boolean;
          i             :Integer;         //counter through all attributes
begin
 Size := 0;                               //no font size found so far
 First := True;
 for i := Low(Attributes) to High(Attributes) do //for each attribute
  if Attributes[i].Attribute = aFont then        //if it sets the font
   begin
    if First then                                  //is the first font?
     begin
      First := False;                                //not anymore
      //some characters are before it?
      if Attributes[i].StartIndex <> 1 then
       Size := FManager.Writer.Size;                   //also use default font
     end;
    if Attributes[i].Font.Size > Size then         //is a bigger font?
     Size := Attributes[i].Font.Size;                //use its size
   end;
 if Size = 0 then                         //no font has been set?
  Size := FManager.TextWriter.CurrentFont.Size; //use default font size
 FFontSize := Size;                       //and set the font size
 Assert(Size <> 0);
end;

{Calculates the number of lines necessary to show the text in the available
 width and where to break it.
~param Breakables the kinds of the characters in ~[link FCharacters], used to
                  determine where to break the text }
procedure TPDFTextColumn.CalculateLines(Breakables: PCharacterBreakable);
var       Count         :Integer;    //number of lines
          StartChar     :Integer;    //the first characters of the lines
          LastChar      :Integer;    //the last character of the paragraph
begin
 Assert(FColumnWidth > 0);
 Assert(Length(FCharacters) <> 0);

 //get room for the information of the lines
 SetLength(FLineInfo,
           Trunc(2 * FSumCharWidths[High(FSumCharWidths)] / FColumnWidth) + 1);

 Count := 0;                      //no lines found yet
 StartChar := 1;                  //start with the first character
 LastChar := Length(FCharacters); //up to the last one
 repeat                           //until whole paragraph splitted up in lines
   if Count >= Length(FLineInfo) then          //not enough room for next line?
    if Count < 2 then                            //grow array for more room
     SetLength(FLineInfo, 2)
    else
     SetLength(FLineInfo, Count + Count div 2);

   //calculate the amount of text of the paragraph fitting in the next line
   FLineInfo[Count] := CalculateWrapPoint(StartChar, LastChar, FColumnWidth,
                                          FSumCharWidths,
                                          PCharBreaksArray(Breakables));
   StartChar := FLineInfo[Count].ResumePoint;  //get beginning of the next line
   Inc(Count);                                 //another line added

 until StartChar > LastChar;      //until whole paragraph splitted up in lines

 FLineCount := Count;             //save number of lines
end;




{Returns the number of spaces in the specified range of the paragraph.
~param FromIndex the beginning of the range to count the spaces in (1-based)
~param ToIndex   the end of the range to count the spaces in (1-based)
~result the number of spaces in the range }
function TPDFTextColumn.GetSpaceCount(FromIndex, ToIndex: Integer): Integer;
var      Chars         :PChar;             //runner through characters
         

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -