Techninis straipsnis

Pasenęs tekstas po redagavimo: PDFium FPDF_TEXTPAGE podėlis

AddText pakeičia PDF puslapį, tačiau iškart iškviestas FindFirst gali nematyti pakeitimo, nes TPdf vis dar turi seną FPDF_TEXTPAGEAddTextFindFirstTPdfFPDF_TEXTPAGE

Kodėl PDFium iškart po redagavimo grąžina pasenusį tekstą

FPDFText_LoadPage sukuria teksto puslapį iš turinio srauto, o redagavimo API veikia kitoje objektų grafiko dalyjeFPDF_TEXTPAGEFPDFText_LoadPageFPDFPage_InsertObjectFPDFPage_GenerateContent

TPdf teksto podėlyje: FTextPage, LoadTextPage ir UnloadTextPage

TPdf FTextPage lauką valdo LoadTextPage ir UnloadTextPage, kuris taip pat panaikina saitynų bei paieškos podėlįTPdfFTextPageLoadTextPageFTextPageFPDFText_LoadPageLoadTextPageUnloadTextPageFPDFText_ClosePageFTextPage

Text, FindFirst ir GetWebLinks naudoja LoadTextPage, todėl senoji rankena pati neaptinka, kad puslapis buvo redaguotasTPdfTextFindFirstGetWebLinksLoadTextPageFTextPageUnloadPage

Kurie PDFiumPas metodai podėlį atnaujina automatiškai

AddText, SetText, SetTextPositions, AddPath, RemoveObject ir InsertFormObjectFromXObject prieš UpdatePage iškviečia UnloadTextPageTPdfAddTextSetTextSetTextPositionsAddPathRemoveObjectInsertFormObjectFromXObjectUnloadTextPageUpdatePageFPDFPage_GenerateContentTextFindFirstGetWebLinks

var
  Pdf: TPdf;
  Index: Integer;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'invoice.pdf';
    Pdf.Active := True;
    Pdf.PageNumber := 1;

    Pdf.AddText('Reviewed by J. Alvarez', 'Helvetica', 10, 72, 40, clBlack, 255, 0);
    // AddText already closed the cached text page, so this FindFirst
    // call rebuilds it fresh before it searches
    Index := Pdf.FindFirst('Reviewed by J. Alvarez');
    if Index >= 0 then
      ShowMessage('Stamp confirmed at character ' + IntToStr(Index));
  finally
    Pdf.Free;
  end;
end;

Šablonas, kuris vis dar sugenda: podėliuojama neapdorota TextPage rankena

TextPage savybė leidžia iškviesti neapgaubtą FPDFText_* funkciją, tačiau nukopijuotos FPDF_TEXTPAGE rankenos gyvavimo ciklas nebesekamasTPdfTextPageFPDFText_*FPDF_TEXTPAGEUnloadTextPage

var
  Pdf: TPdf;
  RawHandle: FPDF_TEXTPAGE;
  StaleCount: Integer;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'contract.pdf';
    Pdf.Active := True;
    Pdf.PageNumber := 1;

    RawHandle := Pdf.TextPage;    // FPDFText_LoadPage handle, cached in FTextPage
    Pdf.SetText(0, 'Amended Clause 4.2');
    // SetText already closed RawHandle and set Pdf.TextPage back to nil.
    // Calling any FPDFText_* function against the old value now touches a
    // handle PDFium has already freed — undefined behavior, not a bug you
    // can catch with a nil check
    StaleCount := FPDFText_CountChars(RawHandle);
  finally
    Pdf.Free;
  end;
end;

Naudoti rankeną po FPDFText_ClosePage yra neapibrėžta, todėl Pdf.TextPage skaitykite iš naujo iškart prieš FPDFText_* iškvietimąFPDFText_ClosePagePdf.TextPageFPDFText_*

Grupuokite redagavimus, tada atlikite vieną užklausą

Po kiekvieno redagavimo nereikia atlikti papildomos teksto užklausos, nes kiekvienas metodas jau sumoka podėlio panaikinimo kainąAddTextRemoveObjectFPDFText_LoadPage

var
  Pdf: TPdf;
  I: Integer;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'watermarked.pdf';
    Pdf.Active := True;
    Pdf.PageNumber := 1;

    // Strip every text object that looks like a draft watermark. Each
    // RemoveObject call already invalidates the cache on its own, so
    // nothing needs refreshing by hand between iterations
    for I := Pdf.ObjectCount - 1 downto 0 do
      if (Pdf.ObjectType[I] = otText) and (Pdf.ObjectBounds[I].Top > 700) then
        Pdf.RemoveObject(I, True);

    // Query once, after the whole batch is done, not once per removal
    if Pdf.FindFirst('DRAFT') < 0 then
      ShowMessage('Watermark cleared');
  finally
    Pdf.Free;
  end;
end;

FindNext ir FindPrevious tęsia FindFirst seansą, tačiau po redagavimo reikia pradėti naują paiešką su FindFirstFindNextFindPreviousFindFirstUnloadTextPageFindNextFindFirstFindFirst

Kaip tai susiję su išskleidimu ir anotacijomis

Nepakeisto puslapio teksto išskleidimas šios problemos neturi, nes jokia operacija nepanaikina rankenosTextsusijusį straipsnį apie teksto išskleidimą su PDFiumPas

Podėlio gyvavimo ciklas svarbus redaguojant ir iškart ieškant teksto, tikrinant ištrynimą ar kuriant anotaciją pagal koordinatesketurių taškų žymėjimo anotacijos

TPdf redagavimo ir teksto API priklauso PDFium Component for Delphi ir C++BuilderTPdfPDFium Component