Rpreview issues - PDF

User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

I reported above some deficiencies in rendering colors by image2pdf. I also observed some inaccurate rendering in some other cases. Both word and fwh internal functions render more accurately. I can not explain the reasons. However, still the attraction is the tiny size of pdf files generated by image2pdf.

In fact, image2pdf reproduced colors printed by using :SayText() correctly but not background colors printed with :Say().
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

Mr. Tim

Please try using LoadLib32() instead of LoadLibrary()
Regards

G. N. Rao.
Hyderabad, India
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

Re: Rpreview issues - PDF

Post by TimStone »

Mr Rao,

I am using loadlib32() just like you originally suggested. The reason I was having problems is that I was using an older version of the Img2Pdf.dll. After Vilian provided the link, and I downloaded the newer version, all of the problems went away. In addition, my license works with the newer version.

I also noted your comments on the renderings. You have also made some other observations I am applying. I respect and appreciate the time you take to provide guidance, and I ALWAYS follow your suggestions.

The Invoice is a very complex document especially adding the colors. I think what remains now is some fine tuning of my code. There were some suggestions you made to improve calls that were working with the defaults, but may need more specific data to perform correctly. Also, it may be that I need to refine a bit of spacing. Specifically, the issues I have now are related to the box and shading I do which are only partially showing in the PDF. It may be that I'm overlapping some values.

One thing I would note is that sample code always use fixed values, and that typically applies to single page. However, a full document, like the Invoice to which this all applies, may have many pages as parts, labor, recommendations, totals, and disclaimer text are all dynamic. Rarely does it get confined to the small spaces defined in samples often used to demonstrate these principles. In fact, some of these invoices can go 10 or more pages if they involve a lot of work, with many parts and long descriptions. Samples have defined spaces for printing, but in real life, the location of all print output must be adjusted dynamically. I've done this for over 35 years and have refined the output quite cleanly. Now I just have to fine tune for the graphics being used.

I will be out of town tomorrow but will continue thursday. Thank you for all your help.


Sent from my iPhone using Tapatalk
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
TimStone
Posts: 2536
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Contact:

Re: Rpreview issues - PDF CONCLUSIONS

Post by TimStone »

My original goal was to use Img2PDF ( .dll ) which makes efficient, and quick, PDF's. It turned out I was using an older version, so I downloaded the update. Although I was able to get it working, there were issues still between that library and the View display of the document. I needed to use tPrinter's SayText() to display color properly, but this was causing issues in the ultimate PDF ( which is related to the no longer supported .dll functions ).

Originally I had avoided the use of the internal PDF development because my clients experienced many difficulties with it. However, when testing it now, I found the results to be far superior to Img2PDF in reproduction of the created documents. I was using a watermark ( not showing up in Img2Pdf ) and some other controls that just didn't reproduce well, and some text was being cut off near the lower part of the page.

The results with the FWH generated PDF is working well for me, and gives a great output that my customers will appreciate. It also accurately matches what is viewed and printed.

It is also nice to know how to substitute in my email system. My clients use a variety of resources for email, and many do it online which leaves no default email system on their computer. The installed default is Windows Mail, but it does NOT support MAPI services.
Tim Stone
http://www.MasterLinkSoftware.com
timstone@masterlinksoftware.com
Using: FWH 19.06 with Harbour 3.2.0 / Microsoft Visual Studio Community 2019
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

Let me explain how FWH creates PDF by default.

If you are generating PDF from the preview, the tpreview class first checks if MSWord is installed. If installed, the emf files are first converted to a Word Document and then saved as PDF instead of as docx. The PDF created is of good quality and of a reasonable size, but still larger than the pdfs created by Image2PDF.

If MSWord is not installed, then PDF is generated by FWH's own function. The quality is acceptable but a bit less than the PDF generated by MSWord. The major disadvantage is that the size of PDF is unduly large. So, this option needs to be used as the last option.

In case of simple documents without much color backgrounds and watermarks, it may still be good to use Image2PDF, because you already have it and use FWH's default in case of documents with color backgrounds and particularly water marks. You may decide which suits which document the best. The biggest advantage of using Image2PDF is that it produces pdf with very tiny size and are suited well for attaching to emails.

In my earlier post, I reproduced PDF generated by all the three methods. Both word and FWH internal function reproduce colors and alignment more accurately than Image2PDF. In the same post, you can also see the sizes of the pdfs using the three methods.

Now, let me explain how you can control which way the PDF is generated.
For example, in your email function, you can

Code: Select all

if lUseImage2PDF
   YourI2PDFFunction(...)
else
   oPreview:SaveAs( .T.,  ; // .T. for PDF and .F. for docx
                    cFileName, ;
                    lView ) // .T. displays the PDF after saving.
endif
 
Regards

G. N. Rao.
Hyderabad, India
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Rpreview issues - PDF

Post by mastintin »

and use this ?
have an example for fivewin.
https://github.com/APerricone/emf2pdf
Is pure harbour code and use libharu .
I use harupdf with good results.
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

Good option.
Can you also please guide a normal user how to use and what libs to link to save preview to pdf?
Regards

G. N. Rao.
Hyderabad, India
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Rpreview issues - PDF

Post by mastintin »

nageswaragunupudi wrote:Good option.
Can you also please guide a normal user how to use and what libs to link to save preview to pdf?
I use Harupdf from Carlos Mora lib : https://bitbucket.org/carlos_mora/pdfprinter , to print pdfs, but this option seems very good and apparently easy to implement.
I will try to look at it to see how it works.
regards
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Rpreview issues - PDF

Post by mastintin »

I have looked at it...
With the cpp code it does not work at all ( for example the box ) and it breaks if they are several pages.
With the prg code , not work , it seems that the implementation is not finished.
Part of implementation of fonts is missing.
It is an interesting job, but at the moment not usable. :(
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

Disappointing news.
Hope the author or masters like you continue the work and finish it for the benefit of all of us.

May I ask? At present, how are you saving preview to pdf? (i.e., emf to pdf)
Regards

G. N. Rao.
Hyderabad, India
User avatar
mastintin
Posts: 1502
Joined: Thu May 27, 2010 2:06 pm

Re: Rpreview issues - PDF

Post by mastintin »

nageswaragunupudi wrote: May I ask? At present, how are you saving preview to pdf? (i.e., emf to pdf)
Depending on the case .
To print directly to pdf I use Tharupdf code to build printer job.
For Preview, i use Standard code from fivewin .
I have a small modification in prv2pdf.prg code to determine Quality and density in images in pdf files ( use gdiplus code )

Code: Select all


function FWSavePreviewToPDF( oDevice, cPDF, lOpen, lQuality, nQuality  )   // oDevice can be oPrinter or oPreview

   local cOrient, oPDF
   local hWnd
   LOCAL aDatos:= {}
   DEFAULT lQuality := .f.

   IF Empty( nQuality )
      nQuality := 50
      nDensity := 300
      lQuality := .t.
   ENDIF

   if lQuality

      EDITVARS nQuality,nDensity TITLE "Atencion" PROMPTS "Calidad", "Densidad" ;
      PICTURES "999", "999"

     // aDatos:= { @nQuality, @nDensity }
     // MsgGet( "Atencion",{ "Calidad", "Densidad" }, aDatos ) // @nQuality  )

   endif

   if oDevice:IsKindOf( "TPREVIEW" )
      hWnd    := oDevice:oWnd:hWnd
      oDevice := oDevice:oDevice
   endif
 

   DEFAULT cPDF   := cGetFile( FWString( "PDF files | *.pdf |" ),;
                               FWString( "Select PDF File to Save" ),, ;
                               CurDir(), .T.,,,;
                               hb_CurDrive() + ":\" + CurDir() + "\" + ;
                               If( oDevice:IsKindOf( "TPreview" ),;
                               oDevice:cName, oDevice:cDocument ) + ".pdf"  )
   if ! Empty( cPDF )
      cPDF = cFileSetExt( cPDF, "pdf" )
      CursorWait()
      cOrient = If( oDevice:nHorzSize() > oDevice:nVertSize(), 'L', 'P' )
      oPdf = fwPdf():New( cPdf, cOrient, nQuality, nDensity )
      AEval( oDevice:aMeta, { | cMeta | oPdf:AddMeta( cMeta ) } )
      oPdf:Close()
      CursorArrow()

      DEFAULT lOpen := MsgYesNo( If( FWLanguageID() == 2, FWString( "¿" ) + " ", "" ) + ;
                       FWString( "View" ) + ;
                       " " + cPDF + " " + FWString( "(Y/N)" ) + " ?",;
                       FWString( "Please select" ) )

      if lOpen
         ShellExecute( IfNil( hWnd, GetWndDefault() ), "open", cPDF )
      endif
   else
      cPDF  := nil
   endif
return cPDF

Code: Select all

static function Emf2Jpeg( cEMF , nCalidad, nDensity )

   local cJpeg    := cFileSetExt( cEMF, "jpg" )
   local cBuf, lRet := .f.

       DEFAULT nCalidad := 20
       DEFAULT nDensity := 300

       NewEMFtoJPG ( cEMF , cJPeg , nCalidad, nDensity )

     cBuf   := If( File( cJpeg ), MemoRead( cJpeg ), "" )
     FErase( cJpeg )

return cBuf

 

Code: Select all

Function NewEMFtoJPG ( cFileIni , cFileFin , nQuality, nDensity )

local hbmp
local cBuffer
local obmp:=GDIbmp():new()  // inicializa sistema gdi+

DEFAULT nQuality := 100
DEFAULT nDensity := 300

   if upper(right(cfileIni,3)) == "EMF"

      GDIPLUSEMFTOJPG( cFileIni , AllTrim( cFileFin )  , nQuality,  nDensity )
   endif

Return nil

 

Code: Select all

HB_FUNC( GDIPLUSEMFTOJPG )
{

  FILE * fil = fopen (  hb_parc(1) , "rb" ) ;
  fseek ( fil , 0 , SEEK_END ) ;
  int filesize = ftell ( fil ) ;

  fseek ( fil , 0 , SEEK_SET ) ;
  HGLOBAL hglobal = GlobalAlloc ( GMEM_MOVEABLE , filesize ) ;

  char * adr = (char *)GlobalLock ( hglobal ) ;
  int nbytes = fread ( adr , 1 , filesize , fil ) ;
  fclose ( fil ) ;

  if ( nbytes != filesize )
      {
       MessageBox( GetActiveWindow(), "fallo", "No carga la imagen", 0x30 );
      } ;

  LPSTREAM pstm = NULL ;
  GlobalUnlock ( hglobal ) ;

 CreateStreamOnHGlobal ( hglobal, TRUE, &pstm ) ;

 Metafile * original  = new Metafile( pstm ) ;

 LPWSTR filefin =   AnsiToWide( ( char * ) hb_parc( 2 ) );

 long quality  =  hb_parnl(3) ;
 double nDensity =  hb_parnl(4) ;

 int nWidth  =  original->GetWidth()  ;
 int nHeight =  original->GetHeight() ;

 CLSID  EncoderQuality ;

  double nAlto ;
  double nAncho ;

  if ( nWidth > nHeight )
     {
       nAlto  = ( 210 * nDensity ) / 25.4  ;
       nAncho = ( 297 * nDensity ) / 25.4  ;
     }
  else
     {
       nAncho =  ( 210 * nDensity) / 25.4  ;
       nAlto  =  ( 297 * nDensity ) / 25.4  ;
     }

  nHeight  = (int) nAlto ;
  nWidth   = (int) nAncho ;


  Bitmap * newImage = new Bitmap(nWidth, nHeight );
           newImage->SetResolution( nDensity, nDensity );

  Graphics * g =  new Graphics( newImage );
  g->Clear( Color::White ) ;
  g->SetSmoothingMode( SmoothingModeAntiAlias );

  g->DrawImage( original,0, 0, nWidth, nHeight);

  CLSIDFromString( L"{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}", &EncoderQuality ) ;
  EncoderParameters encoderParameters;

   encoderParameters.Count = 1;
   encoderParameters.Parameter[0].Guid = EncoderQuality ;
   encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
   encoderParameters.Parameter[0].NumberOfValues = 1;

  encoderParameters.Parameter[0].Value = &quality ;

  CLSID cClsid ;

  CLSIDFromString( L"{557CF401-1A04-11D3-9A73-0000F81EF32E}" , &cClsid ) ;

   newImage->Save( filefin , &cClsid, &encoderParameters );

  delete newImage ;
  delete g ;
  delete original ;
  pstm->Release();

}
 
hua
Posts: 861
Joined: Fri Oct 28, 2005 2:27 am

Re: Rpreview issues - PDF

Post by hua »

Will this be in FWH19.04 Rao?
mastintin wrote: Depending on the case .
To print directly to pdf I use Tharupdf code to build printer job.
For Preview, i use Standard code from fivewin .
I have a small modification in prv2pdf.prg code to determine Quality and density in images in pdf files ( use gdiplus code )

Code: Select all


function FWSavePreviewToPDF( oDevice, cPDF, lOpen, lQuality, nQuality  )   // oDevice can be oPrinter or oPreview

   local cOrient, oPDF
   local hWnd
   LOCAL aDatos:= {}
   DEFAULT lQuality := .f.

   IF Empty( nQuality )
      nQuality := 50
      nDensity := 300
      lQuality := .t.
   ENDIF

   if lQuality

      EDITVARS nQuality,nDensity TITLE "Atencion" PROMPTS "Calidad", "Densidad" ;
      PICTURES "999", "999"

     // aDatos:= { @nQuality, @nDensity }
     // MsgGet( "Atencion",{ "Calidad", "Densidad" }, aDatos ) // @nQuality  )

   endif

   if oDevice:IsKindOf( "TPREVIEW" )
      hWnd    := oDevice:oWnd:hWnd
      oDevice := oDevice:oDevice
   endif
 

   DEFAULT cPDF   := cGetFile( FWString( "PDF files | *.pdf |" ),;
                               FWString( "Select PDF File to Save" ),, ;
                               CurDir(), .T.,,,;
                               hb_CurDrive() + ":\" + CurDir() + "\" + ;
                               If( oDevice:IsKindOf( "TPreview" ),;
                               oDevice:cName, oDevice:cDocument ) + ".pdf"  )
   if ! Empty( cPDF )
      cPDF = cFileSetExt( cPDF, "pdf" )
      CursorWait()
      cOrient = If( oDevice:nHorzSize() > oDevice:nVertSize(), 'L', 'P' )
      oPdf = fwPdf():New( cPdf, cOrient, nQuality, nDensity )
      AEval( oDevice:aMeta, { | cMeta | oPdf:AddMeta( cMeta ) } )
      oPdf:Close()
      CursorArrow()

      DEFAULT lOpen := MsgYesNo( If( FWLanguageID() == 2, FWString( "¿" ) + " ", "" ) + ;
                       FWString( "View" ) + ;
                       " " + cPDF + " " + FWString( "(Y/N)" ) + " ?",;
                       FWString( "Please select" ) )

      if lOpen
         ShellExecute( IfNil( hWnd, GetWndDefault() ), "open", cPDF )
      endif
   else
      cPDF  := nil
   endif
return cPDF

Code: Select all

static function Emf2Jpeg( cEMF , nCalidad, nDensity )

   local cJpeg    := cFileSetExt( cEMF, "jpg" )
   local cBuf, lRet := .f.

       DEFAULT nCalidad := 20
       DEFAULT nDensity := 300

       NewEMFtoJPG ( cEMF , cJPeg , nCalidad, nDensity )

     cBuf   := If( File( cJpeg ), MemoRead( cJpeg ), "" )
     FErase( cJpeg )

return cBuf

 

Code: Select all

Function NewEMFtoJPG ( cFileIni , cFileFin , nQuality, nDensity )

local hbmp
local cBuffer
local obmp:=GDIbmp():new()  // inicializa sistema gdi+

DEFAULT nQuality := 100
DEFAULT nDensity := 300

   if upper(right(cfileIni,3)) == "EMF"

      GDIPLUSEMFTOJPG( cFileIni , AllTrim( cFileFin )  , nQuality,  nDensity )
   endif

Return nil

 

Code: Select all

HB_FUNC( GDIPLUSEMFTOJPG )
{

  FILE * fil = fopen (  hb_parc(1) , "rb" ) ;
  fseek ( fil , 0 , SEEK_END ) ;
  int filesize = ftell ( fil ) ;

  fseek ( fil , 0 , SEEK_SET ) ;
  HGLOBAL hglobal = GlobalAlloc ( GMEM_MOVEABLE , filesize ) ;

  char * adr = (char *)GlobalLock ( hglobal ) ;
  int nbytes = fread ( adr , 1 , filesize , fil ) ;
  fclose ( fil ) ;

  if ( nbytes != filesize )
      {
       MessageBox( GetActiveWindow(), "fallo", "No carga la imagen", 0x30 );
      } ;

  LPSTREAM pstm = NULL ;
  GlobalUnlock ( hglobal ) ;

 CreateStreamOnHGlobal ( hglobal, TRUE, &pstm ) ;

 Metafile * original  = new Metafile( pstm ) ;

 LPWSTR filefin =   AnsiToWide( ( char * ) hb_parc( 2 ) );

 long quality  =  hb_parnl(3) ;
 double nDensity =  hb_parnl(4) ;

 int nWidth  =  original->GetWidth()  ;
 int nHeight =  original->GetHeight() ;

 CLSID  EncoderQuality ;

  double nAlto ;
  double nAncho ;

  if ( nWidth > nHeight )
     {
       nAlto  = ( 210 * nDensity ) / 25.4  ;
       nAncho = ( 297 * nDensity ) / 25.4  ;
     }
  else
     {
       nAncho =  ( 210 * nDensity) / 25.4  ;
       nAlto  =  ( 297 * nDensity ) / 25.4  ;
     }

  nHeight  = (int) nAlto ;
  nWidth   = (int) nAncho ;


  Bitmap * newImage = new Bitmap(nWidth, nHeight );
           newImage->SetResolution( nDensity, nDensity );

  Graphics * g =  new Graphics( newImage );
  g->Clear( Color::White ) ;
  g->SetSmoothingMode( SmoothingModeAntiAlias );

  g->DrawImage( original,0, 0, nWidth, nHeight);

  CLSIDFromString( L"{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}", &EncoderQuality ) ;
  EncoderParameters encoderParameters;

   encoderParameters.Count = 1;
   encoderParameters.Parameter[0].Guid = EncoderQuality ;
   encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
   encoderParameters.Parameter[0].NumberOfValues = 1;

  encoderParameters.Parameter[0].Value = &quality ;

  CLSID cClsid ;

  CLSIDFromString( L"{557CF401-1A04-11D3-9A73-0000F81EF32E}" , &cClsid ) ;

   newImage->Save( filefin , &cClsid, &encoderParameters );

  delete newImage ;
  delete g ;
  delete original ;
  pstm->Release();

}
 
FWH 11.08/FWH 19.03
xHarbour 1.2.1 (Rev 6406) + BCC
Harbour 3.1 (Rev 17062) + BCC
Harbour 3.2.0dev (r1904111533) + BCC
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

Mr. hua

No.

Looks like you got the impression that Mr. Manuel (mastintin) is using GDI+ function and FWH is not using.
The fact is FWH also is using GDI+ function.
There is no need to change it now.
Regards

G. N. Rao.
Hyderabad, India
hua
Posts: 861
Joined: Fri Oct 28, 2005 2:27 am

Re: Rpreview issues - PDF

Post by hua »

Oh ok then. I thought FWH is using something other than Haru pdf
FWH 11.08/FWH 19.03
xHarbour 1.2.1 (Rev 6406) + BCC
Harbour 3.1 (Rev 17062) + BCC
Harbour 3.2.0dev (r1904111533) + BCC
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Rpreview issues - PDF

Post by nageswaragunupudi »

hua wrote:Oh ok then. I thought FWH is using something other than Haru pdf
Again NO.
FWH is not using Haru pdf.
Mr. Manuel (mastintin) also is not using Harupdf for saving preview (emf) to pdf.
Both mastintin and FWH are using GDI+ (different functions) for converting emf to jpg and then embed in pdf.
Regards

G. N. Rao.
Hyderabad, India
Post Reply