packages feed

jammittools-0.5.5.2: cbits/pdfgen.h

/**
 * 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 <stdbool.h>
#include <stdint.h>

/**
 * @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