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

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, 下载次数: 367

pdflib库

评分

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

查看全部评分

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

举报

141个回答
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-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的工具我都没接

这个还只是一个简单的库,实用性还是差一些的

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

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