[win32][cb]création directe de pdf

Description

Sa fait un bout de temps que je devais me mettre au PDF sans passer par des librairies non maîtrisées,
au final le fonctionnement est assez simple, étrangement il y a très peu de source sur le sujet, je poste donc une ébauche de création de fichier PDF.

Pour répondre aux questions :
- oui ce programme ne permet pas grand chose
- oui il manque 1 000 000 de fonctions
- oui le code n'est pas terminé/propre/ complètement documenté
- oui la fonction image n'est pas finie

Mais je vais voir pour le mettre à jour et pourquoi pas faire une interface GUI/RTF/PDF.

on verra, enjoy :p

Si vous avez la moindre remarque n'hésitez pas !!!

Source / Exemple :


//---------------------------------------------------------------------------------------------------------------
// Auteur :  Hanteville Nicolas
// mail : nico248@free.fr
// site : http://omni.a.free.fr
// (coder en C sur Code::Blocks)
// Cette application est libre de droits et
// est inspiré des documents PDF officiels et de la source si dessous.
//---------------------------------------------------------------------------------------------------------------
//doc gratuit d'adoble pour le format PDF : http://www.adobe.com/devnet/pdf/pdf_reference.html
//exemple d'ajout d'image : //http://www.codeproject.com/KB/graphics/imagestotextboxes.aspx
//---------------------------------------------------------------------------------------------------------------
#include "ressources.h"
//---------------------------------------------------------------------------------------------------------------
#define IDENTIFIANT_DOCUMENT "0123456789ABCDEF0123456789ABCDEF"
//---------------------------------------------------------------------------------------------------------------
// dessiner une image
//en dehors d'une stream !!!
void PDF_write_img(int x, int y, int x_s, int y_s, char *path_img, char *titre, HANDLE file_ext)
{
  //ouverture de l'image
  DWORD copiee;
  HANDLE Hsrc = CreateFile(path_img,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
  char *buffer;
  long taille_fic = 0;
  if (Hsrc != INVALID_HANDLE_VALUE)
  {
    taille_fic = GetFileSize(Hsrc,NULL);  //__int64 aurait été plus adapté mais ici que pour des fichiers texte de petites tailles
    if (taille_fic)
    {
      buffer = malloc(sizeof(char*)*taille_fic+1);
      ReadFile(Hsrc, buffer, taille_fic,&copiee,0);
      buffer[taille_fic]=0;

      //on crée l'entête + ajouter une image
      char tmp[MAX_PATH];
      DWORD copiee;
      _snprintf(tmp,MAX_PATH,"%d 0 obj << /Type /Page/Parent 2 0 R/Rotate 0/MediaBox [0 0 595 842]/CropBox [0 0 595842] /Resources"
                             "<</ProcSet /PDF/Text /Font<</T1 3 0 R/T2 4 0 R/T3 5 0 R/T4 6 0 R>> /XObject <</I1 %d 0 R >>>>"
                             "/Contents %d 0 R >>\r\nendobj\r\n",++nb_items,nb_items+1,nb_items+2);
      WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
      debut_emplacement += strlen(tmp);

      //contenu du stream
      //ajout de l'image (emplacement /taille
      char stream[MAX_PATH];
      _snprintf(stream,MAX_PATH,"\r\n"
                             "q\r\n"
                             "%d 0 0 %d 300 700 cm\r\n"
                             "1 0 0 1 0 0 cm\r\n"
                             "/I1 Do\r\n"
                             "Q\r\n"
                             "BT/T3 12 Tf\r\n"
                             "%d %d Td\r\n"
                             "(%s) Tj\r\n"
                             "ET\r\n"
                ,x_s,y_s,x,y,titre);

      //création pour écriture
      _snprintf(tmp,MAX_PATH,"%d 0 obj\r\n"
                             "<</Length %d >>\r\n"
                             "stream%s"
                             "endstream\r\n"
                             "endobj\r\n"
                ,++nb_items,strlen(stream),stream);
      WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
      debut_emplacement += strlen(tmp);

      //ajout du contenu du fichier (entête
      _snprintf(tmp,MAX_PATH,"%d 0 obj\r\n"
                             "<</Name/I1/Type/XObject/Subtype/Image\r\n"
                             "/Width %d\r\n"
                             "/Height %d\r\n"
                             "/Length %d\r\n"
                             "/Filter/DCTDecode/ColorSpace/DeviceRGB\r\n"
                             "/BitsPerComponent 8>>\r\n"
                             "stream\r\n"
                ,++nb_items,x_s,y_s,taille_fic+4);
      WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
      debut_emplacement += strlen(tmp);

      //contenu du fichier

      //manque l'encodage + commentaires

      WriteFile(file_ext,buffer,taille_fic,&copiee,0);
      debut_emplacement += taille_fic;

      //fin de stream
      _snprintf(tmp,MAX_PATH,"\r\nendstream\r\n"
                             "endobj\r\n"
                ,++nb_items,x_s,y_s,taille_fic+2);
      WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
      debut_emplacement += strlen(tmp);

      free(buffer);
    }
  }
  CloseHandle(Hsrc);
}
//---------------------------------------------------------------------------------------------------------------
// dessiner une ligne
void PDF_write_ligne(int x, int y, int x2, int y2, unsigned int epaisseur, HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"\r\n"
                         "%d w\r\n"       //épaisseur de la ligne en point
                         "%d %d m\r\n"    //point de départ de la ligne x,y
                         "%d %d l\r\n"    //point de fin de la ligne x,y
                         "S\r\n"          //c'est une ligne
                         "1 w\r\n"        //on remet l'épaisseur des traits à 1 pt / defaut
            ,epaisseur,x,y,x2,y2);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// dessiner une ligne en pointillé
void PDF_write_ligne_pointille(int x, int y, int x2, int y2,unsigned int epaisseur, HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"\r\n"
                         "%d w\r\n"       //épaisseur de la ligne en point
                         "[4 6] 0 d\r\n"  //format de pointillé en pts : 4pts en dur et 6pts vides
                         "%d %d m\r\n"    //point de départ de la ligne x,y
                         "%d %d l\r\n"    //point de fin de la ligne x,y
                         "S\r\n"          //c'est une ligne
                         "[ ] 0 d\r\n"    //on remet le format par défaut des lignes
                         "1 w\r\n"        //on remet l'épaisseur des traits à 1 pt / defaut
            ,epaisseur,x,y,x2,y2);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// dessiner un  rectangle avec couleur
void PDF_write_rectangle(int x, int y, int x2, int y2,unsigned int epaisseur
                         ,unsigned char c_r,unsigned char c_g,unsigned char c_b //% contour RGB
                         ,unsigned char i_r,unsigned char i_g,unsigned char i_b //% intérieur RGB
                        , HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"%d w\r\n"                   //épaisseur de la ligne en point
                         "%2.1f %2.1f %2.1f RG\r\n"   //couleur de contour en RGB sur 1 : 0.0 0.0 0.0 = noir
                         "%2.1f %2.1f %2.1f rg\r\n"   //couleur intérieur en RGB sur 1 : 0.0 0.0 0.0 = noir
                         "%d %d %d %d re\r\n"         //pt de début x,y et point opposé de fin x,y
                         "B\r\n"                      //un rectangle
                         "1 w\r\n"                    //on remet l'épaisseur des traits à 1 pt / defaut
                         "0.0 0.0 0.0 rg\r\n"         //réinit des couleur en noir par défaut
                         "0.0 0.0 0.0 RG\r\n"
            ,epaisseur,c_r/100.0,c_g/100.0,c_b/100.0,i_r/100.0,i_g/100.0,i_b/100.0,x,y,x2,y2);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// dessiner une elipse avec couleur
// pt_d_x = point de début, pt_f_x =  de fin, pt_i_x = intermédiaire
void PDF_write_elipse(int x, int y, int pt_d_x, int pt_d_y, int pt_i_x, int pt_i_y,int pt_f_x, int pt_f_y
                         ,unsigned int epaisseur
                         ,unsigned char c_r,unsigned char c_g,unsigned char c_b //% contour RGB
                         ,unsigned char i_r,unsigned char i_g,unsigned char i_b //% intérieur RGB
                         , HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"%d w\r\n"                 //épaisseur de la ligne en point
                         "%2.1f %2.1f %2.1f RG\r\n" //couleur de contour en RGB sur 1 : 0.0 0.0 0.0 = noir
                         "%2.1f %2.1f %2.1f rg\r\n" //couleur intérieur en RGB sur 1 : 0.0 0.0 0.0 = noir
                         "%d %d m\r\n"              //point central de départ
                         "%d %d %d %d %d %d c\r\n"  //point de début x,y, point intermédiaire x,y et point final x,y
                         "b\r\n"                    //elipse
                         "1 w\r\n"                  //on remet l'épaisseur des traits à 1 pt / defaut
                         "0.0 0.0 0.0 rg\r\n"       //réinit des couleur en noir par défaut
                         "0.0 0.0 0.0 RG\r\n"
            ,epaisseur,c_r/100.0,c_g/100.0,c_b/100.0,i_r/100.0,i_g/100.0,i_b/100.0,x,y
            ,pt_d_x,pt_d_y,pt_i_x,pt_i_y,pt_f_x,pt_f_y);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// écrire du texte
void PDF_write_txt(int x, int y, unsigned int taille_txt, char *txt, HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"\r\n"
                         "BT\r\n"           //begin/début de la zone de texte
                         "/F1 %d Tf\r\n"    //taille du texte écrit horizontalement
                         "%d %d Td\r\n"     //coordonnées du point
                         "(%s) Tj\r\n"      //text à écrire
                         "ET\r\n"           //end/fin de la zone de texte
            ,taille_txt,x,y,txt);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// écrire du texte en couleur
void PDF_write_txt_color(int x, int y, unsigned int taille_txt, char *txt, HANDLE file_ext
                         ,unsigned char c_r,unsigned char c_g,unsigned char c_b)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  _snprintf(tmp,MAX_PATH,"\r\n"
                         "%2.1f %2.1f %2.1f rg\r\n"   //couleur intérieur en RGB sur 1 : 0.0 0.0 0.0 = noir
                         "BT\r\n"                     //begin/début de la zone de texte
                         "/F1 %d Tf\r\n"              //taille du texte écrit horizontalement
                         "%d %d Td\r\n"               //coordonnées du point
                         "(%s) Tj\r\n"                //text à écrire
                         "ET\r\n"                     //end/fin de la zone de texte
                         "0.0 0.0 0.0 rg\r\n"         //réinit des couleur en noir par défaut
            ,c_r/100.0,c_g/100.0,c_b/100.0,taille_txt,x,y,txt);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement += strlen(tmp);
  taille_stream += strlen(tmp);

  ListeItem[nb_items].debut = debut_emplacement;
}

//---------------------------------------------------------------------------------------------------------------
// debut de stream pour écrire ^^
void PDF_write_debut_stream(HANDLE file_ext)
{
  taille_stream = 0;
  DWORD copiee;

  char tmp[MAX_PATH];
  nb_items++;
  _snprintf(tmp,MAX_PATH,"%d 0 obj\r\n"             //numéro de l'objet
                         "<</Length %d 0 R >>\r\n"  //taille de la stream (contenant le text, images, lignes)
                                                    //et numéro de l'objet contenant la taille
                         "stream"                   //début de la zone stream
            ,nb_items,nb_items+1);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);

  debut_emplacement += strlen(tmp);
  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// fin de stream pour écrire ^^
void PDF_write_fin_stream(HANDLE file_ext)
{
  DWORD copiee;

  char tmp[MAX_PATH];
  nb_items++;
  _snprintf(tmp,MAX_PATH,"sendstream\r\n" //fin de la stream
                         "endobj\r\n"     //fin de l'objet
                         "%d 0 obj\r\n"   //nouvel objet contenant
                         "%d\r\n"         //taille de la stream précédente
                         "endobj\r\n"     //fin de l'objet
            ,++nb_items,taille_stream);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);

  debut_emplacement += strlen(tmp);
  ListeItem[nb_items].debut = debut_emplacement;
}
//---------------------------------------------------------------------------------------------------------------
// début du document
void PDF_write_start(HANDLE file_ext, unsigned int nb_page_total)
{
  DWORD copiee;
  char tmp[MAX_PATH];

  //écriture de la version PDF utilisée
  _snprintf(tmp,MAX_PATH,"%%PDF-1.7\r\n");          //version du format PDF utilisé
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  debut_emplacement = strlen(tmp);

  //format du document
  _snprintf(tmp,MAX_PATH,"%d 0 obj<</Type/Catalog/Outlines 2 0 R/Pages 3 0 R>>\r\nendobj\r\n",++nb_items);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);

  _snprintf(tmp,MAX_PATH,"%d 0 obj<</Type/Outlines/Count 0>>\r\nendobj\r\n",++nb_items);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);

  _snprintf(tmp,MAX_PATH,"%d 0 obj<</Type/Pages/Kids [4 0 R]/Count %d>>\r\nendobj\r\n",++nb_items,nb_page_total); //ici on spécifié le nb de page
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);

  //taille de la page
  _snprintf(tmp,MAX_PATH,"%d 0 obj<</Type/Pages/Parent 3 0 R/MediaBox [0 0 612 792]/Contents 5 0 R/Resources <</ProcSet 6 0 R/Font <</F1 7 0 R>> >> >>\r\nendobj\r\n",++nb_items);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);
}
//---------------------------------------------------------------------------------------------------------------
// fin du document
void PDF_write_end(HANDLE file_ext)
{
  DWORD copiee;
  char tmp[MAX_PATH];

  //format de fin du document
  _snprintf(tmp,MAX_PATH,"%d 0 obj /PDF\r\nendobj\r\n",++nb_items);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);

  _snprintf(tmp,MAX_PATH,"%d 0 obj <</Type/Font/Subtype/Type1/Name/F1/BaseFont/Helvetica/Encoding/MacRomanEncoding>>\r\nendobj\r\n",++nb_items);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  ListeItem[nb_items].debut = debut_emplacement;
  debut_emplacement += strlen(tmp);

  //début de l'index
  _snprintf(tmp,MAX_PATH,"xref\r\n0 %d\r\n0000000000 65535 f\r\n",nb_items+1);
  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);

  //index des objets (octet de début) + infos divers
  unsigned int i;

  for (i=1;i<nb_items-1;i++)
  {
    _snprintf(tmp,MAX_PATH,"%010d 00000 n\r\n",ListeItem[i].debut);
    WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
  }

  //trailer de fin
  _snprintf(tmp,MAX_PATH,"trailer\r\n<</Size %d/Root 1 0 R/ID[<%s><%s>]>>\r\nstartxref\r\n%d\r\n%%%%EOF\r\n"
            ,nb_items+1
            ,IDENTIFIANT_DOCUMENT
            ,IDENTIFIANT_DOCUMENT
            ,debut_emplacement);

  WriteFile(file_ext,tmp,strlen(tmp),&copiee,0);
}

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.