2
* PDF file output routines.
4
* Copyright 2008 by Tobias Hoffmann.
6
* This file is licensed as noted in "LICENSE.txt"
7
* which should have been included with this file. If this file is
8
* file is missing or damaged, see the license at "http://www.cups.org/".
17
#include "fontembed/embed.h"
19
void pdfOut_printf(pdfOut *pdf,const char *fmt,...) // {{{
32
void pdfOut_putString(pdfOut *pdf,const char *str,int len) // {{{ - >len==-1: strlen()
40
// escape special chars: \0 \\ \)
42
for (;len>0;iA++,len--) {
43
if ( (str[iA]<32)||(str[iA]>126) ) {
44
fwrite(str,1,iA,stdout);
45
fprintf(stdout,"\\%03o",str[iA]);
49
} else if ( (str[iA]==')')||(str[iA]=='\\') ) {
50
fwrite(str,1,iA,stdout);
51
fprintf(stdout,"\\%c",str[iA]);
58
fwrite(str,1,iA,stdout);
63
void pdfOut_putHexString(pdfOut *pdf,const char *str,int len) // {{{ - >len==-1: strlen()
70
pdf->filepos+=2*len+2;
72
for (;len>0;str++,len--) {
73
fprintf(stdout,"%02x",(unsigned char)*str);
79
pdfOut *pdfOut_new() // {{{ - NULL on error
81
pdfOut *ret=malloc(sizeof(pdfOut));
83
memset(ret,0,sizeof(pdfOut));
90
// NOTE: uses statically allocated buffer
91
const char *pdfOut_to_pdfdate(struct tm *curtm) // {{{
93
static char curdate[250];
97
curtm = localtime(&curtime);
99
strftime(curdate, sizeof(curdate), "D:%Y%m%d%H%M%S%z", curtm);
102
curdate[21]=curdate[18];
103
curdate[20]=curdate[17];
109
int pdfOut_add_xref(pdfOut *pdf) // {{{ - returns obj_no
112
assert(pdf->xrefsize<=pdf->xrefalloc);
114
if (pdf->xrefsize==pdf->xrefalloc) {
117
tmp=realloc(pdf->xref,sizeof(long)*pdf->xrefalloc);
124
pdf->xref[pdf->xrefsize++]=pdf->filepos;
125
return pdf->xrefsize; // xrefsize+1
129
int pdfOut_add_page(pdfOut *pdf,int obj) // {{{ - returns false on error
133
assert(pdf->pagessize<=pdf->pagesalloc);
135
if (pdf->pagessize==pdf->pagesalloc) {
138
tmp=realloc(pdf->pages,sizeof(int)*pdf->pagesalloc);
145
pdf->pages[pdf->pagessize++]=obj;
150
int pdfOut_add_kv(pdfOut *pdf,const char *key,const char *val) // {{{ - returns false on error
153
assert(pdf->kvsize<=pdf->kvalloc);
155
if (pdf->kvsize==pdf->kvalloc) {
156
struct keyval_t *tmp;
158
tmp=realloc(pdf->kv,sizeof(struct keyval_t)*pdf->kvalloc);
165
pdf->kv[pdf->kvsize].key=strdup(key);
166
pdf->kv[pdf->kvsize].value=strdup(val);
167
if ( (!pdf->kv[pdf->kvsize].key)||(!pdf->kv[pdf->kvsize].value) ) {
175
int pdfOut_begin_pdf(pdfOut *pdf) // ,...output_device?...) // {{{ - false on error
178
assert(pdf->kvsize==0); // otherwise: finish_pdf has not been called
181
pdf->xrefsize=pdf->pagessize=0;
183
pages_obj=pdfOut_add_xref(pdf); // fixed later
187
pdfOut_printf(pdf,"%%PDF-1.3\n");
192
void pdfOut_finish_pdf(pdfOut *pdf) // {{{
195
int root_obj,info_obj=0,xref_start;
196
assert( (pdf)&&(pdf->filepos!=-1) );
199
const int pages_obj=1;
200
pdf->xref[0]=pdf->filepos; // now fix it
201
pdfOut_printf(pdf,"%d 0 obj\n"
205
pages_obj,pdf->pagessize);
206
for (iA=0;iA<pdf->pagessize;iA++) {
207
pdfOut_printf(pdf,"%d 0 R ",pdf->pages[iA]);
209
pdfOut_printf(pdf,"]\n"
214
root_obj=pdfOut_add_xref(pdf);
215
pdfOut_printf(pdf,"%d 0 obj\n"
224
info_obj=pdfOut_add_xref(pdf);
225
pdfOut_printf(pdf,"%d 0 obj\n"
228
for (iA=0;iA<pdf->kvsize;iA++) {
229
pdfOut_printf(pdf," /%s ",pdf->kv[iA].key);
230
pdfOut_putString(pdf,pdf->kv[iA].value,-1);
231
pdfOut_printf(pdf,"\n");
233
pdfOut_printf(pdf,">>\n"
236
// TODO: some return-value checking (??)
239
xref_start=pdf->filepos;
240
pdfOut_printf(pdf,"xref\n"
243
0,pdf->xrefsize+1,0);
244
for (iA=0;iA<pdf->xrefsize;iA++) {
245
pdfOut_printf(pdf,"%010d 00000 n \n",
248
pdfOut_printf(pdf,"trailer\n"
255
pdfOut_printf(pdf," /Info %d 0 R\n",info_obj);
257
pdfOut_printf(pdf,">>\n"
265
for (iA=0;iA<pdf->kvsize;iA++) {
266
free(pdf->kv[iA].key);
267
free(pdf->kv[iA].value);
273
void pdfOut_free(pdfOut *pdf) // {{{
276
assert(pdf->kvsize==0); // otherwise: finish_pdf has not been called
285
static void pdfOut_outfn(const char *buf,int len,void *context) // {{{
287
pdfOut *pdf=(pdfOut *)context;
289
if (fwrite(buf,1,len,stdout)!=len) {
290
fprintf(stderr,"Short write: %m\n");
298
int pdfOut_write_font(pdfOut *pdf,EMB_PARAMS *emb) // {{{
303
EMB_PDF_FONTDESCR *fdes=emb_pdf_fontdescr(emb);
305
if (emb->outtype==EMB_FMT_STDFONT) { // std-14 font
306
const int f_obj=pdfOut_add_xref(pdf);
307
char *res=emb_pdf_simple_stdfont(emb);
312
pdfOut_printf(pdf,"%d 0 obj\n"
322
const int ff_obj=pdfOut_add_xref(pdf);
323
pdfOut_printf(pdf,"%d 0 obj\n"
326
if (emb_pdf_get_fontfile_subtype(emb)) {
327
pdfOut_printf(pdf," /Subtype /%s\n",
328
emb_pdf_get_fontfile_subtype(emb));
330
if (emb->outtype==EMB_FMT_TTF) {
331
pdfOut_printf(pdf," /Length1 %d 0 R\n"
333
} else if (emb->outtype==EMB_FMT_T1) { // TODO
334
pdfOut_printf(pdf," /Length1 ?\n"
339
pdfOut_printf(pdf,">>\n"
341
long streamsize=-pdf->filepos;
342
const int outlen=emb_embed(emb,pdfOut_outfn,pdf);
343
streamsize+=pdf->filepos;
344
pdfOut_printf(pdf,"\nendstream\n"
347
const int l0_obj=pdfOut_add_xref(pdf);
348
assert(l0_obj==ff_obj+1);
349
pdfOut_printf(pdf,"%d 0 obj\n"
354
if (emb->outtype==EMB_FMT_TTF) {
355
const int l1_obj=pdfOut_add_xref(pdf);
356
assert(l1_obj==ff_obj+2);
357
pdfOut_printf(pdf,"%d 0 obj\n"
363
const int fd_obj=pdfOut_add_xref(pdf);
364
char *res=emb_pdf_simple_fontdescr(emb,fdes,ff_obj);
369
pdfOut_printf(pdf,"%d 0 obj\n"
375
EMB_PDF_FONTWIDTHS *fwid=emb_pdf_fontwidths(emb);
380
const int f_obj=pdfOut_add_xref(pdf);
381
res=emb_pdf_simple_font(emb,fdes,fwid,fd_obj);
387
pdfOut_printf(pdf,"%d 0 obj\n"
394
if (emb->plan&EMB_A_MULTIBYTE) {
395
res=emb_pdf_simple_cidfont(emb,fdes->fontname,f_obj);
400
const int cf_obj=pdfOut_add_xref(pdf);
401
pdfOut_printf(pdf,"%d 0 obj\n"
416
one_page(...parent,resources,mediabox,contents);
418
// " /Resources %d 0 R\n"
419
pdfOut_printf(pdf,"%d 0 obj\n"
422
" /MediaBox [0 0 %d %d]\n"
423
" /Contents %d 0 R\n"
426
,,,PageWidth,PageLength // TODO: into pdf->
430
... pfb_embedder ... pfa?