dataops (dataops.cpp) – this example shows how to create documents both direct file (write-only) and a memory-based documents. It mostly uses API for memory-based PDF documents. It contains several sections, which create a PDF document with a rounded filled rectangle on a page. Such document is saved into a file (directly, or through a memory buffer), same as the file loaded and re-saved. It also compares whether the result file content is the same for both save to a disk and save to a memory buffer.

    1 /*
    2  * (c) 2013-2017 http://www.litePDF.cz
    3  *
    4  * The example code is supplied "AS IS". It disclaims all warranties, expressed
    5  * or implied, including, without limitation, the warranties of merchantability
    6  * and of fitness for any purpose. It assumes no liability for direct, indirect,
    7  * incidental, special, exemplary, or consequential damages, which may result
    8  * from the use of the code, even if advised of the possibility of such damage.
    9  *
   10  * Permission is hereby granted to use, copy, modify, and distribute this
   11  * source code, or portions hereof, for any purpose, without fee.
   12  */ 
   13 
   14 #include <windows.h>
   15 #include <stdio.h>
   16 #include <string.h>
   17 #include <string>
   18 
   19 #include "share/litePDF.h"
   20 
   21 static std::string to_string(unsigned int num)
   22 {
   23    char buff[128];
   24 
   25    sprintf(buff, "%u", num);
   26 
   27    return std::string(buff);
   28 }
   29 
   30 static void drawPage(litePDF::TLitePDF &litePDF)
   31 {
   32    // add a new page to it, with large-enough pixel scale
   33    HDC hDC = litePDF.AddPage(litePDF.MMToUnit(210), litePDF.MMToUnit(297), 2100, 2970, LitePDFDrawFlag_None);
   34 
   35    HGDIOBJ oldBrush, oldPen;
   36 
   37    oldBrush = SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
   38    oldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
   39 
   40    // draw rectangle
   41    RoundRect(hDC, 200, 200, 1900, 2770, 300, 300);
   42 
   43    SelectObject(hDC, oldPen);
   44    SelectObject(hDC, oldBrush);
   45 
   46    // finish drawing
   47    litePDF.FinishPage(hDC);
   48 }
   49 
   50 static void saveToData(litePDF::TLitePDF &litePDF,
   51                        BYTE **pdata,
   52                        unsigned int &dataLength)
   53 {
   54    dataLength = 0;
   55    *pdata = NULL;
   56 
   57    if (!litePDF.SaveToData(NULL, &dataLength)) {
   58       throw TLitePDFException(ERROR_CANNOT_MAKE, "Failed to get data length");
   59    }
   60 
   61    if (!dataLength) {
   62       throw TLitePDFException(ERROR_CANNOT_MAKE, "Returned data length is 0");
   63    }
   64 
   65    *pdata = (BYTE *) malloc(sizeof(BYTE) * dataLength);
   66    if (!*pdata) {
   67       std::string msg = "Failed to allocate " + to_string(dataLength) + " bytes";
   68       throw TLitePDFException(ERROR_OUTOFMEMORY, msg.c_str());
   69    }
   70 
   71    if (!litePDF.SaveToData(*pdata, &dataLength)) {
   72       throw TLitePDFException(ERROR_CANNOT_MAKE, "Failed to get data");
   73    }
   74 }
   75 
   76 static void saveDataToFile(const char *fileName,
   77                            const BYTE *data,
   78                            unsigned int dataLength)
   79 {
   80    FILE *f = fopen(fileName, "wb");
   81    if (!f) {
   82       std::string msg = "Failed to open " + std::string(fileName);
   83       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
   84    }
   85 
   86    if (fwrite(data, sizeof(BYTE), dataLength, f) != dataLength) {
   87       fclose(f);
   88       std::string msg = "Failed to write to " + std::string(fileName);
   89       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
   90    }
   91 
   92    fclose(f);
   93 }
   94 
   95 static void cmpFileAndData(const char *fileName,
   96                            const BYTE *data,
   97                            unsigned int dataLength)
   98 {
   99    FILE *f = fopen(fileName, "rb");
  100    if (!f) {
  101       std::string msg = "Failed to open " + std::string(fileName);
  102       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
  103    }
  104 
  105    if (fseek(f, 0, SEEK_END) != 0) {
  106       fclose(f);
  107       throw TLitePDFException(ERROR_CANNOT_MAKE,
  108                               "Failed to move to the end of the file");
  109    }
  110 
  111    long fileLength = ftell(f);
  112    if (fileLength != (long) dataLength) {
  113       fclose(f);
  114       std::string msg = "File length (" + to_string(fileLength) +
  115                         ") differs from data length (" +
  116                         to_string(dataLength) + ")";
  117       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
  118    }
  119 
  120    if (fseek(f, 0, SEEK_SET) != 0) {
  121       fclose(f);
  122       throw TLitePDFException(ERROR_CANNOT_MAKE,
  123                               "Failed to move to the beginning of the file");
  124    }
  125 
  126    BYTE buff[1024];
  127    unsigned int read, dataOffset = 0;
  128    while(read = fread(buff, sizeof(BYTE), 1024, f), read > 0) {
  129       if (memcmp(buff, data + dataOffset, read) != 0) {
  130          fclose(f);
  131          throw TLitePDFException(ERROR_CANNOT_MAKE,
  132                                  "File and data content differs");
  133       }
  134 
  135       dataOffset += read;
  136 
  137       if (feof(f)) {
  138          break;
  139       }
  140    }
  141 
  142    fclose(f);
  143 
  144    if (dataOffset != dataLength) {
  145       std::string msg = "Did not finish with dataOffset (" +
  146                         to_string(dataOffset) +
  147                         ") at the end of data (" + to_string(dataLength) + ")";
  148       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
  149    }
  150 }
  151 
  152 static void cmpDataAndData(const BYTE *data1,
  153                            unsigned int data1Length,
  154                            const BYTE *data2,
  155                            unsigned int data2Length)
  156 {
  157    if (data1Length != data2Length) {
  158       std::string msg = "data1 length (" + to_string(data1Length) +
  159                         ") differs from data2 length (" +
  160                         to_string(data2Length) + ")";
  161       throw TLitePDFException(ERROR_CANNOT_MAKE, msg.c_str());
  162    }
  163 
  164    if (0 != memcmp(data1, data2, data1Length)) {
  165       throw TLitePDFException(ERROR_CANNOT_MAKE, "Data contents differ");
  166    }
  167 }
  168 
  169 int main(void)
  170 {
  171    BYTE *data1 = NULL, *data2 = NULL;
  172    unsigned int data1Length, data2Length;
  173    int res = 0;
  174 
  175    using namespace litePDF;
  176 
  177    try {
  178       TLitePDF litePDF;
  179 
  180       //-----------------------------------------------------------------
  181 
  182       // begin write-only PDF file
  183       litePDF.CreateFileDocument("dataops-file1.pdf");
  184 
  185       // fill a page
  186       drawPage(litePDF);
  187 
  188       // close the document
  189       litePDF.Close();
  190 
  191       //-----------------------------------------------------------------
  192 
  193       // begin write-only PDF file
  194       litePDF.CreateMemDocument();
  195 
  196       // fill a page
  197       drawPage(litePDF);
  198 
  199       // save memory-based PDF to file
  200       litePDF.SaveToFile("dataops-file2.pdf");
  201 
  202       // close the document
  203       litePDF.Close();
  204 
  205       //-----------------------------------------------------------------
  206 
  207       // create memory PDF
  208       litePDF.CreateMemDocument();
  209 
  210       // fill a page
  211       drawPage(litePDF);
  212 
  213       // save to data; the 'data1' and 'data1Length' stores saved PDF now
  214       saveToData(litePDF, &data1, data1Length);
  215 
  216       // close the document
  217       litePDF.Close();
  218 
  219       //-----------------------------------------------------------------
  220 
  221       // save data to file
  222       saveDataToFile("dataops-data1.pdf", data1, data1Length);
  223 
  224       // compare file and data - the content should be the same.
  225       // cannot compare write-only file PDF with memory-based, because the way
  226       // they are written into the disk are different
  227       cmpFileAndData("dataops-file2.pdf", data1, data1Length);
  228 
  229       //-----------------------------------------------------------------
  230 
  231       // load from file
  232       litePDF.LoadFromFile("dataops-file2.pdf", NULL, false);
  233 
  234       // save to data
  235       saveToData(litePDF, &data2, data2Length);
  236 
  237       // close the document
  238       litePDF.Close();
  239 
  240       //-----------------------------------------------------------------
  241 
  242       // save data to file
  243       saveDataToFile("dataops-data2.pdf", data2, data2Length);
  244 
  245       // free the data1 and swap with data2, it's reused
  246       free(data1);
  247       data1 = data2;
  248       data2 = NULL;
  249       data1Length = data2Length;
  250 
  251       //-----------------------------------------------------------------
  252 
  253       // load from file
  254       litePDF.LoadFromFile("dataops-file2.pdf", NULL, true);
  255 
  256       // save to data
  257       saveToData(litePDF, &data2, data2Length);
  258 
  259       // close the document
  260       litePDF.Close();
  261 
  262       // save data to file
  263       saveDataToFile("dataops-data3.pdf", data2, data2Length);
  264 
  265       //-----------------------------------------------------------------
  266 
  267       // compare data - the content should be the same
  268       cmpDataAndData(data1, data1Length, data2, data2Length);
  269 
  270       // free the data2, it's reused
  271       free(data2);
  272       data2 = NULL;
  273 
  274       //-----------------------------------------------------------------
  275 
  276       // load from data
  277       litePDF.LoadFromData(data1, data1Length, NULL);
  278 
  279       // save to data
  280       saveToData(litePDF, &data2, data2Length);
  281 
  282       // close the document
  283       litePDF.Close();
  284 
  285       // save data to file
  286       saveDataToFile("dataops-data4.pdf", data2, data2Length);
  287 
  288       //-----------------------------------------------------------------
  289 
  290       // compare data - the content should be the same
  291       cmpDataAndData(data1, data1Length, data2, data2Length);
  292 
  293       // free the data2, it's reused
  294       free(data2);
  295       data2 = NULL;
  296 
  297       //-----------------------------------------------------------------
  298 
  299    } catch (TLitePDFException &ex) {
  300       fprintf(stderr, "litePDF Exception: %x: %s\n", ex.getCode(), ex.getMessage());
  301       res = 1;
  302    }
  303 
  304    if (data1) {
  305       free(data1);
  306    }
  307 
  308    if (data2) {
  309       free(data2);
  310    }
  311 
  312    return res;
  313 }
TOPlist