gjhk001 发表于 2020-8-4 08:52:01

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

主机环境:Win10 64bit开发环境:MDK5.23目标板:Cortex-M MCU之前有次在群里看到有人询问单片机生成PDF的问题,突然觉得有些兴趣所以就学习了一下libHaru库,libHaru库是一个十分不错的库,对于PDF的实现来说也是相当齐全的,在PC上使用是完全没有问题的,但在资源紧张的MCU上,还是有些困难的,因此就想找一下适用于MCU的生成PDF的库,结果不太理想,都是一些需要实现动态内存管理的平台才行,而且这些库都是把生成的数据放在了内存中,直到保存文件时才写入到文件中,这对于一般只有几十或者几百KB级别的单片机来说更不可能了,于是乎,萌发了自己动手写一个基本的能用于MCU的生成PDF文件的库,我称之为libpdf,其中的接口参考了libHaru,如下所示:http://www.stmcu.org.cn/module/forum/data/attachment/forum/201706/17/225827aap0jhprpahh4ptj.png
当然有些接口还没有实现,但基本的操作还是可以的,等以后再逐渐完善吧,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 */
[*]typedefsigned int          LPDF_INT;
[*]typedefunsigned int      LPDF_UINT;
[*]
[*]
[*]/*32bit integer types
[*]*/
[*]typedefsigned int          LPDF_INT32;
[*]typedefunsigned int      LPDF_UINT32;
[*]
[*]
[*]/*16bit integer types
[*]*/
[*]typedefsigned short      LPDF_INT16;
[*]typedefunsigned short      LPDF_UINT16;
[*]
[*]
[*]/*8bit integer types
[*]*/
[*]typedefsigned char         LPDF_INT8;
[*]typedefunsigned char       LPDF_UINT8;
[*]
[*]
[*]/*8bit binary types
[*]*/
[*]typedefunsigned char       LPDF_BYTE;
[*]
[*]
[*]/*float type (32bit IEEE754)
[*]*/
[*]typedeffloat               LPDF_REAL;
[*]
[*]
[*]/*double type (64bit IEEE754)
[*]*/
[*]typedefdouble            LPDF_DOUBLE;
[*]
[*]
[*]/*boolean type (0: False, !0: True)
[*]*/
[*]typedefsigned int          LPDF_BOOL;
[*]
[*]
[*]/*error-no type (32bit unsigned integer)
[*]*/
[*]typedefunsigned 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;
[*]    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
[*]

复制代码
源文件如下:
[*]#include <stdio.h>
[*]#include <stdlib.h>
[*]#include <stdint.h>
[*]#include <string.h>
[*]#include "pdflib.h"
[*]
[*]#define LPDF_INVALID_OBJECT                     0x1033
[*]
[*]static char pdf_buf;
[*]
[*]#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.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.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.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.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.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.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 \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;
[*]    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.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.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;
[*]}
[*]

复制代码
对于pdf文件结构可以去查看pdf参考手册,这里我看的是pdf-1.4参考手册,该库的测试代码我是在基于LPC54608库中的sdcard_fatfs示例改编的,同样适用于STM32,关键代码如下:
[*]pdf = LPDF_New();
[*]    page = LPDF_AddPage(pdf);
[*]    LPDF_Page_SaveParams(page);
[*]    width = LPDF_Page_GetWidth(page);
[*]    height = LPDF_Page_GetHeight(page);
[*]    LPDF_Page_SetRGBFill(page, 1.0, 0.0, 0.0);
[*]    LPDF_Page_BeginText(page);
[*]    LPDF_Page_MoveTextPos(page, 50, height-20);
[*]    while(font_list)
[*]    {
[*]      LPDF_Page_SetFontAndSize(page, font_list, 24);
[*]      LPDF_Page_ShowText(page, "abcdefgABCDEFG12345!\043$\045&+-@?");
[*]      LPDF_Page_MoveTextPos(page, 0, -30);
[*]      i++;
[*]    }
[*]      LPDF_Page_SetFontAndSize(page, font_list, 24);
[*]    LPDF_Page_ShowText(page, LPDF_GetVersion());
[*]    LPDF_Page_EndText(page);
[*]    LPDF_Page_SaveContext(page);
[*]    page = LPDF_AddPage(pdf);
[*]    LPDF_Page_SaveParams(page);
[*]    LPDF_Page_MoveTo(page, width/2-50, height-200);
[*]    LPDF_Page_LineTo(page, width/2-50, height-300);
[*]    LPDF_Page_LineTo(page, width/2-50+100, height-300);
[*]    LPDF_Page_LineTo(page, width/2-50+100, height-200);
[*]    LPDF_Page_LineTo(page, width/2-50, height-200);
[*]    LPDF_Page_LineTo(page, width/2-50+40, height-140);
[*]    LPDF_Page_LineTo(page, width/2-50+40+100, height-140);
[*]    LPDF_Page_LineTo(page, width/2-50+100, height-200);
[*]    LPDF_Page_Stroke(page);
[*]    LPDF_Page_MoveTo(page, width/2-50+40+100, height-140);
[*]    LPDF_Page_LineTo(page, width/2-50+40+100, height-240);
[*]
[*]    LPDF_Page_LineTo(page, width/2-50+100, height-300);
[*]    LPDF_Page_Stroke(page);
[*]    LPDF_Page_SaveContext(page);
[*]    LPDF_SaveToFile(pdf, "/red.pdf");
[*]      PRINTF("\r\nCreate pdf file success!\r\n");
[*]

复制代码
代码很简单,生成了一个含有两个page的pdf文件,在第一页中用了不同的字体来显示同一个字符串,可以参考libHaru中的font_demo示例,第二页中是画了一个立方体图,下载代码到目标板,并运行该示例,效果如下:http://www.stmcu.org.cn/module/forum/data/attachment/forum/201706/17/230108daxloamq9o9uja9q.png
pdflib库目前来说还是比较简单的,需慢慢完善,pdflib库代码放在下面
PS:更新为V0.04版本了
更新说明: V0.04
[*]增加了SimSun中文字体
[*]修复了LPDF_Page_SetLineWidth接口中内容长度错误的问题
[*]pdflib源文件以及测试文件均需使用ANSI编码,否则无法正确显示中文字体
**** Hidden Message *****

我为什么在这里 发表于 2025-4-12 16:17:18

您好!请问有源码吗,

洪正安 发表于 2024-2-25 18:28:02

谢谢

yq_qin 发表于 2022-11-8 17:14:51

有加密部分就好了

yq_qin 发表于 2022-11-8 17:06:58

加密部分能放出来就好了

purplecomeeast 发表于 2020-8-8 17:19:55

谢谢分享

zhkadqq 发表于 2020-8-5 09:00:53

感谢楼主:victory:

fulifhy 发表于 2020-8-5 09:02:04

Xx谢谢分享!

kunchen 发表于 2020-8-5 09:02:04

谢谢分享
页: [1]
查看完整版本: 开源分享一个MCU生成简单PDF文档,含源代码

Baidu
map