ImageEn, unit iexUserInteractions

TIEPdfViewerInteraction.GetTextRects

TIEPdfViewerInteraction.GetTextRects


Declaration

function GetTextRects(CharIndex: Integer; Length: Integer; SelectionMerging: Integer = 3; ScreenValues: Boolean = True; SortRects: Boolean = False): array of TRect;


Description

Returns the rect(s) containing the text that starts at CharIndex of the specified length.

Parameter Description
CharIndex The starting position of the text
Count The length of the text (or -1 to get all text)
SelectionMerging Merges closely aligned selections into single ones. Sometimes the words in PDF documents have widely spaced letters that show as multiple selections. If you specify a value > zero, then selections that are less than that number PDF points apart will be merged into one
ScreenValues True to return values in terms of the current display (considering scroll, zoom, etc). False to return PDF document valyes (in PDF points)
SortRects Set to True if you want the rects to be sorted from top-to-bottom, then left-to-right

Multiple rects may be returned if the text is spaced or on multiple lines.
Result will be NIL if there are no rects found for the specified text range.

Notes:
- To convert a screen position to a CharIndex, use ScrToCharIndex
- To find text, use Find


Examples

// Get the location of the "Adobe" on the page
var
  wordIdx, wordLen, i: Integer;
  rects : TIERectArray;
begin
  memo1.Lines.Clear();

  // Get the location of the "Adobe" by index and count
  ImageEnView1.PdfViewer.Find( 'Adobe', False, False, False, False );
  ImageEnView1.PdfViewer.FindNext( wordIdx, wordLen, False, False );

  // Convert index and count to rects
  rects := ImageEnView1.PdfViewer.GetTextRects( wordIdx, wordLen );
  if rects = nil then
    memo1.Lines.Add( 'NOT FOUND!' )
  else
  for i := Low( rects ) to High( rects ) do
    memo1.Lines.Add( format( '(%d, %d, %d, %d)', [ rects[i].Left, rects[i].Top, rects[i].Right, rects[i].Bottom ]));
end;


// Same as above, but finds *all* instances of "Adobe" on the page
ImageEnView1.PdfViewer.Find( 'Adobe', False, False, False, False );
While ImageEnView1.PdfViewer.FindNext( wordIdx, wordLen, False, False ) do
begin
  // Convert index and count to rects
  rects := ImageEnView1.PdfViewer.GetTextRects( wordIdx, wordLen );
  if rects <> nil then
    for i := Low( rects ) to High( rects ) do
      memo1.Lines.Add( format( '(%d, %d, %d, %d)', [ rects[i].Left, rects[i].Top, rects[i].Right, rects[i].Bottom ]));
end;

// Output the locations of all text rects in current page to a memo (screen values)
var
  rects: TIERectArray;
  text: string;
begin
  rects := ImageEnView1.PdfViewer.GetTextRects( 0, -1 );
  for i := Low( rects ) to High( rects ) do
  begin
    text := ImageEnView1.PdfViewer.GetText( rects[i] );
    memo1.Lines.Add( Format( '%d (%d, %d, %d, %d): %s', [ i + 1, rects[i].Left, rects[i].Top, rects[i].Right, rects[i].Bottom, text ]));
  end;
end;

// Output the page text to a memo (attempting to format the layout with lines and spaces)
// Note: This is the same as calling Memo1.Text := GetText( true );
const
  Lines_Per_Page = 80; // Typical number of lines on a PDF document
  Chars_Per_Line = 120; // How many characters wide to make our text page
var
  rects: TIERectArray;
  text, currLine: string;
  i, currY: Integer;
  pageW, lineH, wantLeft: Integer;
  newLine: Boolean;
begin
  WindowState := wsMaximized;

  Memo1.Font.Name := 'Courier New'; // Fixed width font
  memo1.Clear;

  pageW := ImageEnView1.PdfViewer.PageWidth;
  lineH := ImageEnView1.PdfViewer.PageHeight div Lines_Per_Page;

  currY := ImageEnView1.PdfViewer.PageHeight; // Note: PDF values are bottom up
  rects := ImageEnView1.PdfViewer.GetTextRects( 0, -1, 3, False, True );

  newLine := False;
  currLine := '';

  for i := Low( rects ) to High( rects ) do
  begin
    text := ImageEnView1.PdfViewer.GetText( rects[i], False );

    // malformatted document?
    if ( text = '' ) or ( rects[i].Right < 0 ) or ( rects[i].Left > pageW ) then
      continue;

    while currY > rects[i].Top do
    begin
      memo1.Lines.Add( currLine );
      currLine := '';
      dec( currY, lineH );
      newLine := True;
    end;

    wantLeft := Round( Chars_Per_Line * rects[i].Left / pageW );
    while Length( currLine ) < wantLeft do
      currLine := currLine + ' ';

    currLine := currLine + text;

    if newLine then
      currY := rects[i].Bottom;
    newLine := False;
  end;
  if currLine <> '' then
      memo1.Lines.Add( currLine );
end;


See Also

- FindNext
- Find