开源分享一个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 *****
您好!请问有源码吗, 谢谢 有加密部分就好了 加密部分能放出来就好了
谢谢分享 感谢楼主:victory: Xx谢谢分享! 谢谢分享
页:
[1]