1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-05 16:37:47 +03:00

Put the Matrix class in a separate module

It avoids imports in functions and makes document.py a bit smaller.
This commit is contained in:
Guillaume Ayoub 2022-03-19 17:22:31 +01:00
parent 78b40094cc
commit abb3184b9e
6 changed files with 57 additions and 61 deletions

View File

@ -27,6 +27,7 @@ from .images import get_image_from_uri as original_get_image_from_uri
from .layout import LayoutContext, layout_document
from .layout.percent import percentage
from .logger import LOGGER, PROGRESS_LOGGER
from .matrix import Matrix
from .text.ffi import ffi, harfbuzz, pango
from .text.fonts import FontConfiguration
from .urls import URLFetchingError
@ -596,56 +597,6 @@ def resolve_links(pages):
yield page_links, paged_anchors.pop(0)
class Matrix(list):
def __init__(self, a=1, b=0, c=0, d=1, e=0, f=0, matrix=None):
if matrix is None:
matrix = [[a, b, 0], [c, d, 0], [e, f, 1]]
super().__init__(matrix)
def __matmul__(self, other):
assert len(self[0]) == len(other) == len(other[0]) == 3
return Matrix(matrix=[
[sum(self[i][k] * other[k][j] for k in range(3)) for j in range(3)]
for i in range(len(self))])
@property
def invert(self):
d = self.determinant
return Matrix(matrix=[
[
(self[1][1] * self[2][2] - self[1][2] * self[2][1]) / d,
(self[0][1] * self[2][2] - self[0][2] * self[2][1]) / -d,
(self[0][1] * self[1][2] - self[0][2] * self[1][1]) / d,
],
[
(self[1][0] * self[2][2] - self[1][2] * self[2][0]) / -d,
(self[0][0] * self[2][2] - self[0][2] * self[2][0]) / d,
(self[0][0] * self[1][2] - self[0][2] * self[1][0]) / -d,
],
[
(self[1][0] * self[2][1] - self[1][1] * self[2][0]) / d,
(self[0][0] * self[2][1] - self[0][1] * self[2][0]) / -d,
(self[0][0] * self[1][1] - self[0][1] * self[1][0]) / d,
],
])
@property
def determinant(self):
assert len(self) == len(self[0]) == 3
return (
self[0][0] * (self[1][1] * self[2][2] - self[1][2] * self[2][1]) -
self[1][0] * (self[0][1] * self[2][2] - self[0][2] * self[2][1]) +
self[2][0] * (self[0][1] * self[1][2] - self[0][2] * self[1][1]))
def transform_point(self, x, y):
return (Matrix(matrix=[[x, y, 1]]) @ self)[0][:2]
@property
def values(self):
(a, b), (c, d), (e, f) = [column[:2] for column in self]
return a, b, c, d, e, f
class Page:
"""Represents a single rendered page.

View File

@ -13,6 +13,7 @@ from .formatting_structure import boxes
from .images import RasterImage, SVGImage
from .layout import replaced
from .layout.background import BackgroundLayer
from .matrix import Matrix
from .stacking import StackingContext
from .text.ffi import ffi, harfbuzz, pango, units_from_double, units_to_double
from .text.line_break import get_last_word_end
@ -357,8 +358,6 @@ def draw_table_backgrounds(stream, page, table):
def draw_background_image(stream, layer, image_rendering):
from .document import Matrix
if layer.image is None or 0 in layer.size:
return
@ -1028,8 +1027,6 @@ def draw_emojis(stream, font_size, x, y, emojis):
def draw_first_line(stream, textbox, text_overflow, block_ellipsis, x, y,
angle=0):
"""Draw the given ``textbox`` line to the document ``stream``."""
from .document import Matrix
pango.pango_layout_set_single_paragraph_mode(
textbox.pango_layout.layout, True)

51
weasyprint/matrix.py Normal file
View File

@ -0,0 +1,51 @@
"""Transformation matrix."""
class Matrix(list):
def __init__(self, a=1, b=0, c=0, d=1, e=0, f=0, matrix=None):
if matrix is None:
matrix = [[a, b, 0], [c, d, 0], [e, f, 1]]
super().__init__(matrix)
def __matmul__(self, other):
assert len(self[0]) == len(other) == len(other[0]) == 3
return Matrix(matrix=[
[sum(self[i][k] * other[k][j] for k in range(3)) for j in range(3)]
for i in range(len(self))])
@property
def invert(self):
d = self.determinant
return Matrix(matrix=[
[
(self[1][1] * self[2][2] - self[1][2] * self[2][1]) / d,
(self[0][1] * self[2][2] - self[0][2] * self[2][1]) / -d,
(self[0][1] * self[1][2] - self[0][2] * self[1][1]) / d,
],
[
(self[1][0] * self[2][2] - self[1][2] * self[2][0]) / -d,
(self[0][0] * self[2][2] - self[0][2] * self[2][0]) / d,
(self[0][0] * self[1][2] - self[0][2] * self[1][0]) / -d,
],
[
(self[1][0] * self[2][1] - self[1][1] * self[2][0]) / d,
(self[0][0] * self[2][1] - self[0][1] * self[2][0]) / -d,
(self[0][0] * self[1][1] - self[0][1] * self[1][0]) / d,
],
])
@property
def determinant(self):
assert len(self) == len(self[0]) == 3
return (
self[0][0] * (self[1][1] * self[2][2] - self[1][2] * self[2][1]) -
self[1][0] * (self[0][1] * self[2][2] - self[0][2] * self[2][1]) +
self[2][0] * (self[0][1] * self[1][2] - self[0][2] * self[1][1]))
def transform_point(self, x, y):
return (Matrix(matrix=[[x, y, 1]]) @ self)[0][:2]
@property
def values(self):
(a, b), (c, d), (e, f) = [column[:2] for column in self]
return a, b, c, d, e, f

View File

@ -11,6 +11,7 @@ from math import ceil, hypot
import pydyf
from ..matrix import Matrix
from .bounding_box import is_valid_bounding_box
from .utils import color, parse_url, size, transform
@ -80,8 +81,6 @@ def draw_gradient_or_pattern(svg, node, name, font_size, opacity, stroke):
def draw_gradient(svg, node, gradient, font_size, opacity, stroke):
"""Draw given gradient node."""
# TODO: merge with Gradient.draw
from ..document import Matrix
positions = []
colors = []
for child in gradient:
@ -455,7 +454,6 @@ def spread_radial_gradient(spread, positions, colors, fx, fy, fr, cx, cy, r,
def draw_pattern(svg, node, pattern, font_size, opacity, stroke):
"""Draw given gradient node."""
from ..document import Matrix
from . import Pattern
pattern._etree_node.tag = 'svg'

View File

@ -2,6 +2,7 @@
from math import atan2, cos, isclose, pi, radians, sin, tan
from ..matrix import Matrix
from .utils import normalize, point
PATH_LETTERS = 'achlmqstvzACHLMQSTVZ'
@ -14,8 +15,6 @@ def _rotate(x, y, angle):
def path(svg, node, font_size):
"""Draw path node."""
from ..document import Matrix
string = node.get('d', '')
for letter in PATH_LETTERS:

View File

@ -12,6 +12,8 @@ from urllib.parse import urlparse
from tinycss2.color3 import parse_color
from ..matrix import Matrix
class PointError(Exception):
"""Exception raised when parsing a point fails."""
@ -144,8 +146,6 @@ def transform(transform_string, font_size, normalized_diagonal):
"""Get a matrix corresponding to the transform string."""
# TODO: merge with Page._gather_links_and_bookmarks and
# css.validation.properties.transform
from ..document import Matrix
transformations = re.findall(
r'(\w+) ?\( ?(.*?) ?\)', normalize(transform_string))
matrix = Matrix()