Host environment: Win10 64bit
Development environment: MDK5.23
Target board: LPC54608
I got an LPC54608 development board from the NXP forum before. The most attractive thing about it is that it comes with a screen, as shown below:
This is also the first time I have come into contact with NXP's development board. I have always used ST's MCU before. The NXP library is quite different from ST's. I feel that ST's development is faster, while NXP's is relatively slower. After getting the development board, I looked at some basic driver routines that come with the library and only became familiar with the development of basic peripherals. I once saw someone in the group asking about the problem of generating PDF with a single-chip microcomputer. I suddenly felt interested, so I had the previous libHaru study notes. The libHaru library is a very good library, and it is also quite complete for the implementation of PDF. It is used on the PC. There is absolutely no problem in using it, but it is still a bit difficult on MCU with limited resources. Therefore, I want to find a library for generating PDF files suitable for MCU. The result is not ideal. They are all platforms that need to implement dynamic memory management. Moreover, these libraries put the generated data in the memory and write it to the file until the file is saved. This is even more impossible for microcontrollers with only tens or hundreds of KB. So, I have the idea of writing a basic library that can be used for MCU to generate PDF files. I call it libpdf, and its interface refers to libHaru, as shown below:
Of course, some interfaces have not been implemented yet, but the basic operations are still possible, and they will be gradually improved in the future. pdflib generates pdf files, so it is necessary to implement file operations based on Fatfs. The pdflib library has only two files, and the pdfgen library is also referenced accordingly. The library has a link at the back.
The header file is as follows:
#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;
/* 32-bit integer types
*/
typedef signed int LPDF_INT32;
typedef unsigned int LPDF_UINT32;
/* 16-bit integer types
*/
typedef signed short LPDF_INT16;
typedef unsigned short LPDF_UINT16;
/* 8-bit integer types
*/
typedef signed char LPDF_INT8;
typedef unsigned char LPDF_UINT8;
/* 8-bit 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
/* Does the structure information of the Page need a tree structure?*/
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
The source files are as follows:
#include
#include
#include
#include
#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); /* Write 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;
/* For each page, this interface can only be called once, that is, when GMODE is 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<>\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;
/* For each page, this interface can only be called once, that is, when GMODE is PAGE_DESCRIPTION mode*/
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 %dm\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 %dl\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;
}
For the PDF file structure, you can check the PDF reference manual. Here I am looking at the PDF-1.4 reference manual. The test code of this library is adapted from the sdcard_fatfs example in the LPC54608 library. The key code is as follows:
The test code is very simple. It generates a PDF file with two pages. Different fonts are used to display the same string in the first page. You can refer to the font_demo example in libHaru. The second page draws a cube. Download the code to the target board and run the example. The serial terminal output is as follows:
Unplug the SD card from the board and insert it into the PC, you can see the red.pdf file
Use a PDF reader to open the file, and the screenshot is as follows:
The pdflib library is still relatively simple at present and needs to be gradually improved.
The pdfgen library link is as follows: https://github.com/AndreRenaud/PDFGen
pdflib download link: There was no response after uploading it for a long time. If you need it, you can find it in my resources. I won’t put the link here.
Previous article:STM32 study notes USB project directory file analysis
Next article:ARM processor working mode and register structure
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Prize live broadcast: TI takes you to learn mobile robots. This Friday at 10 am, make an appointment to watch and there will be a surprise~
- What is HAu(CN)2?
- ADI or TI blood glucose meter solution
- How should the size of the drone be determined?
- Introduction to the Internet of Things Protocol Coap Protocol
- PIC16+CMT2300A, cannot receive data.
- Won the grand prize
- Transformer coupled push-pull power amplifier circuit
- Questions about writing data from DSP to DATARAM in PRU1
- Please recommend a buck-boost chip