From eb9dad9b51480b50626d9aa23f30f56e0dc61bab Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Mon, 9 Dec 2024 19:13:48 -0500 Subject: [PATCH] Add Code 128 example code. --- .gitignore | 2 + examples/code128.c | 209 +++++++++++++++++++++++++++++++++++++++++++ examples/code128.ttf | Bin 0 -> 7884 bytes 3 files changed, 211 insertions(+) create mode 100644 examples/code128.c create mode 100644 examples/code128.ttf diff --git a/.gitignore b/.gitignore index bbf875c..439f92e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,9 @@ /autom4te.cache /config.log /config.status +/configure~ /doc/pdfio.epub +/examples/code128 /Makefile /packages /pdfio.pc diff --git a/examples/code128.c b/examples/code128.c new file mode 100644 index 0000000..c267c04 --- /dev/null +++ b/examples/code128.c @@ -0,0 +1,209 @@ +// +// Code 128 barcode example for PDFio. +// +// Copyright © 2024 by Michael R Sweet. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// +// Usage: +// +// ./code128 "BARCODE" ["TEXT"] >FILENAME.pdf +// + +#include +#include + + +// +// 'make_code128()' - Make a Code 128 barcode string. +// +// This function produces a Code B (printable ASCII) representation of the +// source string and doesn't try to optimize using Code C. Non-printable and +// extended characters are ignored in the source string. +// + + +static char * // O - Output string +make_code128(char *dst, // I - Destination buffer + const char *src, // I - Source string + size_t dstsize) // I - Size of destination buffer +{ + char *dstptr, // Pointer into destination buffer + *dstend; // End of destination buffer + int sum = 0; // Weighted sum + static const char *code128_chars = // Code 128 characters + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~\303" + "\304\305\306\307\310\311\312"; + static const char code128_fnc_3 = '\304'; + // FNC 3 + static const char code128_fnc_2 = '\305'; + // FNC 2 + static const char code128_shift_b = '\306'; + // Shift B (for lowercase) + static const char code128_code_c = '\307'; + // Code C + static const char code128_code_b = '\310'; + // Code B + static const char code128_fnc_4 = '\311'; + // FNC 4 + static const char code128_fnc_1 = '\312'; + // FNC 1 + static const char code128_start_code_a = '\313'; + // Start code A + static const char code128_start_code_b = '\314'; + // Start code A + static const char code128_start_code_c = '\315'; + // Start code A + static const char code128_stop = '\316'; + // Stop pattern + + + // Start a Code B barcode... + dstptr = dst; + dstend = dst + dstsize - 3; + + *dstptr++ = code128_start_code_b; + sum = code128_start_code_b - 100; + + while (*src && dstptr < dstend) + { + if (*src >= ' ' && *src < 0x7f) + { + sum += (dstptr - dst) * (*src - ' '); + *dstptr++ = *src; + } + + src ++; + } + + // Add the weighted sum modulo 103 + *dstptr++ = code128_chars[sum % 103]; + + // Add the stop pattern and return... + *dstptr++ = code128_stop; + *dstptr = '\0'; + + return (dst); +} + + +// +// 'output_cb()' - Write PDF data to the standard output... +// + +static ssize_t // O - Number of bytes written +output_cb(void *output_cbdata, // I - Callback data (not used) + const void *buffer, // I - Buffer to write + size_t bytes) // I - Number of bytes to write +{ + (void)output_cbdata; + + return ((ssize_t)fwrite(buffer, 1, bytes, stdout)); +} + + +// +// 'main()' - Produce a single-page barcode file. +// + +int // O - Exit status +main(int argc, // I - Number of command-line arguments + char *argv[]) // I - Command-line arguments +{ + const char *barcode, // Barcode to show + *text; // Text to display under barcode + pdfio_file_t *pdf; // Output PDF file + pdfio_obj_t *barcode_font; // Barcode font object + pdfio_obj_t *text_font = NULL; // Text font object + pdfio_dict_t *page_dict; // Page dictionary + pdfio_rect_t media_box; // Media/CropBox for page + pdfio_stream_t *page_st; // Page stream + char barcode_temp[256]; // Barcode buffer + double barcode_height = 36.0, // Height of barcode + barcode_width, // Width of barcode + text_height = 0.0, // Height of text + text_width = 0.0; // Width of text + + + // Get the barcode and optional text from the command-line... + if (argc < 2 || argc > 3) + { + fputs("Usage: code128 \"BARCODE\" [\"TEXT\"] >FILENAME.pdf\n", stderr); + return (1); + } + + barcode = argv[1]; + text = argv[2]; + + // Output a PDF file to the standard output... +#ifdef _WIN32 + setmode(1, O_BINARY); // Force binary output on Windows +#endif // _WIN32 + + if ((pdf = pdfioFileCreateOutput(output_cb, /*output_cbdata*/NULL, /*version*/NULL, /*media_box*/NULL, /*crop_box*/NULL, /*error_cb*/NULL, /*error_data*/NULL)) == NULL) + return (1); + + // Load fonts... + barcode_font = pdfioFileCreateFontObjFromFile(pdf, "code128.ttf", /*unicode*/false); + if (text) + text_font = pdfioFileCreateFontObjFromFile(pdf, "../testfiles/OpenSans-Regular.ttf", /*unicode*/true); + + // Generate Code128 characters for the desired barcode... + if (!(barcode[0] & 0x80)) + barcode = make_code128(barcode_temp, barcode, sizeof(barcode_temp)); + + // Compute sizes of the text... + barcode_width = pdfioContentTextMeasure(barcode_font, barcode, barcode_height); + if (text && text_font) + { + text_height = 9.0; + text_width = pdfioContentTextMeasure(text_font, text, text_height); + } + + // Compute the size of the PDF page... + media_box.x1 = 0.0; + media_box.y1 = 0.0; + media_box.x2 = (barcode_width > text_width ? barcode_width : text_width) + 18.0; + media_box.y2 = barcode_height + text_height + 18.0; + + // Start a page for the barcode... + page_dict = pdfioDictCreate(pdf); + + pdfioDictSetRect(page_dict, "MediaBox", &media_box); + pdfioDictSetRect(page_dict, "CropBox", &media_box); + + pdfioPageDictAddFont(page_dict, "B128", barcode_font); + if (text_font) + pdfioPageDictAddFont(page_dict, "TEXT", text_font); + + page_st = pdfioFileCreatePage(pdf, page_dict); + + // Draw the page... + pdfioContentSetStrokeColorGray(page_st, 0.0); + + pdfioContentSetTextFont(page_st, "B128", barcode_height); + pdfioContentTextBegin(page_st); + pdfioContentTextMoveTo(page_st, 0.5 * (media_box.x2 - barcode_width), 9.0 + text_height); + pdfioContentTextShow(page_st, /*unicode*/false, barcode); + pdfioContentTextEnd(page_st); + + if (text && text_font) + { + pdfioContentSetTextFont(page_st, "TEXT", text_height); + pdfioContentTextBegin(page_st); + pdfioContentTextMoveTo(page_st, 0.5 * (media_box.x2 - text_width), 9.0); + pdfioContentTextShow(page_st, /*unicode*/true, text); + pdfioContentTextEnd(page_st); + } + + pdfioStreamClose(page_st); + + // Close and return... + pdfioFileClose(pdf); + + return (0); +} + diff --git a/examples/code128.ttf b/examples/code128.ttf new file mode 100644 index 0000000000000000000000000000000000000000..92466dcb0d1645dcf9e46d0e07ec5a2fd54e704c GIT binary patch literal 7884 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 literal 0 HcmV?d00001