Skip to content

Commit 8d80d3e

Browse files
committed
upload v1.14.16
1 parent b595527 commit 8d80d3e

File tree

10 files changed

+473
-84
lines changed

10 files changed

+473
-84
lines changed

PKG-INFO

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Metadata-Version: 1.1
22
Name: PyMuPDF
3-
Version: 1.14.15
3+
Version: 1.14.16
44
Author: Ruikai Liu
55
Author-email: lrk700@gmail.com
66
Maintainer: Jorj X. McKie
@@ -21,7 +21,7 @@ Description:
2121
Introduction
2222
============
2323

24-
This is **version 1.14.15 of PyMuPDF**, a Python binding for `MuPDF <http://mupdf.com/>`_ - "a lightweight PDF and XPS viewer".
24+
This is **version 1.14.16 of PyMuPDF**, a Python binding for `MuPDF <http://mupdf.com/>`_ - "a lightweight PDF and XPS viewer".
2525

2626
MuPDF can access files in PDF, XPS, OpenXPS, epub, comic and fiction book formats, and it is known for both, its top performance and high rendering quality.
2727

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PyMuPDF 1.14.15
1+
# PyMuPDF 1.14.16
22

33
![logo](https://github.com/pymupdf/PyMuPDF/blob/master/demo/pymupdf.jpg)
44

@@ -14,7 +14,7 @@ On **[PyPI](https://pypi.org/project/PyMuPDF)** since August 2016: [![](https://
1414

1515
# Introduction
1616

17-
This is **version 1.14.15 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer".
17+
This is **version 1.14.16 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer".
1818

1919
MuPDF can access files in PDF, XPS, OpenXPS, CBZ, EPUB and FB2 (e-books) formats, and it is known for its top performance and high rendering quality.
2020

doc/PyMuPDF.pdf

7.48 KB
Binary file not shown.

doc/html.zip

40.1 KB
Binary file not shown.

fitz/fitz.i

+159-33
Original file line numberDiff line numberDiff line change
@@ -403,15 +403,38 @@ struct fz_document_s
403403
DEBUGMSG2;
404404
}
405405
406-
CLOSECHECK(embeddedFileCount)
407-
%feature("autodoc","Return number of embedded files.") embeddedFileCount;
408-
%pythoncode%{@property%}
409-
PyObject *embeddedFileCount()
406+
//---------------------------------------------------------------------
407+
// Get EmbeddedFiles names
408+
//---------------------------------------------------------------------
409+
FITZEXCEPTION(_embeddedFileNames, !result)
410+
CLOSECHECK0(_embeddedFileNames)
411+
PyObject *_embeddedFileNames(PyObject *namelist)
410412
{
411-
pdf_document *pdf = pdf_document_from_fz_document(gctx, $self);
412-
int i = -1;
413-
if (pdf) i = pdf_count_portfolio_entries(gctx, pdf);
414-
return Py_BuildValue("i", i);
413+
pdf_document *pdf = pdf_specifics(gctx, $self); // get pdf document
414+
pdf_obj *names, *o;
415+
char *c = NULL;
416+
417+
fz_try(gctx)
418+
{
419+
assert_PDF(pdf);
420+
names = pdf_dict_getl(gctx, pdf_trailer(gctx, pdf),
421+
PDF_NAME(Root),
422+
PDF_NAME(Names),
423+
PDF_NAME(EmbeddedFiles),
424+
PDF_NAME(Names),
425+
NULL);
426+
if (pdf_is_array(gctx, names))
427+
{
428+
int i, n = pdf_array_len(gctx, names);
429+
for (i=0; i < n; i+=2)
430+
{
431+
c = pdf_to_text_string(gctx, pdf_array_get(gctx, names, i));
432+
PyList_Append(namelist, Py_BuildValue("s", c));
433+
}
434+
}
435+
}
436+
fz_catch(gctx) return NULL;
437+
return NONE;
415438
}
416439
417440
FITZEXCEPTION(embeddedFileDel, !result)
@@ -662,6 +685,96 @@ if self.isClosed or self.isEncrypted:
662685
return NONE;
663686
}
664687
688+
FITZEXCEPTION(_embeddedFileAdd, !result)
689+
PyObject *_embeddedFileAdd(const char *name, PyObject *buffer, char *filename=NULL, char *ufilename=NULL, char *desc=NULL)
690+
{
691+
pdf_document *pdf = pdf_document_from_fz_document(gctx, $self);
692+
fz_buffer *data = NULL;
693+
char *buffdata;
694+
fz_var(data);
695+
int entry = 0;
696+
size_t size = 0;
697+
pdf_obj *names = NULL;
698+
fz_try(gctx)
699+
{
700+
assert_PDF(pdf);
701+
data = JM_BufferFromBytes(gctx, buffer);
702+
if (!data) THROWMSG("bad type: 'buffer'");
703+
size = fz_buffer_storage(gctx, data, &buffdata);
704+
705+
names = pdf_dict_getl(gctx, pdf_trailer(gctx, pdf),
706+
PDF_NAME(Root),
707+
PDF_NAME(Names),
708+
PDF_NAME(EmbeddedFiles),
709+
PDF_NAME(Names),
710+
NULL);
711+
if (!pdf_is_array(gctx, names)) // no embedded files yet
712+
{
713+
pdf_obj *root = pdf_dict_get(gctx, pdf_trailer(gctx, pdf),
714+
PDF_NAME(Root));
715+
names = pdf_new_array(gctx, pdf, 6); // an even number!
716+
pdf_dict_putl_drop(gctx, root, names,
717+
PDF_NAME(Names),
718+
PDF_NAME(EmbeddedFiles),
719+
PDF_NAME(Names),
720+
NULL);
721+
}
722+
723+
pdf_obj *fileentry = JM_embed_file(gctx, pdf, data,
724+
filename,
725+
ufilename,
726+
desc);
727+
pdf_array_push(gctx, names, pdf_new_text_string(gctx, name));
728+
pdf_array_push_drop(gctx, names, fileentry);
729+
}
730+
fz_always(gctx)
731+
{
732+
fz_drop_buffer(gctx, data);
733+
}
734+
fz_catch(gctx) return NULL;
735+
pdf->dirty = 1;
736+
return NONE;
737+
}
738+
739+
%pythoncode %{
740+
def embeddedFileNames(self):
741+
filenames = []
742+
self._embeddedFileNames(filenames)
743+
return filenames
744+
745+
def embeddedFileCount(self):
746+
return len(self.embeddedFileNames())
747+
748+
def embeddedFileNew(self, name, buffer,
749+
filename=None,
750+
ufilename=None,
751+
desc=None):
752+
""" Add an item to the EmbeddedFiles array.
753+
754+
Args:
755+
name: the name of the new item.
756+
buffer: (binary data) the file content.
757+
filename: (str) the file name.
758+
ufilename: (unicode) the filen ame.
759+
desc: (str) the description.
760+
"""
761+
filenames = self.embeddedFileNames()
762+
msg = "Name '%s' already in EmbeddedFiles array." % str(name)
763+
if name in filenames:
764+
raise ValueError(msg)
765+
766+
if filename is None:
767+
filename = name
768+
if ufilename is None:
769+
ufilename = unicode(filename, "utf8") if str is bytes else filename
770+
if desc is None:
771+
desc = name
772+
return self._embeddedFileAdd(name, buffer=buffer,
773+
filename=filename,
774+
ufilename=ufilename,
775+
desc=desc)
776+
%}
777+
665778
FITZEXCEPTION(convertToPDF, !result)
666779
CLOSECHECK(convertToPDF)
667780
%feature("autodoc","Convert document to PDF selecting page range and optional rotation. Output bytes object.") convertToPDF;
@@ -1150,6 +1263,31 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not
11501263
return NONE;
11511264
}
11521265
1266+
//---------------------------------------------------------------------
1267+
// remove one page
1268+
//---------------------------------------------------------------------
1269+
FITZEXCEPTION(deletePage, !result)
1270+
%feature("autodoc","Delete a PDF page.") deletePage;
1271+
CLOSECHECK0(deletePage)
1272+
%pythonappend deletePage %{
1273+
self._reset_page_refs()
1274+
self.initData()%}
1275+
PyObject *deletePage(int pno)
1276+
{
1277+
pdf_document *pdf = pdf_specifics(gctx, $self);
1278+
fz_try(gctx)
1279+
{
1280+
assert_PDF(pdf);
1281+
int count = fz_count_pages(gctx, $self);
1282+
int n = pno;
1283+
while (n < 0) n += count;
1284+
if (!INRANGE(n, 0, count-1))
1285+
THROWMSG("bad page number(s)");
1286+
pdf_delete_page(gctx, pdf, n);
1287+
}
1288+
fz_catch(gctx) return NULL;
1289+
return NONE;
1290+
}
11531291
//********************************************************************
11541292
// get document permissions
11551293
//********************************************************************
@@ -1968,7 +2106,7 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not
19682106
else:
19692107
pl.insert(to, pno)
19702108
return self.select(pl)
1971-
2109+
19722110
def movePage(self, pno, to = -1):
19732111
"""Move a page to before some other page of the document. Specify 'to = -1' to move after last page.
19742112
"""
@@ -1983,34 +2121,22 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not
19832121
else:
19842122
pl.insert(to-1, pno)
19852123
return self.select(pl)
1986-
1987-
def deletePage(self, pno = -1):
1988-
"""Delete a page from the document. First page is '0', last page is '-1'.
1989-
"""
1990-
pl = list(range(len(self)))
1991-
if pno < -1 or pno > pl[-1]:
1992-
raise ValueError("page number out of range")
1993-
if pno >= 0:
1994-
pl.remove(pno)
1995-
else:
1996-
pl.remove(pl[-1])
1997-
return self.select(pl)
1998-
2124+
19992125
def deletePageRange(self, from_page = -1, to_page = -1):
20002126
"""Delete pages from the document. First page is '0', last page is '-1'.
20012127
"""
2002-
pl = list(range(len(self)))
2003-
f = from_page
2004-
t = to_page
2005-
if f == -1:
2006-
f = pl[-1]
2007-
if t == -1:
2008-
t = pl[-1]
2009-
if not 0 <= f <= t <= pl[-1]:
2128+
pageCount = self.pageCount # page count of document
2129+
f = from_page # first page to delete
2130+
t = to_page # last page to delete
2131+
if f == -1: # means 'last page'
2132+
f = pageCount - 1
2133+
if t == -1: # means 'last page'
2134+
t = pageCount - 1
2135+
if not 0 <= f <= t <= pageCount - 1:
20102136
raise ValueError("page number(s) out of range")
2011-
for i in range(f, t+1):
2012-
pl.remove(i)
2013-
return self.select(pl)
2137+
for i in range(t, f - 1, -1): # delete pages, last to first
2138+
self.deletePage(i)
2139+
return None
20142140
20152141
def saveIncr(self):
20162142
""" Save PDF incrementally"""

0 commit comments

Comments
 (0)