mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-12-23 21:46:24 +01:00
added the unit testcases for the pdfa feature in the testpdfio and removed the custom one
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@
|
||||
/testpdfio-*.pdf
|
||||
/testttf
|
||||
/x64
|
||||
/test-pdfa-*
|
||||
|
||||
Binary file not shown.
@@ -1,77 +0,0 @@
|
||||
#include <pdfio.h>
|
||||
#include <pdfio-content.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// 1. Basic PDF setup
|
||||
pdfio_file_t *pdf;
|
||||
pdfio_rect_t media_box = {0.0, 0.0, 612.0, 792.0}; // US Letter size
|
||||
|
||||
// Create the PDF file
|
||||
if ((pdf = pdfioFileCreate("tagged_document.pdf", "2.0", &media_box, &media_box, NULL, NULL)) == NULL)
|
||||
{
|
||||
puts("Error: Could not create PDF file.");
|
||||
return (1);
|
||||
}
|
||||
|
||||
// 2. Build the Structure Tree Root (StructTreeRoot)
|
||||
// This is the master "table of contents" for all tags.
|
||||
pdfio_dict_t *struct_tree_root_dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetName(struct_tree_root_dict, "Type", "StructTreeRoot");
|
||||
|
||||
// Create the top-level document element tag: /Document
|
||||
pdfio_dict_t *doc_elem_dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetName(doc_elem_dict, "Type", "StructElem");
|
||||
pdfioDictSetName(doc_elem_dict, "S", "Document"); // 'S' is the structure type
|
||||
|
||||
// Create the paragraph element tag: /P
|
||||
pdfio_dict_t *p_elem_dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetName(p_elem_dict, "Type", "StructElem");
|
||||
pdfioDictSetName(p_elem_dict, "S", "P"); // 'S' is the structure type (Paragraph)
|
||||
pdfioDictSetNumber(p_elem_dict, "K", 0); // 'K' is the content, pointing to MCID 0 on the page
|
||||
|
||||
// Link the paragraph as a child of the document element
|
||||
pdfio_array_t *doc_kids = pdfioArrayCreate(pdf);
|
||||
pdfioArrayAppendDict(doc_kids, p_elem_dict);
|
||||
pdfioDictSetArray(doc_elem_dict, "K", doc_kids);
|
||||
|
||||
// Link the document element as a child of the StructTreeRoot
|
||||
pdfio_array_t *root_kids = pdfioArrayCreate(pdf);
|
||||
pdfioArrayAppendDict(root_kids, doc_elem_dict);
|
||||
pdfioDictSetArray(struct_tree_root_dict, "K", root_kids);
|
||||
|
||||
// Create a PDF object for the StructTreeRoot and link it to the main catalog
|
||||
pdfio_obj_t *struct_tree_root_obj = pdfioFileCreateObj(pdf, struct_tree_root_dict);
|
||||
pdfioDictSetObj(pdfioFileGetCatalog(pdf), "StructTreeRoot", struct_tree_root_obj);
|
||||
|
||||
// 3. Create a page and its content
|
||||
pdfio_dict_t *page_dict = pdfioDictCreate(pdf);
|
||||
pdfio_obj_t *helvetica = pdfioFileCreateFontObjFromBase(pdf, "Helvetica");
|
||||
pdfioPageDictAddFont(page_dict, "F1", helvetica);
|
||||
|
||||
pdfio_stream_t *st = pdfioFileCreatePage(pdf, page_dict);
|
||||
|
||||
// 4. Write the tagged content to the page stream
|
||||
pdfioContentTextBegin(st);
|
||||
pdfioContentSetTextFont(st, "F1", 24.0);
|
||||
pdfioContentTextMoveTo(st, 72.0, 700.0);
|
||||
|
||||
// Create a dictionary for the marked content, specifying the ID
|
||||
pdfio_dict_t *p_mcid_dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetNumber(p_mcid_dict, "MCID", 0); // This ID must match the 'K' value in the StructElem
|
||||
|
||||
// Use the functions from pdfio-content.c to wrap the text
|
||||
pdfioContentBeginMarked(st, "P", p_mcid_dict); // Start tag for Paragraph
|
||||
pdfioContentTextShow(st, false, "This is a tagged paragraph.");
|
||||
pdfioContentEndMarked(st); // End tag
|
||||
|
||||
pdfioContentTextEnd(st);
|
||||
|
||||
// 5. Finalize and close
|
||||
pdfioStreamClose(st);
|
||||
pdfioFileClose(pdf);
|
||||
|
||||
puts("Successfully created tagged_document.pdf");
|
||||
return (0);
|
||||
}
|
||||
140
my_pdfa_test.c
140
my_pdfa_test.c
@@ -1,140 +0,0 @@
|
||||
// File: my_pdfa_test.c (Final version with embedded font)
|
||||
|
||||
#include "pdfio.h"
|
||||
#include "pdfio-content.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//
|
||||
// Local functions...
|
||||
//
|
||||
static bool my_error_cb(pdfio_file_t *pdf, const char *message, void *data);
|
||||
static bool create_pdfa_test_file(const char *filename, const char *pdfa_version);
|
||||
static int test_pdfa(void);
|
||||
|
||||
|
||||
//
|
||||
// 'my_error_cb()' - A simple error callback to print detailed messages.
|
||||
//
|
||||
static bool // O - true to continue, false to stop
|
||||
my_error_cb(pdfio_file_t *pdf, // I - PDF file
|
||||
const char *message, // I - Error message
|
||||
void *data) // I - Callback data (unused)
|
||||
{
|
||||
(void)pdf; // Unused
|
||||
(void)data; // Unused
|
||||
fprintf(stderr, "PDFio Error: %s\n", message);
|
||||
return (false); // Stop on any error
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'create_pdfa_test_file()' - A helper function to generate a simple PDF/A file.
|
||||
//
|
||||
static bool // O - true on success, false on error
|
||||
create_pdfa_test_file(
|
||||
const char *filename, // I - Name of the PDF file to create
|
||||
const char *pdfa_version) // I - PDF/A version string (e.g., "PDF/A-1b")
|
||||
{
|
||||
pdfio_file_t *pdf; // Output PDF file
|
||||
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
|
||||
// Media box for US Letter
|
||||
pdfio_obj_t *font; // Font object
|
||||
pdfio_dict_t *page_dict; // Page dictionary
|
||||
pdfio_stream_t *st; // Page content stream
|
||||
char text[256]; // Text to write to page
|
||||
|
||||
snprintf(text, sizeof(text), "This is a compliance test for %s.", pdfa_version);
|
||||
printf(" Creating '%s' for %s compliance check...\n", filename, pdfa_version);
|
||||
|
||||
if ((pdf = pdfioFileCreate(filename, pdfa_version, &media_box, NULL, my_error_cb, NULL)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " ERROR: pdfioFileCreate failed for '%s'.\n", filename);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// --- THIS IS THE KEY CHANGE ---
|
||||
// Instead of using a base font, we now load and embed a font from a file.
|
||||
if ((font = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", false)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " ERROR: Unable to embed font 'testfiles/OpenSans-Regular.ttf'.\n");
|
||||
pdfioFileClose(pdf);
|
||||
return (false);
|
||||
}
|
||||
|
||||
page_dict = pdfioDictCreate(pdf);
|
||||
pdfioPageDictAddFont(page_dict, "F1", font);
|
||||
st = pdfioFileCreatePage(pdf, page_dict);
|
||||
|
||||
pdfioContentSetTextFont(st, "F1", 12.0);
|
||||
pdfioContentTextBegin(st);
|
||||
pdfioContentTextMoveTo(st, 72.0, 720.0);
|
||||
pdfioContentTextShow(st, false, text);
|
||||
pdfioContentTextEnd(st);
|
||||
|
||||
pdfioStreamClose(st);
|
||||
pdfioFileClose(pdf);
|
||||
|
||||
printf(" Successfully created '%s'.\n", filename);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'test_pdfa()' - The main test runner for the PDF/A feature.
|
||||
//
|
||||
static int // O - 0 on success, 1 on error
|
||||
test_pdfa(void)
|
||||
{
|
||||
int status = 0;
|
||||
pdfio_file_t *fail_pdf;
|
||||
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
|
||||
|
||||
puts("---- Running PDF/A Generation Tests ----\n");
|
||||
|
||||
if (!create_pdfa_test_file("test-pdfa-1b.pdf", "PDF/A-1b")) status = 1;
|
||||
if (!create_pdfa_test_file("test-pdfa-2b.pdf", "PDF/A-2b")) status = 1;
|
||||
if (!create_pdfa_test_file("test-pdfa-2u.pdf", "PDF/A-2u")) status = 1;
|
||||
if (!create_pdfa_test_file("test-pdfa-3b.pdf", "PDF/A-3b")) status = 1;
|
||||
if (!create_pdfa_test_file("test-pdfa-3u.pdf", "PDF/A-3u")) status = 1;
|
||||
if (!create_pdfa_test_file("test-pdfa-4.pdf", "PDF/A-4")) status = 1;
|
||||
|
||||
puts("\n---- Running PDF/A Encryption Block Test ----\n");
|
||||
|
||||
printf(" Creating PDF/A file to test encryption failure...\n");
|
||||
if ((fail_pdf = pdfioFileCreate("test-pdfa-fail.pdf", "PDF/A-1b", &media_box, NULL, my_error_cb, NULL)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " ERROR: pdfioFileCreate failed for encryption test.\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (pdfioFileSetPermissions(fail_pdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, "owner", "user"))
|
||||
{
|
||||
fputs(" ERROR: pdfioFileSetPermissions succeeded but should have FAILED!\n", stderr);
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
puts(" SUCCESS: Correctly blocked encryption for PDF/A file as expected.");
|
||||
}
|
||||
pdfioFileClose(fail_pdf);
|
||||
|
||||
puts("\n-------------------------------------------");
|
||||
if (status == 0)
|
||||
puts("✅ All PDF/A tests passed.");
|
||||
else
|
||||
puts("❌ One or more PDF/A tests FAILED.");
|
||||
puts("-------------------------------------------\n");
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'main()' - Main entry for the test program.
|
||||
//
|
||||
int // O - Exit status
|
||||
main(void)
|
||||
{
|
||||
return (test_pdfa());
|
||||
}
|
||||
112
testpdfio.c
112
testpdfio.c
@@ -51,7 +51,8 @@ static int write_jpeg_test(pdfio_file_t *pdf, const char *title, int number, pdf
|
||||
static int write_png_tests(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, const char *outname, pdfio_file_t *outpdf, size_t *num_pages, size_t *first_image);
|
||||
|
||||
static int do_pdfa_tests(void);
|
||||
static int create_pdfa_test_file(const char *filename, const char *pdfa_version);
|
||||
|
||||
//
|
||||
// 'main()' - Main entry for test program.
|
||||
@@ -128,6 +129,109 @@ main(int argc, // I - Number of command-line arguments
|
||||
return (ret);
|
||||
}
|
||||
|
||||
//
|
||||
// 'create_pdfa_test_file()' - A helper function to generate a simple PDF/A file.
|
||||
//
|
||||
static int // O - 0 on success, 1 on error
|
||||
create_pdfa_test_file(
|
||||
const char *filename, // I - Name of the PDF file to create
|
||||
const char *pdfa_version) // I - PDF/A version string (e.g., "PDF/A-1b")
|
||||
{
|
||||
pdfio_file_t *pdf; // Output PDF file
|
||||
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
|
||||
// Media box for US Letter
|
||||
pdfio_obj_t *font; // Font object
|
||||
pdfio_dict_t *page_dict; // Page dictionary
|
||||
pdfio_stream_t *st; // Page content stream
|
||||
char text[256]; // Text to write to page
|
||||
bool error = false; // Error flag
|
||||
|
||||
snprintf(text, sizeof(text), "This is a compliance test for %s.", pdfa_version);
|
||||
|
||||
testBegin("Create %s file '%s'", pdfa_version, filename);
|
||||
|
||||
if ((pdf = pdfioFileCreate(filename, pdfa_version, &media_box, NULL, (pdfio_error_cb_t)error_cb, &error)) == NULL)
|
||||
{
|
||||
testEnd(false);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Embed a font, which is required for PDF/A
|
||||
if ((font = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", false)) == NULL)
|
||||
{
|
||||
pdfioFileClose(pdf);
|
||||
testEnd(false);
|
||||
return (1);
|
||||
}
|
||||
|
||||
page_dict = pdfioDictCreate(pdf);
|
||||
pdfioPageDictAddFont(page_dict, "F1", font);
|
||||
st = pdfioFileCreatePage(pdf, page_dict);
|
||||
|
||||
pdfioContentSetTextFont(st, "F1", 12.0);
|
||||
pdfioContentTextBegin(st);
|
||||
pdfioContentTextMoveTo(st, 72.0, 720.0);
|
||||
pdfioContentTextShow(st, false, text);
|
||||
pdfioContentTextEnd(st);
|
||||
|
||||
pdfioStreamClose(st);
|
||||
|
||||
if (pdfioFileClose(pdf))
|
||||
{
|
||||
testEnd(true);
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
testEnd(false);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'do_pdfa_tests()' - Run PDF/A generation and compliance tests.
|
||||
//
|
||||
static int // O - 0 on success, 1 on error
|
||||
do_pdfa_tests(void)
|
||||
{
|
||||
int status = 0; // Overall status
|
||||
pdfio_file_t *fail_pdf; // PDF file for failure test
|
||||
pdfio_rect_t media_box = { 0.0, 0.0, 612.0, 792.0 };
|
||||
// US Letter media box
|
||||
bool error = false; // Error flag
|
||||
|
||||
// Test creation of various PDF/A standards
|
||||
if (create_pdfa_test_file("test-pdfa-1b.pdf", "PDF/A-1b")) status = 1;
|
||||
if (create_pdfa_test_file("test-pdfa-2b.pdf", "PDF/A-2b")) status = 1;
|
||||
if (create_pdfa_test_file("test-pdfa-2u.pdf", "PDF/A-2u")) status = 1;
|
||||
if (create_pdfa_test_file("test-pdfa-3b.pdf", "PDF/A-3b")) status = 1;
|
||||
if (create_pdfa_test_file("test-pdfa-3u.pdf", "PDF/A-3u")) status = 1;
|
||||
if (create_pdfa_test_file("test-pdfa-4.pdf", "PDF/A-4")) status = 1;
|
||||
|
||||
// Test that encryption is not allowed for PDF/A files
|
||||
testBegin("Block encryption for PDF/A file");
|
||||
if ((fail_pdf = pdfioFileCreate("test-pdfa-fail.pdf", "PDF/A-1b", &media_box, NULL, (pdfio_error_cb_t)error_cb, &error)) == NULL)
|
||||
{
|
||||
testEndMessage(false, "pdfioFileCreate failed for encryption test.");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (pdfioFileSetPermissions(fail_pdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, "owner", "user"))
|
||||
{
|
||||
testEndMessage(false, "pdfioFileSetPermissions succeeded but should have failed.");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the expected outcome
|
||||
testEnd(true);
|
||||
}
|
||||
pdfioFileClose(fail_pdf);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'do_crypto_tests()' - Test the various cryptographic functions in PDFio.
|
||||
@@ -1057,6 +1161,8 @@ do_unit_tests(void)
|
||||
if (do_crypto_tests())
|
||||
return (1);
|
||||
|
||||
|
||||
|
||||
// Create a new PDF file...
|
||||
testBegin("pdfioFileCreate(\"testpdfio-out.pdf\", ...)");
|
||||
if ((outpdf = pdfioFileCreate("testpdfio-out.pdf", NULL, NULL, NULL, (pdfio_error_cb_t)error_cb, &error)) != NULL)
|
||||
@@ -1222,6 +1328,10 @@ do_unit_tests(void)
|
||||
if (read_unit_file(temppdf, num_pages, first_image, false))
|
||||
return (1);
|
||||
|
||||
// Do PDF/A tests...
|
||||
if (do_pdfa_tests())
|
||||
goto fail;
|
||||
|
||||
pdfioFileClose(inpdf);
|
||||
|
||||
return (0);
|
||||
|
||||
Reference in New Issue
Block a user