LPC54608生成PDF文件

来源:互联网 发布:现金返利系统源码 编辑:程序博客网 时间:2024/06/08 02:49

主机环境:Win10 64bit

开发环境:MDK5.23

目标板:LPC54608

之前在NXP论坛里得到了一块LPC54608开发板,最吸引人的地方是带了一块屏,如下图:


这也是第一次接触NXP的开发板,之前一直都是用的ST的MCU,NXP的库跟ST的还是差别蛮大的,自我感觉ST的开发入手要快一些,而NXP的相对慢一些,入手开发板之后就看了库里面自带的一些基本驱动例程,只熟悉了一下基本外设的开发,之前有次在群里看到有人询问单片机生成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
源文件如下:

#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include "pdflib.h"#define LPDF_INVALID_OBJECT                       0x1033static char pdf_buf[512];#define LPDF_VERSIOIN_TEXT          "0.0.1"#define LPDF_FILE_HEADER_LEN        15#define LPDF_BASEFONT_NUM           14const 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[i]);        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[i]);        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[i].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[i])    {        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[i])    {        if(0 == strcmp(font_list[i],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;}
对于pdf文件结构可以去查看pdf参考手册,这里我看的是pdf-1.4参考手册,该库的测试代码我是在基于LPC54608库中的sdcard_fatfs示例改编的,关键代码如下:


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


拔下板上的SD卡,插入到PC上,可以看到red.pdf文件


使用pdf阅读器打开该文件,截图如下:


pdflib库目前来说还是比较简单的,需慢慢完善,

pdfgen库链接如下:https://github.com/AndreRenaud/PDFGen

pdflib下载链接:上传了半天没反应,有需要的可以去我的资源里面找下,这里就不放链接了。