Adding upstream version 0.9.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3bcef22498
commit
d4a07804fe
6 changed files with 215 additions and 12 deletions
2
.github/workflows/doconfly.yml
vendored
2
.github/workflows/doconfly.yml
vendored
|
@ -2,7 +2,7 @@ name: doconfly
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
tags:
|
tags:
|
||||||
- "*"
|
- "*"
|
||||||
|
|
||||||
|
|
8
.github/workflows/tests.yml
vendored
8
.github/workflows/tests.yml
vendored
|
@ -8,15 +8,15 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
python-version: ['3.11']
|
python-version: ['3.12']
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
python-version: '3.7'
|
python-version: '3.8'
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
python-version: 'pypy-3.8'
|
python-version: 'pypy-3.8'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-python@v2
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- name: Install Ghostscript (Ubuntu)
|
- name: Install Ghostscript (Ubuntu)
|
||||||
|
|
|
@ -2,6 +2,88 @@ Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.9.0
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Released on 2024-02-26.
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
|
||||||
|
* Python 3.12 is supported and tested
|
||||||
|
* Python 3.8+ is now needed, Python 3.7 is not supported anymore
|
||||||
|
|
||||||
|
New features:
|
||||||
|
|
||||||
|
* Add inline images support
|
||||||
|
|
||||||
|
Performance:
|
||||||
|
|
||||||
|
* Simplify `_to_bytes()`
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
|
||||||
|
* Add sample to create a PDF with metadata
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
|
||||||
|
* Panagiotis H.M. Issaris
|
||||||
|
* Guillaume Ayoub
|
||||||
|
* Lucie Anglade
|
||||||
|
|
||||||
|
Backers and sponsors:
|
||||||
|
|
||||||
|
* Spacinov
|
||||||
|
* Kobalt
|
||||||
|
* Grip Angebotssoftware
|
||||||
|
* Manuel Barkhau
|
||||||
|
* SimonSoft
|
||||||
|
* Menutech
|
||||||
|
* KontextWork
|
||||||
|
* René Fritz
|
||||||
|
* Simon Sapin
|
||||||
|
* Arcanite
|
||||||
|
* TrainingSparkle
|
||||||
|
* Healthchecks.io
|
||||||
|
* Hammerbacher
|
||||||
|
* Docraptor
|
||||||
|
* Yanal-Yvez Fargialla
|
||||||
|
* Morntag
|
||||||
|
* NBCO
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.0
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Released on 2023-09-25.
|
||||||
|
|
||||||
|
New features:
|
||||||
|
|
||||||
|
* Add text rise operator
|
||||||
|
|
||||||
|
Backers and sponsors:
|
||||||
|
|
||||||
|
* Spacinov
|
||||||
|
* Kobalt
|
||||||
|
* Grip Angebotssoftware
|
||||||
|
* Manuel Barkhau
|
||||||
|
* SimonSoft
|
||||||
|
* Menutech
|
||||||
|
* KontextWork
|
||||||
|
* NCC Group
|
||||||
|
* René Fritz
|
||||||
|
* Nicola Auchmuty
|
||||||
|
* Syslifters
|
||||||
|
* Hammerbacher
|
||||||
|
* TrainingSparkle
|
||||||
|
* Daniel Kucharski
|
||||||
|
* Healthchecks.io
|
||||||
|
* Yanal-Yvez Fargialla
|
||||||
|
* WakaTime
|
||||||
|
* Paheko
|
||||||
|
* Synapsium
|
||||||
|
* DocRaptor
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.0
|
Version 0.7.0
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -179,3 +179,87 @@ Display text
|
||||||
|
|
||||||
with open('document.pdf', 'wb') as f:
|
with open('document.pdf', 'wb') as f:
|
||||||
document.write(f)
|
document.write(f)
|
||||||
|
|
||||||
|
|
||||||
|
Add metadata
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import pydyf
|
||||||
|
|
||||||
|
document = pydyf.PDF()
|
||||||
|
document.info['Author'] = pydyf.String('Jane Doe')
|
||||||
|
document.info['Creator'] = pydyf.String('pydyf')
|
||||||
|
document.info['Keywords'] = pydyf.String('some keywords')
|
||||||
|
document.info['Producer'] = pydyf.String('The producer')
|
||||||
|
document.info['Subject'] = pydyf.String('An example PDF')
|
||||||
|
document.info['Title'] = pydyf.String('A PDF containing metadata')
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
document.info['CreationDate'] = pydyf.String(now.strftime('D:%Y%m%d%H%M%S'))
|
||||||
|
|
||||||
|
document.add_page(
|
||||||
|
pydyf.Dictionary(
|
||||||
|
{
|
||||||
|
'Type': '/Page',
|
||||||
|
'Parent': document.pages.reference,
|
||||||
|
'MediaBox': pydyf.Array([0, 0, 200, 200]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# 550 bytes PDF
|
||||||
|
with open('metadata.pdf', 'wb') as f:
|
||||||
|
document.write(f)
|
||||||
|
|
||||||
|
|
||||||
|
Display inline QR-code image
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import pydyf
|
||||||
|
import qrcode
|
||||||
|
|
||||||
|
# Create a QR code image
|
||||||
|
image = qrcode.make('Some data here')
|
||||||
|
raw_data = image.tobytes()
|
||||||
|
width = image.size[0]
|
||||||
|
height = image.size[1]
|
||||||
|
|
||||||
|
document = pydyf.PDF()
|
||||||
|
stream = pydyf.Stream(compress=True)
|
||||||
|
stream.push_state()
|
||||||
|
x = 0
|
||||||
|
y = 0
|
||||||
|
stream.transform(width, 0, 0, height, x, y)
|
||||||
|
# Add the 1-bit grayscale image inline in the PDF
|
||||||
|
stream.inline_image(width, height, 'Gray', 1, raw_data)
|
||||||
|
stream.pop_state()
|
||||||
|
document.add_object(stream)
|
||||||
|
|
||||||
|
# Put the image in the resources of the PDF
|
||||||
|
document.add_page(
|
||||||
|
pydyf.Dictionary(
|
||||||
|
{
|
||||||
|
'Type': '/Page',
|
||||||
|
'Parent': document.pages.reference,
|
||||||
|
'MediaBox': pydyf.Array([0, 0, 400, 400]),
|
||||||
|
'Resources': pydyf.Dictionary(
|
||||||
|
{
|
||||||
|
'ProcSet': pydyf.Array(
|
||||||
|
['/PDF', '/ImageB', '/ImageC', '/ImageI']
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'Contents': stream.reference,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# 909 bytes PDF
|
||||||
|
with open('qrcode.pdf', 'wb') as f:
|
||||||
|
document.write(f, compress=True)
|
||||||
|
|
||||||
|
|
|
@ -3,28 +3,27 @@ A low-level PDF generator.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
import re
|
import re
|
||||||
import zlib
|
import zlib
|
||||||
from codecs import BOM_UTF16_BE
|
from codecs import BOM_UTF16_BE
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
from math import ceil, log
|
from math import ceil, log
|
||||||
|
|
||||||
VERSION = __version__ = '0.7.0'
|
VERSION = __version__ = '0.9.0'
|
||||||
|
|
||||||
|
|
||||||
def _to_bytes(item):
|
def _to_bytes(item):
|
||||||
"""Convert item to bytes."""
|
"""Convert item to bytes."""
|
||||||
if isinstance(item, bytes):
|
if isinstance(item, bytes):
|
||||||
return item
|
return item
|
||||||
elif isinstance(item, Object):
|
|
||||||
return item.data
|
|
||||||
elif isinstance(item, float):
|
elif isinstance(item, float):
|
||||||
if item.is_integer():
|
if item.is_integer():
|
||||||
return f'{int(item):d}'.encode('ascii')
|
return str(int(item)).encode('ascii')
|
||||||
else:
|
else:
|
||||||
return f'{item:f}'.rstrip('0').encode('ascii')
|
return f'{item:f}'.rstrip('0').encode('ascii')
|
||||||
elif isinstance(item, int):
|
elif isinstance(item, Object):
|
||||||
return f'{item:d}'.encode('ascii')
|
return item.data
|
||||||
return str(item).encode('ascii')
|
return str(item).encode('ascii')
|
||||||
|
|
||||||
|
|
||||||
|
@ -366,6 +365,44 @@ class Stream(Object):
|
||||||
_to_bytes(a), _to_bytes(b), _to_bytes(c),
|
_to_bytes(a), _to_bytes(b), _to_bytes(c),
|
||||||
_to_bytes(d), _to_bytes(e), _to_bytes(f), b'cm')))
|
_to_bytes(d), _to_bytes(e), _to_bytes(f), b'cm')))
|
||||||
|
|
||||||
|
def inline_image(self, width, height, color_space, bpc, raw_data):
|
||||||
|
"""Add an inline image.
|
||||||
|
|
||||||
|
:param width: The width of the image.
|
||||||
|
:type width: :obj:`int`
|
||||||
|
:param height: The height of the image.
|
||||||
|
:type height: :obj:`int`
|
||||||
|
:param colorspace: The color space of the image, f.e. RGB, Gray.
|
||||||
|
:type colorspace: :obj:`str`
|
||||||
|
:param bpc: The bits per component. 1 for BW, 8 for grayscale.
|
||||||
|
:type bpc: :obj:`int`
|
||||||
|
:param raw_data: The raw pixel data.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if self.compress:
|
||||||
|
data = zlib.compress(raw_data)
|
||||||
|
else:
|
||||||
|
data = raw_data
|
||||||
|
enc_data = base64.a85encode(data)
|
||||||
|
self.stream.append(
|
||||||
|
b' '.join(
|
||||||
|
(
|
||||||
|
b'BI',
|
||||||
|
b'/W', _to_bytes(width),
|
||||||
|
b'/H', _to_bytes(height),
|
||||||
|
b'/BPC', _to_bytes(bpc),
|
||||||
|
b'/CS',
|
||||||
|
b'/Device' + color_space.encode(),
|
||||||
|
b'/F',
|
||||||
|
b'[/A85 /Fl]' if self.compress else b'/A85',
|
||||||
|
b'/L', _to_bytes(len(enc_data) + 2),
|
||||||
|
b'ID',
|
||||||
|
enc_data + b'~>',
|
||||||
|
b'EI',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data(self):
|
def data(self):
|
||||||
stream = b'\n'.join(_to_bytes(item) for item in self.stream)
|
stream = b'\n'.join(_to_bytes(item) for item in self.stream)
|
||||||
|
|
|
@ -19,11 +19,11 @@ classifiers = [
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3 :: Only',
|
'Programming Language :: Python :: 3 :: Only',
|
||||||
'Programming Language :: Python :: 3.7',
|
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
'Programming Language :: Python :: 3.9',
|
'Programming Language :: Python :: 3.9',
|
||||||
'Programming Language :: Python :: 3.10',
|
'Programming Language :: Python :: 3.10',
|
||||||
'Programming Language :: Python :: 3.11',
|
'Programming Language :: Python :: 3.11',
|
||||||
|
'Programming Language :: Python :: 3.12',
|
||||||
'Programming Language :: Python :: Implementation :: CPython',
|
'Programming Language :: Python :: Implementation :: CPython',
|
||||||
'Programming Language :: Python :: Implementation :: PyPy',
|
'Programming Language :: Python :: Implementation :: PyPy',
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Reference in a new issue