Skip to content

Commit

Permalink
Merge pull request #9 from orouge/master
Browse files Browse the repository at this point in the history
Updated hpdf_pdfa.c file
  • Loading branch information
tony2001 committed May 21, 2012
2 parents a05cbf8 + 3c03661 commit bc755fa
Showing 1 changed file with 173 additions and 71 deletions.
244 changes: 173 additions & 71 deletions src/hpdf_pdfa.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,33 @@
#include <string.h>


#define XMP_HEADER "<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?><?adobe-xap-filters esc=\"CRLF\"?><x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>"
#define XMP_FOOTER "</rdf:RDF></x:xmpmeta><?xpacket end='w'?>"
#define XMP_PDFA1A "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='A'/>"
#define XMP_PDFA1B "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='B'/>"
#define XMP_PRODUCER_STARTTAG "<rdf:Description rdf:about='' xmlns:pdf='http://ns.adobe.com/pdf/1.3/' pdf:Producer='"
#define XMP_PRODUCER_ENDTAG "'/>"
#define XMP_INFODATA_STARTTAG "<rdf:Description rdf:about='' xmlns:xmp='http://ns.adobe.com/xap/1.0/'>"
#define XMP_INFODATA_ENDTAG "</rdf:Description>"
#define XMP_CREATE_DATE_STARTTAG "<xmp:CreateDate>"
#define XMP_CREATE_DATE_ENDTAG "</xmp:CreateDate>"
#define XMP_MOD_DATE_STARTTAG "<xmp:ModifyDate>"
#define XMP_MOD_DATE_ENDTAG "</xmp:ModifyDate>"
#define HEADER "<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?><x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>"
#define DC_HEADER "<rdf:Description xmlns:dc='http://purl.org/dc/elements/1.1/' rdf:about=''>"
#define DC_TITLE_STARTTAG "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">"
#define DC_TITLE_ENDTAG "</rdf:li></rdf:Alt></dc:title>"
#define DC_CREATOR_STARTTAG "<dc:creator><rdf:Seq><rdf:li>"
#define DC_CREATOR_ENDTAG "</rdf:li></rdf:Seq></dc:creator>"
#define DC_DESCRIPTION_STARTTAG "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">"
#define DC_DESCRIPTION_ENDTAG "</rdf:li></rdf:Alt></dc:description>"
#define DC_FOOTER "</rdf:Description>"
#define XMP_HEADER "<rdf:Description xmlns:xmp='http://ns.adobe.com/xap/1.0/' rdf:about=''>"
#define XMP_CREATORTOOL_STARTTAG "<xmp:CreatorTool>"
#define XMP_CREATORTOOL_ENDTAG "</xmp:CreatorTool>"
#define XMP_CREATORTOOL_ENDTAG "</xmp:CreatorTool>"
#define XMP_CREATE_DATE_STARTTAG "<xmp:CreateDate>"
#define XMP_CREATE_DATE_ENDTAG "</xmp:CreateDate>"
#define XMP_MOD_DATE_STARTTAG "<xmp:ModifyDate>"
#define XMP_MOD_DATE_ENDTAG "</xmp:ModifyDate>"
#define XMP_FOOTER "</rdf:Description>"
#define PDF_HEADER "<rdf:Description xmlns:pdf='http://ns.adobe.com/pdf/1.3/' rdf:about=''>"
#define PDF_KEYWORDS_STARTTAG "<pdf:Keywords>"
#define PDF_KEYWORDS_ENDTAG "</pdf:Keywords>"
#define PDF_PRODUCER_STARTTAG "<pdf:Producer>"
#define PDF_PRODUCER_ENDTAG "</pdf:Producer>"
#define PDF_FOOTER "</rdf:Description>"
#define PDFAID_PDFA1A "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='A'/>"
#define PDFAID_PDFA1B "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='B'/>"
#define FOOTER "</rdf:RDF></x:xmpmeta><?xpacket end='w'?>"


/*
* Convert date in PDF specific format: D:YYYYMMDDHHmmSS
Expand Down Expand Up @@ -100,12 +113,21 @@ HPDF_STATUS ConvertDateToXMDate(HPDF_Stream stream, const char *pDate)
pDate+=2;
/* Write +... */
if(pDate[0]==0) {
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"+0:00", 5);
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"Z", 1);
return ret;
}
if(pDate[0]=='+'||pDate[0]=='-') {
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, strlen(pDate));
return ret;
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 3);
if (ret != HPDF_OK)
return ret;
pDate+=4;
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)":", 1);
if (ret != HPDF_OK)
return ret;
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
if (ret != HPDF_OK)
return ret;
return ret;
}
return HPDF_SetError (stream->error, HPDF_INVALID_PARAMETER, 0);
}
Expand All @@ -117,68 +139,148 @@ HPDF_PDFA_SetPDFAConformance (HPDF_Doc pdf,HPDF_PDFAType pdfatype)
{
HPDF_OutputIntent xmp;
HPDF_STATUS ret;

const char *dc_title = NULL;
const char *dc_creator = NULL;
const char *dc_description = NULL;

const char *xmp_CreatorTool = NULL;
const char *xmp_CreateDate = NULL;
const char *xmp_ModifyDate = NULL;

const char *pdf_Keywords = NULL;
const char *pdf_Producer = NULL;

const char *info = NULL;

if (!HPDF_HasDoc(pdf)) {
return HPDF_INVALID_DOCUMENT;
}

xmp = HPDF_DictStream_New(pdf->mmgr,pdf->xref);
if (!xmp) {
return HPDF_INVALID_STREAM;
}

HPDF_Dict_AddName(xmp,"Type","Metadata");
HPDF_Dict_AddName(xmp,"SubType","XML");

ret = HPDF_OK;
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_HEADER);

ret += HPDF_Stream_WriteStr(xmp->stream, XMP_PRODUCER_STARTTAG);

info = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_PRODUCER);
ret += HPDF_Stream_WriteStr(xmp->stream, info);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_PRODUCER_ENDTAG);

/* Add CreateDate, ModifyDate, and CreatorTool */
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_INFODATA_STARTTAG);
info = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATION_DATE);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_STARTTAG);
/* Convert date to XMP compatible format */
ret += ConvertDateToXMDate(xmp->stream, info);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_ENDTAG);

info = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_MOD_DATE);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_STARTTAG);
ret += ConvertDateToXMDate(xmp->stream, info);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_ENDTAG);

info = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATOR);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, info);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_ENDTAG);

ret += HPDF_Stream_WriteStr(xmp->stream, XMP_INFODATA_ENDTAG);

switch(pdfatype) {
case HPDF_PDFA_1A:
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_PDFA1A);
break;
case HPDF_PDFA_1B:
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_PDFA1B);
break;
}
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_FOOTER);
dc_title = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_TITLE);
dc_creator = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_AUTHOR);
dc_description = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_SUBJECT);

if (ret != HPDF_OK) {
return HPDF_INVALID_STREAM;
}

if ((ret = HPDF_Dict_Add(pdf->catalog, "Metadata", xmp)) != HPDF_OK) {
return ret;
xmp_CreateDate = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATION_DATE);
xmp_ModifyDate = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_MOD_DATE);
xmp_CreatorTool = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATOR);

pdf_Keywords = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_KEYWORDS);
pdf_Producer = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_PRODUCER);

if((dc_title != NULL) || (dc_creator != NULL) || (dc_description != NULL)
|| (xmp_CreateDate != NULL) || (xmp_ModifyDate != NULL) || (xmp_CreatorTool != NULL)
|| (pdf_Keywords != NULL)) {

xmp = HPDF_DictStream_New(pdf->mmgr,pdf->xref);
if (!xmp) {
return HPDF_INVALID_STREAM;
}

/* Update the PDF number version */
pdf->pdf_version = HPDF_VER_14;

HPDF_Dict_AddName(xmp,"Type","Metadata");
HPDF_Dict_AddName(xmp,"SubType","XML");

ret = HPDF_OK;
ret += HPDF_Stream_WriteStr(xmp->stream, HEADER);

/* Add the dc block */
if((dc_title != NULL) || (dc_creator != NULL) || (dc_description != NULL)) {
ret += HPDF_Stream_WriteStr(xmp->stream, DC_HEADER);

if(dc_title != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, DC_TITLE_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, dc_title);
ret += HPDF_Stream_WriteStr(xmp->stream, DC_TITLE_ENDTAG);
}

if(dc_creator != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, DC_CREATOR_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, dc_creator);
ret += HPDF_Stream_WriteStr(xmp->stream, DC_CREATOR_ENDTAG);
}

if(dc_description != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, DC_DESCRIPTION_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, dc_description);
ret += HPDF_Stream_WriteStr(xmp->stream, DC_DESCRIPTION_ENDTAG);
}

ret += HPDF_Stream_WriteStr(xmp->stream, DC_FOOTER);
}

/* Add the xmp block */
if((xmp_CreateDate != NULL) || (xmp_ModifyDate != NULL) || (xmp_CreatorTool != NULL)) {
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_HEADER);

/* Add CreateDate, ModifyDate, and CreatorTool */
if(xmp_CreatorTool != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, xmp_CreatorTool);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_ENDTAG);
}

if(xmp_CreateDate != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_STARTTAG);
/* Convert date to XMP compatible format */
ret += ConvertDateToXMDate(xmp->stream, xmp_CreateDate);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_ENDTAG);
}

if(xmp_ModifyDate != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_STARTTAG);
ret += ConvertDateToXMDate(xmp->stream, xmp_ModifyDate);
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_ENDTAG);
}

ret += HPDF_Stream_WriteStr(xmp->stream, XMP_FOOTER);
}

/* Add the pdf block */
if((pdf_Keywords != NULL) || (pdf_Producer != NULL)) {
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_HEADER);

if(pdf_Keywords != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_KEYWORDS_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, pdf_Keywords);
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_KEYWORDS_ENDTAG);
}

if(pdf_Producer != NULL) {
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_PRODUCER_STARTTAG);
ret += HPDF_Stream_WriteStr(xmp->stream, pdf_Producer);
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_PRODUCER_ENDTAG);
}

ret += HPDF_Stream_WriteStr(xmp->stream, PDF_FOOTER);
}

/* Add the pdfaid block */
switch(pdfatype) {
case HPDF_PDFA_1A:
ret += HPDF_Stream_WriteStr(xmp->stream, PDFAID_PDFA1A);
break;
case HPDF_PDFA_1B:
ret += HPDF_Stream_WriteStr(xmp->stream, PDFAID_PDFA1B);
break;
}

ret += HPDF_Stream_WriteStr(xmp->stream, FOOTER);

if (ret != HPDF_OK) {
return HPDF_INVALID_STREAM;
}

if ((ret = HPDF_Dict_Add(pdf->catalog, "Metadata", xmp)) != HPDF_OK) {
return ret;
}

return HPDF_PDFA_GenerateID(pdf);
}
return HPDF_PDFA_GenerateID(pdf);

return HPDF_OK;
}

/* Generate an ID for the trailer dict, PDF/A needs this.
Expand Down

0 comments on commit bc755fa

Please sign in to comment.