#1 2015-05-03 13:44:47

PeterPanino
Member
Registered: 2015-05-03
Posts: 1

Extended RTF formatting not saved with SynPDF

Hi! Create an RTF document file (e.g. in MS Word 2010) containing formatted text and an image. In Delphi XE7 (or Delphi XE8), load this RTF file in a TJvRichEdit:

procedure TForm1.btnLoadRTFClick(Sender: TObject);
begin
  JvRichEdit1.Lines.LoadFromFile(edtRTFFileToConvertToPDF.Text);
end;

RTF file loaded in TJvRichEdit

Then, with SynPDF save it to a PDF document:

uses mORMotReport;
...
with mORMotReport.TGDIPages.Create(Self) do
begin
  try
    BeginDoc;
    AppendRichEdit(JvRichEdit1.Handle);
    EndDoc;
    ExportPDF('R:\Exported.pdf', True, False);
  finally
    Free;
  end;
end;

This saves the format attributes Bold, Italic, Underlined and Text Color in the PDF, but NOT the Text Background Color:

PDF file created from TJvRichEdit with SynPDF

So how can I save ALL text formattings in the exported PDF?

Offline

#2 2015-05-05 05:32:09

nosa
Member
From: Tehran, Iran
Registered: 2015-04-15
Posts: 5
Website

Re: Extended RTF formatting not saved with SynPDF

Hi

I checked the issue with a sample EMF containing text with BkColor. As mentioned in this post, the background is not rendered in PDF.

It seems that (at least in a sample EMF) text's BkColor is not represented by brush color. In TPdfEnum.TextOut, OPAQUE processing is dependent to brush - and does not work properly. Also, font.BkMode is not necessarily set in EMFs. I am not sure if this is the case in all EMFs and all use cases, bit some minor changes worked for me (and the text backgrounds appeared in PDF):

procedure TPdfEnum.TextOut(var R: TEMRExtTextOut);
:
:
    bOpaque := (not brush.null) and (brush.Color<>clWhite) and
       ((R.emrtext.fOptions and ETO_OPAQUE<>0) or
        ((font.BkMode=OPAQUE) and (font.BkColor=brush.color)));

    bOpaque := (R.emrtext.fOptions and ETO_OPAQUE<>0);
:
:
      if bOpaque then begin
        FillRectangle(backRect,false);
        FillTextBk(backRect,false);
        bOpaque := False; //do not handle more
        :
:
    if bOpaque then
      // don't handle BkMode, since global to the page, but only specific text
      // don't handle rotation here, since should not be used much
      FillRectangle(backRect,true);
      FillTextBk(backRect,true);
:
:

FillTextBk is a new method which I wrote by copying FillRectangle and using font.BkColor instead of brush.color:

procedure TPdfEnum.FillTextBk(const Rect: TRect; ResetNewPath: boolean);
begin
  Canvas.NewPath;
  FillColor := DC[nDC].font.BkColor;
  with Canvas.BoxI(Rect,true) do
    Canvas.Rectangle(Left,Top,Width,Height);
  Canvas.Fill;
  if ResetNewPath then
    Canvas.FNewPath := false;
end;

As mentioned before, I am not sure if this fix is complete or covers all of use cases. It's just a work around for a specific problem in hand.

Cheers

Last edited by nosa (2015-05-05 05:34:48)

Offline

Board footer

Powered by FluxBB