// // Test program for PDFio. // // Copyright © 2021 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Usage: // // ./testpdfio // // ./testpdfio FILENAME [OBJECT-NUMBER] [FILENAME [OBJECT-NUMBER]] ... // // // Include necessary headers... // #include "pdfio-private.h" #include "pdfio-content.h" #include #ifndef M_PI # define M_PI 3.14159265358979323846264338327950288 #endif // M_PI // // Local functions... // static int do_crypto_tests(void); static int do_test_file(const char *filename, int objnum, bool verbose); static int do_unit_tests(void); static int draw_image(pdfio_stream_t *st, const char *name, double x, double y, double w, double h, const char *label); static bool error_cb(pdfio_file_t *pdf, const char *message, bool *error); static bool iterate_cb(pdfio_dict_t *dict, const char *key, void *cb_data); static ssize_t output_cb(int *fd, const void *buffer, size_t bytes); static const char *password_cb(void *data, const char *filename); static int read_unit_file(const char *filename, size_t num_pages, size_t first_image, bool is_output); static ssize_t token_consume_cb(const char **s, size_t bytes); static ssize_t token_peek_cb(const char **s, char *buffer, size_t bytes); static int verify_image(pdfio_file_t *pdf, size_t number); static int write_alpha_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font); static int write_color_patch(pdfio_stream_t *st, bool device); static int write_color_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font); static int write_font_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font, const char *textfontfile, bool unicode); static int write_header_footer(pdfio_stream_t *st, const char *title, int number); static pdfio_obj_t *write_image_object(pdfio_file_t *pdf, _pdfio_predictor_t predictor); static int write_images_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font); static int write_jpeg_test(pdfio_file_t *pdf, const char *title, int number, pdfio_obj_t *font, pdfio_obj_t *image); static int write_png_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font); static int write_text_test(pdfio_file_t *pdf, int first_page, pdfio_obj_t *font, const char *filename); static int write_unit_file(pdfio_file_t *inpdf, pdfio_file_t *outpdf, size_t *num_pages, size_t *first_image); // // 'main()' - Main entry for test program. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { int ret = 0; // Return value if (argc > 1) { int i; // Looping var bool verbose = false; // Be verbose? for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) { puts("Usage: ./testpdfio [--help] [--verbose] [filename [objnum] ...]"); return (0); } else if (!strcmp(argv[i], "--verbose")) { verbose = true; } else if (argv[i][0] == '-') { printf("Unknown option '%s'.\n\n", argv[i]); puts("Usage: ./testpdfio [--help] [--verbose] [filename [objnum] ...]"); return (1); } else if ((i + 1) < argc && isdigit(argv[i + 1][0] & 255)) { // filename.pdf object-number if (do_test_file(argv[i], atoi(argv[i + 1]), verbose)) ret = 1; i ++; } else if (do_test_file(argv[i], 0, verbose)) ret = 1; } } else { #if _WIN32 // Windows puts executables in Platform/Configuration subdirs... if (!_access("../../testfiles", 0)) _chdir("../.."); #endif // _WIN32 ret = do_unit_tests(); } return (ret); } // // 'do_crypto_tests()' - Test the various cryptographic functions in PDFio. // static int // O - Exit status do_crypto_tests(void) { int ret = 0; // Return value size_t i; // Looping var _pdfio_aes_t aes; // AES context _pdfio_md5_t md5; // MD5 context _pdfio_rc4_t rc4; // RC4 context _pdfio_sha256_t sha256; // SHA256 context uint8_t key[32], // Encryption/decryption key iv[32], // Initialization vector buffer[256], // Output buffer buffer2[256]; // Second output buffer const char *prefix, *suffix; // Prefix/suffix strings static const char *text = "Hello, World! Now is the time for all good men to come to the aid of their country.\n"; // Test text static uint8_t aes128key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; static uint8_t aes128rounds[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, 0xa0, 0xfa, 0xfe, 0x17, 0x88, 0x54, 0x2c, 0xb1, 0x23, 0xa3, 0x39, 0x39, 0x2a, 0x6c, 0x76, 0x05, 0xf2, 0xc2, 0x95, 0xf2, 0x7a, 0x96, 0xb9, 0x43, 0x59, 0x35, 0x80, 0x7a, 0x73, 0x59, 0xf6, 0x7f, 0x3d, 0x80, 0x47, 0x7d, 0x47, 0x16, 0xfe, 0x3e, 0x1e, 0x23, 0x7e, 0x44, 0x6d, 0x7a, 0x88, 0x3b, 0xef, 0x44, 0xa5, 0x41, 0xa8, 0x52, 0x5b, 0x7f, 0xb6, 0x71, 0x25, 0x3b, 0xdb, 0x0b, 0xad, 0x00, 0xd4, 0xd1, 0xc6, 0xf8, 0x7c, 0x83, 0x9d, 0x87, 0xca, 0xf2, 0xb8, 0xbc, 0x11, 0xf9, 0x15, 0xbc, 0x6d, 0x88, 0xa3, 0x7a, 0x11, 0x0b, 0x3e, 0xfd, 0xdb, 0xf9, 0x86, 0x41, 0xca, 0x00, 0x93, 0xfd, 0x4e, 0x54, 0xf7, 0x0e, 0x5f, 0x5f, 0xc9, 0xf3, 0x84, 0xa6, 0x4f, 0xb2, 0x4e, 0xa6, 0xdc, 0x4f, 0xea, 0xd2, 0x73, 0x21, 0xb5, 0x8d, 0xba, 0xd2, 0x31, 0x2b, 0xf5, 0x60, 0x7f, 0x8d, 0x29, 0x2f, 0xac, 0x77, 0x66, 0xf3, 0x19, 0xfa, 0xdc, 0x21, 0x28, 0xd1, 0x29, 0x41, 0x57, 0x5c, 0x00, 0x6e, 0xd0, 0x14, 0xf9, 0xa8, 0xc9, 0xee, 0x25, 0x89, 0xe1, 0x3f, 0x0c, 0xc8, 0xb6, 0x63, 0x0c, 0xa6 }; // FIPS-197 example key expansion static uint8_t aes128text[] = { 0xfb, 0x77, 0xac, 0xce, 0x3c, 0x95, 0x40, 0xcf, 0xca, 0xc8, 0x26, 0xbf, 0xc0, 0x69, 0x73, 0x3c, 0x01, 0xfd, 0x72, 0x01, 0xeb, 0x4d, 0x6f, 0xf7, 0xb4, 0x72, 0x6d, 0x84, 0x69, 0x9f, 0x89, 0xab, 0xe6, 0x2b, 0x9a, 0x9a, 0x6e, 0xc1, 0x61, 0xd7, 0x9d, 0x83, 0x2d, 0x58, 0x55, 0xa7, 0x58, 0x50, 0x00, 0xad, 0x19, 0x7b, 0xee, 0x6a, 0x36, 0x6f, 0xd1, 0xa7, 0xa4, 0x6b, 0xc5, 0x78, 0x9a, 0x18, 0x05, 0xf0, 0x2c, 0xd4, 0x60, 0x25, 0xe0, 0xa7, 0xb1, 0x36, 0xdb, 0x18, 0xd3, 0xf7, 0x59, 0x29, 0x22, 0xec, 0x25, 0x77, 0x0d, 0x9e, 0x5a, 0x01, 0xcc, 0xf6, 0x29, 0xc2, 0x08, 0xc2, 0xfc, 0x4f }; // Expected AES-128 CBC result static uint8_t aes256text[] = { 0x2b, 0x94, 0x45, 0x9e, 0xed, 0xa0, 0x89, 0x7b, 0x35, 0x4e, 0xde, 0x06, 0x00, 0x4d, 0xda, 0x6b, 0x61, 0x2f, 0xb9, 0x06, 0xd5, 0x0f, 0x22, 0xed, 0xd2, 0xe3, 0x6b, 0x39, 0x5a, 0xa1, 0xe3, 0x7d, 0xa1, 0xcc, 0xd4, 0x0b, 0x6b, 0xa4, 0xff, 0xe9, 0x9c, 0x89, 0x0c, 0xc7, 0x95, 0x47, 0x19, 0x9b, 0x06, 0xdc, 0xc8, 0x7c, 0x5c, 0x5d, 0x56, 0x99, 0x1e, 0x90, 0x7d, 0x99, 0xc5, 0x7b, 0xc4, 0xe4, 0xfb, 0x02, 0x15, 0x50, 0x23, 0x2a, 0xe4, 0xc1, 0x20, 0xfd, 0xf4, 0x03, 0xfe, 0x6f, 0x15, 0x48, 0xd8, 0x62, 0x36, 0x98, 0x2a, 0x62, 0xf5, 0x2c, 0xa6, 0xfa, 0x7a, 0x43, 0x53, 0xcd, 0xad, 0x18 }; // Expected AES-256 CBC result static uint8_t md5text[16] = { 0x74, 0x0c, 0x2c, 0xea, 0xe1, 0xab, 0x06, 0x7c, 0xdb, 0x1d, 0x49, 0x1d, 0x2d, 0x66, 0xf2, 0x93 }; // Expected MD5 hash result static uint8_t rc4text[] = { 0xd2, 0xa2, 0xa0, 0xf6, 0x0f, 0xb1, 0x3e, 0xa0, 0xdd, 0xe1, 0x44, 0xfd, 0xec, 0xc4, 0x55, 0xf8, 0x25, 0x68, 0xad, 0xe6, 0xb0, 0x60, 0x7a, 0x0f, 0x4e, 0xfe, 0xed, 0x9c, 0x78, 0x3a, 0xf8, 0x73, 0x79, 0xbd, 0x82, 0x88, 0x39, 0x01, 0xc7, 0xd0, 0x34, 0xfe, 0x40, 0x16, 0x93, 0x5a, 0xec, 0x81, 0xda, 0x34, 0xdf, 0x5b, 0xd1, 0x47, 0x2c, 0xfa, 0xe0, 0x13, 0xc5, 0xe2, 0xb0, 0x57, 0x5c, 0x17, 0x62, 0xaa, 0x83, 0x1c, 0x4f, 0xa0, 0x0a, 0xed, 0x6c, 0x42, 0x41, 0x8a, 0x45, 0x03, 0xb8, 0x72, 0xa8, 0x99, 0xd7, 0x06 }; // Expected RC4 result static uint8_t sha256text[32] = { 0x19, 0x71, 0x9b, 0xf0, 0xc6, 0xd8, 0x34, 0xc9, 0x6e, 0x8a, 0x56, 0xcc, 0x34, 0x45, 0xb7, 0x1d, 0x5b, 0x74, 0x9c, 0x52, 0x40, 0xcd, 0x30, 0xa2, 0xc2, 0x84, 0x53, 0x83, 0x16, 0xf8, 0x1a, 0xbb }; // Expected SHA-256 hash result fputs("_pdfioAESInit(128-bit sample key): ", stdout); _pdfioCryptoAESInit(&aes, aes128key, sizeof(aes128key), NULL); if (!memcmp(aes128rounds, aes.round_key, sizeof(aes128rounds))) { puts("PASS"); } else { for (i = 0; i < (sizeof(aes128rounds) - 4); i ++) { if (aes.round_key[i] != aes128rounds[i]) break; } prefix = i > 0 ? "..." : ""; suffix = i < (sizeof(aes128rounds) - 4) ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, aes.round_key[i], aes.round_key[i + 1], aes.round_key[i + 2], aes.round_key[i + 3], suffix, prefix, aes128rounds[i], aes128rounds[i + 1], aes128rounds[i + 2], aes128rounds[i + 3], suffix); ret = 1; } fputs("_pdfioAESInit/Encrypt(128-bit CBC): ", stdout); for (i = 0; i < 16; i ++) { key[i] = (uint8_t)i + 1; iv[i] = (uint8_t)(0xff - i); } _pdfioCryptoAESInit(&aes, key, 16, iv); _pdfioCryptoAESEncrypt(&aes, buffer, (uint8_t *)text, strlen(text)); if (!memcmp(aes128text, buffer, sizeof(aes128text))) { puts("PASS"); } else { for (i = 0; i < (sizeof(aes128text) - 4); i ++) { if (buffer[i] != aes128text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = i < (sizeof(aes128text) - 4) ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3], suffix, prefix, aes128text[i], aes128text[i + 1], aes128text[i + 2], aes128text[i + 3], suffix); ret = 1; } fputs("_pdfioAESInit/Decrypt(128-bit CBC): ", stdout); _pdfioCryptoAESInit(&aes, key, 16, iv); _pdfioCryptoAESDecrypt(&aes, buffer2, buffer, sizeof(aes128text)); if (!memcmp(buffer2, text, strlen(text))) { puts("PASS"); } else { for (i = 0; text[i + 4]; i ++) { if (buffer2[i] != text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = text[i + 4] ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer2[i], buffer2[i + 1], buffer2[i + 2], buffer2[i + 3], suffix, prefix, text[i], text[i + 1], text[i + 2], text[i + 3], suffix); ret = 1; } fputs("_pdfioAESInit/Encrypt(256-bit CBC): ", stdout); for (i = 0; i < 32; i ++) { key[i] = (uint8_t)i + 1; iv[i] = (uint8_t)(0xff - i); } _pdfioCryptoAESInit(&aes, key, 32, iv); _pdfioCryptoAESEncrypt(&aes, buffer, (uint8_t *)text, strlen(text)); if (!memcmp(aes256text, buffer, sizeof(aes256text))) { puts("PASS"); } else { for (i = 0; i < (sizeof(aes256text) - 4); i ++) { if (buffer[i] != aes256text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = i < (sizeof(aes256text) - 4) ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3], suffix, prefix, aes256text[i], aes256text[i + 1], aes256text[i + 2], aes256text[i + 3], suffix); ret = 1; } fputs("_pdfioAESInit/Decrypt(256-bit CBC): ", stdout); _pdfioCryptoAESInit(&aes, key, 32, iv); _pdfioCryptoAESDecrypt(&aes, buffer2, buffer, sizeof(aes256text)); if (!memcmp(buffer2, text, strlen(text))) { puts("PASS"); } else { for (i = 0; text[i + 4]; i ++) { if (buffer2[i] != text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = text[i + 4] ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer2[i], buffer2[i + 1], buffer2[i + 2], buffer2[i + 3], suffix, prefix, text[i], text[i + 1], text[i + 2], text[i + 3], suffix); ret = 1; } fputs("_pdfioMD5Init/Append/Finish: ", stdout); _pdfioCryptoMD5Init(&md5); _pdfioCryptoMD5Append(&md5, (uint8_t *)text, strlen(text)); _pdfioCryptoMD5Finish(&md5, buffer); if (!memcmp(md5text, buffer, sizeof(md5text))) { puts("PASS"); } else { printf("FAIL (got '%02X%02X%02X%02X...%02X%02X%02X%02X', expected '%02X%02X%02X%02X...%02X%02X%02X%02X')\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[12], buffer[13], buffer[14], buffer[15], md5text[0], md5text[1], md5text[2], md5text[3], md5text[12], md5text[13], md5text[14], md5text[15]); ret = 1; } fputs("_pdfioRC4Init/Encrypt(128-bit): ", stdout); for (i = 0; i < 16; i ++) key[i] = (uint8_t)i + 1; _pdfioCryptoRC4Init(&rc4, key, 16); _pdfioCryptoRC4Crypt(&rc4, buffer, (uint8_t *)text, strlen(text)); if (!memcmp(rc4text, buffer, sizeof(rc4text))) { puts("PASS"); } else { for (i = 0; i < (sizeof(rc4text) - 4); i ++) { if (buffer[i] != rc4text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = i < (sizeof(rc4text) - 4) ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3], suffix, prefix, rc4text[i], rc4text[i + 1], rc4text[i + 2], rc4text[i + 3], suffix); ret = 1; } fputs("_pdfioRC4Init/Decrypt(128-bit): ", stdout); _pdfioCryptoRC4Init(&rc4, key, 16); _pdfioCryptoRC4Crypt(&rc4, buffer2, buffer, strlen(text)); if (!memcmp(buffer2, text, strlen(text))) { puts("PASS"); } else { for (i = 0; text[i + 4]; i ++) { if (buffer2[i] != text[i]) break; } prefix = i > 0 ? "..." : ""; suffix = text[i + 4] ? "..." : ""; printf("FAIL (got '%s%02X%02X%02X%02X%s', expected '%s%02X%02X%02X%02X%s')\n", prefix, buffer2[i], buffer2[i + 1], buffer2[i + 2], buffer2[i + 3], suffix, prefix, text[i], text[i + 1], text[i + 2], text[i + 3], suffix); ret = 1; } fputs("_pdfioSHA256Init/Append/Finish: ", stdout); _pdfioCryptoSHA256Init(&sha256); _pdfioCryptoSHA256Append(&sha256, (uint8_t *)text, strlen(text)); _pdfioCryptoSHA256Finish(&sha256, buffer); if (!memcmp(sha256text, buffer, sizeof(sha256text))) { puts("PASS"); } else { printf("FAIL (got '%02X%02X%02X%02X...%02X%02X%02X%02X', expected '%02X%02X%02X%02X...%02X%02X%02X%02X')\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[28], buffer[29], buffer[30], buffer[31], sha256text[0], sha256text[1], sha256text[2], sha256text[3], sha256text[28], sha256text[29], sha256text[30], sha256text[31]); ret = 1; } return (ret); } // // 'do_test_file()' - Try loading a PDF file and listing pages and objects. // static int // O - Exit status do_test_file(const char *filename, // I - PDF filename int objnum, // I - Object number to dump, if any bool verbose) // I - Be verbose? { bool error = false; // Have we shown an error yet? pdfio_file_t *pdf; // PDF file size_t n, // Object/page index num_objs, // Number of objects num_pages; // Number of pages pdfio_obj_t *obj; // Object pdfio_dict_t *dict; // Object dictionary // Try opening the file... if (!objnum) { printf("%s: ", filename); fflush(stdout); } if ((pdf = pdfioFileOpen(filename, /*password_cb*/NULL, /*password_data*/NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) { if (objnum) { const char *filter; // Stream filter pdfio_stream_t *st; // Stream char buffer[8192]; // Read buffer ssize_t bytes; // Bytes read if ((obj = pdfioFileFindObj(pdf, (size_t)objnum)) == NULL) { puts("Not found."); return (1); } if ((dict = pdfioObjGetDict(obj)) == NULL) { _pdfioValueDebug(&obj->value, stdout); putchar('\n'); return (0); } filter = pdfioDictGetName(dict, "Filter"); if ((st = pdfioObjOpenStream(obj, filter && !strcmp(filter, "FlateDecode"))) == NULL) { _pdfioValueDebug(&obj->value, stdout); putchar('\n'); return (0); } while ((bytes = pdfioStreamRead(st, buffer, sizeof(buffer))) > 0) fwrite(buffer, 1, (size_t)bytes, stdout); pdfioStreamClose(st); return (0); } else { puts("PASS"); // Show basic stats... num_objs = pdfioFileGetNumObjs(pdf); num_pages = pdfioFileGetNumPages(pdf); printf(" PDF %s, %d pages, %d objects.\n", pdfioFileGetVersion(pdf), (int)num_pages, (int)num_objs); if (verbose) { // Show a summary of each page... for (n = 0; n < num_pages; n ++) { if ((obj = pdfioFileGetPage(pdf, n)) == NULL) { printf("%s: Unable to get page #%d.\n", filename, (int)n + 1); } else { pdfio_rect_t media_box; // MediaBox value memset(&media_box, 0, sizeof(media_box)); dict = pdfioObjGetDict(obj); if (!pdfioDictGetRect(dict, "MediaBox", &media_box)) { if ((obj = pdfioDictGetObj(dict, "Parent")) != NULL) { dict = pdfioObjGetDict(obj); pdfioDictGetRect(dict, "MediaBox", &media_box); } } printf(" Page #%d (obj %d) is %gx%g.\n", (int)n + 1, (int)pdfioObjGetNumber(obj), media_box.x2, media_box.y2); } } // Show the associated value with each object... for (n = 0; n < num_objs; n ++) { if ((obj = pdfioFileGetObj(pdf, n)) == NULL) { printf(" Unable to get object #%d.\n", (int)n); } else { dict = pdfioObjGetDict(obj); printf(" %u %u obj dict=%p(%lu pairs)\n", (unsigned)pdfioObjGetNumber(obj), (unsigned)pdfioObjGetGeneration(obj), dict, dict ? (unsigned long)dict->num_pairs : 0UL); fputs(" ", stdout); _pdfioValueDebug(&obj->value, stdout); putchar('\n'); } } } } // Close the file and return success... pdfioFileClose(pdf); return (0); } else { // Error message will already be displayed so just indicate failure... return (1); } } // // 'do_unit_tests()' - Do unit tests. // static int // O - Exit status do_unit_tests(void) { pdfio_file_t *inpdf, // Input PDF file *outpdf; // Output PDF file int outfd; // Output file descriptor bool error = false; // Error callback data _pdfio_token_t tb; // Token buffer const char *s; // String buffer _pdfio_value_t value; // Value size_t first_image, // First image object num_pages; // Number of pages written char temppdf[1024]; // Temporary PDF file pdfio_dict_t *dict; // Test dictionary int count = 0; // Number of key/value pairs static const char *complex_dict = // Complex dictionary value "<>/ExtGState<>/Font<<" "/TT0 21384 0 R/TT1 21390 0 R/TT2 21423 0 R/TT3 21403 0 R/TT4 21397 0 R>>" "/ProcSet[/PDF/Text/ImageC]/Properties<>" "/XObject<>>>/Rotate 0/StructParents 2105" "/Tabs/S/Type/Page>>"; static const char *cid_dict = // CID font dictionary "<" ">\nendobj\n"; setbuf(stdout, NULL); // First open the test PDF file... fputs("pdfioFileOpen(\"testfiles/testpdfio.pdf\"): ", stdout); if ((inpdf = pdfioFileOpen("testfiles/testpdfio.pdf", /*password_cb*/NULL, /*password_data*/NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); // TODO: Test for known values in this test file. // Test dictionary APIs fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(inpdf)) != NULL) { puts("PASS"); fputs("pdfioDictSet*: ", stdout); if (pdfioDictSetBoolean(dict, "Boolean", true) && pdfioDictSetName(dict, "Name", "Name") && pdfioDictSetNumber(dict, "Number", 42.0) && pdfioDictSetString(dict, "String", "String")) { puts("PASS"); } else { puts("FAIL"); return (1); } fputs("pdfioDictIterateKeys: ", stdout); pdfioDictIterateKeys(dict, iterate_cb, &count); if (count == 4) { puts("PASS"); } else { printf("FAIL (got %d, expected 4)\n", count); return (1); } } else { puts("FAIL"); return (1); } // Test the value parsers for edge cases... fputs("_pdfioValueRead(complex_dict): ", stdout); s = complex_dict; _pdfioTokenInit(&tb, inpdf, (_pdfio_tconsume_cb_t)token_consume_cb, (_pdfio_tpeek_cb_t)token_peek_cb, (void *)&s); if (_pdfioValueRead(inpdf, NULL, &tb, &value, 0)) { // TODO: Check value... fputs("PASS: ", stdout); _pdfioValueDebug(&value, stdout); puts("\n"); } else goto fail; // Test the value parsers for edge cases... fputs("_pdfioValueRead(cid_dict): ", stdout); s = cid_dict; _pdfioTokenInit(&tb, inpdf, (_pdfio_tconsume_cb_t)token_consume_cb, (_pdfio_tpeek_cb_t)token_peek_cb, (void *)&s); if (_pdfioValueRead(inpdf, NULL, &tb, &value, 0)) { // TODO: Check value... fputs("PASS: ", stdout); _pdfioValueDebug(&value, stdout); puts("\n"); } else goto fail; // Do crypto tests... if (do_crypto_tests()) return (1); // Create a new PDF file... fputs("pdfioFileCreate(\"testpdfio-out.pdf\", ...): ", stdout); if ((outpdf = pdfioFileCreate("testpdfio-out.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else goto fail; if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) goto fail; if (read_unit_file("testpdfio-out.pdf", num_pages, first_image, false)) goto fail; // Stream a new PDF file... if ((outfd = open("testpdfio-out2.pdf", O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) { perror("Unable to open \"testpdfio-out2.pdf\""); goto fail; } fputs("pdfioFileCreateOutput(...): ", stdout); if ((outpdf = pdfioFileCreateOutput((pdfio_output_cb_t)output_cb, &outfd, NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else goto fail; if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) goto fail; close(outfd); if (read_unit_file("testpdfio-out2.pdf", num_pages, first_image, true)) goto fail; // Create new encrypted PDF files... fputs("pdfioFileCreate(\"testpdfio-rc4.pdf\", ...): ", stdout); if ((outpdf = pdfioFileCreate("testpdfio-rc4.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileSetPermissions(all, RC4-128, no passwords): ", stdout); if (pdfioFileSetPermissions(outpdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, NULL, NULL)) puts("PASS"); else return (1); if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) return (1); if (read_unit_file("testpdfio-rc4.pdf", num_pages, first_image, false)) return (1); // Create new encrypted PDF files... fputs("pdfioFileCreate(\"testpdfio-rc4p.pdf\", ...): ", stdout); if ((outpdf = pdfioFileCreate("testpdfio-rc4p.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileSetPermissions(no-print, RC4-128, passwords='owner' and 'user'): ", stdout); if (pdfioFileSetPermissions(outpdf, PDFIO_PERMISSION_ALL ^ PDFIO_PERMISSION_PRINT, PDFIO_ENCRYPTION_RC4_128, "owner", "user")) puts("PASS"); else return (1); if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) return (1); if (read_unit_file("testpdfio-rc4p.pdf", num_pages, first_image, false)) return (1); fputs("pdfioFileCreate(\"testpdfio-aes.pdf\", ...): ", stdout); if ((outpdf = pdfioFileCreate("testpdfio-aes.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileSetPermissions(all, AES-128, no passwords): ", stdout); if (pdfioFileSetPermissions(outpdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_AES_128, NULL, NULL)) puts("PASS"); else return (1); if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) return (1); if (read_unit_file("testpdfio-aes.pdf", num_pages, first_image, false)) return (1); fputs("pdfioFileCreate(\"testpdfio-aesp.pdf\", ...): ", stdout); if ((outpdf = pdfioFileCreate("testpdfio-aesp.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileSetPermissions(no-print, AES-128, passwords='owner' and 'user'): ", stdout); if (pdfioFileSetPermissions(outpdf, PDFIO_PERMISSION_ALL ^ PDFIO_PERMISSION_PRINT, PDFIO_ENCRYPTION_AES_128, "owner", "user")) puts("PASS"); else return (1); if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) return (1); if (read_unit_file("testpdfio-aesp.pdf", num_pages, first_image, false)) return (1); fputs("pdfioFileCreateTemporary: ", stdout); if ((outpdf = pdfioFileCreateTemporary(temppdf, sizeof(temppdf), NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL) printf("PASS (%s)\n", temppdf); else return (1); if (write_unit_file(inpdf, outpdf, &num_pages, &first_image)) return (1); if (read_unit_file(temppdf, num_pages, first_image, false)) return (1); pdfioFileClose(inpdf); return (0); fail: pdfioFileClose(inpdf); return (1); } // // 'draw_image()' - Draw an image with a label. // static int // O - 1 on failure, 0 on success draw_image(pdfio_stream_t *st, const char *name, // I - Name double x, // I - X offset double y, // I - Y offset double w, // I - Image width double h, // I - Image height const char *label) // I - Label { printf("pdfioContentDrawImage(name=\"%s\", x=%g, y=%g, w=%g, h=%g): ", name, x, y, w, h); if (pdfioContentDrawImage(st, name, x, y, w, h)) puts("PASS"); else return (1); fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else return (1); fputs("pdfioContentSetTextFont(\"F1\", 18.0): ", stdout); if (pdfioContentSetTextFont(st, "F1", 18.0)) puts("PASS"); else return (1); printf("pdfioContentTextMoveTo(%g, %g): ", x, y + h + 9); if (pdfioContentTextMoveTo(st, x, y + h + 9)) puts("PASS"); else return (1); printf("pdfioContentTextShow(\"%s\"): ", label); if (pdfioContentTextShow(st, false, label)) puts("PASS"); else return (1); fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else return (1); return (0); } // // 'error_cb()' - Display an error message during a unit test. // static bool // O - `true` to stop, `false` to continue error_cb(pdfio_file_t *pdf, // I - PDF file const char *message, // I - Error message bool *error) // IO - Have we displayed an error? { (void)pdf; if (!*error) { // First error, so show a "FAIL" indicator *error = true; puts("FAIL"); } // Indent error messages... printf(" %s\n", message); // Continue to catch more errors... return (false); } // // 'iterate_cb()' - Test pdfioDictIterateKeys function. // static bool // O - `true` to continue, `false` to stop iterate_cb(pdfio_dict_t *dict, // I - Dictionary const char *key, // I - Key void *cb_data) // I - Callback data { int *count = (int *)cb_data; // Pointer to counter if (!dict || !key || !cb_data) return (false); (*count)++; return (true); } // // 'output_cb()' - Write output to a file. // static ssize_t // O - Number of bytes written output_cb(int *fd, // I - File descriptor const void *buffer, // I - Output buffer size_t bytes) // I - Number of bytes to write { return (write(*fd, buffer, bytes)); } // // 'password_cb()' - Password callback for PDF file. // static const char * // O - Password string password_cb(void *data, // I - Callback data const char *filename) // I - Filename (not used) { (void)filename; return ((const char *)data); } // // 'read_unit_file()' - Read back a unit test file and confirm its contents. // static int // O - Exit status read_unit_file(const char *filename, // I - File to read size_t num_pages, // I - Expected number of pages size_t first_image, // I - First image object bool is_output) // I - File written with output callback? { pdfio_file_t *pdf; // PDF file size_t i; // Looping var const char *s; // String bool error = false; // Error callback data // Open the new PDF file to read it... printf("pdfioFileOpen(\"%s\", ...): ", filename); if ((pdf = pdfioFileOpen(filename, password_cb, (void *)"user", (pdfio_error_cb_t)error_cb, &error)) != NULL) puts("PASS"); else return (1); // Verify metadata... fputs("pdfioFileGetAuthor: ", stdout); if ((s = pdfioFileGetAuthor(pdf)) != NULL && !strcmp(s, "Michael R Sweet")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Michael R Sweet')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Michael R Sweet')"); return (1); } fputs("pdfioFileGetCreator: ", stdout); if ((s = pdfioFileGetCreator(pdf)) != NULL && !strcmp(s, "testpdfio")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'testpdfio')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'testpdfio')"); return (1); } fputs("pdfioFileGetKeywords: ", stdout); if ((s = pdfioFileGetKeywords(pdf)) != NULL && !strcmp(s, "one fish,two fish,red fish,blue fish")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'one fish,two fish,red fish,blue fish')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'one fish,two fish,red fish,blue fish')"); return (1); } fputs("pdfioFileGetSubject: ", stdout); if ((s = pdfioFileGetSubject(pdf)) != NULL && !strcmp(s, "Unit test document")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Unit test document')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Unit test document')"); return (1); } fputs("pdfioFileGetTitle: ", stdout); if ((s = pdfioFileGetTitle(pdf)) != NULL && !strcmp(s, "Test Document")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Test Document')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Test Document')"); return (1); } // Verify the number of pages is the same... fputs("pdfioFileGetNumPages: ", stdout); if (num_pages == pdfioFileGetNumPages(pdf)) { puts("PASS"); } else { printf("FAIL (%lu != %lu)\n", (unsigned long)num_pages, (unsigned long)pdfioFileGetNumPages(pdf)); return (1); } // Verify the images for (i = 0; i < 7; i ++) { if (is_output) { if (verify_image(pdf, first_image + (size_t)i * 2)) return (1); } else if (verify_image(pdf, first_image + (size_t)i)) return (1); } // Close the new PDF file... fputs("pdfioFileClose(\"testpdfio-out.pdf\"): ", stdout); if (pdfioFileClose(pdf)) puts("PASS"); else return (1); return (0); } // // 'token_consume_cb()' - Consume bytes from a test string. // static ssize_t // O - Number of bytes consumed token_consume_cb(const char **s, // IO - Test string size_t bytes) // I - Bytes to consume { size_t len = strlen(*s); // Number of bytes remaining // "Consume" bytes by incrementing the string pointer, limiting to the // remaining length... if (bytes > len) bytes = len; *s += bytes; return ((ssize_t)bytes); } // // 'token_peek_cb()' - Peek bytes from a test string. // static ssize_t // O - Number of bytes peeked token_peek_cb(const char **s, // IO - Test string char *buffer, // I - Buffer size_t bytes) // I - Bytes to peek { size_t len = strlen(*s); // Number of bytes remaining // Copy bytes from the test string as possible... if (bytes > len) bytes = len; if (bytes > 0) memcpy(buffer, *s, bytes); return ((ssize_t)bytes); } // // 'verify_image()' - Verify an image object. // static int // O - 1 on failure, 0 on success verify_image(pdfio_file_t *pdf, // I - PDF file size_t number) // I - Object number { pdfio_obj_t *obj; // Image object const char *type, // Object type *subtype; // Object subtype double width, // Width of object height; // Height of object pdfio_stream_t *st; // Stream int x, y; // Coordinates in image unsigned char buffer[768], // Expected data *bufptr, // Pointer into buffer line[768]; // Line from file ssize_t bytes; // Bytes read from stream printf("pdfioFileFindObj(%lu): ", (unsigned long)number); if ((obj = pdfioFileFindObj(pdf, number)) != NULL) puts("PASS"); else return (1); fputs("pdfioObjGetType: ", stdout); if ((type = pdfioObjGetType(obj)) != NULL && !strcmp(type, "XObject")) { puts("PASS"); } else { printf("FAIL (got %s, expected XObject)\n", type); return (1); } fputs("pdfioObjGetSubtype: ", stdout); if ((subtype = pdfioObjGetSubtype(obj)) != NULL && !strcmp(subtype, "Image")) { puts("PASS"); } else { printf("FAIL (got %s, expected Image)\n", subtype); return (1); } fputs("pdfioImageGetWidth: ", stdout); if ((width = pdfioImageGetWidth(obj)) == 256.0) { puts("PASS"); } else { printf("FAIL (got %g, expected 256)\n", width); return (1); } fputs("pdfioImageGetHeight: ", stdout); if ((height = pdfioImageGetHeight(obj)) == 256.0) { puts("PASS"); } else { printf("FAIL (got %g, expected 256)\n", height); return (1); } // Open the image stream, read the image, and verify it matches expectations... fputs("pdfioObjOpenStream: ", stdout); if ((st = pdfioObjOpenStream(obj, PDFIO_FILTER_FLATE)) != NULL) puts("PASS"); else return (1); for (y = 0; y < 256; y ++) { for (x = 0, bufptr = buffer; x < 256; x ++, bufptr += 3) { bufptr[0] = (unsigned char)y; bufptr[1] = (unsigned char)(y + x); bufptr[2] = (unsigned char)(y - x); } if ((bytes = pdfioStreamRead(st, line, sizeof(line))) != (ssize_t)sizeof(line)) { printf("pdfioStreamRead: FAIL (got %d for line %d, expected 768)\n", y, (int)bytes); pdfioStreamClose(st); return (1); } if (memcmp(buffer, line, sizeof(buffer))) { printf("pdfioStreamRead: FAIL (line %d doesn't match expectations)\n", y); pdfioStreamClose(st); return (1); } } pdfioStreamClose(st); return (0); } // // 'write_alpha_test()' - Write a series of test images with alpha channels. // static int // O - 1 on failure, 0 on success write_alpha_test( pdfio_file_t *pdf, // I - PDF file int number, // I - Page number pdfio_obj_t *font) // I - Text font { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page stream pdfio_obj_t *images[6]; // Images using PNG predictors char iname[32]; // Image name int i, // Image number x, y; // Coordinates in image unsigned char buffer[1280 * 256], // Buffer for image *bufptr; // Pointer into buffer // Create the images... for (i = 0; i < 6; i ++) { size_t num_colors = 0; // Number of colors // Generate test image data... switch (i) { case 0 : // Grayscale case 3 : // Grayscale + alpha num_colors = 1; for (y = 0, bufptr = buffer; y < 256; y ++) { for (x = 0; x < 256; x ++) { unsigned char r = (unsigned char)y; unsigned char g = (unsigned char)(y + x); unsigned char b = (unsigned char)(y - x); *bufptr++ = (unsigned char)((r * 30 + g * 59 + b * 11) / 100); if (i > 2) { // Add alpha channel if (x < 112 || x >= 144 || y < 112 || y >= 144) *bufptr++ = (unsigned char)((x - 128) * (y - 128)); else *bufptr++ = 0; } } } break; case 1 : // RGB case 4 : // RGB + alpha num_colors = 3; for (y = 0, bufptr = buffer; y < 256; y ++) { for (x = 0; x < 256; x ++) { *bufptr++ = (unsigned char)y; *bufptr++ = (unsigned char)(y + x); *bufptr++ = (unsigned char)(y - x); if (i > 2) { // Add alpha channel if (x < 112 || x >= 144 || y < 112 || y >= 144) *bufptr++ = (unsigned char)((x - 128) * (y - 128)); else *bufptr++ = 0; } } } break; case 2 : // CMYK case 5 : // CMYK + alpha num_colors = 4; for (y = 0, bufptr = buffer; y < 256; y ++) { for (x = 0; x < 256; x ++) { unsigned char cc = (unsigned char)y; unsigned char mm = (unsigned char)(y + x); unsigned char yy = (unsigned char)(y - x); unsigned char kk = cc < mm ? cc < yy ? cc : yy : mm < yy ? mm : yy; *bufptr++ = (unsigned char)(cc - kk); *bufptr++ = (unsigned char)(mm - kk); *bufptr++ = (unsigned char)(yy - kk); *bufptr++ = (unsigned char)(kk); if (i > 2) { // Add alpha channel if (x < 112 || x >= 144 || y < 112 || y >= 144) *bufptr++ = (unsigned char)((x - 128) * (y - 128)); else *bufptr++ = 0; } } } break; } // Write the image... printf("pdfioFileCreateImageObjFromData(num_colors=%u, alpha=%s): ", (unsigned)num_colors, i > 2 ? "true" : "false"); if ((images[i] = pdfioFileCreateImageObjFromData(pdf, buffer, 256, 256, num_colors, NULL, i > 2, false)) != NULL) { printf("PASS (%u)\n", (unsigned)pdfioObjGetNumber(images[i])); } else { puts("FAIL"); return (1); } } // Create the page dictionary, object, and stream... fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); for (i = 0; i < 6; i ++) { printf("pdfioPageDictAddImage(%d): ", i + 1); snprintf(iname, sizeof(iname), "IM%d", i + 1); if (pdfioPageDictAddImage(dict, pdfioStringCreate(pdf, iname), images[i])) puts("PASS"); else return (1); } fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if (write_header_footer(st, "Image Writing Test", number)) goto error; // Draw images for (i = 0; i < 6; i ++) { static const char *labels[] = { "DeviceGray", "DeviceRGB", "DeviceCMYK", "DevGray + Alpha", "DevRGB + Alpha", "DevCMYK + Alpha" }; snprintf(iname, sizeof(iname), "IM%d", i + 1); if (draw_image(st, iname, 36 + 180 * (i % 3), 306 - 216 * (i / 3), 144, 144, labels[i])) goto error; } // Wrap up... fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_color_patch()' - Write a color patch... // static int // O - 1 on failure, 0 on success write_color_patch(pdfio_stream_t *st, // I - Content stream bool device)// I - Use device color? { int col, // Current column row; // Current row double x, y, // Relative position r, // Radius hue, // Hue angle sat, // Saturation cc, // Computed color red, // Red value green, // Green value blue; // Blue value // Draw an 11x11 patch... for (col = 0; col < 21; col ++) { for (row = 0; row < 21; row ++) { // Compute color in patch... x = 0.1 * (col - 10); y = 0.1 * (row - 10); r = sqrt(x * x + y * y); if (r == 0.0) { red = green = blue = 1.0; } else { sat = pow(r, 1.5); x /= r; y /= r; hue = 3.0 * atan2(y, x) / M_PI; if (hue < 0.0) hue += 6.0; cc = sat * (1.0 - fabs(fmod(hue, 2.0) - 1.0)) + 1.0 - sat; if (hue < 1.0) { red = 1.0; green = cc; blue = 1.0 - sat; } else if (hue < 2.0) { red = cc; green = 1.0; blue = 1.0 - sat; } else if (hue < 3.0) { red = 1.0 - sat; green = 1.0; blue = cc; } else if (hue < 4.0) { red = 1.0 - sat; green = cc; blue = 1.0; } else if (hue < 5.0) { red = cc; green = 1.0 - sat; blue = 1.0; } else { red = 1.0; green = 1.0 - sat; blue = cc; } } // Draw it... if (device) { // Use device CMYK color instead of a calibrated RGB space... double cyan = 1.0 - red; // Cyan color double magenta = 1.0 - green; // Magenta color double yellow = 1.0 - blue; // Yellow color double black = cyan; // Black color if (black > magenta) black = magenta; if (black > yellow) black = yellow; cyan -= black; magenta -= black; yellow -= black; printf("pdfioContentSetFillColorDeviceCMYK(c=%g, m=%g, y=%g, k=%g): ", cyan, magenta, yellow, black); if (pdfioContentSetFillColorDeviceCMYK(st, cyan, magenta, yellow, black)) puts("PASS"); else return (1); } else { // Use calibrate RGB space... printf("pdfioContentSetFillColorRGB(r=%g, g=%g, b=%g): ", red, green, blue); if (pdfioContentSetFillColorRGB(st, red, green, blue)) puts("PASS"); else return (1); } printf("pdfioContentPathRect(x=%g, y=%g, w=%g, h=%g): ", col * 6.0, row * 6.0, 6.0, 6.0); if (pdfioContentPathRect(st, col * 6.0, row * 6.0, 6.0, 6.0)) puts("PASS"); else return (1); fputs("pdfioContentFill(even_odd=false): ", stdout); if (pdfioContentFill(st, false)) puts("PASS"); else return (1); } } return (0); } // // 'write_color_test()' - Write a color test page... // static int // O - 1 on failure, 0 on success write_color_test(pdfio_file_t *pdf, // I - PDF file int number, // I - Page number pdfio_obj_t *font) // I - Text font { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream pdfio_array_t *cs; // Color space array pdfio_obj_t *prophoto; // ProPhotoRGB ICC profile object fputs("pdfioFileCreateICCObjFromFile(ProPhotoRGB): ", stdout); if ((prophoto = pdfioFileCreateICCObjFromFile(pdf, "testfiles/iso22028-2-romm-rgb.icc", 3)) != NULL) puts("PASS"); else return (1); fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioArrayCreateColorFromStandard(AdobeRGB): ", stdout); if ((cs = pdfioArrayCreateColorFromStandard(pdf, 3, PDFIO_CS_ADOBE)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddColorSpace(AdobeRGB): ", stdout); if (pdfioPageDictAddColorSpace(dict, "AdobeRGB", cs)) puts("PASS"); else return (1); fputs("pdfioArrayCreateColorFromStandard(DisplayP3): ", stdout); if ((cs = pdfioArrayCreateColorFromStandard(pdf, 3, PDFIO_CS_P3_D65)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddColorSpace(DisplayP3): ", stdout); if (pdfioPageDictAddColorSpace(dict, "DisplayP3", cs)) puts("PASS"); else return (1); fputs("pdfioArrayCreateColorFromICCObj(ProPhotoRGB): ", stdout); if ((cs = pdfioArrayCreateColorFromICCObj(pdf, prophoto)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddColorSpace(ProPhotoRGB): ", stdout); if (pdfioPageDictAddColorSpace(dict, "ProPhotoRGB", cs)) puts("PASS"); else return (1); fputs("pdfioArrayCreateColorFromStandard(sRGB): ", stdout); if ((cs = pdfioArrayCreateColorFromStandard(pdf, 3, PDFIO_CS_SRGB)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddColorSpace(sRGB): ", stdout); if (pdfioPageDictAddColorSpace(dict, "sRGB", cs)) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if (write_header_footer(st, "Color Space Test", number)) goto error; fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else goto error; fputs("pdfioContentSetTextFont(\"F1\", 18.0): ", stdout); if (pdfioContentSetTextFont(st, "F1", 18.0)) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(82, 234): ", stdout); if (pdfioContentTextMoveTo(st, 82, 234)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"AdobeRGB\"): ", stdout); if (pdfioContentTextShow(st, false, "AdobeRGB")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(234, 0): ", stdout); if (pdfioContentTextMoveTo(st, 234, 0)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"DisplayP3\"): ", stdout); if (pdfioContentTextShow(st, false, "DisplayP3")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(-234, 216): ", stdout); if (pdfioContentTextMoveTo(st, -234, 216)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"sRGB\"): ", stdout); if (pdfioContentTextShow(st, false, "sRGB")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(234, 0): ", stdout); if (pdfioContentTextMoveTo(st, 234, 0)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"ProPhotoRGB\"): ", stdout); if (pdfioContentTextShow(st, false, "ProPhotoRGB")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(-234, 216): ", stdout); if (pdfioContentTextMoveTo(st, -234, 216)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"DeviceCMYK\"): ", stdout); if (pdfioContentTextShow(st, false, "DeviceCMYK")) puts("PASS"); else goto error; fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else goto error; fputs("pdfioContentSave(): ", stdout); if (pdfioContentSave(st)) puts("PASS"); else goto error; fputs("pdfioContentSetFillColorSpace(AdobeRGB): ", stdout); if (pdfioContentSetFillColorSpace(st, "AdobeRGB")) puts("PASS"); else goto error; fputs("pdfioContentMatrixTranslate(82, 90): ", stdout); if (pdfioContentMatrixTranslate(st, 82, 90)) puts("PASS"); else goto error; if (write_color_patch(st, false)) goto error; fputs("pdfioContentRestore(): ", stdout); if (pdfioContentRestore(st)) puts("PASS"); else goto error; fputs("pdfioContentSave(): ", stdout); if (pdfioContentSave(st)) puts("PASS"); else goto error; fputs("pdfioContentSetFillColorSpace(DisplayP3): ", stdout); if (pdfioContentSetFillColorSpace(st, "DisplayP3")) puts("PASS"); else goto error; fputs("pdfioContentMatrixTranslate(316, 90): ", stdout); if (pdfioContentMatrixTranslate(st, 316, 90)) puts("PASS"); else goto error; if (write_color_patch(st, false)) goto error; fputs("pdfioContentRestore(): ", stdout); if (pdfioContentRestore(st)) puts("PASS"); else goto error; fputs("pdfioContentSave(): ", stdout); if (pdfioContentSave(st)) puts("PASS"); else goto error; fputs("pdfioContentSetFillColorSpace(sRGB): ", stdout); if (pdfioContentSetFillColorSpace(st, "sRGB")) puts("PASS"); else goto error; fputs("pdfioContentMatrixTranslate(82, 306): ", stdout); if (pdfioContentMatrixTranslate(st, 82, 306)) puts("PASS"); else goto error; if (write_color_patch(st, false)) goto error; fputs("pdfioContentRestore(): ", stdout); if (pdfioContentRestore(st)) puts("PASS"); else goto error; fputs("pdfioContentSave(): ", stdout); if (pdfioContentSave(st)) puts("PASS"); else goto error; fputs("pdfioContentSetFillColorSpace(ProPhotoRGB): ", stdout); if (pdfioContentSetFillColorSpace(st, "ProPhotoRGB")) puts("PASS"); else goto error; fputs("pdfioContentMatrixTranslate(316, 306): ", stdout); if (pdfioContentMatrixTranslate(st, 316, 306)) puts("PASS"); else goto error; if (write_color_patch(st, false)) goto error; fputs("pdfioContentRestore(): ", stdout); if (pdfioContentRestore(st)) puts("PASS"); else goto error; fputs("pdfioContentSave(): ", stdout); if (pdfioContentSave(st)) puts("PASS"); else goto error; fputs("pdfioContentMatrixTranslate(82, 522): ", stdout); if (pdfioContentMatrixTranslate(st, 82, 522)) puts("PASS"); else goto error; if (write_color_patch(st, true)) goto error; fputs("pdfioContentRestore(): ", stdout); if (pdfioContentRestore(st)) puts("PASS"); else goto error; fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_font_test()' - Write a font test page. // static int // O - 1 on failure, 0 on success write_font_test( pdfio_file_t *pdf, // I - PDF file int number, // I - Page number pdfio_obj_t *font, // I - Page number font const char *textfontfile, // I - Text font file bool unicode) // I - Use Unicode font? { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream pdfio_obj_t *textfont; // Text font char title[256], // Page title textname[256], // Name of text font *ptr; // Pointer into name int i; // Looping var static const char * const welcomes[] =// "Welcome" in many languages { "Welcome", "Welkom", "ḫaṣānu", "Mayad-ayad nga pad-abot", "Mir se vjên", "Mirë se vjen", "Wellkumma", "Bienveniu", "Ghini vinit!", "Bienveníu", "Miro peicak", "Xoş gəlmişsiniz!", "Salamat datang", "Сәләм бирем!", "Menjuah-juah!", "Še das d' kemma bisd", "Mwaiseni", "Maogmáng Pag-abót", "Welkam", "Dobrodošli", "Degemer mat", "Benvingut", "Maayong pag-abot", "Kopisanangan do kinorikatan", "Bienvenida", "Bien binidu", "Bienbenidu", "Hóʔą", "Boolkhent!", "Kopivosian do kinoikatan", "Malipayeng Pag-abot!", "Vítej", "Velkommen", "Salâm", "Welkom", "Emedi", "Welkumin", "Tere tulemast", "Woé zɔ", "Bienveníu", "Vælkomin", "Bula", "Tervetuloa", "Bienvenue", "Wäljkiimen", "Wäilkuumen", "Wäilkuumen", "Wolkom", "Benvignût", "Benvido", "Willkommen", "Ἀσπάζομαι!", "Καλώς Ήρθες", "Tikilluarit", "Byen venu", "Sannu da zuwa", "Aloha", "Wayakurua", "Dayón", "Zoo siab txais tos!", "Üdvözlet", "Selamat datai", "Velkomin", "Nnọọ", "Selamat datang", "Qaimarutin", "Fáilte", "Benvenuto", "Voschata", "Murakaza neza", "Mauri", "Tu be xér hatî ye!", "Taŋyáŋ yahí", "Salve", "Laipni lūdzam", "Wilkóm", "Sveiki atvykę", "Willkamen", "Mu amuhezwi", "Tukusanyukidde", "Wëllkomm", "Swagatam", "Tonga soa", "Selamat datang", "Merħba", "B’a’ntulena", "Failt ort", "Haere mai", "mai", "Pjila’si", "Benvegnüu", "Ne y kena", "Ximopanōltih", "Yá'át'ééh", "Siyalemukela", "Siyalemukela", "Bures boahtin", "Re a go amogela", "Velkommen", "Benvengut!", "Bon bini", "Witam Cię", "Bem-vindo", "Haykuykuy!", "T'aves baxtalo", "Bainvegni", "Afio mai", "Ennidos", "Walcome", "Fàilte", "Mauya", "Bon vinutu", "Vitaj", "Dobrodošli", "Soo dhowow", "Witaj", "Bienvenido", "Wilujeng sumping", "Karibu", "Wamukelekile", "Välkommen", "Wilkomme", "Maligayang pagdating", "Maeva", "Räxim itegez", "Ksolok Bodik Mai", "Ulu tons mai", "Welkam", "Talitali fiefia", "Lek oy li la tale", "amogetswe", "Tempokani", "Hoş geldin", "Koş geldiniz", "Ulufale mai!", "Xush kelibsiz", "Benvignùo", "Tervhen tuldes", "Hoan nghênh", "Tere tulõmast", "Benvnuwe", "Croeso", "Merhbe", "Wamkelekile", "Märr-ŋamathirri", "Ẹ ku abọ", "Kíimak 'oolal", "Ngiyakwemukela" }; printf("pdfioFileCreateFontObjFromFile(%s): ", textfontfile); if ((textfont = pdfioFileCreateFontObjFromFile(pdf, textfontfile, unicode)) != NULL) puts("PASS"); else return (1); fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F2): ", stdout); if (pdfioPageDictAddFont(dict, "F2", textfont)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if ((ptr = strrchr(textfontfile, '/')) != NULL) strncpy(textname, ptr + 1, sizeof(textname) - 1); else strncpy(textname, textfontfile, sizeof(textname) - 1); textname[sizeof(textname) - 1] = '\0'; if ((ptr = strrchr(textname, '.')) != NULL) *ptr = '\0'; if (unicode) snprintf(title, sizeof(title), "Unicode %s Font Test", textname); else snprintf(title, sizeof(title), "CP1252 %s Font Test", textname); if (write_header_footer(st, title, number)) goto error; fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else return (1); fputs("pdfioContentSetTextFont(\"F2\", 10.0): ", stdout); if (pdfioContentSetTextFont(st, "F2", 10.0)) puts("PASS"); else return (1); fputs("pdfioContentSetTextLeading(12.0): ", stdout); if (pdfioContentSetTextLeading(st, 12.0)) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(36.0, 702.0): ", stdout); if (pdfioContentTextMoveTo(st, 36.0, 702.0)) puts("PASS"); else return (1); for (i = 0; i < (int)(sizeof(welcomes) / sizeof(welcomes[0])); i ++) { if (i > 0 && (i % 50) == 0) { fputs("pdfioContentTextMoveTo(200.0, 600.0): ", stdout); if (pdfioContentTextMoveTo(st, 200.0, 600.0)) puts("PASS"); else return (1); } printf("pdfioContentTextShowf(\"%s\"): ", welcomes[i]); if (pdfioContentTextShowf(st, unicode, "%s\n", welcomes[i])) puts("PASS"); else return (1); } fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else return (1); fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_header_footer()' - Write common header and footer text. // static int // O - 1 on failure, 0 on success write_header_footer( pdfio_stream_t *st, // I - Page content stream const char *title, // I - Title int number) // I - Page number { fputs("pdfioContentSetFillColorDeviceGray(0.0): ", stdout); if (pdfioContentSetFillColorDeviceGray(st, 0.0)) puts("PASS"); else return (1); fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else return (1); fputs("pdfioContentSetTextFont(\"F1\", 18.0): ", stdout); if (pdfioContentSetTextFont(st, "F1", 18.0)) puts("PASS"); else return (1); fputs("pdfioContentTextMoveTo(36.0, 738.0): ", stdout); if (pdfioContentTextMoveTo(st, 36.0, 738.0)) puts("PASS"); else return (1); printf("pdfioContentTextShow(\"%s\"): ", title); if (pdfioContentTextShow(st, false, title)) puts("PASS"); else return (1); fputs("pdfioContentSetTextFont(\"F1\", 12.0): ", stdout); if (pdfioContentSetTextFont(st, "F1", 12.0)) puts("PASS"); else return (1); fputs("pdfioContentTextMoveTo(514.0, -702.0): ", stdout); if (pdfioContentTextMoveTo(st, 514.0, -702.0)) puts("PASS"); else return (1); printf("pdfioContentTextShowf(\"%d\"): ", number); if (pdfioContentTextShowf(st, false, "%d", number)) puts("PASS"); else return (1); fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else return (1); return (0); } // // 'write_image_object()' - Write an image object using the specified predictor. // static pdfio_obj_t * // O - Image object write_image_object( pdfio_file_t *pdf, // I - PDF file _pdfio_predictor_t predictor) // I - Predictor to use { pdfio_dict_t *dict, // Image dictionary *decode; // Decode dictionary pdfio_obj_t *obj; // Image object pdfio_stream_t *st; // Image stream int x, y; // Coordinates in image unsigned char buffer[768], // Buffer for image *bufptr; // Pointer into buffer // Create the image dictionary... if ((dict = pdfioDictCreate(pdf)) == NULL) return (NULL); pdfioDictSetName(dict, "Type", "XObject"); pdfioDictSetName(dict, "Subtype", "Image"); pdfioDictSetNumber(dict, "Width", 256); pdfioDictSetNumber(dict, "Height", 256); pdfioDictSetNumber(dict, "BitsPerComponent", 8); pdfioDictSetName(dict, "ColorSpace", "DeviceRGB"); pdfioDictSetName(dict, "Filter", "FlateDecode"); // DecodeParms dictionary... if ((decode = pdfioDictCreate(pdf)) == NULL) return (NULL); pdfioDictSetNumber(decode, "BitsPerComponent", 8); pdfioDictSetNumber(decode, "Colors", 3); pdfioDictSetNumber(decode, "Columns", 256); pdfioDictSetNumber(decode, "Predictor", predictor); pdfioDictSetDict(dict, "DecodeParms", decode); // Create the image object... if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL) return (NULL); // Create the image stream and write the image... if ((st = pdfioObjCreateStream(obj, PDFIO_FILTER_FLATE)) == NULL) return (NULL); // This creates a useful criss-cross image that highlights predictor errors... for (y = 0; y < 256; y ++) { for (x = 0, bufptr = buffer; x < 256; x ++, bufptr += 3) { bufptr[0] = (unsigned char)y; bufptr[1] = (unsigned char)(y + x); bufptr[2] = (unsigned char)(y - x); } if (!pdfioStreamWrite(st, buffer, sizeof(buffer))) { pdfioStreamClose(st); return (NULL); } } // Close the object and stream... pdfioStreamClose(st); return (obj); } // // 'write_images_test()' - Write a series of test images. // static int // O - 1 on failure, 0 on success write_images_test( pdfio_file_t *pdf, // I - PDF file int number, // I - Page number pdfio_obj_t *font) // I - Text font { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page stream _pdfio_predictor_t p; // Current predictor pdfio_obj_t *noimage, // No predictor *pimages[6]; // Images using PNG predictors char pname[32], // Image name plabel[32]; // Image label // Create the images... fputs("Create Image (Predictor 1): ", stdout); if ((noimage = write_image_object(pdf, _PDFIO_PREDICTOR_NONE)) != NULL) puts("PASS"); else return (1); for (p = _PDFIO_PREDICTOR_PNG_NONE; p <= _PDFIO_PREDICTOR_PNG_AUTO; p ++) { printf("Create Image (Predictor %d): ", p); if ((pimages[p - _PDFIO_PREDICTOR_PNG_NONE] = write_image_object(pdf, p)) != NULL) puts("PASS"); else return (1); } // Create the page dictionary, object, and stream... fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddImage(1): ", stdout); if (pdfioPageDictAddImage(dict, "IM1", noimage)) puts("PASS"); else return (1); for (p = _PDFIO_PREDICTOR_PNG_NONE; p <= _PDFIO_PREDICTOR_PNG_AUTO; p ++) { printf("pdfioPageDictAddImage(%d): ", p); snprintf(pname, sizeof(pname), "IM%d", p); if (pdfioPageDictAddImage(dict, pdfioStringCreate(pdf, pname), pimages[p - _PDFIO_PREDICTOR_PNG_NONE])) puts("PASS"); else return (1); } fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if (write_header_footer(st, "Image Predictor Test", number)) goto error; // Draw images if (draw_image(st, "IM1", 36, 522, 144, 144, "No Predictor")) goto error; for (p = _PDFIO_PREDICTOR_PNG_NONE; p <= _PDFIO_PREDICTOR_PNG_AUTO; p ++) { int i = (int)p - _PDFIO_PREDICTOR_PNG_NONE; snprintf(pname, sizeof(pname), "IM%d", p); snprintf(plabel, sizeof(plabel), "PNG Predictor %d", p); if (draw_image(st, pname, 36 + 180 * (i % 3), 306 - 216 * (i / 3), 144, 144, plabel)) goto error; } // Wrap up... fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_jpeg_test()' - Write a page with a JPEG image to a PDF file. // static int // O - 1 on failure, 0 on success write_jpeg_test(pdfio_file_t *pdf, // I - PDF file const char *title, // I - Page title int number, // I - Page number pdfio_obj_t *font, // I - Text font pdfio_obj_t *image) // I - Image to draw { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream double width, // Width of image height; // Height of image double swidth, // Scaled width sheight, // Scaled height tx, // X offset ty; // Y offset // Create the page dictionary, object, and stream... fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddImage: ", stdout); if (pdfioPageDictAddImage(dict, "IM1", image)) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if (write_header_footer(st, title, number)) goto error; // Calculate the scaled size of the image... fputs("pdfioImageGetWidth(): ", stdout); if ((width = pdfioImageGetWidth(image)) > 0.0) puts("PASS"); else goto error; fputs("pdfioImageGetHeight(): ", stdout); if ((height = pdfioImageGetHeight(image)) > 0.0) puts("PASS"); else goto error; swidth = 400.0; sheight = swidth * height / width; if (sheight > 500.0) { sheight = 500.0; swidth = sheight * width / height; } tx = 0.5 * (595.28 - swidth); ty = 0.5 * (792 - sheight); // Show "raw" content (a bordered box for the image...) fputs("pdfioStreamPrintf(...): ", stdout); if (pdfioStreamPrintf(st, "1 0 0 RG 0 g 5 w\n" "%g %g %g %g re %g %g %g %g re B*\n", tx - 36, ty - 36, swidth + 72, sheight + 72, tx - 1, ty - 1, swidth + 2, sheight + 2)) puts("PASS"); else goto error; // Draw the image inside the border box... printf("pdfioContentDrawImage(\"IM1\", x=%g, y=%g, w=%g, h=%g): ", tx, ty, swidth, sheight); if (pdfioContentDrawImage(st, "IM1", tx, ty, swidth, sheight)) puts("PASS"); else goto error; // Close the page stream/object... fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_png_test()' - Write a page of PNG test images. // static int // O - 0 on success, 1 on failure write_png_test(pdfio_file_t *pdf, // I - PDF file int number, // I - Page number pdfio_obj_t *font) // I - Page number font { pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream pdfio_obj_t *color, // pdfio-color.png *gray, // pdfio-gray.png *indexed; // pdfio-indexed.png // Import the PNG test images fputs("pdfioFileCreateImageObjFromFile(\"testfiles/pdfio-color.png\"): ", stdout); if ((color = pdfioFileCreateImageObjFromFile(pdf, "testfiles/pdfio-color.png", false)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileCreateImageObjFromFile(\"testfiles/pdfio-gray.png\"): ", stdout); if ((gray = pdfioFileCreateImageObjFromFile(pdf, "testfiles/pdfio-gray.png", false)) != NULL) puts("PASS"); else return (1); fputs("pdfioFileCreateImageObjFromFile(\"testfiles/pdfio-indexed.png\"): ", stdout); if ((indexed = pdfioFileCreateImageObjFromFile(pdf, "testfiles/pdfio-indexed.png", false)) != NULL) puts("PASS"); else return (1); // Create the page dictionary, object, and stream... fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddImage(color): ", stdout); if (pdfioPageDictAddImage(dict, "IM1", color)) puts("PASS"); else return (1); fputs("pdfioPageDictAddImage(gray): ", stdout); if (pdfioPageDictAddImage(dict, "IM2", gray)) puts("PASS"); else return (1); fputs("pdfioPageDictAddImage(indexed): ", stdout); if (pdfioPageDictAddImage(dict, "IM3", indexed)) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); printf("pdfioFileCreatePage(%d): ", number); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else return (1); if (write_header_footer(st, "PNG Image Test Page", number)) goto error; // Show content... fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else goto error; fputs("pdfioContentSetTextFont(\"F1\", 18.0): ", stdout); if (pdfioContentSetTextFont(st, "F1", 18.0)) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(36.0, 342.0): ", stdout); if (pdfioContentTextMoveTo(st, 36.0, 342.0)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"PNG RGB Color\"): ", stdout); if (pdfioContentTextShow(st, false, "PNG RGB Color")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(288.0, 0.0): ", stdout); if (pdfioContentTextMoveTo(st, 288.0, 0.0)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"PNG Gray\"): ", stdout); if (pdfioContentTextShow(st, false, "PNG Gray")) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(-288.0, 288.0): ", stdout); if (pdfioContentTextMoveTo(st, -288.0, 288.0)) puts("PASS"); else goto error; fputs("pdfioContentTextShow(\"PNG Indexed\"): ", stdout); if (pdfioContentTextShow(st, false, "PNG Indexed")) puts("PASS"); else goto error; fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else goto error; fputs("pdfioContentDrawImage(\"IM1\"): ", stdout); if (pdfioContentDrawImage(st, "IM1", 36, 108, 216, 216)) puts("PASS"); else goto error; fputs("pdfioContentDrawImage(\"IM2\"): ", stdout); if (pdfioContentDrawImage(st, "IM2", 324, 108, 216, 216)) puts("PASS"); else goto error; fputs("pdfioContentDrawImage(\"IM3\"): ", stdout); if (pdfioContentDrawImage(st, "IM3", 36, 396, 216, 216)) puts("PASS"); else goto error; fputs("pdfioContentSetFillColorDeviceRGB(0, 1, 1): ", stdout); if (pdfioContentSetFillColorDeviceRGB(st, 0.0, 1.0, 1.0)) puts("PASS"); else goto error; fputs("pdfioContentPathRect(315, 387, 234, 234): ", stdout); if (pdfioContentPathRect(st, 315, 387, 234, 234)) puts("PASS"); else goto error; fputs("pdfioContentFill(false): ", stdout); if (pdfioContentFill(st, false)) puts("PASS"); else goto error; fputs("pdfioContentDrawImage(\"IM3\"): ", stdout); if (pdfioContentDrawImage(st, "IM3", 324, 396, 216, 216)) puts("PASS"); else goto error; // Close the object and stream... fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); return (0); error: pdfioStreamClose(st); return (1); } // // 'write_text_test()' - Print a plain text file. // static int // O - 0 on success, 1 on failure write_text_test(pdfio_file_t *pdf, // I - PDF file int first_page, // I - First page number pdfio_obj_t *font, // I - Page number font const char *filename) // I - File to print { pdfio_obj_t *courier; // Courier font pdfio_dict_t *dict; // Page dictionary FILE *fp; // Print file char line[1024]; // Line from file int page, // Current page number plinenum, // Current line number on page flinenum; // Current line number in file pdfio_stream_t *st = NULL; // Page contents stream // Create text font... fputs("pdfioFileCreateFontObjFromBase(\"Courier\"): ", stdout); if ((courier = pdfioFileCreateFontObjFromBase(pdf, "Courier")) != NULL) puts("PASS"); else return (1); // Create the page dictionary... fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F1): ", stdout); if (pdfioPageDictAddFont(dict, "F1", font)) puts("PASS"); else return (1); fputs("pdfioPageDictAddFont(F2): ", stdout); if (pdfioPageDictAddFont(dict, "F2", courier)) puts("PASS"); else return (1); // Open the print file... if ((fp = fopen(filename, "r")) == NULL) { printf("Unable to open \"%s\": %s\n", filename, strerror(errno)); return (1); } page = first_page; plinenum = 0; flinenum = 0; while (fgets(line, sizeof(line), fp)) { flinenum ++; if (plinenum == 0) { printf("pdfioFileCreatePage(%d): ", page); if ((st = pdfioFileCreatePage(pdf, dict)) != NULL) puts("PASS"); else goto error; if (write_header_footer(st, "README.md", page)) goto error; page ++; plinenum ++; fputs("pdfioContentTextBegin(): ", stdout); if (pdfioContentTextBegin(st)) puts("PASS"); else goto error; fputs("pdfioContentSetTextFont(\"F2\", 10.0): ", stdout); if (pdfioContentSetTextFont(st, "F2", 10.0)) puts("PASS"); else goto error; fputs("pdfioContentSetTextLeading(12.0): ", stdout); if (pdfioContentSetTextLeading(st, 12.0)) puts("PASS"); else goto error; fputs("pdfioContentTextMoveTo(36.0, 708.0): ", stdout); if (pdfioContentTextMoveTo(st, 36.0, 708.0)) puts("PASS"); else goto error; } if (!pdfioContentSetFillColorDeviceGray(st, 0.75)) goto error; if (!pdfioContentTextShowf(st, false, "%3d ", flinenum)) goto error; if (!pdfioContentSetFillColorDeviceGray(st, 0.0)) goto error; if (strlen(line) > 81) { char temp[82]; // Temporary string memcpy(temp, line, 80); temp[80] = '\n'; temp[81] = '\0'; if (!pdfioContentTextShow(st, false, temp)) goto error; if (!pdfioContentTextShowf(st, false, " %s", line + 80)) goto error; plinenum ++; } else if (!pdfioContentTextShow(st, false, line)) goto error; plinenum ++; if (plinenum >= 56) { fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else goto error; fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else goto error; st = NULL; plinenum = 0; } } if (plinenum > 0) { fputs("pdfioContentTextEnd(): ", stdout); if (pdfioContentTextEnd(st)) puts("PASS"); else goto error; fputs("pdfioStreamClose: ", stdout); if (pdfioStreamClose(st)) puts("PASS"); else return (1); } fclose(fp); return (0); error: fclose(fp); pdfioStreamClose(st); return (1); } // // 'write_unit_file()' - Write a unit test file. // static int // O - Exit status write_unit_file( pdfio_file_t *inpdf, // I - Input PDF file pdfio_file_t *outpdf, // I - Output PDF file size_t *num_pages, // O - Number of pages size_t *first_image) // O - First image object { const char *s; // String buffer pdfio_obj_t *color_jpg, // color.jpg image *gray_jpg, // gray.jpg image *helvetica, // Helvetica font *page; // Page from test PDF file // Set info values... fputs("pdfioFileGet/SetAuthor: ", stdout); pdfioFileSetAuthor(outpdf, "Michael R Sweet"); if ((s = pdfioFileGetAuthor(outpdf)) != NULL && !strcmp(s, "Michael R Sweet")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Michael R Sweet')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Michael R Sweet')"); return (1); } fputs("pdfioFileGet/SetCreator: ", stdout); pdfioFileSetCreator(outpdf, "testpdfio"); if ((s = pdfioFileGetCreator(outpdf)) != NULL && !strcmp(s, "testpdfio")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'testpdfio')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'testpdfio')"); return (1); } fputs("pdfioFileGet/SetKeywords: ", stdout); pdfioFileSetKeywords(outpdf, "one fish,two fish,red fish,blue fish"); if ((s = pdfioFileGetKeywords(outpdf)) != NULL && !strcmp(s, "one fish,two fish,red fish,blue fish")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'one fish,two fish,red fish,blue fish')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'one fish,two fish,red fish,blue fish')"); return (1); } fputs("pdfioFileGet/SetSubject: ", stdout); pdfioFileSetSubject(outpdf, "Unit test document"); if ((s = pdfioFileGetSubject(outpdf)) != NULL && !strcmp(s, "Unit test document")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Unit test document')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Unit test document')"); return (1); } fputs("pdfioFileGet/SetTitle: ", stdout); pdfioFileSetTitle(outpdf, "Test Document"); if ((s = pdfioFileGetTitle(outpdf)) != NULL && !strcmp(s, "Test Document")) { puts("PASS"); } else if (s) { printf("FAIL (got '%s', expected 'Test Document')\n", s); return (1); } else { puts("FAIL (got NULL, expected 'Test Document')"); return (1); } // Create some image objects... fputs("pdfioFileCreateImageObjFromFile(\"testfiles/color.jpg\"): ", stdout); if ((color_jpg = pdfioFileCreateImageObjFromFile(outpdf, "testfiles/color.jpg", true)) != NULL) printf("PASS (%u)\n", (unsigned)pdfioObjGetNumber(color_jpg)); else return (1); fputs("pdfioFileCreateImageObjFromFile(\"testfiles/gray.jpg\"): ", stdout); if ((gray_jpg = pdfioFileCreateImageObjFromFile(outpdf, "testfiles/gray.jpg", true)) != NULL) printf("PASS (%u)\n", (unsigned)pdfioObjGetNumber(gray_jpg)); else return (1); // Create fonts... fputs("pdfioFileCreateFontObjFromBase(\"Helvetica\"): ", stdout); if ((helvetica = pdfioFileCreateFontObjFromBase(outpdf, "Helvetica")) != NULL) puts("PASS"); else return (1); // Copy the first page from the test PDF file... fputs("pdfioFileGetPage(0): ", stdout); if ((page = pdfioFileGetPage(inpdf, 0)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageCopy(first page): ", stdout); if (pdfioPageCopy(outpdf, page)) puts("PASS"); else return (1); // Write a page with a color image... if (write_jpeg_test(outpdf, "Color JPEG Test", 2, helvetica, color_jpg)) return (1); // Copy the third page from the test PDF file... fputs("pdfioFileGetPage(2): ", stdout); if ((page = pdfioFileGetPage(inpdf, 2)) != NULL) puts("PASS"); else return (1); fputs("pdfioPageCopy(third page): ", stdout); if (pdfioPageCopy(outpdf, page)) puts("PASS"); else return (1); // Write a page with a grayscale image... if (write_jpeg_test(outpdf, "Grayscale JPEG Test", 4, helvetica, gray_jpg)) return (1); // Write a page with PNG images... if (write_png_test(outpdf, 5, helvetica)) return (1); // Write a page that tests multiple color spaces... if (write_color_test(outpdf, 6, helvetica)) return (1); // Write a page with test images... *first_image = pdfioFileGetNumObjs(outpdf) + 1; if (write_images_test(outpdf, 7, helvetica)) return (1); // Write a page width alpha (soft masks)... if (write_alpha_test(outpdf, 8, helvetica)) return (1); // Test TrueType fonts... if (write_font_test(outpdf, 9, helvetica, "testfiles/OpenSans-Regular.ttf", false)) return (1); if (write_font_test(outpdf, 10, helvetica, "testfiles/OpenSans-Regular.ttf", true)) return (1); if (write_font_test(outpdf, 11, helvetica, "testfiles/NotoSansJP-Regular.otf", true)) return (1); // Print this text file... if (write_text_test(outpdf, 12, helvetica, "README.md")) return (1); fputs("pdfioFileGetNumPages: ", stdout); if ((*num_pages = pdfioFileGetNumPages(outpdf)) > 0) { printf("PASS (%lu)\n", (unsigned long)*num_pages); } else { puts("FAIL"); return (1); } // Close the new PDF file... fputs("pdfioFileClose(...): ", stdout); if (pdfioFileClose(outpdf)) puts("PASS"); else return (1); return (0); }