aboutsummaryrefslogtreecommitdiffstats
path: root/env/lib/python3.10/site-packages/pikepdf/models/matrix.py
diff options
context:
space:
mode:
authorLibravatarLibravatar Biswakalyan Bhuyan <biswa@surgot.in> 2022-11-13 23:46:45 +0530
committerLibravatarLibravatar Biswakalyan Bhuyan <biswa@surgot.in> 2022-11-13 23:46:45 +0530
commit9468226a9e2e2ab8cdd599f1d8538e860ca86120 (patch)
tree0a77ada226d6db80639f96b438bf83e4e756edb5 /env/lib/python3.10/site-packages/pikepdf/models/matrix.py
downloadidcard-9468226a9e2e2ab8cdd599f1d8538e860ca86120.tar.gz
idcard-9468226a9e2e2ab8cdd599f1d8538e860ca86120.tar.bz2
idcard-9468226a9e2e2ab8cdd599f1d8538e860ca86120.zip
id card generator
Diffstat (limited to 'env/lib/python3.10/site-packages/pikepdf/models/matrix.py')
-rw-r--r--env/lib/python3.10/site-packages/pikepdf/models/matrix.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/env/lib/python3.10/site-packages/pikepdf/models/matrix.py b/env/lib/python3.10/site-packages/pikepdf/models/matrix.py
new file mode 100644
index 0000000..c660320
--- /dev/null
+++ b/env/lib/python3.10/site-packages/pikepdf/models/matrix.py
@@ -0,0 +1,145 @@
+# SPDX-FileCopyrightText: 2022 James R. Barlow
+# SPDX-License-Identifier: MPL-2.0
+
+"""PDF content matrix support."""
+
+from __future__ import annotations
+
+from math import cos, pi, sin
+
+
+class PdfMatrix:
+ """
+ Support class for PDF content stream matrices.
+
+ PDF content stream matrices are 3x3 matrices summarized by a shorthand
+ ``(a, b, c, d, e, f)`` which correspond to the first two column vectors.
+ The final column vector is always ``(0, 0, 1)`` since this is using
+ `homogenous coordinates <https://en.wikipedia.org/wiki/Homogeneous_coordinates>`_.
+
+ PDF uses row vectors. That is, ``vr @ A'`` gives the effect of transforming
+ a row vector ``vr=(x, y, 1)`` by the matrix ``A'``. Most textbook
+ treatments use ``A @ vc`` where the column vector ``vc=(x, y, 1)'``.
+
+ (``@`` is the Python matrix multiplication operator.)
+
+ Addition and other operations are not implemented because they're not that
+ meaningful in a PDF context (they can be defined and are mathematically
+ meaningful in general).
+
+ PdfMatrix objects are immutable. All transformations on them produce a new
+ matrix.
+
+ """
+
+ def __init__(self, *args):
+ # fmt: off
+ if not args:
+ self.values = ((1, 0, 0), (0, 1, 0), (0, 0, 1))
+ elif len(args) == 6:
+ a, b, c, d, e, f = map(float, args)
+ self.values = ((a, b, 0),
+ (c, d, 0),
+ (e, f, 1))
+ elif isinstance(args[0], PdfMatrix):
+ self.values = args[0].values
+ elif len(args[0]) == 6:
+ a, b, c, d, e, f = map(float, args[0])
+ self.values = ((a, b, 0),
+ (c, d, 0),
+ (e, f, 1))
+ elif len(args[0]) == 3 and len(args[0][0]) == 3:
+ self.values = (tuple(args[0][0]),
+ tuple(args[0][1]),
+ tuple(args[0][2]))
+ else:
+ raise ValueError('invalid arguments: ' + repr(args))
+ # fmt: on
+
+ @staticmethod
+ def identity():
+ """Constructs and returns an identity matrix."""
+ return PdfMatrix()
+
+ def __matmul__(self, other):
+ """Multiply this matrix by another matrix.
+
+ Can be used to concatenate transformations.
+ """
+ a = self.values
+ b = other.values
+ return PdfMatrix(
+ [
+ [sum(float(i) * float(j) for i, j in zip(row, col)) for col in zip(*b)]
+ for row in a
+ ]
+ )
+
+ def scaled(self, x, y):
+ """Concatenates a scaling matrix on this matrix."""
+ return self @ PdfMatrix((x, 0, 0, y, 0, 0))
+
+ def rotated(self, angle_degrees_ccw):
+ """Concatenates a rotation matrix on this matrix."""
+ angle = angle_degrees_ccw / 180.0 * pi
+ c, s = cos(angle), sin(angle)
+ return self @ PdfMatrix((c, s, -s, c, 0, 0))
+
+ def translated(self, x, y):
+ """Translates this matrix."""
+ return self @ PdfMatrix((1, 0, 0, 1, x, y))
+
+ @property
+ def shorthand(self):
+ """Return the 6-tuple (a,b,c,d,e,f) that describes this matrix."""
+ return (self.a, self.b, self.c, self.d, self.e, self.f)
+
+ @property
+ def a(self):
+ """Return matrix this value."""
+ return self.values[0][0]
+
+ @property
+ def b(self):
+ """Return matrix this value."""
+ return self.values[0][1]
+
+ @property
+ def c(self):
+ """Return matrix this value."""
+ return self.values[1][0]
+
+ @property
+ def d(self):
+ """Return matrix this value."""
+ return self.values[1][1]
+
+ @property
+ def e(self):
+ """Return matrix this value.
+
+ Typically corresponds to translation on the x-axis.
+ """
+ return self.values[2][0]
+
+ @property
+ def f(self):
+ """Return matrix this value.
+
+ Typically corresponds to translation on the y-axis.
+ """
+ return self.values[2][1]
+
+ def __eq__(self, other):
+ if isinstance(other, PdfMatrix):
+ return self.shorthand == other.shorthand
+ return False
+
+ def encode(self):
+ """Encode this matrix in binary suitable for including in a PDF."""
+ return '{:.6f} {:.6f} {:.6f} {:.6f} {:.6f} {:.6f}'.format(
+ self.a, self.b, self.c, self.d, self.e, self.f
+ ).encode()
+
+ def __repr__(self):
+ return f"pikepdf.PdfMatrix({repr(self.values)})"