375
481
doc->saveAs(&outs, writeForceRewrite);
485
* Get value according to key.
487
const char *lookup_opt(opt_t *opt, const char *key) {
488
if ( ! opt || ! key ) {
493
if (opt->key && opt->val) {
494
if ( strcmp(opt->key, key) == 0 ) {
505
* 1. Lookup in PDF template file for form.
506
* 2. Lookup for form fields' names.
507
* 3. Fill recognized fields with information.
509
extern "C" int pdf_fill_form(pdf_t *doc, opt_t *opt)
511
XRef *xref = doc->getXRef();
512
Catalog *catalog = doc->getCatalog();
513
Catalog::FormType form_type = catalog->getFormType();
514
if ( form_type == Catalog::NoForm ) {
515
fprintf(stderr, "PDF template file doesn't have form. It's okay.\n");
519
Page *page = catalog->getPage(1);
521
fprintf(stderr, "Can't get page from PDF tamplate file.\n");
525
Ref pageref = page->getRef();
526
xref->fetch(pageref.num, pageref.gen, &pageobj);
528
const char *font_size = lookup_opt(opt, "banner-font-size");
530
/* Font size isn't specified use next one. */
534
/* Embed font into PDF */
535
const char *font = lookup_opt(opt, "banner-font");
537
/* Font isn't specified use next one. */
540
int res = pdf_embed_font(doc, page, font);
542
fprintf(stderr, "Can't integrate %s font into PDF file.\n", font);
546
/* Page's resources dictionary */
549
Object *ret = get_resource_dict(xref, pageobj.getDict(), &resdict, &resref);
551
FormPageWidgets *widgets = page->getFormWidgets();
553
fprintf(stderr, "Can't get page's widgets.\n");
556
int num_widgets = widgets->getNumWidgets();
558
/* Go through widgets and fill them as necessary */
559
for (int i=0; i < num_widgets; ++i)
561
FormWidget *fm = widgets->getWidget(i);
563
/* Take into consideration only Text widgets */
564
if ( fm->getType() != formText ) {
568
FormWidgetText *fm_text = static_cast<FormWidgetText*>(fm);
570
/* Ignore R/O widget */
571
if ( fm_text->isReadOnly() ) {
575
FormField *ff = fm_text->getField();
576
GooString *field_name;
577
field_name = ff->getFullyQualifiedName();
579
field_name = ff->getPartialName();
580
if ( ! field_name ) {
581
fprintf(stderr, "Ignore widget #%d (unknown name)\n", i);
585
const char *name = field_name->getCString();
586
const char *fill_with = lookup_opt(opt, name);
588
fprintf(stderr, "Lack information for widget: %s.\n", name);
592
fprintf(stderr, "Fill widget name %s with value %s.\n", name, fill_with);
594
unsigned short *fill_with_w;
595
int len = utf8_to_utf16(fill_with, &fill_with_w);
597
fprintf(stderr, "Bad data for widget: %s.\n", name);
601
GooString *content = new GooString((char*)fill_with_w, len);
602
fm_text->setContent(content);
604
/* Object for form field */
605
Object *field_obj = ff->getObj();
606
Ref field_ref = ff->getRef();
608
/* Construct appearance object in form of: "/stanv_font 12 Tf" */
609
GooString *appearance = new GooString();
610
appearance->append("/stanv_font ");
611
appearance->append(font_size);
612
appearance->append(" Tf");
614
/* Modify field's appearance */
615
Object appearance_obj;
616
appearance_obj.initString(appearance);
617
field_obj->getDict()->set("DA", &appearance_obj);
620
* Create /AP - entry stuff.
621
* This is right way to display characters other then Latin1
624
/* UTF8 '/0' ending string */
625
const char *ptr_text = fill_with;
627
GooString *ap_text = new GooString("<");
628
while ( *ptr_text ) {
630
/* Get next character in Unicode */
631
ptr_text = get_next_wide(ptr_text, &unicode);
632
const unsigned short gid = emb_get(Font, unicode);
634
memset(text, 0, sizeof(text));
635
sprintf(text,"%04x", gid);
636
ap_text->append(text, 4);
638
ap_text->append("> Tj\n");
640
/* Create empty string for stream */
641
GooString *appearance_stream = new GooString();
643
/* Orde has matter */
644
appearance_stream->append("/Tx BMC \n");
645
appearance_stream->append("BT\n"); // Begin text object
646
appearance_stream->append("/stanv_font ");
647
appearance_stream->append(font_size);
648
appearance_stream->append(" Tf\n");
649
appearance_stream->append("2 12.763 Td\n");
650
appearance_stream->append(ap_text);
651
appearance_stream->append("ET\n");
652
appearance_stream->append("EMC\n");
654
Object appearance_stream_dic;
655
appearance_stream_dic.initDict(xref);
658
* Appearance stream dic.
659
* See: 4.9 Form XObjects
660
* TABLE 4.41 Additional entries specific to a type 1 form dictionary
662
appearance_stream_dic.dictSet("Type", name_object("XObject"));
663
appearance_stream_dic.dictSet("Subtype", name_object("Form"));
664
appearance_stream_dic.dictSet("FormType", int_object(1));
666
obj_ref_x.initRef(resref.num, resref.gen);
667
appearance_stream_dic.dictSet("Resources", &obj_ref_x);
669
/* BBox array: TODO. currently out of the head. */
671
array.initArray(xref);
681
appearance_stream_dic.dictSet("BBox", &array);
682
appearance_stream_dic.dictSet("Length", int_object(appearance_stream->getLength()));
684
MemStream *mem_stream = new MemStream(appearance_stream->getCString(),
685
0, appearance_stream->getLength(), &appearance_stream_dic);
687
/* Make obj stream */
689
stream.initStream(mem_stream);
692
r = xref->addIndirectObject(&stream);
694
/* Update Xref table */
696
obj_ref.initRef(r.num, r.gen);
699
* Fill Annotation's appearance streams dic /AP
700
* See: 8.4.4 Appearance Streams
702
Object appearance_streams_dic;
703
appearance_streams_dic.initDict(xref);
704
appearance_streams_dic.dictSet("N", &obj_ref);
706
field_obj->getDict()->set("AP", &appearance_streams_dic);
708
/* Notify poppler about changes */
709
xref->setModifiedObject(field_obj, field_ref);
713
* Adjust form's NeedAppearances flag.
714
* We need to fill form's fields with specified font.
715
* The right way to this is via /AP.
717
* false - is default value for PDF. See:
718
* PDFReference.pdf - table 8.47 Entries in the interactive form dictionary
720
* OpenOffice - by default sets it to 'true'.
722
Object *obj_form = catalog->getAcroForm();
724
obj1.initBool(gFalse);
725
obj_form->dictSet("NeedAppearances", &obj1);
726
/* Add AccroForm as indirect obj */
727
Ref ref_form = xref->addIndirectObject(obj_form);
730
* So update Catalog object.
732
Object* catObj = new Object();
733
catObj = xref->getCatalog(catObj);
735
catRef.gen = xref->getRootGen();
736
catRef.num = xref->getRootNum();
738
obj2.initRef(ref_form.num, ref_form.gen);
739
catObj->dictSet("AcroForm", &obj2);
740
xref->setModifiedObject(catObj, catRef);
746
/* Embeded font into PDF */
747
static int pdf_embed_font(pdf_t *doc,
749
const char *typeface) {
751
/* Load font using libfontconfig */
752
Font = get_font(typeface);
754
fprintf(stderr, "Can't load font: %s\n", typeface);
758
/* Font's description */
759
EMB_PDF_FONTDESCR *Fdes = emb_pdf_fontdescr(Font);
764
/* Font's widths description */
765
EMB_PDF_FONTWIDTHS *Fwid=emb_pdf_fontwidths(Font);
770
/* Create empty string for stream */
771
GooString *font_stream = new GooString();
774
const int outlen = emb_embed(Font, fill_font_stream, font_stream);
775
assert( font_stream->getLength() == outlen );
778
XRef *xref = doc->getXRef();
780
/* Font dictionary object for embeded font */
782
f_dic.initDict(xref);
783
f_dic.dictSet("Type", name_object("Font"));
786
f_dic.dictSet("Length", int_object(outlen));
788
/* Lenght for EMB_FMT_TTF font type */
789
if ( Font->outtype == EMB_FMT_TTF ) {
790
f_dic.dictSet("Length1", int_object(outlen));
793
/* Add font subtype */
794
const char *subtype = emb_pdf_get_fontfile_subtype(Font);
796
f_dic.dictSet("Subtype", name_object(copyString(subtype)));
799
/* Create memory stream font. Add it to font dic. */
800
MemStream *mem_stream = new MemStream(font_stream->getCString(),
803
/* Make obj stream */
805
stream.initStream(mem_stream);
809
/* Update Xref table */
810
r = xref->addIndirectObject(&stream);
812
/* Get page object */
814
Ref pageref = page->getRef();
815
xref->fetch(pageref.num, pageref.gen, &pageobj);
816
if (!pageobj.isDict()) {
817
fprintf(stderr, "Error: malformed pdf.\n");
821
/* Page's resources dictionary */
824
Object *ret = get_resource_dict(xref, pageobj.getDict(), &resdict, &resref);
826
fprintf(stderr, "Error: malformed pdf\n");
831
/* Dictionary for all fonts in page's resources */
834
resdict.dictLookupNF("Font", &fonts);
835
if (fonts.isNull()) {
836
/* Create new one, if doesn't exists */
837
fonts.initDict(xref);
838
resdict.dictSet("Font", &fonts);
839
fprintf(stderr, "Create new font dict in page's resources.\n");
843
* For embeded font there are 4 inderect objects and 4 reference obj.
844
* Each next point to previsious one.
845
* Last one object goes to Font dic.
847
* 1. Font stream obj + reference obj
848
* 2. FontDescriptor obj + reference obj
849
* 3. Width resource obj + reference obj
850
* 4. Multibyte resourcse obj + reference obj
854
/* r - indirect object refrence to dict with stream */
855
Object *font_desc_resource_dic = make_fontdescriptor_dic(doc, Font, Fdes, r);
856
r = xref->addIndirectObject(font_desc_resource_dic);
858
/* r - indirect object reference to dict font descriptor resource */
859
Object *font_resource_dic = make_font_dic(doc, Font, Fdes, Fwid, r);
860
r = xref->addIndirectObject(font_resource_dic);
862
/* r - widths resource dic */
863
Object *cidfont_resource_dic = make_cidfont_dic(doc, Font, Fdes->fontname, r);
864
r = xref->addIndirectObject(cidfont_resource_dic);
866
/* r - cid resource dic */
867
Object font_res_obj_ref;
868
font_res_obj_ref.initRef(r.num, r.gen);
871
Object dereferenced_obj;
873
if ( fonts.isDict() ) {
874
/* "Font" resource is dictionary object */
876
} else if ( fonts.isRef() ) {
877
/* "Font" resource is indirect reference object */
878
xref->fetch(fonts.getRefNum(), fonts.getRefGen(), &dereferenced_obj);
879
fonts_dic = &dereferenced_obj;
882
if ( ! fonts_dic->isDict() ) {
883
fprintf(stderr, "Can't recognize Font resource in PDF template.\n");
887
/* Add to fonts dic new font */
888
fonts_dic->dictSet("stanv_font", &font_res_obj_ref);
890
/* Notify poppler about changes in fonts dic */
891
if ( fonts.isRef() ) {
892
xref->setModifiedObject(fonts_dic, fonts.getRef());
895
/* Notify poppler about changes in resources dic */
896
xref->setModifiedObject(&resdict, resref);
897
fprintf(stderr, "Resource dict was changed.\n");
906
* Call-back function to fill font stream object.
908
static void fill_font_stream(const char *buf, int len, void *context)
910
GooString *s = (GooString *)context;
915
* Use libfontconfig to pick up suitable font.
916
* Memory should be freed.
917
* XXX: doesn't work correctly. Need to do some revise.
919
static char *get_font_libfontconfig(const char *font) {
920
FcPattern *pattern = NULL;
921
FcFontSet *candidates = NULL;
922
FcChar8* found_font = NULL;
926
pattern = FcNameParse ((const FcChar8 *)font);
928
/* guide fc, in case substitution becomes necessary */
929
FcPatternAddInteger (pattern, FC_SPACING, FC_MONO);
930
FcConfigSubstitute (0, pattern, FcMatchPattern);
931
FcDefaultSubstitute (pattern);
933
/* Receive a sorted list of fonts matching our pattern */
934
candidates = FcFontSort (0, pattern, FcFalse, 0, &result);
935
FcPatternDestroy (pattern);
937
/* In the list of fonts returned by FcFontSort()
938
find the first one that is both in TrueType format and monospaced */
939
for (int i = 0; i < candidates->nfont; i++) {
941
/* TODO? or just try? */
942
FcChar8 *fontformat=NULL;
944
/* sane default, as FC_MONO == 100 */
947
candidates->fonts[i],
953
candidates->fonts[i],
958
if ( (fontformat) && (spacing == FC_MONO) ) {
959
if (strcmp((const char *)fontformat, "TrueType") == 0) {
960
found_font = FcPatternFormat (
961
candidates->fonts[i],
962
(const FcChar8 *)"%{file|cescape}/%{index}");
964
/* Don't take into consideration remain candidates */
966
} else if (strcmp((const char *)fontformat, "CFF") == 0) {
968
/* TTC only possible with non-cff glyphs! */
969
found_font = FcPatternFormat (
970
candidates->fonts[i],
971
(const FcChar8 *)"%{file|cescape}");
973
/* Don't take into consideration remain candidates */
979
FcFontSetDestroy (candidates);
981
if ( ! found_font ) {
982
fprintf(stderr,"No viable font found\n");
986
return (char *)found_font;
990
* Load font file using fontembed file.
991
* Test for requirements.
993
static EMB_PARAMS *load_font(const char *font) {
997
otf = otf_load(font);
1002
FONTFILE *ff=fontfile_open_sfnt(otf);
1007
EMB_PARAMS *emb=emb_new(ff,
1009
static_cast<EMB_CONSTRAINTS>( /* bad fontembed */
1010
EMB_C_FORCE_MULTIBYTE|
1011
EMB_C_TAKE_FONTFILE|
1012
EMB_C_NEVER_SUBSET));
1017
if ( ! (emb->plan & EMB_A_MULTIBYTE) ) {
1021
EMB_PDF_FONTDESCR *fdes=emb_pdf_fontdescr(emb);
1031
* Return fontembed library object that corresponds requirements.
1033
static EMB_PARAMS *get_font(const char *font)
1037
char *fontname = NULL;
1038
EMB_PARAMS *emb = NULL;
1040
/* Font file specified. */
1041
if ( (font[0]=='/') || (font[0]=='.') ) {
1042
fontname = strdup(font);
1043
emb = load_font(fontname);
1046
/* Use libfontconfig. */
1048
fontname = get_font_libfontconfig(font);
1049
emb = load_font(fontname);
1058
* Was taken from ./fontembed/embed_pdf.c
1060
static const char *emb_pdf_escape_name(const char *name, int len)
1067
/* PDF implementation limit */
1070
static char buf[128*3];
1072
const char hex[]="0123456789abcdef";
1074
for (iA=0,iB=0;iA<len;iA++,iB++) {
1075
if ( ((unsigned char)name[iA]<33)||((unsigned char)name[iA]>126)||
1076
(strchr("#()<>[]{}/%",name[iA])) ) {
1078
buf[++iB]=hex[(name[iA]>>4)&0x0f];
1079
buf[++iB]=hex[name[iA]&0xf];
1089
* Construct font description dictionary.
1090
* Translated to Poppler function emb_pdf_simple_fontdescr() from
1091
* cups-filters/fontembed/embed_pdf.c
1093
static Object *make_fontdescriptor_dic(
1096
EMB_PDF_FONTDESCR *fdes,
1097
Ref fontfile_obj_ref)
1102
/* Get XREF table */
1103
XRef *xref = doc->getXRef();
1105
/* Font dictionary for embeded font */
1106
Object *dic = new Object();
1107
dic->initDict(xref);
1109
dic->dictSet("Type", name_object("FontDescriptor"));
1112
name_object(copyString(emb_pdf_escape_name(fdes->fontname,-1))));
1113
dic->dictSet("Flags", int_object(fdes->flags));
1114
dic->dictSet("ItalicAngle", int_object(fdes->italicAngle));
1115
dic->dictSet("Ascent", int_object(fdes->ascent));
1116
dic->dictSet("Descent", int_object(fdes->descent));
1117
dic->dictSet("CapHeight", int_object(fdes->capHeight));
1118
dic->dictSet("StemV", int_object(fdes->stemV));
1122
array.initArray(xref);
1126
el.initReal(fdes->bbxmin);
1127
array.arrayAdd(&el);
1129
el.initReal(fdes->bbymin);
1130
array.arrayAdd(&el);
1132
el.initReal(fdes->bbxmax);
1133
array.arrayAdd(&el);
1135
el.initReal(fdes->bbymax);
1136
array.arrayAdd(&el);
1138
dic->dictSet("FontBBox", &array);
1140
if (fdes->xHeight) {
1141
dic->dictSet("XHeight", int_object(fdes->xHeight));
1144
if (fdes->avgWidth) {
1145
dic->dictSet("AvgWidth", int_object(fdes->avgWidth));
1149
/* Font dictionary for embeded font */
1151
style_dic.initDict(xref);
1155
GooString *panose_str = new GooString(fdes->panose, 12);
1156
panose.initString(panose_str);
1157
style_dic.dictSet("Panose", &panose);
1159
dic->dictSet("Style", &style_dic);
1163
ref_obj.initRef(fontfile_obj_ref.num, fontfile_obj_ref.gen);
1164
dic->dictSet(emb_pdf_get_fontfile_key(emb), &ref_obj);
1169
static Object *make_font_dic(
1172
EMB_PDF_FONTDESCR *fdes,
1173
EMB_PDF_FONTWIDTHS *fwid,
1174
Ref fontdescriptor_obj_ref)
1180
/* Get XREF table */
1181
XRef *xref = doc->getXRef();
1183
Object *dic = new Object();
1184
dic->initDict(xref);
1186
dic->dictSet("Type", name_object("Font"));
1189
name_object(copyString(emb_pdf_get_font_subtype(emb))));
1192
name_object(copyString(emb_pdf_escape_name(fdes->fontname,-1))));
1195
ref_obj.initRef(fontdescriptor_obj_ref.num, fontdescriptor_obj_ref.gen);
1196
dic->dictSet("FontDescriptor", &ref_obj);
1198
if ( emb->plan & EMB_A_MULTIBYTE ) {
1199
assert(fwid->warray);
1201
Object CIDSystemInfo_dic;
1202
CIDSystemInfo_dic.initDict(xref);
1209
str = new GooString(copyString(fdes->registry));
1210
registry.initString(str);
1211
CIDSystemInfo_dic.dictSet("Registry", ®istry);
1213
str = new GooString(copyString(fdes->ordering));
1214
ordering.initString(str);
1215
CIDSystemInfo_dic.dictSet("Ordering", &ordering);
1217
CIDSystemInfo_dic.dictSet("Supplement", int_object(fdes->supplement));
1219
dic->dictSet("CIDSystemInfo", &CIDSystemInfo_dic);
1221
dic->dictSet("DW", int_object(fwid->default_width));
1228
static Object *make_cidfont_dic(
1231
const char *fontname,
1232
Ref fontdescriptor_obj_ref)
1239
* UniGB-UCS2-H, UniCNS-UCS2-H, UniJIS-UCS2-H, UniKS-UCS2-H
1241
const char *encoding="Identity-H";
1242
const char *addenc="-";
1244
if ( emb->outtype == EMB_FMT_TTF ) { // !=CidType0
1248
/* Get XREF table */
1249
XRef *xref = doc->getXRef();
1251
Object *dic = new Object();
1252
dic->initDict(xref);
1254
dic->dictSet("Type", name_object("Font"));
1255
dic->dictSet("Subtype", name_object("Type0"));
1258
GooString * basefont = new GooString();
1259
basefont->append(emb_pdf_escape_name(fontname,-1));
1260
basefont->append(addenc);
1261
basefont->append((addenc[0])?encoding:"");
1263
dic->dictSet("BaseFont",
1264
name_object(copyString(basefont->getCString())));
1266
dic->dictSet("Encoding", name_object(copyString(encoding)));
1269
obj.initRef(fontdescriptor_obj_ref.num, fontdescriptor_obj_ref.gen);
1272
array.initArray(xref);
1273
array.arrayAdd(&obj);
1275
dic->dictSet("DescendantFonts", &array);
1282
* Convert UTF8 to UTF16.
1283
* Version for poppler - UTF16BE.
1286
* http://stackoverflow.com/questions/7153935/how-to-convert-utf-8-stdstring-to-utf-16-stdwstring
1288
static int utf8_to_utf16(const char *utf8, unsigned short **out_ptr)
1290
unsigned long *unicode, *head;
1292
int strl = strlen(utf8);
1294
unicode = head = (unsigned long*) malloc(strl * sizeof(unsigned long));
1297
fprintf(stderr,"stanv: 1\n");
1304
unsigned char ch = *utf8;
1311
else if (ch <= 0xBF)
1313
/* not a UTF-8 string */
1316
else if (ch <= 0xDF)
1321
else if (ch <= 0xEF)
1326
else if (ch <= 0xF7)
1333
/* not a UTF-8 string */
1337
for (size_t j = 0; j < todo; ++j)
1341
/* not a UTF-8 string */
1345
unsigned char ch = *utf8;
1347
if (ch < 0x80 || ch > 0xBF) {
1348
/* not a UTF-8 string */
1356
if (uni >= 0xD800 && uni <= 0xDFFF) {
1357
/* not a UTF-8 string */
1361
if (uni > 0x10FFFF) {
1362
/* not a UTF-8 string */
1371
ssize_t len = sizeof(unsigned short) * (unicode - head + 1) * 2;
1372
unsigned short * out = (unsigned short *)malloc(len);
1380
while ( head != unicode ) {
1381
unsigned long uni = *head;
1385
*out = (unsigned short)uni;
1386
*out = ((0xff & uni) << 8) | ((uni & 0xff00) >> 8);
1392
*out += (unsigned short)((uni >> 10) + 0xD800);
1393
*out = ((0xff & uni) << 8) | ((uni & 0xff00) >> 8);
1395
*out += (unsigned short)((uni >> 10) + 0xD800);
1396
*out = ((0xff & uni) << 8) | ((uni & 0xff00) >> 8);
1403
return (out - *out_ptr) * sizeof (unsigned short);
1406
const char *get_next_wide(const char *utf8, int *unicode_out) {
1411
if ( !utf8 || !*utf8 ) {
1415
unsigned char ch = *utf8;
1424
else if (ch <= 0xBF)
1426
/* not a UTF-8 string */
1429
else if (ch <= 0xDF)
1434
else if (ch <= 0xEF)
1439
else if (ch <= 0xF7)
1446
/* not a UTF-8 string */
1450
for (size_t j = 0; j < todo; ++j)
1454
/* not a UTF-8 string */
1458
unsigned char ch = *utf8;
1460
if (ch < 0x80 || ch > 0xBF) {
1461
/* not a UTF-8 string */
1469
if (uni >= 0xD800 && uni <= 0xDFFF) {
1470
/* not a UTF-8 string */
1474
if (uni > 0x10FFFF) {
1475
/* not a UTF-8 string */
1479
*unicode_out = (int)uni;