mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00

* sumatrapdf - vendor import * everything compiles (libjpeg, poppler, fitz, sumatrapdf) * does NOT link (remove the comment tags in the parent directory.rbuild file (rosapps dir) to build it) svn path=/trunk/; revision=29295
326 lines
6.2 KiB
C
326 lines
6.2 KiB
C
#include <fitz.h>
|
|
#include <mupdf.h>
|
|
|
|
#define TIGHT 1
|
|
|
|
static fz_error *
|
|
writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen)
|
|
{
|
|
fz_error *error;
|
|
fz_stream *dststm;
|
|
fz_stream *srcstm;
|
|
unsigned char buf[4096];
|
|
fz_filter *ef;
|
|
int n;
|
|
|
|
fz_print(out, "stream\n");
|
|
|
|
if (encrypt)
|
|
{
|
|
error = pdf_cryptstream(&ef, encrypt, oid, gen);
|
|
if (error)
|
|
return error;
|
|
|
|
error = fz_openrfilter(&dststm, ef, out);
|
|
fz_dropfilter(ef);
|
|
if (error)
|
|
return error;
|
|
}
|
|
else
|
|
{
|
|
dststm = fz_keepstream(out);
|
|
}
|
|
|
|
error = pdf_openrawstream(&srcstm, xref, oid, gen);
|
|
if (error)
|
|
goto cleanupdst;
|
|
|
|
while (1)
|
|
{
|
|
n = fz_read(srcstm, buf, sizeof buf);
|
|
if (n == 0)
|
|
break;
|
|
if (n < 0)
|
|
{
|
|
error = fz_ioerror(srcstm);
|
|
goto cleanupsrc;
|
|
}
|
|
|
|
n = fz_write(dststm, buf, n);
|
|
if (n < 0)
|
|
{
|
|
error = fz_ioerror(dststm);
|
|
goto cleanupsrc;
|
|
}
|
|
}
|
|
|
|
fz_dropstream(srcstm);
|
|
fz_dropstream(dststm);
|
|
|
|
fz_print(out, "endstream\n");
|
|
|
|
return nil;
|
|
|
|
cleanupsrc:
|
|
fz_dropstream(srcstm);
|
|
cleanupdst:
|
|
fz_dropstream(dststm);
|
|
return error;
|
|
}
|
|
|
|
static fz_error *
|
|
writeobject(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen)
|
|
{
|
|
pdf_xrefentry *x = xref->table + oid;
|
|
fz_error *error;
|
|
|
|
error = pdf_cacheobject(xref, oid, gen);
|
|
if (error)
|
|
return error;
|
|
|
|
if (encrypt)
|
|
pdf_cryptobj(encrypt, x->obj, oid, gen);
|
|
|
|
fz_print(out, "%d %d obj\n", oid, gen);
|
|
fz_printobj(out, x->obj, TIGHT);
|
|
fz_print(out, "\n");
|
|
|
|
if (encrypt)
|
|
pdf_cryptobj(encrypt, x->obj, oid, gen);
|
|
|
|
if (pdf_isstream(xref, oid, gen))
|
|
{
|
|
error = writestream(out, xref, encrypt, oid, gen);
|
|
if (error)
|
|
return error;
|
|
}
|
|
|
|
fz_print(out, "endobj\n\n");
|
|
|
|
return nil;
|
|
}
|
|
|
|
static int countmodified(pdf_xref *xref, int oid)
|
|
{
|
|
int i;
|
|
for (i = oid; i < xref->len; i++)
|
|
if (xref->table[i].type != 'a' && xref->table[i].type != 'd')
|
|
return i - oid;
|
|
return i - oid;
|
|
}
|
|
|
|
fz_error *
|
|
pdf_updatexref(pdf_xref *xref, char *path)
|
|
{
|
|
fz_error *error;
|
|
fz_stream *out;
|
|
int oid;
|
|
int i, n;
|
|
int startxref;
|
|
fz_obj *obj;
|
|
|
|
pdf_logxref("updatexref '%s' %p\n", path, xref);
|
|
|
|
error = fz_openafile(&out, path);
|
|
if (error)
|
|
return error;
|
|
|
|
fz_print(out, "\n");
|
|
|
|
for (oid = 0; oid < xref->len; oid++)
|
|
{
|
|
if (xref->table[oid].type == 'a')
|
|
{
|
|
xref->table[oid].ofs = fz_tell(out);
|
|
error = writeobject(out, xref, xref->crypt, oid, xref->table[oid].gen);
|
|
if (error)
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
/* always write out entry 0 in appended xref sections */
|
|
xref->table[0].type = 'd';
|
|
|
|
startxref = fz_tell(out);
|
|
fz_print(out, "xref\n");
|
|
|
|
oid = 0;
|
|
while (oid < xref->len)
|
|
{
|
|
n = countmodified(xref, oid);
|
|
|
|
pdf_logxref(" section %d +%d\n", oid, n);
|
|
|
|
fz_print(out, "%d %d\n", oid, n);
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
if (xref->table[oid + i].type == 'd')
|
|
xref->table[oid + i].type = 'f';
|
|
if (xref->table[oid + i].type == 'a')
|
|
xref->table[oid + i].type = 'n';
|
|
|
|
fz_print(out, "%010d %05d %c \n",
|
|
xref->table[oid + i].ofs,
|
|
xref->table[oid + i].gen,
|
|
xref->table[oid + i].type);
|
|
}
|
|
|
|
oid += n;
|
|
while (oid < xref->len &&
|
|
xref->table[oid].type != 'a' &&
|
|
xref->table[oid].type != 'd')
|
|
oid ++;
|
|
}
|
|
|
|
fz_print(out, "\n");
|
|
|
|
fz_print(out, "trailer\n<<\n /Size %d\n /Prev %d", xref->len, xref->startxref);
|
|
|
|
obj = fz_dictgets(xref->trailer, "Root");
|
|
fz_print(out,"\n /Root %d %d R", fz_tonum(obj), fz_togen(obj));
|
|
|
|
obj = fz_dictgets(xref->trailer, "Info");
|
|
if (obj)
|
|
fz_print(out,"\n /Info %d %d R", fz_tonum(obj), fz_togen(obj));
|
|
|
|
obj = fz_dictgets(xref->trailer, "Encrypt");
|
|
if (obj) {
|
|
fz_print(out,"\n /Encrypt ");
|
|
fz_printobj(out, obj, TIGHT);
|
|
}
|
|
|
|
obj = fz_dictgets(xref->trailer, "ID");
|
|
if (obj) {
|
|
fz_print(out,"\n /ID ");
|
|
fz_printobj(out, obj, TIGHT);
|
|
}
|
|
|
|
fz_print(out, "\n>>\n\n");
|
|
|
|
fz_print(out, "startxref\n");
|
|
fz_print(out, "%d\n", startxref);
|
|
fz_print(out, "%%%%EOF\n");
|
|
|
|
xref->startxref = startxref;
|
|
|
|
fz_dropstream(out);
|
|
return nil;
|
|
|
|
cleanup:
|
|
fz_dropstream(out);
|
|
return error;
|
|
}
|
|
|
|
fz_error *
|
|
pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt)
|
|
{
|
|
fz_error *error;
|
|
fz_stream *out;
|
|
int oid;
|
|
int startxref;
|
|
int *ofsbuf;
|
|
fz_obj *obj;
|
|
int eoid, egen;
|
|
|
|
pdf_logxref("savexref '%s' %p\n", path, xref);
|
|
|
|
/* need to add encryption object for acrobat < 6 */
|
|
if (encrypt)
|
|
{
|
|
pdf_logxref("make encryption dict\n");
|
|
|
|
error = pdf_allocobject(xref, &eoid, &egen);
|
|
if (error)
|
|
return error;
|
|
|
|
pdf_cryptobj(encrypt, encrypt->encrypt, eoid, egen);
|
|
|
|
error = pdf_updateobject(xref, eoid, egen, encrypt->encrypt);
|
|
if (error)
|
|
return error;
|
|
}
|
|
|
|
ofsbuf = fz_malloc(sizeof(int) * xref->len);
|
|
if (!ofsbuf)
|
|
return fz_outofmem;
|
|
|
|
error = fz_openwfile(&out, path);
|
|
if (error)
|
|
{
|
|
fz_free(ofsbuf);
|
|
return error;
|
|
}
|
|
|
|
fz_print(out, "%%PDF-%1.1f\n", xref->version);
|
|
fz_print(out, "%%\342\343\317\323\n\n");
|
|
|
|
for (oid = 0; oid < xref->len; oid++)
|
|
{
|
|
pdf_xrefentry *x = xref->table + oid;
|
|
if (x->type == 'n' || x->type == 'o' || x->type == 'a')
|
|
{
|
|
ofsbuf[oid] = fz_tell(out);
|
|
error = writeobject(out, xref, encrypt, oid, x->type == 'o' ? 0 : x->gen);
|
|
if (error)
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
ofsbuf[oid] = x->ofs;
|
|
}
|
|
}
|
|
|
|
startxref = fz_tell(out);
|
|
fz_print(out, "xref\n");
|
|
fz_print(out, "0 %d\n", xref->len);
|
|
|
|
for (oid = 0; oid < xref->len; oid++)
|
|
{
|
|
int gen = xref->table[oid].gen;
|
|
int type = xref->table[oid].type;
|
|
if (type == 'o')
|
|
gen = 0;
|
|
if (type == 'a' || type == 'o')
|
|
type = 'n';
|
|
if (type == 'd')
|
|
type = 'f';
|
|
fz_print(out, "%010d %05d %c \n", ofsbuf[oid], gen, type);
|
|
}
|
|
|
|
fz_print(out, "\n");
|
|
|
|
fz_print(out, "trailer\n<<\n /Size %d", xref->len);
|
|
obj = fz_dictgets(xref->trailer, "Root");
|
|
fz_print(out, "\n /Root %d %d R", fz_tonum(obj), fz_togen(obj));
|
|
obj = fz_dictgets(xref->trailer, "Info");
|
|
if (obj)
|
|
fz_print(out, "\n /Info %d %d R", fz_tonum(obj), fz_togen(obj));
|
|
if (encrypt)
|
|
{
|
|
fz_print(out, "\n /Encrypt %d %d R", eoid, egen);
|
|
fz_print(out, "\n /ID [");
|
|
fz_printobj(out, encrypt->id, 1);
|
|
fz_printobj(out, encrypt->id, 1);
|
|
fz_print(out, "]");
|
|
|
|
pdf_cryptobj(encrypt, encrypt->encrypt, eoid, egen);
|
|
}
|
|
fz_print(out, "\n>>\n\n");
|
|
|
|
fz_print(out, "startxref\n");
|
|
fz_print(out, "%d\n", startxref);
|
|
fz_print(out, "%%%%EOF\n");
|
|
|
|
xref->startxref = startxref;
|
|
|
|
if(ofsbuf) fz_free(ofsbuf);
|
|
fz_dropstream(out);
|
|
return nil;
|
|
|
|
cleanup:
|
|
if(ofsbuf) fz_free(ofsbuf);
|
|
fz_dropstream(out);
|
|
return error;
|
|
}
|
|
|