主机环境: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
复制代码
源文件如下: - #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;
- }
复制代码
对于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");
复制代码
代码很简单,生成了一个含有两个page的pdf文件,在第一页中用了不同的字体来显示同一个字符串,可以参考libHaru中的font_demo示例,第二页中是画了一个立方体图,下载代码到目标板,并运行该示例,效果如下:
pdflib库目前来说还是比较简单的,需慢慢完善,pdflib库代码放在下面 pdfgen链接:https://github.com/AndreRenaud/PDFGen PS:更新为V0.04版本了
更新说明: V0.04 - 增加了SimSun中文字体
- 修复了LPDF_Page_SetLineWidth接口中内容长度错误的问题
- pdflib源文件以及测试文件均需使用ANSI编码,否则无法正确显示中文字体
|