]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blob - displayio/_area.py
f7272dd747bf25ae79ca94987ce278f0914b797a
[hackapet/Adafruit_Blinka_Displayio.git] / displayio / _area.py
1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2 # SPDX-FileCopyrightText: 2021 James Carr
3 #
4 # SPDX-License-Identifier: MIT
5
6 """
7 `displayio._area`
8 ================================================================================
9
10 Area for Blinka Displayio
11
12 **Software and Dependencies:**
13
14 * Adafruit Blinka:
15   https://github.com/adafruit/Adafruit_Blinka/releases
16
17 * Author(s): James Carr, Melissa LeBlanc-Williams
18
19 """
20
21 from __future__ import annotations
22
23 __version__ = "0.0.0+auto.0"
24 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_Displayio.git"
25
26
27 class Area:
28     """Area Class to represent an area to be updated."""
29
30     # pylint: disable=invalid-name
31     def __init__(self, x1: int = 0, y1: int = 0, x2: int = 0, y2: int = 0):
32         self.x1 = x1
33         self.y1 = y1
34         self.x2 = x2
35         self.y2 = y2
36         self.next = None
37
38     def __str__(self):
39         return f"Area TL({self.x1},{self.y1}) BR({self.x2},{self.y2})"
40
41     def copy_into(self, dst) -> None:
42         """Copy the area into another area."""
43         dst.x1 = self.x1
44         dst.y1 = self.y1
45         dst.x2 = self.x2
46         dst.y2 = self.y2
47
48     def scale(self, scale: int) -> None:
49         """Scale the area by scale."""
50         self.x1 *= scale
51         self.y1 *= scale
52         self.x2 *= scale
53         self.y2 *= scale
54
55     def shift(self, dx: int, dy: int) -> None:
56         """Shift the area by dx and dy."""
57         self.x1 += dx
58         self.y1 += dy
59         self.x2 += dx
60         self.y2 += dy
61
62     def compute_overlap(self, other, overlap) -> bool:
63         """Compute the overlap between two areas. Returns True if there is an overlap."""
64         a = self
65         overlap.x1 = max(a.x1, other.x1)
66         overlap.x2 = min(a.x2, other.x2)
67
68         if overlap.x1 >= overlap.x2:
69             return False
70
71         overlap.y1 = max(a.y1, other.y1)
72         overlap.y2 = min(a.y2, other.y2)
73
74         return overlap.y1 < overlap.y2
75
76     def empty(self):
77         """Return True if the area is empty."""
78         return (self.x1 == self.x2) or (self.y1 == self.y2)
79
80     def canon(self):
81         """Make sure the area is in canonical form."""
82         if self.x1 > self.x2:
83             self.x1, self.x2 = self.x2, self.x1
84         if self.y1 > self.y2:
85             self.y1, self.y2 = self.y2, self.y1
86
87     def union(self, other, union):
88         """Combine this area along with another into union"""
89         if self.empty():
90             self.copy_into(union)
91             return
92         if other.empty():
93             other.copy_into(union)
94             return
95
96         union.x1 = min(self.x1, other.x1)
97         union.y1 = min(self.y1, other.y1)
98         union.x2 = max(self.x2, other.x2)
99         union.y2 = max(self.y2, other.y2)
100
101     def width(self) -> int:
102         """Return the width of the area."""
103         return self.x2 - self.x1
104
105     def height(self) -> int:
106         """Return the height of the area."""
107         return self.y2 - self.y1
108
109     def size(self) -> int:
110         """Return the size of the area."""
111         return self.width() * self.height()
112
113     def __eq__(self, other):
114         if not isinstance(other, Area):
115             return False
116
117         return (
118             self.x1 == other.x1
119             and self.y1 == other.y1
120             and self.x2 == other.x2
121             and self.y2 == other.y2
122         )
123
124     @staticmethod
125     def transform_within(
126         mirror_x: bool,
127         mirror_y: bool,
128         transpose_xy: bool,
129         original: Area,
130         whole: Area,
131         transformed: Area,
132     ):
133         """Transform an area within a larger area."""
134         # pylint: disable=too-many-arguments
135         # Original and whole must be in the same coordinate space.
136         if mirror_x:
137             transformed.x1 = whole.x1 + (whole.x2 - original.x2)
138             transformed.x2 = whole.x2 - (original.x1 - whole.x1)
139         else:
140             transformed.x1 = original.x1
141             transformed.x2 = original.x2
142
143         if mirror_y:
144             transformed.y1 = whole.y1 + (whole.y2 - original.y2)
145             transformed.y2 = whole.y2 - (original.y1 - whole.y1)
146         else:
147             transformed.y1 = original.y1
148             transformed.y2 = original.y2
149
150         if transpose_xy:
151             y1 = transformed.y1
152             y2 = transformed.y2
153             transformed.y1 = whole.y1 + (transformed.x1 - whole.x1)
154             transformed.y2 = whole.y1 + (transformed.x2 - whole.x1)
155             transformed.x1 = whole.x1 + (y1 - whole.y1)
156             transformed.x2 = whole.x1 + (y2 - whole.y1)