查看: 3460|回复: 7

开源分享一个MCU生成简单PDF文档,含源代码

[复制链接]
  • TA的每日心情
    无聊
    2018-11-16 10:48
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2020-8-4 08:52:01 | 显示全部楼层 |阅读模式
    分享到:

    主机环境:Win10 64bit

    开发环境:MDK5.23

    目标板:Cortex-M MCU

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


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

    头文件如下:

    • #ifndef __PDFLIB_H__
    • #define __PDFLIB_H__
    • #include "ff.h"
    • /*----- standard C library functions -----------------------------------------*/
    • #define LPDF_FOPEN                  f_open
    • #define LPDF_FCLOSE                 f_close
    • #define LPDF_FREAD                  f_read
    • #define LPDF_FWRITE                 f_write
    • #define LPDF_FFLUSH                 f_sync
    • #define LPDF_FSEEK                  f_seek
    • #define LPDF_FTELL                  f_tell
    • #define LPDF_FEOF                   f_eof
    • #define LPDF_FERROR                 f_error
    • #define LPDF_RENAME                 f_rename
    • #define LPDF_REMOVE                 f_unlink
    • #define LPDF_MALLOC                 malloc
    • #define LPDF_FREE                   free
    • #define LPDF_FILE                   FIL
    • #define LPDF_TIME                   time
    • #define LPDF_PRINTF                 printf
    • #define LPDF_SPRINTF                sprintf
    • #define LPDF_FPRINTF                f_printf
    • #define LPDF_VOID                   void
    • #define LPDF_SIN                    sin
    • #define LPDF_COS                    cos
    • /*  native OS integer types */
    • typedef  signed int          LPDF_INT;
    • typedef  unsigned int        LPDF_UINT;
    • /*  32bit integer types
    • */
    • typedef  signed int          LPDF_INT32;
    • typedef  unsigned int        LPDF_UINT32;
    • /*  16bit integer types
    • */
    • typedef  signed short        LPDF_INT16;
    • typedef  unsigned short      LPDF_UINT16;
    • /*  8bit integer types
    • */
    • typedef  signed char         LPDF_INT8;
    • typedef  unsigned char       LPDF_UINT8;
    • /*  8bit binary types
    • */
    • typedef  unsigned char       LPDF_BYTE;
    • /*  float type (32bit IEEE754)
    • */
    • typedef  float               LPDF_REAL;
    • /*  double type (64bit IEEE754)
    • */
    • typedef  double              LPDF_DOUBLE;
    • /*  boolean type (0: False, !0: True)
    • */
    • typedef  signed int          LPDF_BOOL;
    • /*  error-no type (32bit unsigned integer)
    • */
    • typedef  unsigned long       LPDF_STATUS;
    • #define LPDF_OK                     0
    • #define LPDF_FAILED                 1
    • /*----- font state -----------------------------------------------------------*/
    • #define   LPDF_FONT_INVALID                 0x00FF
    • #define   LPDF_FONT_COURIER                 0x0000
    • #define   LPDF_FONT_COURIER_B               0x0001
    • #define   LPDF_FONT_COURIER_O               0x0002
    • #define   LPDF_FONT_COURIER_OB              0x0003
    • #define   LPDF_FONT_HELVETICA               0x0004
    • #define   LPDF_FONT_HELVETICA_B             0x0005
    • #define   LPDF_FONT_HELVETICA_O             0x0006
    • #define   LPDF_FONT_HELVETICA_BO            0x0007
    • #define   LPDF_FONT_TIMES_R                 0x0008
    • #define   LPDF_FONT_TIMES_B                 0x0009
    • #define   LPDF_FONT_TIMES_I                 0x000A
    • #define   LPDF_FONT_TIMES_BI                0x000B
    • #define   LPDF_FONT_SYMBOL                  0x000C
    • #define   LPDF_FONT_ZAP                     0x000D
    • /*----- Graphis mode ---------------------------------------------------------*/
    • #define   LPDF_GMODE_PAGE_DESCRIPTION       0x0001
    • #define   LPDF_GMODE_PATH_OBJECT            0x0002
    • #define   LPDF_GMODE_TEXT_OBJECT            0x0004
    • #define   LPDF_GMODE_CLIPPING_PATH          0x0008
    • #define   LPDF_GMODE_SHADING                0x0010
    • #define   LPDF_GMODE_INLINE_IMAGE           0x0020
    • #define   LPDF_GMODE_EXTERNAL_OBJECT        0x0040
    • #define   LPDF_GMODE_INVALID                0x0080
    • #define   LPDF_GMODE_OVER                   0x0100
    • #define OBJ_MAX_NUM     256
    • /* Page的结构信息是否需要树形结构 */
    • typedef enum
    • {
    •     OBJ_info,
    •     OBJ_stream,
    •     OBJ_font,
    •     OBJ_page,
    •     OBJ_catalog,
    •     OBJ_pages,
    •     OBJ_image,
    • }LPDF_ObjType;
    • typedef struct
    • {
    •     LPDF_ObjType objType;
    •     LPDF_UINT16 objIdx;
    •     LPDF_UINT16 height;
    •     LPDF_UINT16 width;
    •     LPDF_UINT16 length;
    •     LPDF_UINT gMode;
    •     LPDF_BYTE fontType;
    •     LPDF_BYTE fontSize;
    •     LPDF_BYTE pState;
    •     LPDF_VOID *doc;
    • }LPDF_Obj;
    • typedef struct
    • {
    •     LPDF_Obj obj[OBJ_MAX_NUM];
    •     LPDF_UINT32 offset;
    •     LPDF_UINT16 objNumber;
    •     LPDF_FILE file;
    • }LPDF_Doc_Rec;
    • typedef LPDF_Doc_Rec *LPDF_Doc;
    • typedef LPDF_Obj *LPDF_Page;
    • typedef LPDF_Obj *LPDF_Image;
    • extern const char *font_list[];
    • /*----- LPDF Interfaces-------------------------------------------------------*/
    • const char * LPDF_GetVersion(void);
    • LPDF_Doc LPDF_New(void);
    • LPDF_Page LPDF_AddPage(LPDF_Doc pdf);
    • LPDF_STATUS LPDF_SaveToFile(LPDF_Doc pdf,const char *file_name);
    • LPDF_STATUS LPDF_Free(LPDF_Doc pdf);
    • LPDF_STATUS LPDF_Page_CheckState(LPDF_Page page, LPDF_UINT mode);
    • LPDF_STATUS LPDF_Page_SetFontAndSize(LPDF_Page page,
    •                            const char *font_name, LPDF_UINT8 size);
    • LPDF_STATUS LPDF_Page_SaveParams(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_SaveContext(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_BeginText(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_EndText(LPDF_Page page);
    • LPDF_UINT16 LPDF_Page_GetHeight(LPDF_Page page);
    • LPDF_UINT16 LPDF_Page_GetWidth(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_SetHeight(LPDF_Page page, LPDF_UINT16 value);
    • LPDF_STATUS LPDF_Page_SetWidth(LPDF_Page page, LPDF_UINT16 value);
    • LPDF_STATUS LPDF_Page_ShowText(LPDF_Page page, const char *text);
    • LPDF_STATUS LPDF_Page_MoveTextPos(LPDF_Page page,
    •                          LPDF_INT x, LPDF_INT y);
    • LPDF_STATUS LPDF_Page_TextOut(LPDF_Page page,
    •                          LPDF_UINT16 x, LPDF_UINT16 y,
    •                          const char *text);
    • LPDF_STATUS LPDF_Page_SetRGBStroke(LPDF_Page page,
    •                          LPDF_REAL r,
    •                          LPDF_REAL g,
    •                          LPDF_REAL b);
    • LPDF_STATUS LPDF_Page_SetRGBFill(LPDF_Page page,
    •                          LPDF_REAL r,
    •                          LPDF_REAL g,
    •                          LPDF_REAL b);
    • LPDF_STATUS LPDF_Page_MoveTo (LPDF_Page page,
    •                          LPDF_UINT16 x,
    •                          LPDF_UINT16 y);
    • LPDF_STATUS LPDF_Page_LineTo (LPDF_Page page,
    •                          LPDF_UINT16 x,
    •                          LPDF_UINT16 y);
    • LPDF_STATUS LPDF_Page_Stroke(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_ClosePathStroke(LPDF_Page page);
    • LPDF_STATUS LPDF_Page_DrawImage(LPDF_Page page,
    •                       LPDF_Image image,
    •                       LPDF_UINT16 x,
    •                       LPDF_UINT16 y,
    •                       LPDF_UINT16 width,
    •                       LPDF_UINT16 height);
    • #endif


    [color=rgb(51, 102, 153) !important]复制代码

    源文件如下:

    • #include <stdio.h>
    • #include <stdlib.h>
    • #include <stdint.h>
    • #include <string.h>
    • #include "pdflib.h"
    • #define LPDF_INVALID_OBJECT                       0x1033
    • static char pdf_buf[512];
    • #define LPDF_VERSIOIN_TEXT          "0.0.1"
    • #define LPDF_FILE_HEADER_LEN        15
    • #define LPDF_BASEFONT_NUM           14
    • const char LPDF_FILE_HEADER[] = "%%PDF-1.4\n%%\xAA\xBB\xCC\xDD\n";
    • const char *font_list[] = {
    •     "Courier",
    •     "Courier-Bold",
    •     "Courier-Oblique",
    •     "Courier-BoldOblique",
    •     "Helvetica",
    •     "Helvetica-Bold",
    •     "Helvetica-Oblique",
    •     "Helvetica-BoldOblique",
    •     "Times-Roman",
    •     "Times-Bold",
    •     "Times-Italic",
    •     "Times-BoldItalic",
    •     "Symbol",
    •     "ZapfDingbats",
    •     NULL
    • };
    • const char * LPDF_GetVersion(void)
    • {
    •     return LPDF_VERSIOIN_TEXT;
    • }
    • LPDF_Doc LPDF_New(void)
    • {
    •     static LPDF_Doc_Rec pdf;
    •     LPDF_INT length = 0, i = 0;
    •         LPDF_UINT writeBytes = 0;
    •         FRESULT fr;
    •     fr = LPDF_FOPEN(&pdf.file,"/tmp.pdf",FA_CREATE_ALWAYS|FA_WRITE);
    •         if(fr)
    •         {
    •                 LPDF_PRINTF("create tmp.pdf failed!\r\n");
    •                 return NULL;
    •         }
    •     LPDF_FPRINTF(&pdf.file,LPDF_FILE_HEADER);   /* 写入文件头 */
    •     pdf.offset = LPDF_FILE_HEADER_LEN;
    •     pdf.obj[0].objIdx = pdf.offset;
    •     length = LPDF_SPRINTF(pdf_buf,"1 0 obj\n<<\n/Type /Catalog\n/Pages 17 0 R\n>>\nendobj\n\n");
    •     LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    •     pdf.offset += length;
    •     pdf.obj[1].objIdx = pdf.offset;
    •     length = LPDF_SPRINTF(pdf_buf,"2 0 obj\n<<\n/Creator (light pdf library 0.0.1)\n"
    •                     "/Auther (anobodykey)\n>>\nendobj\n\n");
    •     LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    •     pdf.offset += length;
    •     for(i = 0; i < LPDF_BASEFONT_NUM-2; i++)
    •     {
    •         pdf.obj[2+i].objIdx = pdf.offset;
    •         length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
    •                         "/BaseFont /%s\n/Encoding /WinAnsiEncoding\n>>\n"
    •                         "endobj\n\n",3+i,font_list);
    •         LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    •         pdf.offset += length;
    •     }
    •     for(; i < LPDF_BASEFONT_NUM; i++)
    •     {
    •         pdf.obj[2+i].objIdx = pdf.offset;
    •         length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
    •                         "/BaseFont /%s\n>>\nendobj\n\n",3+i,font_list);
    •         LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    •         pdf.offset += length;
    •     }
    •     pdf.objNumber = 3+i;
    •     return (LPDF_Doc)&pdf;
    • }
    • LPDF_STATUS LPDF_SaveToFile(LPDF_Doc pdf,const char *file_name)
    • {
    •     LPDF_UINT16 i = 0, child_pages = 0;
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     pdf->obj[16].objIdx = pdf->offset;
    •     child_pages = (pdf->objNumber-2-LPDF_BASEFONT_NUM)/3 ;
    •     length = LPDF_SPRINTF(pdf_buf,"17 0 obj\n<<\n/Types /Pages\n/Count %d\n/Kids [ ",child_pages);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     for(i = 0; i < child_pages; i++)
    •     {
    •         length = LPDF_SPRINTF(pdf_buf,"%d 0 R\n",18+i*3);
    •         LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •         pdf->offset += length;
    •     }
    •     length = LPDF_SPRINTF(pdf_buf,"]\n>>\nendobj\n\n");
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     LPDF_FPRINTF(&pdf->file,"xref\n0 %d\n0000000000 65535 f\r\n",pdf->objNumber+1);
    •     for(i = 0 ; i < pdf->objNumber; i++)
    •     {
    •         LPDF_FPRINTF(&pdf->file,"%10.10d 00000 n\r\n",pdf->obj.objIdx);
    •     }
    •     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",
    •                 pdf->objNumber+1,pdf->offset);
    •     LPDF_FCLOSE(&pdf->file);
    •     LPDF_REMOVE(file_name);
    •     LPDF_RENAME("tmp.pdf",file_name);
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Free(LPDF_Doc pdf)
    • {
    •     memset(pdf,sizeof(LPDF_Doc_Rec),0);
    •     return LPDF_OK;
    • }
    • LPDF_Page LPDF_AddPage(LPDF_Doc pdf)
    • {
    •     LPDF_INT length = 0,i = 0;
    •     LPDF_Page page = NULL;
    •         LPDF_UINT writeBytes = 0;
    •     pdf->obj[pdf->objNumber].objIdx = pdf->offset;
    •     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Page\n/Parent 4 0 R\n/Contents %d 0 R\n"
    •                     "/Resources <<\n/ProcSet [/PDF /TEXT /ImageB /ImageC /ImageI]\n"
    •                     "/Font <<\n",pdf->objNumber+1,pdf->objNumber+2);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     while(font_list)
    •     {
    •         length = LPDF_SPRINTF(pdf_buf,"/F%d %d 0 R\n",i+1,3+i);
    •         LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •         pdf->offset += length;
    •         i+=1;
    •     }
    •     LPDF_FPRINTF(&pdf->file,">>\n>>\n");
    •     pdf->offset += 4;
    •     page = (LPDF_Page)&pdf->obj[pdf->objNumber];
    •     page->width = 595;
    •     page->height = 842;
    •     page->gMode = LPDF_GMODE_INVALID;
    •     page->fontType = LPDF_FONT_INVALID;
    •     page->doc = pdf;
    •     return page;
    • }
    • LPDF_STATUS LPDF_Page_SetHeight(LPDF_Page page, LPDF_UINT16 value)
    • {
    •     page->height = value;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SetWidth(LPDF_Page page, LPDF_UINT16 value)
    • {
    •     page->width = value;
    •     return LPDF_OK;
    • }
    • LPDF_UINT16 LPDF_Page_GetHeight(LPDF_Page page)
    • {
    •     if(page)
    •     {
    •         return page->height;
    •     }
    •     return LPDF_OK;
    • }
    • LPDF_UINT16 LPDF_Page_GetWidth(LPDF_Page page)
    • {
    •     if(page)
    •     {
    •         return page->width;
    •     }
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_CheckState(LPDF_Page page, LPDF_UINT mode)
    • {
    •     if(!page)
    •         return LPDF_INVALID_OBJECT;
    •     if(!(page->gMode&mode))
    •         return LPDF_FAILED;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SetFontAndSize(LPDF_Page page,
    •                            const char *font_name, LPDF_UINT8 size)
    • {
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_INT i = 0,length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     while(font_list)
    •     {
    •         if(0 == strcmp(font_list,font_name))
    •         {
    •             page->fontType = i;
    •             page->fontSize = size;
    •             length = LPDF_SPRINTF(pdf_buf,"/F%d %d Tf\n",i+1,size);
    •             LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •             pdf->offset += length;
    •             page->length += length;
    •             return LPDF_OK;
    •         }
    •         i+=1;
    •     }
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SaveParams(LPDF_Page page)
    • {
    •     LPDF_INT length;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_INVALID);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     /* 对于每个page来说该接口只能调用一次即在GMODE为INVALID的模式下 */
    •     length = LPDF_SPRINTF(pdf_buf,"/MediaBox [ 0 0 %d %d ]\n>>\nendobj\n\n",
    •                         page->width, page->height);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     pdf->obj[pdf->objNumber+1].objIdx = pdf->offset;
    •     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<</Length %d 0 R>>\nstream\n",
    •                         pdf->objNumber+2, pdf->objNumber+3);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length = 0;
    •     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SaveContext(LPDF_Page page)
    • {
    •     LPDF_INT length;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
    •     if(LPDF_OK != ret)
    •         return ret;
    •      /* 对于每个page来说该接口只能调用一次即在GMODE为PAGE_DESCRIPTION的模式下 */
    •     length = LPDF_SPRINTF(pdf_buf,"endstream\nendobj\n\n");
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     pdf->obj[pdf->objNumber+2].objIdx = pdf->offset;
    •     length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n%d\nendobj\n\n",
    •                         pdf->objNumber+3,page->length);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     pdf->objNumber += 3;
    •     page->gMode = LPDF_GMODE_OVER;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_BeginText(LPDF_Page page)
    • {
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     LPDF_FPRINTF(&pdf->file,"BT\n");
    •     pdf->offset += 3;
    •     page->length += 3;
    •     page->gMode = LPDF_GMODE_TEXT_OBJECT;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_EndText(LPDF_Page page)
    • {
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     LPDF_FPRINTF(&pdf->file,"ET\n");
    •     pdf->offset += 3;
    •     page->length += 3;
    •     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_ShowText(LPDF_Page page, const char *text)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     if(LPDF_FONT_INVALID == page->fontType)
    •         return LPDF_OK;
    •     length = LPDF_SPRINTF(pdf_buf,"(%s) Tj\n",text);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_MoveTextPos(LPDF_Page page,
    •                         LPDF_INT x, LPDF_INT y)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     length = LPDF_SPRINTF(pdf_buf,"%d %d Td\n",x,y);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_TextOut(LPDF_Page page,
    •                         LPDF_UINT16 x, LPDF_UINT16 y,
    •                         const char *text)
    • {
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SetRGBStroke(LPDF_Page page,
    •                          LPDF_REAL r,
    •                          LPDF_REAL g,
    •                          LPDF_REAL b)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f RG\n",r,g,b);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_SetRGBFill(LPDF_Page page,
    •                          LPDF_REAL r,
    •                          LPDF_REAL g,
    •                          LPDF_REAL b)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f rg\n",r,g,b);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_MoveTo (LPDF_Page page,
    •                          LPDF_UINT16 x,
    •                          LPDF_UINT16 y)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION|LPDF_GMODE_PATH_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     length = LPDF_SPRINTF(pdf_buf,"%d %d m\n",x,y);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     page->gMode = LPDF_GMODE_PATH_OBJECT;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_LineTo (LPDF_Page page,
    •                          LPDF_UINT16 x,
    •                          LPDF_UINT16 y)
    • {
    •     LPDF_INT length = 0;
    •         LPDF_UINT writeBytes = 0;
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     length = LPDF_SPRINTF(pdf_buf,"%d %d l\n",x,y);
    •     LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    •     pdf->offset += length;
    •     page->length += length;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_Stroke(LPDF_Page page)
    • {
    •     LPDF_Doc pdf = (LPDF_Doc)page->doc;
    •     LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
    •     if(LPDF_OK != ret)
    •         return ret;
    •     LPDF_FPRINTF(&pdf->file,"S\n");
    •     pdf->offset += 2;
    •     page->length += 2;
    •     page->gMode = LPDF_GMODE_PAGE_DESCRIPTION;
    •     return LPDF_OK;
    • }
    • LPDF_STATUS LPDF_Page_DrawImage(LPDF_Page page,
    •                       LPDF_Image image,
    •                       LPDF_UINT16 x,
    •                       LPDF_UINT16 y,
    •                       LPDF_UINT16 width,
    •                       LPDF_UINT16 height)
    • {
    •         return LPDF_OK;
    • }


    [color=rgb(51, 102, 153) !important]复制代码

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

    • pdf = LPDF_New();
    •     page[0] = LPDF_AddPage(pdf);
    •     LPDF_Page_SaveParams(page[0]);
    •     width = LPDF_Page_GetWidth(page[0]);
    •     height = LPDF_Page_GetHeight(page[0]);
    •     LPDF_Page_SetRGBFill(page[0], 1.0, 0.0, 0.0);
    •     LPDF_Page_BeginText(page[0]);
    •     LPDF_Page_MoveTextPos(page[0], 50, height-20);
    •     while(font_list)
    •     {
    •         LPDF_Page_SetFontAndSize(page[0], font_list, 24);
    •         LPDF_Page_ShowText(page[0], "abcdefgABCDEFG12345!\043$\045&+-@?");
    •         LPDF_Page_MoveTextPos(page[0], 0, -30);
    •         i++;
    •     }
    •         LPDF_Page_SetFontAndSize(page[0], font_list[0], 24);
    •     LPDF_Page_ShowText(page[0], LPDF_GetVersion());
    •     LPDF_Page_EndText(page[0]);
    •     LPDF_Page_SaveContext(page[0]);
    •     page[1] = LPDF_AddPage(pdf);
    •     LPDF_Page_SaveParams(page[1]);
    •     LPDF_Page_MoveTo(page[1], width/2-50, height-200);
    •     LPDF_Page_LineTo(page[1], width/2-50, height-300);
    •     LPDF_Page_LineTo(page[1], width/2-50+100, height-300);
    •     LPDF_Page_LineTo(page[1], width/2-50+100, height-200);
    •     LPDF_Page_LineTo(page[1], width/2-50, height-200);
    •     LPDF_Page_LineTo(page[1], width/2-50+40, height-140);
    •     LPDF_Page_LineTo(page[1], width/2-50+40+100, height-140);
    •     LPDF_Page_LineTo(page[1], width/2-50+100, height-200);
    •     LPDF_Page_Stroke(page[1]);
    •     LPDF_Page_MoveTo(page[1], width/2-50+40+100, height-140);
    •     LPDF_Page_LineTo(page[1], width/2-50+40+100, height-240);
    •     LPDF_Page_LineTo(page[1], width/2-50+100, height-300);
    •     LPDF_Page_Stroke(page[1]);
    •     LPDF_Page_SaveContext(page[1]);
    •     LPDF_SaveToFile(pdf, "/red.pdf");
    •         PRINTF("\r\nCreate pdf file success!\r\n");


    [color=rgb(51, 102, 153) !important]复制代码

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


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


    PS:更新为V0.04版本了

    更新说明: V0.04

    • 增加了SimSun中文字体
    • 修复了LPDF_Page_SetLineWidth接口中内容长度错误的问题
    • pdflib源文件以及测试文件均需使用ANSI编码,否则无法正确显示中文字体
    游客,如果您要查看本帖隐藏内容请回复


    回复

    使用道具 举报

    该用户从未签到

    发表于 2020-8-5 09:02:04 | 显示全部楼层
    Xx谢谢分享!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    郁闷
    2024-4-19 09:04
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2022-11-8 17:06:58 | 显示全部楼层
    加密部分能放出来就好了
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    郁闷
    2024-4-19 09:04
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2022-11-8 17:14:51 | 显示全部楼层
    有加密部分就好了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-5-20 11:58 , Processed in 0.204920 second(s), 31 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.