Skip to content

Commit

Permalink
Merge remote-tracking branch 'py-pdf/main' into iss2138
Browse files Browse the repository at this point in the history
  • Loading branch information
pubpub-zz committed Sep 16, 2023
2 parents 7dec536 + a85c1c6 commit f11e4df
Show file tree
Hide file tree
Showing 21 changed files with 274 additions and 104 deletions.
17 changes: 11 additions & 6 deletions .github/workflows/github-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
use-crypto-lib: ["pycryptodome"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
use-crypto-lib: ["cryptography"]
include:
- python-version: "3.6"
use-crypto-lib: "pycryptodome"
- python-version: "3.9"
use-crypto-lib: "cryptography"
use-crypto-lib: "pycryptodome"
- python-version: "3.10"
use-crypto-lib: ""
steps:
Expand Down Expand Up @@ -72,14 +74,17 @@ jobs:
run: |
pip install -r requirements/ci-3.11.txt
if: matrix.python-version == '3.11' || matrix.python-version == '3.12'
- name: Remove pycryptodome
- name: Remove pycryptodome and cryptography
run: |
pip uninstall pycryptodome -y
if: matrix.use-crypto-lib != 'pycryptodome'
pip uninstall pycryptodome cryptography -y
- name: Install cryptography
run: |
pip install cryptography
if: matrix.use-crypto-lib == 'cryptography'
- name: Install pycryptodome
run: |
pip install pycryptodome
if: matrix.use-crypto-lib == 'pycryptodome'
- name: Install pypdf
run: |
pip install .
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# CHANGELOG

## Version 3.16.0, 2023-09-10

### Security (SEC)
- Infinite recursion caused by IndirectObject clone (#2156)

### New Features (ENH)
- Ease access to ViewerPreferences (#2144)

### Bug Fixes (BUG)
- Catch the case where w[0] is an IndirectObject instead of an int (#2154)
- Cope with indirect objects in filters and remove deprecated code (#2177)
- Accept tabs in cmaps (#2174) / cope with extra space (#2151)
- Merge pages without resources (#2150)
- getcontents() shall return None if contents is NullObject (#2161)
- Fix conversion from 1 to LA (#2175)

### Robustness (ROB)
- Accept XYZ with no arguments (#2178)

[Full Changelog](https://github.com/py-pdf/pypdf/compare/3.15.5...3.16.0)

## Version 3.15.5, 2023-09-03

### Bug Fixes (BUG)
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ history and [GitHubs 'Contributors' feature](https://github.com/py-pdf/pypdf/gra
* [Majumder, Jonah](https://github.com/jonahmajumder)
* [Manini, Lorenzo](https://github.com/lorenzomanini)
* [maxbeer99](https://github.com/maxbeer99)
* [nalin-udhaar](https://github.com/nalin-udhaar)
* [McNeil, Karen](https://github.com/karenlmcneil): Arabic Language Support
* [Mérino, Antoine](https://github.com/Merinorus)
* [nalin-udhaar](https://github.com/nalin-udhaar)
* [Paternault, Louis](https://framagit.org/spalax)
* [Perrensen, Olsen](https://github.com/olsonperrensen)
* [Pinheiro, Arthur](https://github.com/xilopaint)
Expand All @@ -43,11 +43,12 @@ history and [GitHubs 'Contributors' feature](https://github.com/py-pdf/pypdf/gra
* [pubpub-zz](https://github.com/pubpub-zz): involved in community development
* [Ramos, Leodanis Pozo](https://github.com/lpozo)
* [RitchieP](https://github.com/RitchieP) | [LinkedIn](https://www.linkedin.com/in/ritchie-p-892b31115/) | [StackOverflow](https://stackoverflow.com/users/13328625/casual-r?tab=profile)
* [Rogmann, Sascha](https://github.com/srogmann)
* [robbiebusinessacc](https://github.com/robbiebusinessacc)
* [Roder, Thomas](https://github.com/MrTomRod)
* [Rogmann, Sascha](https://github.com/srogmann)
* [Röthenbacher, Thomas](https://github.com/troethe)
* [sietzeberends](https://github.com/sietzeberends)
* [Stober, Marc](https://github.com/marcstober)
* [Stüber, Timo](https://github.com/omit66)
* [Thoma, Martin](https://github.com/MartinThoma): Maintainer of pypdf since April 2022. I hope to build a great community with many awesome contributors. [LinkedIn](https://www.linkedin.com/in/martin-thoma/) | [StackOverflow](https://stackoverflow.com/users/562769/martin-thoma) | [Blog](https://martin-thoma.com/)
* [Thomas, Reuben](https://github.com/rrthomas)
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ You can contribute to `pypdf on GitHub <https://github.com/py-pdf/pypdf>`_.
user/add-watermark
user/reading-pdf-annotations
user/adding-pdf-annotations
user/viewer-preferences
user/forms
user/streaming-data
user/file-size
Expand Down
79 changes: 79 additions & 0 deletions docs/user/viewer-preferences.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Adding Viewer Preferences

It is possible to set viewer preferences of the PDF file.
These properties are described in Section 12.2 of the [PDF 1.7 specification](https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf).

Note that the `\ViewerPreferences` dictionary does not exist by default.
If it's not already present, it must be created by calling the `create_viewer_preferences` method
of the `PdfWriter` object.

If viewer preferences exist in a PDF file being read with `PdfReader`,
you can access them as properties of the `viewer_preferences` properties.
Otherwise, the `viewer_preferences` property will be set to `None`.

## Example

```python
from pypdf import PdfWriter
from pypdf.generic import ArrayObject, NumberObject

writer = PdfWriter()

writer.create_viewer_preferences()

# /HideToolbar
writer.viewer_preferences.hide_toolbar = True
# /HideMenubar
writer.viewer_preferences.hide_menubar = True
# /HideWindowUI
writer.viewer_preferences.hide_windowui = True
# /FitWindow
writer.viewer_preferences.fit_window = True
# /CenterWindow
writer.viewer_preferences.center_window = True
# /DisplayDocTitle
writer.viewer_preferences.display_doctitle = True

# /NonFullScreenPageMode
writer.viewer_preferences.non_fullscreen_pagemode = "/UseNone" # default
writer.viewer_preferences.non_fullscreen_pagemode = "/UseOutlines"
writer.viewer_preferences.non_fullscreen_pagemode = "/UseThumbs"
writer.viewer_preferences.non_fullscreen_pagemode = "/UseOC"

# /Direction
writer.viewer_preferences.direction = "/L2R" # default,
writer.viewer_preferences.direction = "/R2L"

# /ViewArea
writer.viewer_preferences.view_area = "/CropBox"
# /ViewClip
writer.viewer_preferences.view_clip = "/CropBox"
# /PrintArea
writer.viewer_preferences.print_area = "/CropBox"
# /PrintClip
writer.viewer_preferences.print_clip = "/CropBox"

# /PrintScaling
writer.viewer_preferences.print_scaling = "/None"
writer.viewer_preferences.print_scaling = "/AppDefault" # default according to PDF spec

# /Duplex
writer.viewer_preferences.duplex = "/Simplex"
writer.viewer_preferences.duplex = "/DuplexFlipShortEdge"
writer.viewer_preferences.duplex = "/DuplexFlipLongEdge"

# /PickTrayByPDFSize
writer.viewer_preferences.pick_tray_by_pdfsize = True
# /PrintPageRange
writer.viewer_preferences.print_pagerange = ArrayObject(
[NumberObject("1"), NumberObject("10"), NumberObject("20"), NumberObject("30")]
)
# /NumCopies
writer.viewer_preferences.num_copies = 2

for i in range(40):
writer.add_blank_page(10, 10)

with open("output.pdf", "wb") as output_stream:
writer.write(output_stream)
```
2 changes: 1 addition & 1 deletion pypdf/_cmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ def compute_space_width(
else:
w = []
while len(w) > 0:
st = w[0]
st = w[0] if isinstance(w[0], int) else w[0].get_object()
second = w[1].get_object()
if isinstance(second, int):
for x in range(st, second):
Expand Down
1 change: 0 additions & 1 deletion pypdf/_codecs/adobe_glyphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
# (2) Unicode scalar value--four uppercase hexadecimal digits
#
adobe_glyphs = {
"/.notdef": "\u0000",
"/A": "\u0041",
"/AA": "\uA732",
"/AE": "\u00C6",
Expand Down
2 changes: 1 addition & 1 deletion pypdf/_crypt_providers/_fallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from pypdf._crypt_providers._base import CryptBase
from pypdf.errors import DependencyError

_DEPENDENCY_ERROR_STR = "PyCryptodome is required for AES algorithm"
_DEPENDENCY_ERROR_STR = "cryptography>=3.1 is required for AES algorithm"


crypt_provider = ("local_crypt_fallback", "0.0.0")
Expand Down
7 changes: 6 additions & 1 deletion pypdf/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -1183,8 +1183,13 @@ def _merge_page_writer(
pdf = self.indirect_reference.pdf

rename = {}
if PG.RESOURCES not in self:
self[NameObject(PG.RESOURCES)] = DictionaryObject()
original_resources = cast(DictionaryObject, self[PG.RESOURCES].get_object())
page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object())
if PG.RESOURCES not in page2:
page2resources = DictionaryObject()
else:
page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object())

for res in (
RES.EXT_G_STATE,
Expand Down
2 changes: 1 addition & 1 deletion pypdf/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.15.5"
__version__ = "3.16.0"
3 changes: 2 additions & 1 deletion pypdf/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ def viewer_preferences(self) -> Optional[ViewerPreferences]:
self._root_object[NameObject(CD.VIEWER_PREFERENCES)] = o
return o

def create_viewer_preference(self) -> ViewerPreferences:
def create_viewer_preferences(self) -> ViewerPreferences:
o = ViewerPreferences()
self._root_object[NameObject(CD.VIEWER_PREFERENCES)] = self._add_object(o)
return o
Expand Down Expand Up @@ -862,6 +862,7 @@ def _update_text_field(self, field: DictionaryObject) -> None:
# Extract font information
da = cast(str, field[AA.DA])
font_properties = da.replace("\n", " ").replace("\r", " ").split(" ")
font_properties = [x for x in font_properties if x != ""]
font_name = font_properties[font_properties.index("Tf") - 2]
font_height = float(font_properties[font_properties.index("Tf") - 1])
if font_height == 0:
Expand Down
Loading

0 comments on commit f11e4df

Please sign in to comment.