/** * Simple engine for creating PDF files. * It supports text, shapes, images etc... * Capable of handling millions of objects without too much performance * penalty. * Public domain license - no warrenty implied; use at your own risk. */ #ifndef PDFGEN_H #define PDFGEN_H #include #include /** * @defgroup subsystem Simple PDF Generation * Allows for quick generation of simple PDF documents. * This is useful for producing easily printed output from C code, where * advanced formatting is not required * * Note: All coordinates/sizes are in points (1/72 of an inch). * All coordinates are based on 0,0 being the bottom left of the page. * All colours are specified as a packed 32-bit value - see @ref PDF_RGB. * Text strings are interpreted as UTF-8 encoded, but only a small subset of * characters beyond 7-bit ascii are supported (see @ref pdf_add_text for * details). * * @par PDF library example: * @code #include "pdfgen.h" ... struct pdf_info info = { .creator = "My software", .producer = "My software", .title = "My document", .author = "My name", .subject = "My subject", .date = "Today" }; struct pdf_doc *pdf = pdf_create(PDF_A4_WIDTH, PDF_A4_HEIGHT, &info); pdf_set_font(pdf, "Times-Roman"); pdf_append_page(pdf); pdf_add_text(pdf, NULL, "This is text", 12, 50, 20); pdf_add_line(pdf, NULL, 50, 24, 150, 24); pdf_save(pdf, "output.pdf"); pdf_destroy(pdf); * @endcode */ struct pdf_doc; struct pdf_object; struct pdf_info { char creator[64]; char producer[64]; char title[64]; char author[64]; char subject[64]; char date[64]; }; /** * Convert a value in inches into a number of points. * Always returns an integer value */ #define PDF_INCH_TO_POINT(inch) ((int)((inch)*72 + 0.5)) /** * Convert a value in milli-meters into a number of points. * Always returns an integer value */ #define PDF_MM_TO_POINT(mm) ((int)((mm)*72 / 25.4 + 0.5)) /** * Point width of a standard US-Letter page */ #define PDF_LETTER_WIDTH PDF_INCH_TO_POINT(8.5) /** * Point height of a standard US-Letter page */ #define PDF_LETTER_HEIGHT PDF_INCH_TO_POINT(11) /** * Point width of a standard A4 page */ #define PDF_A4_WIDTH PDF_MM_TO_POINT(210) /** * Point height of a standard A4 page */ #define PDF_A4_HEIGHT PDF_MM_TO_POINT(297) /** * Point width of a standard A3 page */ #define PDF_A3_WIDTH PDF_MM_TO_POINT(297) /** * Point height of a standard A3 page */ #define PDF_A3_HEIGHT PDF_MM_TO_POINT(420) /** * Convert three 8-bit RGB values into a single packed 32-bit * colour. These 32-bit colours are used by various functions * in PDFGen */ #define PDF_RGB(r, g, b) \ ((((r)&0xff) << 16) | (((g)&0xff) << 8) | (((b)&0xff))) /** * Utility macro to provide bright red */ #define PDF_RED PDF_RGB(0xff, 0, 0) /** * Utility macro to provide bright green */ #define PDF_GREEN PDF_RGB(0, 0xff, 0) /** * Utility macro to provide bright blue */ #define PDF_BLUE PDF_RGB(0, 0, 0xff) /** * Utility macro to provide black */ #define PDF_BLACK PDF_RGB(0, 0, 0) /** * Utility macro to provide white */ #define PDF_WHITE PDF_RGB(0xff, 0xff, 0xff) /** * Utility macro to provide a transparent colour * This is used in some places for 'fill' colours, where no fill is required */ #define PDF_TRANSPARENT (0xff << 24) enum { PDF_ALIGN_LEFT, PDF_ALIGN_RIGHT, PDF_ALIGN_CENTER, PDF_ALIGN_JUSTIFY, PDF_ALIGN_JUSTIFY_ALL, // Like PDF_ALIGN_JUSTIFY, except even short lines // will be fully justified }; /** * Create a new PDF object, with the given page * width/height * @param width Width of the page * @param height Height of the page * @param info Optional information to be put into the PDF header * @return PDF document object, or NULL on failure */ struct pdf_doc *pdf_create(int width, int height, struct pdf_info *info); /** * Destroy the pdf object, and all of its associated memory */ void pdf_destroy(struct pdf_doc *pdf); /** * Retrieve the error message if any operation fails * @param pdf pdf document to retrieve error message from * @param errval optional pointer to an integer to be set to the error code * @return NULL if no error message, string description of error otherwise */ const char *pdf_get_err(struct pdf_doc *pdf, int *errval); /** * Acknowledge an outstanding pdf error * @param pdf pdf document to clear the error message from */ void pdf_clear_err(struct pdf_doc *pdf); /** * Sets the font to use for text objects. Default value is Times-Roman if * this function is not called * Note: The font selection should be done before text is output, * and will remain until pdf_set_font is called again * @param pdf PDF document to update font on * @param font New font to use. This must be one of the standard PDF fonts: * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique, * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique, * Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, * Symbol or ZapfDingbats * @return < 0 on failure, 0 on success */ int pdf_set_font(struct pdf_doc *pdf, const char *font); /** * Returns the width of a given string in the current font * @param pdf PDF document * @param font_name Name of the font to get the width of. * This must be one of the standard PDF fonts: * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique, * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique, * Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, * Symbol or ZapfDingbats * @param text Text to determine width of * @param size Size of the text, in points * @return < 0 on failure, 0 on success */ int pdf_get_font_text_width(struct pdf_doc *pdf, const char *font_name, const char *text, int size); /** * Retrieves a PDF document height */ int pdf_height(struct pdf_doc *pdf); /** * Retrieves a PDF document width */ int pdf_width(struct pdf_doc *pdf); /** * Add a new page to the given pdf * @return new page object */ struct pdf_object *pdf_append_page(struct pdf_doc *pdf); /** * Adjust the width/height of a specific page * @param pdf PDF document that the page belongs to * @param page object returned from @ref pdf_append_page * @param width Width of the page in points * @param height Height of the page in points * @return < 0 on failure, 0 on success */ int pdf_page_set_size(struct pdf_doc *pdf, struct pdf_object *page, int width, int height); /** * Save the given pdf document to the supplied filename * If the filename is NULL, defaults to stdout */ int pdf_save(struct pdf_doc *pdf, const char *filename); /** * Save the given pdf document to the given FILE output */ int pdf_save_file(struct pdf_doc *pdf, FILE *fp); /** * Add a text string to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param text String to display * @param size Point size of the font * @param xoff X location to put it in * @param yoff Y location to put it in * @param colour Colour to draw the text * @return 0 on success, < 0 on failure */ int pdf_add_text(struct pdf_doc *pdf, struct pdf_object *page, const char *text, int size, int xoff, int yoff, uint32_t colour); /** * Add a text string to the document, making it wrap if it is too * long * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param text String to display * @param size Point size of the font * @param xoff X location to put it in * @param yoff Y location to put it in * @param colour Colour to draw the text * @param wrap_width Width at which to wrap the text * @param align Text alignment (see PDF_ALIGN_xxx) * @return height of drawn text on success, < 0 on failure */ int pdf_add_text_wrap(struct pdf_doc *pdf, struct pdf_object *page, const char *text, int size, int xoff, int yoff, uint32_t colour, int wrap_width, int align); /** * Add a line to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x1 X offset of start of line * @param y1 Y offset of start of line * @param x2 X offset of end of line * @param y2 Y offset of end of line * @param width Width of the line * @param colour Colour to draw the line * @return 0 on success, < 0 on failure */ int pdf_add_line(struct pdf_doc *pdf, struct pdf_object *page, int x1, int y1, int x2, int y2, int width, uint32_t colour); /** * Add an ellipse to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x X offset of the center of the ellipse * @param y Y offset of the center of the ellipse * @param xradius Radius of the ellipse in the X axis * @param yradius Radius of the ellipse in the Y axis * @param colour Colour to draw the ellipse outline stroke * @param width Width of the ellipse outline stroke * @param fill_colour Colour to fill the ellipse * @return 0 on success, < 0 on failure */ int pdf_add_ellipse(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int xradius, int yradius, int width, uint32_t colour, uint32_t fill_colour); /** * Add a circle to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x X offset of the center of the circle * @param y Y offset of the center of the circle * @param radius Radius of the circle * @param width Width of the circle outline stroke * @param colour Colour to draw the circle outline stroke * @param fill_colour Colour to fill the circle * @return 0 on success, < 0 on failure */ int pdf_add_circle(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int radius, int width, uint32_t colour, uint32_t fill_colour); /** * Add an outline rectangle to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x X offset to start rectangle at * @param y Y offset to start rectangle at * @param width Width of rectangle * @param height Height of rectangle * @param border_width Width of rectangle border * @param colour Colour to draw the rectangle * @return 0 on succss, < 0 on failure */ int pdf_add_rectangle(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int width, int height, int border_width, uint32_t colour); /** * Add a filled rectangle to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x X offset to start rectangle at * @param y Y offset to start rectangle at * @param width Width of rectangle * @param height Height of rectangle * @param border_width Width of rectangle border * @param colour Colour to draw the rectangle * @return 0 on succss, < 0 on failure */ int pdf_add_filled_rectangle(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int width, int height, int border_width, uint32_t colour); /** * Add an outline polygon to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x array of X offsets for points comprising the polygon * @param y array of Y offsets for points comprising the polygon * @param count Number of points comprising the polygon * @param border_width Width of polygon border * @param colour Colour to draw the polygon * @return 0 on succss, < 0 on failure */ int pdf_add_polygon(struct pdf_doc *pdf, struct pdf_object *page, int x[], int y[], int count, int border_width, uint32_t colour); /** * Add a filled polygon to the document * @param pdf PDF document to add to * @param page Page to add object to (NULL => most recently added page) * @param x array of X offsets of points comprising the polygon * @param y array of Y offsets of points comprising the polygon * @param count Number of points comprising the polygon * @param border_width Width of polygon border * @param colour Colour to draw the polygon * @return 0 on succss, < 0 on failure */ int pdf_add_filled_polygon(struct pdf_doc *pdf, struct pdf_object *page, int x[], int y[], int count, int border_width, uint32_t colour); /** * Add a bookmark to the document * * @param pdf PDF document to add bookmark to * @param page Page to jump to for bookmark (or NULL for the most recently added page) * @param parent ID of a previosly created bookmark that is the parent of this one. -1 if this should be a top-level bookmark. * @param name String to associate with the bookmark * @return < 0 on failure, new bookmark id on success */ int pdf_add_bookmark(struct pdf_doc *pdf, struct pdf_object *page, int parent, const char *name); /** * List of different barcode encodings that are supported */ enum { PDF_BARCODE_128A, PDF_BARCODE_39, }; /** * Add a barcode to the document * @param pdf PDF document to add bookmark to * @param page Page to add barcode to (NULL => most recently added page) * @param code Type of barcode to add (PDF_BARCODE_xxx) * @param x X offset to put barcode at * @param y Y offset to put barcode at * @param width Width of barcode * @param height Height of barcode * @param string Barcode contents * @param colour Colour to draw barcode */ int pdf_add_barcode(struct pdf_doc *pdf, struct pdf_object *page, int code, int x, int y, int width, int height, const char *string, uint32_t colour); /** * Add a PPM file as an image to the document * @param pdf PDF document to add bookmark to * @param page Page to add PPM to (NULL => most recently added page) * @param x X offset to put PPM at * @param y Y offset to put PPM at * @param display_width Displayed width of image * @param display_height Displayed height of image * @param ppm_file Filename of P6 (binary) ppm file to display */ int pdf_add_ppm(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int display_width, int display_height, const char *ppm_file); /** * Add a JPEG file as an image to the document * @param pdf PDF document to add bookmark to * @param page Page to add PPM to (NULL => most recently added page) * @param x X offset to put JPEG at * @param y Y offset to put JPEG at * @param display_width Displayed width of image * @param display_height Displayed height of image * @param jpeg_file Filename of JPEG file to display */ int pdf_add_jpeg(struct pdf_doc *pdf, struct pdf_object *page, int x, int y, int display_width, int display_height, const char *jpeg_file); #endif // PDFGEN_H