mirror of
				https://github.com/michaelrsweet/pdfio.git
				synced 2025-10-31 18:35:45 +01:00 
			
		
		
		
	Cleanup PR for PDF/A support and add documentation (Issue #122)
This commit is contained in:
		| @@ -15,6 +15,7 @@ v1.6.0 - YYYY-MM-DD | |||||||
| - Added explicit support for warning messages (Issue #118) | - Added explicit support for warning messages (Issue #118) | ||||||
| - Added `pdfioFileCreateFontObjFromData` function for embedding fonts in | - Added `pdfioFileCreateFontObjFromData` function for embedding fonts in | ||||||
|   memory (Issue #120) |   memory (Issue #120) | ||||||
|  | - Added support for specifying PDF/A versions for created PDF files (Issue #122) | ||||||
| - Added `pdfioContentBeginMarked` and `pdfioContentEndMarked` functions for | - Added `pdfioContentBeginMarked` and `pdfioContentEndMarked` functions for | ||||||
|   creating tagged PDF content (Issue #123) |   creating tagged PDF content (Issue #123) | ||||||
| - Added `pdfioFileGetLanguage` and `pdfioFileSetLanguage` functions for getting | - Added `pdfioFileGetLanguage` and `pdfioFileSetLanguage` functions for getting | ||||||
|   | |||||||
| @@ -1700,6 +1700,8 @@ pdfioFileAddOutputIntent( | |||||||
| // (ISO-8859-1 with additional characters such as the Euro symbol) subset of | // (ISO-8859-1 with additional characters such as the Euro symbol) subset of | ||||||
| // Unicode. | // Unicode. | ||||||
| // | // | ||||||
|  | // > Note: This function cannot be used when producing PDF/A files. | ||||||
|  | // | ||||||
|  |  | ||||||
| pdfio_obj_t *				// O - Font object | pdfio_obj_t *				// O - Font object | ||||||
| pdfioFileCreateFontObjFromBase( | pdfioFileCreateFontObjFromBase( | ||||||
| @@ -1709,7 +1711,8 @@ pdfioFileCreateFontObjFromBase( | |||||||
|   pdfio_dict_t	*dict;			// Font dictionary |   pdfio_dict_t	*dict;			// Font dictionary | ||||||
|   pdfio_obj_t	*obj;			// Font object |   pdfio_obj_t	*obj;			// Font object | ||||||
|  |  | ||||||
|   if (pdf && pdf->pdfa != _PDFIO_PDFA_NONE) |  | ||||||
|  |   if (pdf && pdf->profile >= _PDFIO_PROFILE_PDFA_1A && pdf->profile <= _PDFIO_PROFILE_PDFA_4) | ||||||
|   { |   { | ||||||
|     _pdfioFileError(pdf, "Base fonts are not allowed in PDF/A files; use pdfioFileCreateFontObjFromFile to embed a font."); |     _pdfioFileError(pdf, "Base fonts are not allowed in PDF/A files; use pdfioFileCreateFontObjFromFile to embed a font."); | ||||||
|     return (NULL); |     return (NULL); | ||||||
| @@ -2052,8 +2055,9 @@ pdfioFileCreateICCObjFromFile( | |||||||
| // "interpolate" parameter specifies whether to interpolate when scaling the | // "interpolate" parameter specifies whether to interpolate when scaling the | ||||||
| // image on the page. | // image on the page. | ||||||
| // | // | ||||||
| // Note: When creating an image object with alpha, a second image object is | // > Note: When creating an image object with alpha, a second image object is | ||||||
| // created to hold the "soft mask" data for the primary image. | // > created to hold the "soft mask" data for the primary image.  PDF/A-1 | ||||||
|  | // > files do not support alpha-based transparency. | ||||||
| // | // | ||||||
|  |  | ||||||
| pdfio_obj_t *				// O - Object | pdfio_obj_t *				// O - Object | ||||||
| @@ -2078,7 +2082,7 @@ pdfioFileCreateImageObjFromData( | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   if (pdf && (pdf->pdfa == _PDFIO_PDFA_1A || pdf->pdfa == _PDFIO_PDFA_1B) && alpha) |   if (pdf && pdf->profile >= _PDFIO_PROFILE_PDFA_1A && pdf->profile <= _PDFIO_PROFILE_PDFA_1B && alpha) | ||||||
|   { |   { | ||||||
|     _pdfioFileError(pdf, "Images with transparency (alpha channels) are not allowed in PDF/A-1 files."); |     _pdfioFileError(pdf, "Images with transparency (alpha channels) are not allowed in PDF/A-1 files."); | ||||||
|     return (NULL); |     return (NULL); | ||||||
| @@ -2117,9 +2121,8 @@ pdfioFileCreateImageObjFromData( | |||||||
| // the "interpolate" parameter specifies whether to interpolate when scaling the | // the "interpolate" parameter specifies whether to interpolate when scaling the | ||||||
| // image on the page. | // image on the page. | ||||||
| // | // | ||||||
| // > Note: Currently PNG support is limited to grayscale, RGB, or indexed files | // > Note: PNG files containing transparency cannot be used when producing | ||||||
| // > without interlacing or alpha.  Transparency (masking) based on color/index | // > PDF/A files. | ||||||
| // > is supported. |  | ||||||
| // | // | ||||||
|  |  | ||||||
| pdfio_obj_t *				// O - Object | pdfio_obj_t *				// O - Object | ||||||
| @@ -2750,7 +2753,7 @@ copy_png(pdfio_dict_t *dict,		// I - Dictionary | |||||||
|   depth      = png_get_bit_depth(pp, info); |   depth      = png_get_bit_depth(pp, info); | ||||||
|   color_type = png_get_color_type(pp, info); |   color_type = png_get_color_type(pp, info); | ||||||
|  |  | ||||||
|   if ((dict->pdf->pdfa == _PDFIO_PDFA_1A || dict->pdf->pdfa == _PDFIO_PDFA_1B) && (color_type & PNG_COLOR_MASK_ALPHA)) |   if (dict->pdf->profile >= _PDFIO_PROFILE_PDFA_1A && dict->pdf->profile <= _PDFIO_PROFILE_PDFA_1B && (color_type & PNG_COLOR_MASK_ALPHA)) | ||||||
|   { |   { | ||||||
|     _pdfioFileError(dict->pdf, "PNG images with transparency (alpha channels) are not allowed in PDF/A-1 files."); |     _pdfioFileError(dict->pdf, "PNG images with transparency (alpha channels) are not allowed in PDF/A-1 files."); | ||||||
|     goto finish_png; |     goto finish_png; | ||||||
| @@ -2874,7 +2877,6 @@ copy_png(pdfio_dict_t *dict,		// I - Dictionary | |||||||
|  |  | ||||||
|   if (pp && info) |   if (pp && info) | ||||||
|   { |   { | ||||||
|     png_read_end(pp, info); |  | ||||||
|     png_destroy_read_struct(&pp, &info, NULL); |     png_destroy_read_struct(&pp, &info, NULL); | ||||||
|  |  | ||||||
|     pp   = NULL; |     pp   = NULL; | ||||||
|   | |||||||
							
								
								
									
										145
									
								
								pdfio-file.c
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								pdfio-file.c
									
									
									
									
									
								
							| @@ -181,8 +181,20 @@ pdfioFileClose(pdfio_file_t *pdf)	// I - PDF file | |||||||
| // name of the PDF file to create. | // name of the PDF file to create. | ||||||
| // | // | ||||||
| // The "version" argument specifies the PDF version number for the file or | // The "version" argument specifies the PDF version number for the file or | ||||||
| // `NULL` for the default ("2.0").  The value "PCLm-1.0" can be specified to | // `NULL` for the default ("2.0").  The following values are recognized: | ||||||
| // produce the PCLm subset of PDF. | // | ||||||
|  | // - "1.3", "1.4", "1.5", "1.6", "1.7", "2.0": Generic PDF files of the | ||||||
|  | //   specified versions. | ||||||
|  | // - "PCLm-1.0": The PCLm (raster) subset of PDF supported by some printers. | ||||||
|  | // - "PDF/A-1a": PDF/A-1a:2005 | ||||||
|  | // - "PDF/A-1b": PDF/A-1b:2005 | ||||||
|  | // - "PDF/A-2a": PDF/A-2a:2011 | ||||||
|  | // - "PDF/A-2b": PDF/A-2b:2011 | ||||||
|  | // - "PDF/A-2u": PDF/A-2u:2011 | ||||||
|  | // - "PDF/A-3a": PDF/A-3a:2012 | ||||||
|  | // - "PDF/A-3b": PDF/A-3b:2012 | ||||||
|  | // - "PDF/A-3u": PDF/A-3u:2012 | ||||||
|  | // - "PDF/A-4": PDF/A-4:2020 | ||||||
| // | // | ||||||
| // The "media_box" and "crop_box" arguments specify the default MediaBox and | // The "media_box" and "crop_box" arguments specify the default MediaBox and | ||||||
| // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | ||||||
| @@ -433,9 +445,22 @@ _pdfioFileCreateObj( | |||||||
| // ``` | // ``` | ||||||
| // | // | ||||||
| // The "version" argument specifies the PDF version number for the file or | // The "version" argument specifies the PDF version number for the file or | ||||||
| // `NULL` for the default ("2.0").  Unlike @link pdfioFileCreate@ and | // `NULL` for the default ("2.0").  The following values are recognized: | ||||||
| // @link pdfioFileCreateTemporary@, it is generally not safe to pass the | // | ||||||
| // "PCLm-1.0" version string. | // - "1.3", "1.4", "1.5", "1.6", "1.7", "2.0": Generic PDF files of the | ||||||
|  | //   specified versions. | ||||||
|  | // - "PDF/A-1a": PDF/A-1a:2005 | ||||||
|  | // - "PDF/A-1b": PDF/A-1b:2005 | ||||||
|  | // - "PDF/A-2a": PDF/A-2a:2011 | ||||||
|  | // - "PDF/A-2b": PDF/A-2b:2011 | ||||||
|  | // - "PDF/A-2u": PDF/A-2u:2011 | ||||||
|  | // - "PDF/A-3a": PDF/A-3a:2012 | ||||||
|  | // - "PDF/A-3b": PDF/A-3b:2012 | ||||||
|  | // - "PDF/A-3u": PDF/A-3u:2012 | ||||||
|  | // - "PDF/A-4": PDF/A-4:2020 | ||||||
|  | // | ||||||
|  | // Unlike @link pdfioFileCreate@ and @link pdfioFileCreateTemporary@, it is | ||||||
|  | // generally not safe to pass the "PCLm-1.0" version string. | ||||||
| // | // | ||||||
| // The "media_box" and "crop_box" arguments specify the default MediaBox and | // The "media_box" and "crop_box" arguments specify the default MediaBox and | ||||||
| // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | ||||||
| @@ -591,8 +616,20 @@ pdfioFileCreateStringObj( | |||||||
| // will have a ".pdf" extension. | // will have a ".pdf" extension. | ||||||
| // | // | ||||||
| // The "version" argument specifies the PDF version number for the file or | // The "version" argument specifies the PDF version number for the file or | ||||||
| // `NULL` for the default ("2.0").  The value "PCLm-1.0" can be specified to | // `NULL` for the default ("2.0").  The following values are recognized: | ||||||
| // produce the PCLm subset of PDF. | // | ||||||
|  | // - "1.3", "1.4", "1.5", "1.6", "1.7", "2.0": Generic PDF files of the | ||||||
|  | //   specified versions. | ||||||
|  | // - "PCLm-1.0": The PCLm (raster) subset of PDF supported by some printers. | ||||||
|  | // - "PDF/A-1a": PDF/A-1a:2005 | ||||||
|  | // - "PDF/A-1b": PDF/A-1b:2005 | ||||||
|  | // - "PDF/A-2a": PDF/A-2a:2011 | ||||||
|  | // - "PDF/A-2b": PDF/A-2b:2011 | ||||||
|  | // - "PDF/A-2u": PDF/A-2u:2011 | ||||||
|  | // - "PDF/A-3a": PDF/A-3a:2012 | ||||||
|  | // - "PDF/A-3b": PDF/A-3b:2012 | ||||||
|  | // - "PDF/A-3u": PDF/A-3u:2012 | ||||||
|  | // - "PDF/A-4": PDF/A-4:2020 | ||||||
| // | // | ||||||
| // The "media_box" and "crop_box" arguments specify the default MediaBox and | // The "media_box" and "crop_box" arguments specify the default MediaBox and | ||||||
| // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | // CropBox for pages in the PDF file - if `NULL` then a default "Universal" size | ||||||
| @@ -1329,7 +1366,7 @@ pdfioFileSetPermissions( | |||||||
|   if (!pdf) |   if (!pdf) | ||||||
|     return (false); |     return (false); | ||||||
|  |  | ||||||
|   if (pdf->pdfa != _PDFIO_PDFA_NONE && encryption != PDFIO_ENCRYPTION_NONE) |   if (pdf->profile >= _PDFIO_PROFILE_PDFA_1A && pdf->profile <= _PDFIO_PROFILE_PDFA_4 && encryption != PDFIO_ENCRYPTION_NONE) | ||||||
|   { |   { | ||||||
|     _pdfioFileError(pdf, "Encryption is not allowed for PDF/A files."); |     _pdfioFileError(pdf, "Encryption is not allowed for PDF/A files."); | ||||||
|     return (false); |     return (false); | ||||||
| @@ -1520,7 +1557,8 @@ create_common( | |||||||
|   unsigned char	id_value[16];		// File ID value |   unsigned char	id_value[16];		// File ID value | ||||||
|   time_t	curtime;		// Creation date/time |   time_t	curtime;		// Creation date/time | ||||||
|   _pdfio_sha256_t ctx;			// Hashing context |   _pdfio_sha256_t ctx;			// Hashing context | ||||||
|   const char *file_version;   // Actual PDF version string |   const char	*file_version;		// PDF file version string | ||||||
|  |  | ||||||
|  |  | ||||||
|   PDFIO_DEBUG("create_common(filename=\"%s\", fd=%d, output_cb=%p, output_cbdata=%p, version=\"%s\", media_box=%p, crop_box=%p, error_cb=%p, error_cbdata=%p)\n", filename, fd, (void *)output_cb, (void *)output_cbdata, version, (void *)media_box, (void *)crop_box, (void *)error_cb, (void *)error_cbdata); |   PDFIO_DEBUG("create_common(filename=\"%s\", fd=%d, output_cb=%p, output_cbdata=%p, version=\"%s\", media_box=%p, crop_box=%p, error_cb=%p, error_cbdata=%p)\n", filename, fd, (void *)output_cb, (void *)output_cbdata, version, (void *)media_box, (void *)crop_box, (void *)error_cb, (void *)error_cbdata); | ||||||
|  |  | ||||||
| @@ -1528,12 +1566,10 @@ create_common( | |||||||
|   if (!filename || (fd < 0 && !output_cb)) |   if (!filename || (fd < 0 && !output_cb)) | ||||||
|     return (NULL); |     return (NULL); | ||||||
|  |  | ||||||
|  |  | ||||||
|   if (!error_cb) |   if (!error_cb) | ||||||
|   { |   { | ||||||
|     error_cb     = _pdfioFileDefaultError; |     error_cb     = _pdfioFileDefaultError; | ||||||
|     error_cbdata = NULL; |     error_cbdata = NULL; | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Allocate a PDF file structure... |   // Allocate a PDF file structure... | ||||||
| @@ -1557,47 +1593,53 @@ create_common( | |||||||
|   pdf->filename    = strdup(filename); |   pdf->filename    = strdup(filename); | ||||||
|  |  | ||||||
|   if (!version) |   if (!version) | ||||||
|   { |  | ||||||
|     version = "2.0"; |     version = "2.0"; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (!strncmp(version, "PDF/A-1", 7)) |   if (!strncmp(version, "PDF/A-1", 7)) | ||||||
|   { |   { | ||||||
|     file_version = "1.4"; |     file_version = "1.4"; | ||||||
|  |  | ||||||
|     if (version[7] == 'a') |     if (version[7] == 'a') | ||||||
|       pdf->pdfa = _PDFIO_PDFA_1A; |       pdf->profile = _PDFIO_PROFILE_PDFA_1A; | ||||||
|     else |     else | ||||||
|       pdf->pdfa = _PDFIO_PDFA_1B; // Default to 'b' |       pdf->profile = _PDFIO_PROFILE_PDFA_1B; // Default to 'b' | ||||||
|   } |   } | ||||||
|   else if (!strncmp(version, "PDF/A-2", 7)) |   else if (!strncmp(version, "PDF/A-2", 7)) | ||||||
|   { |   { | ||||||
|     file_version = "1.7"; |     file_version = "1.7"; | ||||||
|  |  | ||||||
|     if (version[7] == 'a') |     if (version[7] == 'a') | ||||||
|       pdf->pdfa = _PDFIO_PDFA_2A; |       pdf->profile = _PDFIO_PROFILE_PDFA_2A; | ||||||
|     else if (version[7] == 'u') |     else if (version[7] == 'u') | ||||||
|       pdf->pdfa = _PDFIO_PDFA_2U; |       pdf->profile = _PDFIO_PROFILE_PDFA_2U; | ||||||
|     else |     else | ||||||
|       pdf->pdfa = _PDFIO_PDFA_2B; // Default to 'b' |       pdf->profile = _PDFIO_PROFILE_PDFA_2B; // Default to 'b' | ||||||
|   } |   } | ||||||
|   else if (!strncmp(version, "PDF/A-3", 7)) |   else if (!strncmp(version, "PDF/A-3", 7)) | ||||||
|   { |   { | ||||||
|     file_version = "1.7"; |     file_version = "1.7"; | ||||||
|  |  | ||||||
|     if (version[7] == 'a') |     if (version[7] == 'a') | ||||||
|       pdf->pdfa = _PDFIO_PDFA_3A; |       pdf->profile = _PDFIO_PROFILE_PDFA_3A; | ||||||
|     else if (version[7] == 'u') |     else if (version[7] == 'u') | ||||||
|       pdf->pdfa = _PDFIO_PDFA_3U; |       pdf->profile = _PDFIO_PROFILE_PDFA_3U; | ||||||
|     else |     else | ||||||
|       pdf->pdfa = _PDFIO_PDFA_3B; // Default to 'b' |       pdf->profile = _PDFIO_PROFILE_PDFA_3B; // Default to 'b' | ||||||
|   } |   } | ||||||
|   else if (!strncmp(version, "PDF/A-4", 7)) |   else if (!strncmp(version, "PDF/A-4", 7)) | ||||||
|   { |   { | ||||||
|     file_version = "2.0"; |     file_version = "2.0"; | ||||||
|     pdf->pdfa = _PDFIO_PDFA_4; |     pdf->profile = _PDFIO_PROFILE_PDFA_4; | ||||||
|  |   } | ||||||
|  |   else if (!strncmp(version, "PCLm-", 5)) | ||||||
|  |   { | ||||||
|  |     file_version = "1.4"; | ||||||
|  |     pdf->profile = _PDFIO_PROFILE_PCLM; | ||||||
|   } |   } | ||||||
|   else |   else | ||||||
|   { |   { | ||||||
|     file_version = version; |     file_version = version; | ||||||
|     pdf->pdfa = _PDFIO_PDFA_NONE; |     pdf->profile = _PDFIO_PROFILE_NONE; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   pdf->version     = strdup(file_version); |   pdf->version     = strdup(file_version); | ||||||
| @@ -1630,19 +1672,17 @@ create_common( | |||||||
|     pdf->crop_box.y2 = 11.0f * 72.0f; |     pdf->crop_box.y2 = 11.0f * 72.0f; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Write the PDF header (special case for PCLm, otherwise standard/PDF-A header) |   // Write the PDF header (special case for PCLm, otherwise standard header) | ||||||
|   if (!strncmp(version, "PCLm-", 5)) |   if (pdf->profile == _PDFIO_PROFILE_PCLM) | ||||||
|   { |   { | ||||||
|     if (!_pdfioFilePrintf(pdf, "%%PDF-1.4\n%%%s\n", version)) |     if (!_pdfioFilePrintf(pdf, "%%PDF-1.4\n%%%s\n", version)) | ||||||
|       goto error; |       goto error; | ||||||
|   } |   } | ||||||
|   else |   else if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", pdf->version)) | ||||||
|   { |   { | ||||||
|     if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", pdf->version)) |     goto error; | ||||||
|       goto error; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|    |  | ||||||
|   // Create the pages object... |   // Create the pages object... | ||||||
|   if ((dict = pdfioDictCreate(pdf)) == NULL) |   if ((dict = pdfioDictCreate(pdf)) == NULL) | ||||||
|     goto error; |     goto error; | ||||||
| @@ -2735,43 +2775,30 @@ write_metadata(pdfio_file_t *pdf)	// I - PDF file | |||||||
|     status &= pdfioStreamPrintf(st, "            <dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">%H</rdf:li></rdf:Alt></dc:description>\n", value); |     status &= pdfioStreamPrintf(st, "            <dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">%H</rdf:li></rdf:Alt></dc:description>\n", value); | ||||||
|   status &= pdfioStreamPuts(st, "        </rdf:Description>\n"); |   status &= pdfioStreamPuts(st, "        </rdf:Description>\n"); | ||||||
|  |  | ||||||
|   // TODO: Need a better way to choose the output profile - something that lets |   if (pdf->profile >= _PDFIO_PROFILE_PDFA_1A && pdf->profile <= _PDFIO_PROFILE_PDFA_4) | ||||||
|   // us choose the base PDF version and PDF/A, PDF/E, PDF/X, etc. |  | ||||||
| #if 0 |  | ||||||
|   status &= pdfioStreamPuts(st, "        <rdf:Description rdf:about=\"\" xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"); |  | ||||||
|   status &= pdfioStreamPuts(st, "            <pdfaid:conformance>A</pdfaid:conformance>\n"); |  | ||||||
|   status &= pdfioStreamPuts(st, "            <pdfaid:part>1</pdfaid:part>\n"); |  | ||||||
|   status &= pdfioStreamPuts(st, "        </rdf:Description>\n"); |  | ||||||
| #endif // 0 |  | ||||||
|  |  | ||||||
|   if (pdf->pdfa != _PDFIO_PDFA_NONE) |  | ||||||
|   { |   { | ||||||
|    static const char * const pdfa_versions[] =  |     static const char * const pdfa_versions[] = | ||||||
|    { |     { | ||||||
|      "1A", // _PDFIO_PDFA_1A |       "1A", // _PDFIO_PROFILE_PDFA_1A | ||||||
|      "1B", // _PDFIO_PDFA_1B |       "1B", // _PDFIO_PROFILE_PDFA_1B | ||||||
|      "2A", // _PDFIO_PDFA_2A |       "2A", // _PDFIO_PROFILE_PDFA_2A | ||||||
|      "2B", // _PDFIO_PDFA_2B |       "2B", // _PDFIO_PROFILE_PDFA_2B | ||||||
|      "2U", // _PDFIO_PDFA_2U |       "2U", // _PDFIO_PROFILE_PDFA_2U | ||||||
|      "3A", // _PDFIO_PDFA_3A |       "3A", // _PDFIO_PROFILE_PDFA_3A | ||||||
|      "3B", // _PDFIO_PDFA_3B |       "3B", // _PDFIO_PROFILE_PDFA_3B | ||||||
|      "3U", // _PDFIO_PDFA_3U |       "3U", // _PDFIO_PROFILE_PDFA_3U | ||||||
|      "4",  // _PDFIO_PDFA_4 |       "4",  // _PDFIO_PROFILE_PDFA_4 | ||||||
|     }; |     }; | ||||||
|    const char *version_info = pdfa_versions[pdf->pdfa - _PDFIO_PDFA_1A]; |  | ||||||
|    const char *conformance; |     const char *info = pdfa_versions[pdf->profile - _PDFIO_PROFILE_PDFA_1A]; | ||||||
|    conformance = version_info + 1; |  | ||||||
|  |  | ||||||
|     status &= pdfioStreamPuts(st, "     <rdf:Description rdf:about=\"\" xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"); |     status &= pdfioStreamPuts(st, "     <rdf:Description rdf:about=\"\" xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"); | ||||||
|     status &= pdfioStreamPrintf(st, "       <pdfaid:part>%c</pdfaid:part>\n",version_info[0]); |     status &= pdfioStreamPrintf(st, "       <pdfaid:part>%c</pdfaid:part>\n", *info); | ||||||
|     if (*conformance) |     if (info[1]) | ||||||
|       status &= pdfioStreamPrintf(st, "       <pdfaid:conformance>%s</pdfaid:conformance>\n", conformance); |        status &= pdfioStreamPrintf(st, "       <pdfaid:conformance>%s</pdfaid:conformance>\n", info + 1); | ||||||
|     status &= pdfioStreamPuts(st, " </rdf:Description>\n"); |     status &= pdfioStreamPuts(st, " </rdf:Description>\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   status &= pdfioStreamPuts(st, "    </rdf:RDF>\n"); |   status &= pdfioStreamPuts(st, "    </rdf:RDF>\n"); | ||||||
|   status &= pdfioStreamPuts(st, "</x:xmpmeta>\n"); |   status &= pdfioStreamPuts(st, "</x:xmpmeta>\n"); | ||||||
|   status &= pdfioStreamPuts(st, "<?xpacket end=\"r\"?>\n"); |   status &= pdfioStreamPuts(st, "<?xpacket end=\"r\"?>\n"); | ||||||
|   | |||||||
| @@ -105,20 +105,6 @@ typedef enum _pdfio_mode_e		// Read/write mode | |||||||
|   _PDFIO_MODE_WRITE			// Write a PDF file |   _PDFIO_MODE_WRITE			// Write a PDF file | ||||||
| } _pdfio_mode_t; | } _pdfio_mode_t; | ||||||
|  |  | ||||||
| typedef enum _pdfio_pdfa_e    // PDF/A version constants |  | ||||||
| { |  | ||||||
|   _PDFIO_PDFA_NONE = 0,   // Not a PDF/A file |  | ||||||
|   _PDFIO_PDFA_1A,         // PDF/A-1a:2005 |  | ||||||
|   _PDFIO_PDFA_1B,         // PDF/A-1b:2005 |  | ||||||
|   _PDFIO_PDFA_2A,         // PDF/A-2a:2011 |  | ||||||
|   _PDFIO_PDFA_2B,         // PDF/A-2b:20011 |  | ||||||
|   _PDFIO_PDFA_2U,         // PDF/A-2u:2011 |  | ||||||
|   _PDFIO_PDFA_3A,         // PDF/A-3a:2012 |  | ||||||
|   _PDFIO_PDFA_3B,         // PDF/A-3b:2012 |  | ||||||
|   _PDFIO_PDFA_3U,         // PDF/A-3u:2012 |  | ||||||
|   _PDFIO_PDFA_4,          // PDF/A-4:2020 |  | ||||||
| } _pdfio_pdfa_t; |  | ||||||
|  |  | ||||||
| typedef enum _pdfio_predictor_e		// PNG predictor constants | typedef enum _pdfio_predictor_e		// PNG predictor constants | ||||||
| { | { | ||||||
|   _PDFIO_PREDICTOR_NONE = 1,		// No predictor (default) |   _PDFIO_PREDICTOR_NONE = 1,		// No predictor (default) | ||||||
| @@ -131,6 +117,21 @@ typedef enum _pdfio_predictor_e		// PNG predictor constants | |||||||
|   _PDFIO_PREDICTOR_PNG_AUTO = 15	// PNG "auto" predictor (currently mapped to Paeth) |   _PDFIO_PREDICTOR_PNG_AUTO = 15	// PNG "auto" predictor (currently mapped to Paeth) | ||||||
| } _pdfio_predictor_t; | } _pdfio_predictor_t; | ||||||
|  |  | ||||||
|  | typedef enum _pdfio_profile_e		// PDF profile constants | ||||||
|  | { | ||||||
|  |   _PDFIO_PROFILE_NONE = 0,		// Base PDF file | ||||||
|  |   _PDFIO_PROFILE_PCLM,			// PCLm (PDF raster) file | ||||||
|  |   _PDFIO_PROFILE_PDFA_1A,		// PDF/A-1a:2005 | ||||||
|  |   _PDFIO_PROFILE_PDFA_1B,		// PDF/A-1b:2005 | ||||||
|  |   _PDFIO_PROFILE_PDFA_2A,		// PDF/A-2a:2011 | ||||||
|  |   _PDFIO_PROFILE_PDFA_2B,		// PDF/A-2b:2011 | ||||||
|  |   _PDFIO_PROFILE_PDFA_2U,		// PDF/A-2u:2011 | ||||||
|  |   _PDFIO_PROFILE_PDFA_3A,		// PDF/A-3a:2012 | ||||||
|  |   _PDFIO_PROFILE_PDFA_3B,		// PDF/A-3b:2012 | ||||||
|  |   _PDFIO_PROFILE_PDFA_3U,		// PDF/A-3u:2012 | ||||||
|  |   _PDFIO_PROFILE_PDFA_4			// PDF/A-4:2020 | ||||||
|  | } _pdfio_profile_t; | ||||||
|  |  | ||||||
| typedef ssize_t (*_pdfio_tconsume_cb_t)(void *data, size_t bytes); | typedef ssize_t (*_pdfio_tconsume_cb_t)(void *data, size_t bytes); | ||||||
| typedef ssize_t (*_pdfio_tpeek_cb_t)(void *data, void *buffer, size_t bytes); | typedef ssize_t (*_pdfio_tpeek_cb_t)(void *data, void *buffer, size_t bytes); | ||||||
|  |  | ||||||
| @@ -253,7 +254,7 @@ struct _pdfio_file_s			// PDF file structure | |||||||
|   unsigned char	file_id[32];		// File identifier bytes |   unsigned char	file_id[32];		// File identifier bytes | ||||||
|   struct lconv	*loc;			// Locale data |   struct lconv	*loc;			// Locale data | ||||||
|   char		*version;		// Version number |   char		*version;		// Version number | ||||||
|   _pdfio_pdfa_t pdfa;       // PDF/A conformance |   _pdfio_profile_t profile;		// PDF profile, if any | ||||||
|   pdfio_rect_t	media_box,		// Default MediaBox value |   pdfio_rect_t	media_box,		// Default MediaBox value | ||||||
| 		crop_box;		// Default CropBox value | 		crop_box;		// Default CropBox value | ||||||
|   _pdfio_mode_t	mode;			// Read/write mode |   _pdfio_mode_t	mode;			// Read/write mode | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								testfiles/pdfio-rgba.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								testfiles/pdfio-rgba.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 15 KiB | 
							
								
								
									
										304
									
								
								testpdfio.c
									
									
									
									
									
								
							
							
						
						
									
										304
									
								
								testpdfio.c
									
									
									
									
									
								
							| @@ -28,6 +28,7 @@ | |||||||
| // | // | ||||||
|  |  | ||||||
| static int	do_crypto_tests(void); | static int	do_crypto_tests(void); | ||||||
|  | static int	do_pdfa_tests(void); | ||||||
| static int	do_test_file(const char *filename, int objnum, const char *password, bool verbose); | static int	do_test_file(const char *filename, int objnum, const char *password, bool verbose); | ||||||
| static int	do_unit_tests(void); | 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 int	draw_image(pdfio_stream_t *st, const char *name, double x, double y, double w, double h, const char *label); | ||||||
| @@ -48,11 +49,11 @@ 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 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_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_jpeg_test(pdfio_file_t *pdf, const char *title, int number, pdfio_obj_t *font, pdfio_obj_t *image); | ||||||
|  | static int	write_pdfa_file(const char *filename, const char *pdfa_version); | ||||||
| static int	write_png_tests(pdfio_file_t *pdf, int number, pdfio_obj_t *font); | 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_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	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. | // 'main()' - Main entry for test program. | ||||||
| @@ -129,108 +130,6 @@ main(int  argc,				// I - Number of command-line arguments | |||||||
|   return (ret); |   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 |  | ||||||
|   bool		error = false;		// Error flag |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   testBegin("pdfioFileCreate(%s)", pdfa_version); |  | ||||||
|  |  | ||||||
|   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); |  | ||||||
|   pdfioContentTextShowf(st, false, "This is a compliance test for %s.", pdfa_version); |  | ||||||
|   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 |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-1b.pdf", "PDF/A-1b"); |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-2b.pdf", "PDF/A-2b"); |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-2u.pdf", "PDF/A-2u"); |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-3b.pdf", "PDF/A-3b"); |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-3u.pdf", "PDF/A-3u"); |  | ||||||
|   status |= create_pdfa_test_file("testpdfio-pdfa-4.pdf", "PDF/A-4"); |  | ||||||
|  |  | ||||||
|   // Test that encryption is not allowed for PDF/A files |  | ||||||
|   testBegin("pdfioFileCreate(testpdfio-pdfa-rc4.pdf)"); |  | ||||||
|   if ((fail_pdf = pdfioFileCreate("testpdfio-pdfa-rc4.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, "encryption allowed on PDF/A file"); |  | ||||||
|     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. | // 'do_crypto_tests()' - Test the various cryptographic functions in PDFio. | ||||||
| // | // | ||||||
| @@ -474,6 +373,56 @@ do_crypto_tests(void) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // | ||||||
|  | // '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	*pdf;			// PDF file for encryption test | ||||||
|  |   bool		error = false;		// Error flag | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   // Test creation of files using various PDF/A standards | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-1a.pdf", "PDF/A-1a"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-1b.pdf", "PDF/A-1b"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-2a.pdf", "PDF/A-2a"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-2b.pdf", "PDF/A-2b"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-2u.pdf", "PDF/A-2u"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-3a.pdf", "PDF/A-3a"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-3b.pdf", "PDF/A-3b"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-3u.pdf", "PDF/A-3u"); | ||||||
|  |   status |= write_pdfa_file("testpdfio-pdfa-4.pdf", "PDF/A-4"); | ||||||
|  |  | ||||||
|  |   // Test that encryption is not allowed for PDF/A files | ||||||
|  |   testBegin("pdfioFileCreate(testpdfio-pdfa-rc4.pdf)"); | ||||||
|  |   if ((pdf = pdfioFileCreate("testpdfio-pdfa-rc4.pdf", "PDF/A-1b", /*media_box*/NULL, /*crop_box*/NULL, (pdfio_error_cb_t)error_cb, &error)) == NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     return (1); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   testBegin("pdfioFileSetPermissions(PDFIO_ENCRYPTION_RC4_128)"); | ||||||
|  |   if (pdfioFileSetPermissions(pdf, PDFIO_PERMISSION_ALL, PDFIO_ENCRYPTION_RC4_128, "owner", "user")) | ||||||
|  |   { | ||||||
|  |     testEndMessage(false, "incorrectly allowed encryption"); | ||||||
|  |     status = 1; | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |   { | ||||||
|  |     testEndMessage(true, "correctly prevented encryption"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   pdfioFileClose(pdf); | ||||||
|  |  | ||||||
|  |   return (status); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // | // | ||||||
| // 'do_test_file()' - Try loading a PDF file and listing pages and objects. | // 'do_test_file()' - Try loading a PDF file and listing pages and objects. | ||||||
| // | // | ||||||
| @@ -1326,7 +1275,6 @@ do_unit_tests(void) | |||||||
|   if (read_unit_file(temppdf, num_pages, first_image, false)) |   if (read_unit_file(temppdf, num_pages, first_image, false)) | ||||||
|     return (1); |     return (1); | ||||||
|  |  | ||||||
|  |  | ||||||
|   pdfioFileClose(inpdf); |   pdfioFileClose(inpdf); | ||||||
|  |  | ||||||
|   // Do PDF/A tests... |   // Do PDF/A tests... | ||||||
| @@ -3483,6 +3431,152 @@ write_jpeg_test(pdfio_file_t *pdf,	// I - PDF file | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // | ||||||
|  | // 'write_pdfa_file()' - Generate a simple PDF/A file. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | static int				// O - Exit status | ||||||
|  | write_pdfa_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") | ||||||
|  | { | ||||||
|  |   int		status = 1;		// Exit status | ||||||
|  |   pdfio_file_t	*pdf;			// Output PDF file | ||||||
|  |   pdfio_obj_t	*font;			// Font object | ||||||
|  |   pdfio_obj_t	*color_jpg,		// JPEG file | ||||||
|  | 		*pdfio_png;		// PNG file with transparency | ||||||
|  |   pdfio_dict_t	*page_dict;		// Page dictionary | ||||||
|  |   pdfio_stream_t *st;			// Page content stream | ||||||
|  |   bool		error = false;		// Error flag | ||||||
|  |   double	width,			// Width of image | ||||||
|  | 		height;			// Height of image | ||||||
|  |   double	swidth,			// Scaled width | ||||||
|  | 		sheight,		// Scaled height | ||||||
|  | 		tx,			// X offset | ||||||
|  | 		ty;			// Y offset | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   testBegin("pdfioFileCreate(%s)", filename); | ||||||
|  |  | ||||||
|  |   if ((pdf = pdfioFileCreate(filename, pdfa_version, /*media_box*/NULL, /*crop_box*/NULL, (pdfio_error_cb_t)error_cb, &error)) == NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     return (1); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   // Embed a base font, which are not allowed for PDF/A | ||||||
|  |   testBegin("pdfioFileCreateFontObjFromBase(Helvetica)"); | ||||||
|  |   if ((font = pdfioFileCreateFontObjFromBase(pdf, "Helvetica")) != NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     goto done; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   // Embed a font, which is required for PDF/A | ||||||
|  |   testBegin("pdfioFileCreateFontObjFromFile(testfiles/OpenSans-Regular.ttf)"); | ||||||
|  |   if ((font = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", false)) == NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     goto done; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   // Try embedding two images, one with alpha and one without... | ||||||
|  |   testBegin("pdfioFileCreateImageObjFromFile(testfiles/color.jpg)"); | ||||||
|  |   if ((color_jpg = pdfioFileCreateImageObjFromFile(pdf, "testfiles/color.jpg", true)) == NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     goto done; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   testBegin("pdfioFileCreateImageObjFromFile(testfiles/pdfio-rgba.png)"); | ||||||
|  |   pdfio_png = pdfioFileCreateImageObjFromFile(pdf, "testfiles/pdfio-rgba.png", false); | ||||||
|  |  | ||||||
|  |   if ((pdfio_png != NULL && !strncmp(pdfa_version, "PDF/A-1", 7)) || (pdfio_png == NULL && strncmp(pdfa_version, "PDF/A-1", 7))) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     goto done; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   if (!pdfio_png) | ||||||
|  |   { | ||||||
|  |     testBegin("pdfioFileCreateImageObjFromFile(testfiles/pdfio-color.png)"); | ||||||
|  |     if ((pdfio_png = pdfioFileCreateImageObjFromFile(pdf, "testfiles/pdfio-color.png", false)) == NULL) | ||||||
|  |     { | ||||||
|  |       testEnd(false); | ||||||
|  |       goto done; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     testEnd(true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Create a page... | ||||||
|  |   page_dict = pdfioDictCreate(pdf); | ||||||
|  |   pdfioPageDictAddFont(page_dict, "F1", font); | ||||||
|  |   pdfioPageDictAddImage(page_dict, "I1", pdfio_png); | ||||||
|  |   pdfioPageDictAddImage(page_dict, "I2", color_jpg); | ||||||
|  |  | ||||||
|  |   testBegin("pdfioFileCreatePage()"); | ||||||
|  |   if ((st = pdfioFileCreatePage(pdf, page_dict)) == NULL) | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     goto done; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   testEnd(true); | ||||||
|  |  | ||||||
|  |   pdfioContentSetTextFont(st, "F1", 18.0); | ||||||
|  |   pdfioContentTextBegin(st); | ||||||
|  |   pdfioContentTextMoveTo(st, 72.0, 720.0); | ||||||
|  |   pdfioContentTextShowf(st, false, "This is a %s compliance test page.", pdfa_version); | ||||||
|  |   pdfioContentDrawImage(st, "IM1", 36.0, 720.0, 18.0, 18.0); | ||||||
|  |  | ||||||
|  |   width  = pdfioImageGetWidth(color_jpg); | ||||||
|  |   height = pdfioImageGetHeight(color_jpg); | ||||||
|  |  | ||||||
|  |   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 * (720.0 - sheight); | ||||||
|  |  | ||||||
|  |   pdfioContentDrawImage(st, "IM2", tx, ty, swidth, sheight); | ||||||
|  |   pdfioContentTextEnd(st); | ||||||
|  |  | ||||||
|  |   pdfioStreamClose(st); | ||||||
|  |  | ||||||
|  |   status = 0; | ||||||
|  |  | ||||||
|  |   done: | ||||||
|  |  | ||||||
|  |   testBegin("pdfioFileClose()"); | ||||||
|  |   if (pdfioFileClose(pdf)) | ||||||
|  |   { | ||||||
|  |     testEnd(true); | ||||||
|  |     return (status); | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |   { | ||||||
|  |     testEnd(false); | ||||||
|  |     return (1); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // | // | ||||||
| // 'write_png_tests()' - Write pages of PNG test images. | // 'write_png_tests()' - Write pages of PNG test images. | ||||||
| // | // | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user