#1 2015-02-11 01:19:41

omersoft
Member
Registered: 2015-02-10
Posts: 2

rich text file and reverse hebrew lines

Hi,

I'm using delphi7 pro with quickreprt ver 5.  (Although I Own Delphi 2010 And XE4)

I Have 2 Issues To Solve And I Hope That I Get  Help To Solve Them.  (rich text file and reverse hebrew lines)

Usine unit SynPdf and Define -> Pdf : TPdfDocument;

1.rich text file lines -  the easy Issue.

during  QuickRep.Prepare ->  Excute Snip That Load rtf file to QRRichText component ->   QRRichText.Lines.LoadFromFile(Company_Logo_Rtf_File_Name);
the lines contain hebrew and english  text with few kind of fonts.
in lines that contain Font "MS San Serif "  the text became carbish. 
I Test  TQRSynPDFDocumentFilter (unit QRPDFSynFilt)  and the Rtf text shown Ok.
By Rename  The Font "MS San Serif "  to Other Font Like "Arial"  The Problem Solved.  But Sometimes It"s Exhausting To Search And Rename The Font.
any Idea How To Solve This Issue ?


2.Reverse Hebrew Text Lines.


{$define USE_UNISCRIBE}
{ - if defined, the PDF engine will use the Windows Uniscribe API  -> (usp10.dll)  }

Set  PdfDocument.UseUniscribe := True; //   TPdfDocument.UseUniscribe , if false the hebrew is in inverse

Lines that contain hebrew text and  english text or numbers  does not shown in the pdf file correct.
By using unit QRPDFFilt to create pdf file i add my own Inverse_str function in  procedure ProcessItem(ir: TPDFItemRec) that reverse the line
and then Search in the line the numbers and english parts and reverse then again.

  procedure ProcessItem(ir: TPDFItemRec);
  var   tstr : string;
         String_Contain_Hebrew_Chars : Boolean; 

  if ir.ItemType=IT_TEXT then
  begin

    tstr := ir.FText;

    String_Contain_Hebrew_Chars := String_Contain_Chars_In_Heb_Range(tstr);
    if String_Contain_Hebrew_Chars then
    begin
        tstr := Inverse_Str(tstr);   //  inverse and analize to find numbers and english snips
        ir.FText := tstr;
    end;
    ...
    ...
  end;

there is a way by using  TPdfDocument - unit SynPdf  to check and correct  the text line  ?

Does the reverse  done in Windows Uniscribe API . (usp10.dll)  ?

if the answer is Yes  then if  I will Set  PdfDocument.UseUniscribe := False
there is a way In unit SynPdf  to check and correct  the text line before excute the function textout ?

Tnx In Advance For Any Help .

Avi Jackobson.


//  reverse string and analize to find numbers and english snips 
function Inverse_Str(const S: String): String; 
var I,Snip_Length : Integer;
    F_I,T_I,N_I : Integer;
    S_Result,Snip_Str1,Snip_Str2 : string;

function Set_Not_Hebrew_Range(F_R,T_R : Integer) : Integer;
var I,Char_Ord : Integer;
begin

  Result := 0;

  F_I := 0;  T_I := 0;
//  for I := 1 To Length(S) do
  for I := F_R To T_R do
  begin
    Char_Ord := Ord(S[i]);

    if not (Char_Ord in [224..250]) then
    begin
      if (F_I = 0) and (not (Char_Ord in [0..47,58..64]))
        then F_I := I;
      if (F_I > 0) and (not (Char_Ord in [0..47,58..64]))
        then T_I := I; //Inc(T_I);
    end
    else
      if (F_I > 0)
        then Break;
      //  and (Char_Ord > 47) //(not (S[i] in [' ','+','/','\',',')) then Break;
  end;

  if (T_I > F_I) and (F_I > 0)
    then Result := T_I - F_I + 1;

end;

begin // Inverse_Str

  Result := S;

  if Trim(S) = ''
    then Exit;

  for I := Length(Result) downto 1 do
    Result[i] := S[Length(Result)-I+1];

  S_Result := Result;


  // next we have to find the numbers and english parts and to inverse them back

  F_I := 1;  T_I := Length(S);
  repeat
    Snip_Length := Set_Not_Hebrew_Range(F_I,T_I); 
    if Snip_Length > 0 then
    begin
      Snip_Str1 := Copy(S,F_I,Snip_Length); {T_I}
      Snip_Str2 := Snip_Str1;

      for I := Length(Snip_Str1) downto 1 do
        Snip_Str2[i] := Snip_Str1[Length(Snip_Str1)-I+1];

      if Snip_Str2 <> Snip_Str1
        then S_Result := StringReplace(S_Result,Snip_Str2,Snip_Str1,[]); // rfReplaceAll,rfIgnoreCase

      T_I := F_I + Snip_Length - 1;
    end
    else T_I := Length(S); // cause exit

    N_I := T_I + 1;
    if N_I < Length(S) then
    begin
      F_I := N_I;
      T_I := Length(S);
    end;

  until N_I >= Length(S);

//  S_Result := StringReplace(S_Result, '(', ')', [rfReplaceAll]);
//  S_Result := StringReplace(S_Result, ')', '(', [rfReplaceAll]);
  for I := 1 to Length(S_Result) do // Add At 03/2007
  begin
    if S_Result[i] = '('
      then S_Result[i] := ')'
      else
        if S_Result[i] = ')'
          then S_Result[i] := '(';
  end;

  Result := S_Result;

//  Result := ReverseString(S);  // In StrUtils

end;

Offline

#2 2015-02-11 20:09:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: rich text file and reverse hebrew lines

My concern is that Uniscribe is supposed to do the whole inversion by itself.
The glyph shading should take in account the logical -> physical conversion...
I would like to find the right way of consuming the Uniscribe API on those, but I tried to follow the docs at best...

Offline

#3 2015-02-14 22:04:24

omersoft
Member
Registered: 2015-02-10
Posts: 2

Re: rich text file and reverse hebrew lines

Hello ab,

    Thanks For Your Response.

    Since Windows Uniscribe API (usp10.dll) that used by unit SynPdf to inverse the hebrew text does not work ok.
    in a meanwhile (till find the right way of consuming the Uniscribe API on those)
    I  Inverse the lines with hebrew text with my functions.

    I Left  the boolean UseUniscribe := False and I  add my  inverse_str functions to 
    function TPdfWrite.AddUnicodeHexText(PW: PWideChar; NextLine: boolean; Canvas: TPdfCanvas): TPdfWrite;

    Since The Function AddUnicodeHexText Result Is PWideChar.
    the function Inverse_Str(const S: String): String   Adjusted to WideChar in ->  function Inverse_The_Text(const W : PWideChar): PWideChar;

begin   // AddUnicodeHexText
  if PW <> nil then
  begin
    with Canvas.FPage do
      if FFont.FTrueTypeFontsIndex = 0
        then TTF := nil  // mark we don't have an Unicode font, i.e. a TTF
        else TTF := TPdfFontTrueType(FFont);

    {} // 10/02/2015 , AJ , avi
    if not Canvas.fDoc.UseUniScribe then
    begin
      if String_Contain_Win_Heb_Chars(PW)
        then PW := Inverse_The_Text(PW);
    end;
    {}

{$ifdef USE_UNISCRIBE}
    // use the Windows Uniscribe API if required
    if not Canvas.fDoc.UseUniScribe or (TTF=nil) or
       not AddUnicodeHexTextUniScribe(PW,TTF.WinAnsiFont,NextLine,Canvas) then
{$endif}
      // fastest version, without Ordering and/or Shaping of the text
      AddUnicodeHexTextNoUniScribe(PW,TTF,NextLine,Canvas);
  end;
  result := self;
end;

Now The Inverse Work Fine For Me.


you have any idea about the Rich Text File Lines Problem.
why lines that contain hebrew chars with Font "MS San Serif "  showen as carbish text.

the test that done with TQRSynPDFDocumentFilter (unit QRPDFSynFilt)  the Rtf text shown Ok , I asume that
it a setting the right flags issue.

I'll Appreciation any Answer .

Avi

Offline

#4 2015-02-15 05:05:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: rich text file and reverse hebrew lines

Try to enable font fallback.

Offline

#5 2015-04-18 08:10:10

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,205
Website

Re: rich text file and reverse hebrew lines

Please try the latest SynPDF commit proposed by "nosa".
See http://synopse.info/forum/viewtopic.php?id=2515

It includes a lot of improvements for Uniscribe, especially for Right To Left languages.

Offline

Board footer

Powered by FluxBB