你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

MCU生成简单PDF文档  

[复制链接]
anobodykey 发布时间:2017-6-17 23:03
本帖最后由 anobodykey 于 2017-9-24 14:09 编辑

主机环境:Win10 64bit

开发环境:MDK5.23

目标板:Cortex-M MCU

之前有次在群里看到有人询问单片机生成PDF的问题,突然觉得有些兴趣所以就学习了一下libHaru库,libHaru库是一个十分不错的库,对于PDF的实现来说也是相当齐全的,在PC上使用是完全没有问题的,但在资源紧张的MCU上,还是有些困难的,因此就想找一下适用于MCU的生成PDF的库,结果不太理想,都是一些需要实现动态内存管理的平台才行,而且这些库都是把生成的数据放在了内存中,直到保存文件时才写入到文件中,这对于一般只有几十或者几百KB级别的单片机来说更不可能了,于是乎,萌发了自己动手写一个基本的能用于MCU的生成PDF文件的库,我称之为libpdf,其中的接口参考了libHaru,如下所示:

捕获.PNG

当然有些接口还没有实现,但基本的操作还是可以的,等以后再逐渐完善吧,pdflib是生成pdf文件的,因此要基于Fatfs来实现文件的操作,pdflib库只有两个文件,也相应的参考了pdfgen库,该库在后面有链接,

头文件如下:

  1. #ifndef __PDFLIB_H__
  2. #define __PDFLIB_H__

  3. #include "ff.h"
  4. /*----- standard C library functions -----------------------------------------*/

  5. #define LPDF_FOPEN                  f_open
  6. #define LPDF_FCLOSE                 f_close
  7. #define LPDF_FREAD                  f_read
  8. #define LPDF_FWRITE                 f_write
  9. #define LPDF_FFLUSH                 f_sync
  10. #define LPDF_FSEEK                  f_seek
  11. #define LPDF_FTELL                  f_tell
  12. #define LPDF_FEOF                   f_eof
  13. #define LPDF_FERROR                 f_error
  14. #define LPDF_RENAME                 f_rename
  15. #define LPDF_REMOVE                 f_unlink
  16. #define LPDF_MALLOC                 malloc
  17. #define LPDF_FREE                   free
  18. #define LPDF_FILE                   FIL
  19. #define LPDF_TIME                   time
  20. #define LPDF_PRINTF                 printf
  21. #define LPDF_SPRINTF                sprintf
  22. #define LPDF_FPRINTF                f_printf
  23. #define LPDF_VOID                   void
  24. #define LPDF_SIN                    sin
  25. #define LPDF_COS                    cos

  26. /*  native OS integer types */
  27. typedef  signed int          LPDF_INT;
  28. typedef  unsigned int        LPDF_UINT;


  29. /*  32bit integer types
  30. */
  31. typedef  signed int          LPDF_INT32;
  32. typedef  unsigned int        LPDF_UINT32;


  33. /*  16bit integer types
  34. */
  35. typedef  signed short        LPDF_INT16;
  36. typedef  unsigned short      LPDF_UINT16;


  37. /*  8bit integer types
  38. */
  39. typedef  signed char         LPDF_INT8;
  40. typedef  unsigned char       LPDF_UINT8;


  41. /*  8bit binary types
  42. */
  43. typedef  unsigned char       LPDF_BYTE;


  44. /*  float type (32bit IEEE754)
  45. */
  46. typedef  float               LPDF_REAL;


  47. /*  double type (64bit IEEE754)
  48. */
  49. typedef  double              LPDF_DOUBLE;


  50. /*  boolean type (0: False, !0: True)
  51. */
  52. typedef  signed int          LPDF_BOOL;


  53. /*  error-no type (32bit unsigned integer)
  54. */
  55. typedef  unsigned long       LPDF_STATUS;

  56. #define LPDF_OK                     0
  57. #define LPDF_FAILED                 1

  58. /*----- font state -----------------------------------------------------------*/
  59. #define   LPDF_FONT_INVALID                 0x00FF
  60. #define   LPDF_FONT_COURIER                 0x0000
  61. #define   LPDF_FONT_COURIER_B               0x0001
  62. #define   LPDF_FONT_COURIER_O               0x0002
  63. #define   LPDF_FONT_COURIER_OB              0x0003
  64. #define   LPDF_FONT_HELVETICA               0x0004
  65. #define   LPDF_FONT_HELVETICA_B             0x0005
  66. #define   LPDF_FONT_HELVETICA_O             0x0006
  67. #define   LPDF_FONT_HELVETICA_BO            0x0007
  68. #define   LPDF_FONT_TIMES_R                 0x0008
  69. #define   LPDF_FONT_TIMES_B                 0x0009
  70. #define   LPDF_FONT_TIMES_I                 0x000A
  71. #define   LPDF_FONT_TIMES_BI                0x000B
  72. #define   LPDF_FONT_SYMBOL                  0x000C
  73. #define   LPDF_FONT_ZAP                     0x000D
  74. /*----- Graphis mode ---------------------------------------------------------*/
  75. #define   LPDF_GMODE_PAGE_DESCRIPTION       0x0001
  76. #define   LPDF_GMODE_PATH_OBJECT            0x0002
  77. #define   LPDF_GMODE_TEXT_OBJECT            0x0004
  78. #define   LPDF_GMODE_CLIPPING_PATH          0x0008
  79. #define   LPDF_GMODE_SHADING                0x0010
  80. #define   LPDF_GMODE_INLINE_IMAGE           0x0020
  81. #define   LPDF_GMODE_EXTERNAL_OBJECT        0x0040
  82. #define   LPDF_GMODE_INVALID                0x0080
  83. #define   LPDF_GMODE_OVER                   0x0100

  84. #define OBJ_MAX_NUM     256

  85. /* Page的结构信息是否需要树形结构 */
  86. typedef enum
  87. {
  88.     OBJ_info,
  89.     OBJ_stream,
  90.     OBJ_font,
  91.     OBJ_page,
  92.     OBJ_catalog,
  93.     OBJ_pages,
  94.     OBJ_image,
  95. }LPDF_ObjType;

  96. typedef struct
  97. {
  98.     LPDF_ObjType objType;
  99.     LPDF_UINT16 objIdx;
  100.     LPDF_UINT16 height;
  101.     LPDF_UINT16 width;
  102.     LPDF_UINT16 length;
  103.     LPDF_UINT gMode;
  104.     LPDF_BYTE fontType;
  105.     LPDF_BYTE fontSize;
  106.     LPDF_BYTE pState;
  107.     LPDF_VOID *doc;
  108. }LPDF_Obj;

  109. typedef struct
  110. {
  111.     LPDF_Obj obj[OBJ_MAX_NUM];
  112.     LPDF_UINT32 offset;
  113.     LPDF_UINT16 objNumber;
  114.     LPDF_FILE file;
  115. }LPDF_Doc_Rec;

  116. typedef LPDF_Doc_Rec *LPDF_Doc;
  117. typedef LPDF_Obj *LPDF_Page;
  118. typedef LPDF_Obj *LPDF_Image;
  119. extern const char *font_list[];
  120. /*----- LPDF Interfaces-------------------------------------------------------*/
  121. const char * LPDF_GetVersion(void);
  122. LPDF_Doc LPDF_New(void);
  123. LPDF_Page LPDF_AddPage(LPDF_Doc pdf);
  124. LPDF_STATUS LPDF_SaveToFile(LPDF_Doc pdf,const char *file_name);
  125. LPDF_STATUS LPDF_Free(LPDF_Doc pdf);
  126. LPDF_STATUS LPDF_Page_CheckState(LPDF_Page page, LPDF_UINT mode);
  127. LPDF_STATUS LPDF_Page_SetFontAndSize(LPDF_Page page,
  128.                            const char *font_name, LPDF_UINT8 size);
  129. LPDF_STATUS LPDF_Page_SaveParams(LPDF_Page page);
  130. LPDF_STATUS LPDF_Page_SaveContext(LPDF_Page page);
  131. LPDF_STATUS LPDF_Page_BeginText(LPDF_Page page);
  132. LPDF_STATUS LPDF_Page_EndText(LPDF_Page page);
  133. LPDF_UINT16 LPDF_Page_GetHeight(LPDF_Page page);
  134. LPDF_UINT16 LPDF_Page_GetWidth(LPDF_Page page);
  135. LPDF_STATUS LPDF_Page_SetHeight(LPDF_Page page, LPDF_UINT16 value);
  136. LPDF_STATUS LPDF_Page_SetWidth(LPDF_Page page, LPDF_UINT16 value);
  137. LPDF_STATUS LPDF_Page_ShowText(LPDF_Page page, const char *text);
  138. LPDF_STATUS LPDF_Page_MoveTextPos(LPDF_Page page,
  139.                          LPDF_INT x, LPDF_INT y);
  140. LPDF_STATUS LPDF_Page_TextOut(LPDF_Page page,
  141.                          LPDF_UINT16 x, LPDF_UINT16 y,
  142.                          const char *text);
  143. LPDF_STATUS LPDF_Page_SetRGBStroke(LPDF_Page page,
  144.                          LPDF_REAL r,
  145.                          LPDF_REAL g,
  146.                          LPDF_REAL b);
  147. LPDF_STATUS LPDF_Page_SetRGBFill(LPDF_Page page,
  148.                          LPDF_REAL r,
  149.                          LPDF_REAL g,
  150.                          LPDF_REAL b);
  151. LPDF_STATUS LPDF_Page_MoveTo (LPDF_Page page,
  152.                          LPDF_UINT16 x,
  153.                          LPDF_UINT16 y);
  154. LPDF_STATUS LPDF_Page_LineTo (LPDF_Page page,
  155.                          LPDF_UINT16 x,
  156.                          LPDF_UINT16 y);
  157. LPDF_STATUS LPDF_Page_Stroke(LPDF_Page page);
  158. LPDF_STATUS LPDF_Page_ClosePathStroke(LPDF_Page page);
  159. LPDF_STATUS LPDF_Page_DrawImage(LPDF_Page page,
  160.                       LPDF_Image image,
  161.                       LPDF_UINT16 x,
  162.                       LPDF_UINT16 y,
  163.                       LPDF_UINT16 width,
  164.                       LPDF_UINT16 height);
  165.                                                                                        
  166. #endif
复制代码

源文件如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include "pdflib.h"

  6. #define LPDF_INVALID_OBJECT                       0x1033

  7. static char pdf_buf[512];

  8. #define LPDF_VERSIOIN_TEXT          "0.0.1"
  9. #define LPDF_FILE_HEADER_LEN        15
  10. #define LPDF_BASEFONT_NUM           14
  11. const char LPDF_FILE_HEADER[] = "%%PDF-1.4\n%%\xAA\xBB\xCC\xDD\n";
  12. const char *font_list[] = {
  13.     "Courier",
  14.     "Courier-Bold",
  15.     "Courier-Oblique",
  16.     "Courier-BoldOblique",
  17.     "Helvetica",
  18.     "Helvetica-Bold",
  19.     "Helvetica-Oblique",
  20.     "Helvetica-BoldOblique",
  21.     "Times-Roman",
  22.     "Times-Bold",
  23.     "Times-Italic",
  24.     "Times-BoldItalic",
  25.     "Symbol",
  26.     "ZapfDingbats",
  27.     NULL
  28. };


  29. const char * LPDF_GetVersion(void)
  30. {
  31.     return LPDF_VERSIOIN_TEXT;
  32. }

  33. LPDF_Doc LPDF_New(void)
  34. {
  35.     static LPDF_Doc_Rec pdf;
  36.     LPDF_INT length = 0, i = 0;
  37.         LPDF_UINT writeBytes = 0;
  38.         FRESULT fr;
  39.    
  40.     fr = LPDF_FOPEN(&pdf.file,"/tmp.pdf",FA_CREATE_ALWAYS|FA_WRITE);
  41.         if(fr)
  42.         {
  43.                 LPDF_PRINTF("create tmp.pdf failed!\r\n");
  44.                 return NULL;
  45.         }
  46.     LPDF_FPRINTF(&pdf.file,LPDF_FILE_HEADER);   /* 写入文件头 */
  47.     pdf.offset = LPDF_FILE_HEADER_LEN;
  48.    
  49.     pdf.obj[0].objIdx = pdf.offset;
  50.     length = LPDF_SPRINTF(pdf_buf,"1 0 obj\n<<\n/Type /Catalog\n/Pages 17 0 R\n>>\nendobj\n\n");
  51.     LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
  52.     pdf.offset += length;
  53.    
  54.     pdf.obj[1].objIdx = pdf.offset;
  55.     length = LPDF_SPRINTF(pdf_buf,"2 0 obj\n<<\n/Creator (light pdf library 0.0.1)\n"
  56.                     "/Auther (anobodykey)\n>>\nendobj\n\n");
  57.     LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
  58.     pdf.offset += length;
  59.    
  60.     for(i = 0; i < LPDF_BASEFONT_NUM-2; i++)
  61.     {
  62.         pdf.obj[2+i].objIdx = pdf.offset;
  63.         length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
  64.                         "/BaseFont /%s\n/Encoding /WinAnsiEncoding\n>>\n"
  65.                         "endobj\n\n",3+i,font_list[i]);
  66.         LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
  67.         pdf.offset += length;
  68.     }
  69.     for(; i < LPDF_BASEFONT_NUM; i++)
  70.     {
  71.         pdf.obj[2+i].objIdx = pdf.offset;
  72.         length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
  73.                         "/BaseFont /%s\n>>\nendobj\n\n",3+i,font_list[i]);
  74.         LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
  75.         pdf.offset += length;
  76.     }
  77.     pdf.objNumber = 3+i;
  78.   
  79.     return (LPDF_Doc)&pdf;
  80. }

  81. LPDF_STATUS LPDF_SaveToFile(LPDF_Doc pdf,const char *file_name)
  82. {
  83.     LPDF_UINT16 i = 0, child_pages = 0;
  84.     LPDF_INT length = 0;
  85.         LPDF_UINT writeBytes = 0;

  86.     pdf->obj[16].objIdx = pdf->offset;
  87.     child_pages = (pdf->objNumber-2-LPDF_BASEFONT_NUM)/3 ;
  88.     length = LPDF_SPRINTF(pdf_buf,"17 0 obj\n<<\n/Types /Pages\n/Count %d\n/Kids [ ",child_pages);
  89.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  90.     pdf->offset += length;
  91.     for(i = 0; i < child_pages; i++)
  92.     {
  93.         length = LPDF_SPRINTF(pdf_buf,"%d 0 R\n",18+i*3);
  94.         LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  95.         pdf->offset += length;
  96.     }
  97.     length = LPDF_SPRINTF(pdf_buf,"]\n>>\nendobj\n\n");
  98.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  99.     pdf->offset += length;
  100.    
  101.     LPDF_FPRINTF(&pdf->file,"xref\n0 %d\n0000000000 65535 f\r\n",pdf->objNumber+1);
  102.     for(i = 0 ; i < pdf->objNumber; i++)
  103.     {
  104.         LPDF_FPRINTF(&pdf->file,"%10.10d 00000 n\r\n",pdf->obj[i].objIdx);
  105.     }
  106.     LPDF_FPRINTF(&pdf->file,"trailer\n<<\n/Size %d\n/Root 1 0 R\n/Info 2 0 R\n>>\nstartxref\n%d\n%%%%EOF",
  107.                 pdf->objNumber+1,pdf->offset);
  108.     LPDF_FCLOSE(&pdf->file);
  109.     LPDF_REMOVE(file_name);
  110.     LPDF_RENAME("tmp.pdf",file_name);
  111.     return LPDF_OK;
  112. }

  113. LPDF_STATUS LPDF_Free(LPDF_Doc pdf)
  114. {
  115.     memset(pdf,sizeof(LPDF_Doc_Rec),0);
  116.     return LPDF_OK;
  117. }

  118. LPDF_Page LPDF_AddPage(LPDF_Doc pdf)
  119. {
  120.     LPDF_INT length = 0,i = 0;
  121.     LPDF_Page page = NULL;
  122.         LPDF_UINT writeBytes = 0;
  123.    
  124.     pdf->obj[pdf->objNumber].objIdx = pdf->offset;
  125.     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Page\n/Parent 4 0 R\n/Contents %d 0 R\n"
  126.                     "/Resources <<\n/ProcSet [/PDF /TEXT /ImageB /ImageC /ImageI]\n"
  127.                     "/Font <<\n",pdf->objNumber+1,pdf->objNumber+2);
  128.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  129.     pdf->offset += length;
  130.     while(font_list[i])
  131.     {
  132.         length = LPDF_SPRINTF(pdf_buf,"/F%d %d 0 R\n",i+1,3+i);
  133.         LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  134.         pdf->offset += length;
  135.         i+=1;
  136.     }
  137.     LPDF_FPRINTF(&pdf->file,">>\n>>\n");
  138.     pdf->offset += 4;
  139.     page = (LPDF_Page)&pdf->obj[pdf->objNumber];
  140.     page->width = 595;
  141.     page->height = 842;
  142.     page->gMode = LPDF_GMODE_INVALID;
  143.     page->fontType = LPDF_FONT_INVALID;
  144.     page->doc = pdf;
  145.     return page;
  146. }

  147. LPDF_STATUS LPDF_Page_SetHeight(LPDF_Page page, LPDF_UINT16 value)
  148. {
  149.     page->height = value;
  150.     return LPDF_OK;
  151. }
  152. LPDF_STATUS LPDF_Page_SetWidth(LPDF_Page page, LPDF_UINT16 value)
  153. {
  154.     page->width = value;
  155.     return LPDF_OK;
  156. }

  157. LPDF_UINT16 LPDF_Page_GetHeight(LPDF_Page page)
  158. {
  159.     if(page)
  160.     {
  161.         return page->height;
  162.     }
  163.    
  164.     return LPDF_OK;
  165. }

  166. LPDF_UINT16 LPDF_Page_GetWidth(LPDF_Page page)
  167. {
  168.     if(page)
  169.     {
  170.         return page->width;
  171.     }
  172.    
  173.     return LPDF_OK;
  174. }

  175. LPDF_STATUS LPDF_Page_CheckState(LPDF_Page page, LPDF_UINT mode)
  176. {
  177.     if(!page)
  178.         return LPDF_INVALID_OBJECT;
  179.     if(!(page->gMode&mode))
  180.         return LPDF_FAILED;

  181.     return LPDF_OK;
  182. }

  183. LPDF_STATUS LPDF_Page_SetFontAndSize(LPDF_Page page,
  184.                            const char *font_name, LPDF_UINT8 size)
  185. {
  186.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  187.     LPDF_INT i = 0,length = 0;
  188.         LPDF_UINT writeBytes = 0;
  189.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
  190.     if(LPDF_OK != ret)
  191.         return ret;

  192.     while(font_list[i])
  193.     {
  194.         if(0 == strcmp(font_list[i],font_name))
  195.         {
  196.             page->fontType = i;
  197.             page->fontSize = size;
  198.             length = LPDF_SPRINTF(pdf_buf,"/F%d %d Tf\n",i+1,size);
  199.             LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  200.             pdf->offset += length;
  201.             page->length += length;
  202.             return LPDF_OK;
  203.         }
  204.         i+=1;
  205.     }
  206.    
  207.     return LPDF_OK;
  208. }

  209. LPDF_STATUS LPDF_Page_SaveParams(LPDF_Page page)
  210. {
  211.     LPDF_INT length;
  212.         LPDF_UINT writeBytes = 0;
  213.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  214.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_INVALID);
  215.     if(LPDF_OK != ret)
  216.         return ret;
  217.    
  218.     /* 对于每个page来说该接口只能调用一次即在GMODE为INVALID的模式下 */
  219.     length = LPDF_SPRINTF(pdf_buf,"/MediaBox [ 0 0 %d %d ]\n>>\nendobj\n\n",
  220.                         page->width, page->height);
  221.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  222.     pdf->offset += length;
  223.     pdf->obj[pdf->objNumber+1].objIdx = pdf->offset;
  224.     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<</Length %d 0 R>>\nstream\n",
  225.                         pdf->objNumber+2, pdf->objNumber+3);
  226.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  227.     pdf->offset += length;
  228.     page->length = 0;
  229.     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
  230.     return LPDF_OK;
  231. }

  232. LPDF_STATUS LPDF_Page_SaveContext(LPDF_Page page)
  233. {
  234.     LPDF_INT length;
  235.         LPDF_UINT writeBytes = 0;
  236.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  237.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
  238.     if(LPDF_OK != ret)
  239.         return ret;
  240.      /* 对于每个page来说该接口只能调用一次即在GMODE为PAGE_DESCRIPTION的模式下 */
  241.     length = LPDF_SPRINTF(pdf_buf,"endstream\nendobj\n\n");
  242.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  243.     pdf->offset += length;
  244.     pdf->obj[pdf->objNumber+2].objIdx = pdf->offset;
  245.     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n%d\nendobj\n\n",
  246.                         pdf->objNumber+3,page->length);
  247.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  248.     pdf->offset += length;
  249.     pdf->objNumber += 3;
  250.     page->gMode = LPDF_GMODE_OVER;
  251.     return LPDF_OK;
  252. }

  253. LPDF_STATUS LPDF_Page_BeginText(LPDF_Page page)
  254. {
  255.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  256.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
  257.     if(LPDF_OK != ret)
  258.         return ret;
  259.     LPDF_FPRINTF(&pdf->file,"BT\n");
  260.     pdf->offset += 3;
  261.     page->length += 3;
  262.     page->gMode = LPDF_GMODE_TEXT_OBJECT;
  263.     return LPDF_OK;
  264. }
  265. LPDF_STATUS LPDF_Page_EndText(LPDF_Page page)
  266. {
  267.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  268.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
  269.     if(LPDF_OK != ret)
  270.         return ret;
  271.     LPDF_FPRINTF(&pdf->file,"ET\n");
  272.     pdf->offset += 3;
  273.     page->length += 3;
  274.     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
  275.     return LPDF_OK;
  276. }

  277. LPDF_STATUS LPDF_Page_ShowText(LPDF_Page page, const char *text)
  278. {
  279.     LPDF_INT length = 0;
  280.         LPDF_UINT writeBytes = 0;
  281.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  282.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
  283.     if(LPDF_OK != ret)
  284.         return ret;
  285.     if(LPDF_FONT_INVALID == page->fontType)
  286.         return LPDF_OK;
  287.     length = LPDF_SPRINTF(pdf_buf,"(%s) Tj\n",text);
  288.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  289.     pdf->offset += length;
  290.     page->length += length;
  291.     return LPDF_OK;
  292.    
  293. }
  294. LPDF_STATUS LPDF_Page_MoveTextPos(LPDF_Page page,
  295.                         LPDF_INT x, LPDF_INT y)
  296. {
  297.     LPDF_INT length = 0;
  298.         LPDF_UINT writeBytes = 0;
  299.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  300.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
  301.     if(LPDF_OK != ret)
  302.         return ret;
  303.     length = LPDF_SPRINTF(pdf_buf,"%d %d Td\n",x,y);
  304.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  305.     pdf->offset += length;
  306.     page->length += length;

  307.     return LPDF_OK;
  308. }
  309. LPDF_STATUS LPDF_Page_TextOut(LPDF_Page page,
  310.                         LPDF_UINT16 x, LPDF_UINT16 y,
  311.                         const char *text)
  312. {
  313.     return LPDF_OK;
  314. }

  315. LPDF_STATUS LPDF_Page_SetRGBStroke(LPDF_Page page,
  316.                          LPDF_REAL r,
  317.                          LPDF_REAL g,
  318.                          LPDF_REAL b)
  319. {
  320.     LPDF_INT length = 0;
  321.         LPDF_UINT writeBytes = 0;
  322.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  323.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
  324.     if(LPDF_OK != ret)
  325.         return ret;

  326.     length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f RG\n",r,g,b);
  327.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  328.     pdf->offset += length;
  329.     page->length += length;
  330.     return LPDF_OK;
  331. }

  332. LPDF_STATUS LPDF_Page_SetRGBFill(LPDF_Page page,
  333.                          LPDF_REAL r,
  334.                          LPDF_REAL g,
  335.                          LPDF_REAL b)
  336. {
  337.     LPDF_INT length = 0;
  338.         LPDF_UINT writeBytes = 0;
  339.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  340.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
  341.     if(LPDF_OK != ret)
  342.         return ret;

  343.     length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f rg\n",r,g,b);
  344.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  345.     pdf->offset += length;
  346.     page->length += length;
  347.     return LPDF_OK;
  348. }
  349. LPDF_STATUS LPDF_Page_MoveTo (LPDF_Page page,
  350.                          LPDF_UINT16 x,
  351.                          LPDF_UINT16 y)
  352. {
  353.     LPDF_INT length = 0;
  354.         LPDF_UINT writeBytes = 0;
  355.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  356.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION|LPDF_GMODE_PATH_OBJECT);
  357.     if(LPDF_OK != ret)
  358.         return ret;
  359.     length = LPDF_SPRINTF(pdf_buf,"%d %d m\n",x,y);
  360.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  361.     pdf->offset += length;
  362.     page->length += length;
  363.     page->gMode = LPDF_GMODE_PATH_OBJECT;
  364.     return LPDF_OK;
  365. }
  366. LPDF_STATUS LPDF_Page_LineTo (LPDF_Page page,
  367.                          LPDF_UINT16 x,
  368.                          LPDF_UINT16 y)
  369. {
  370.     LPDF_INT length = 0;
  371.         LPDF_UINT writeBytes = 0;
  372.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  373.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
  374.     if(LPDF_OK != ret)
  375.         return ret;
  376.     length = LPDF_SPRINTF(pdf_buf,"%d %d l\n",x,y);
  377.     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
  378.     pdf->offset += length;
  379.     page->length += length;
  380.     return LPDF_OK;
  381. }
  382. LPDF_STATUS LPDF_Page_Stroke(LPDF_Page page)
  383. {
  384.     LPDF_Doc pdf = (LPDF_Doc)page->doc;
  385.     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
  386.     if(LPDF_OK != ret)
  387.         return ret;
  388.     LPDF_FPRINTF(&pdf->file,"S\n");
  389.     pdf->offset += 2;
  390.     page->length += 2;
  391.     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
  392.     return LPDF_OK;
  393. }
  394. LPDF_STATUS LPDF_Page_DrawImage(LPDF_Page page,
  395.                       LPDF_Image image,
  396.                       LPDF_UINT16 x,
  397.                       LPDF_UINT16 y,
  398.                       LPDF_UINT16 width,
  399.                       LPDF_UINT16 height)
  400. {
  401.         return LPDF_OK;
  402. }
复制代码

对于pdf文件结构可以去查看pdf参考手册,这里我看的是pdf-1.4参考手册,该库的测试代码我是在基于LPC54608库中的sdcard_fatfs示例改编的,同样适用于STM32,关键代码如下:

  1. pdf = LPDF_New();
  2.     page[0] = LPDF_AddPage(pdf);
  3.     LPDF_Page_SaveParams(page[0]);
  4.     width = LPDF_Page_GetWidth(page[0]);
  5.     height = LPDF_Page_GetHeight(page[0]);
  6.     LPDF_Page_SetRGBFill(page[0], 1.0, 0.0, 0.0);
  7.     LPDF_Page_BeginText(page[0]);
  8.     LPDF_Page_MoveTextPos(page[0], 50, height-20);
  9.     while(font_list[i])
  10.     {
  11.         LPDF_Page_SetFontAndSize(page[0], font_list[i], 24);
  12.         LPDF_Page_ShowText(page[0], "abcdefgABCDEFG12345!\043$\045&+-@?");
  13.         LPDF_Page_MoveTextPos(page[0], 0, -30);
  14.         i++;
  15.     }
  16.         LPDF_Page_SetFontAndSize(page[0], font_list[0], 24);
  17.     LPDF_Page_ShowText(page[0], LPDF_GetVersion());
  18.     LPDF_Page_EndText(page[0]);
  19.     LPDF_Page_SaveContext(page[0]);
  20.     page[1] = LPDF_AddPage(pdf);
  21.     LPDF_Page_SaveParams(page[1]);
  22.     LPDF_Page_MoveTo(page[1], width/2-50, height-200);
  23.     LPDF_Page_LineTo(page[1], width/2-50, height-300);
  24.     LPDF_Page_LineTo(page[1], width/2-50+100, height-300);
  25.     LPDF_Page_LineTo(page[1], width/2-50+100, height-200);
  26.     LPDF_Page_LineTo(page[1], width/2-50, height-200);
  27.     LPDF_Page_LineTo(page[1], width/2-50+40, height-140);
  28.     LPDF_Page_LineTo(page[1], width/2-50+40+100, height-140);
  29.     LPDF_Page_LineTo(page[1], width/2-50+100, height-200);
  30.     LPDF_Page_Stroke(page[1]);
  31.     LPDF_Page_MoveTo(page[1], width/2-50+40+100, height-140);
  32.     LPDF_Page_LineTo(page[1], width/2-50+40+100, height-240);
  33.     LPDF_Page_LineTo(page[1], width/2-50+100, height-300);
  34.     LPDF_Page_Stroke(page[1]);
  35.     LPDF_Page_SaveContext(page[1]);
  36.     LPDF_SaveToFile(pdf, "/red.pdf");
  37.         PRINTF("\r\nCreate pdf file success!\r\n");
  38.   
复制代码

代码很简单,生成了一个含有两个page的pdf文件,在第一页中用了不同的字体来显示同一个字符串,可以参考libHaru中的font_demo示例,第二页中是画了一个立方体图,下载代码到目标板,并运行该示例,效果如下:

无标题.png

pdflib库目前来说还是比较简单的,需慢慢完善,pdflib库代码放在下面

pdfgen链接:http://github.com/AndreRenaud/PDFGen

PS:更新为V0.04版本了

更新说明: V0.04

  • 增加了SimSun中文字体
  • 修复了LPDF_Page_SetLineWidth接口中内容长度错误的问题
  • pdflib源文件以及测试文件均需使用ANSI编码,否则无法正确显示中文字体

pdflib_V0.04.rar

下载

6.1 KB, 下载次数: 443

pdflib库

点评

加密怎么处理呀,有没有大佬指点一下  发表于 2024-7-13 16:56

评分

参与人数 4 ST金币 +24 收起 理由
tanganrong-1584 + 5
g921002 + 8 很给力!
lemonjohn + 1 很给力!
wofei1314 + 10 很给力!

查看全部评分

4 收藏 22 评论152 发布时间:2017-6-17 23:03

举报

152个回答
kiki.zhang 回答时间:2018-2-27 10:19:19
anobodykey 发表于 2018-2-26 22:55
只研究了一点,现在这个版本可以添加图片的,你可以看下,添加图片也有好几种方式,弄了个最简单的 ...

LZ,我怎么没看到有添加image的接口,您的pdflib.c中LPDF_LoadRawImageFromFile也没有实现哇,您说的可以添加image,是哪里~LPDF_LoadRawImageFromMem这个是直接传入读到图片的buf么?有什么办法可以直接拿别的pdf中通过编辑软件看到pdf语法格式,拷贝图片的那段buf,直接添加到我自己的pdf中呢?
anobodykey 回答时间:2017-11-20 13:35:19
醉宇a 发表于 2017-11-20 09:33
首先谢谢你的回复和帮助。。。还有你那个更新的dflib_v0.04(可以输出中文)里面没有HPDF_UseCNSFonts(), ...

66楼附件有的
anobodykey 回答时间:2017-6-17 23:04:09
自己顶一下,
深谷幽泉 回答时间:2017-6-18 11:45:33
看起来很高端的样子,居然没人顶。不过,请问楼主,用MCU生成PDF文件这种操作会在哪种应用场景下出现?求分享~
weigr 回答时间:2017-6-18 15:47:15
有意思
anobodykey 回答时间:2017-6-18 15:55:19
深谷幽泉 发表于 2017-6-18 11:45
看起来很高端的样子,居然没人顶。不过,请问楼主,用MCU生成PDF文件这种操作会在哪种应用场景下出现?求分 ...

这个我也还没遇到过,只是之前看到有人问这个,所以看看
pwdzsj 回答时间:2017-6-18 17:04:27
不错还挺好的
好吃好好吃 回答时间:2017-6-18 19:07:12
高手啊
netlhx 回答时间:2017-6-18 20:27:00
赞,楼主功力深厚
graycker 回答时间:2017-6-19 08:44:11
厉害啊,前几个月朋友让做个单片机生成pdf的工具我都没接
anobodykey 回答时间:2017-6-19 10:41:48
graycker 发表于 2017-6-19 08:44
厉害啊,前几个月朋友让做个单片机生成pdf的工具我都没接

这个还只是一个简单的库,实用性还是差一些的
zero99 回答时间:2017-6-26 13:17:46
厉害了楼主~
我为电狂 回答时间:2017-6-27 16:27:22
ff.h在哪里呀,我的是keil4.73版本,需要手动添加吗
epochal 回答时间:2017-6-27 18:30:17
不错,学习了!
anobodykey 回答时间:2017-6-28 09:22:13
我为电狂 发表于 2017-6-27 16:27
ff.h在哪里呀,我的是keil4.73版本,需要手动添加吗

ff.h是FATfs中的文件
我为电狂 回答时间:2017-7-10 10:00:04
anobodykey 发表于 2017-6-28 09:22
ff.h是FATfs中的文件

嗯,这个画线能改变线宽吗

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版