Files
rk_pve/pve/shape.py
2025-10-21 13:18:23 +02:00

165 lines
4.1 KiB
Python

# People's Video Editor: high quality, GPU accelerated mp4 editor
# Copyright (C) 2025 Roz K <roz@rozk.net>
#
# This file is part of People's Video Editor.
#
# People's Video Editor is free software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# People's Video Editor is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with People's Video Editor.
# If not, see <https://www.gnu.org/licenses/>.
#TODO: split channels
import itertools
from array import array
_X, _Y, _U, _V, _Channels = itertools.count(0)
_Type = 'f'
_Size = array(_Type).itemsize * _Channels
class Vertex:
__slots__ = 'view'
Type = _Type
Channels = _Channels
Size = _Size
def __init__(self, view):
assert isinstance(view, memoryview)
self.view = view
def __del__(self):
del self.view
@property
def xy(self):
return self.view[_X], self.view[_Y]
@xy.setter
def xy(self, value):
self.view[_X], self.view[_Y] = value
@property
def x(self):
return self.view[_X]
@x.setter
def x(self, value):
self.view[_X] = value
@property
def y(self):
return self.view[_Y]
@y.setter
def y(self, value):
self.view[_Y] = value
@property
def uv(self):
return self.view[_U], self.view[_V]
@uv.setter
def uv(self, value):
self.view[_U], self.view[_V] = value
@property
def u(self):
return self.view[_U]
@u.setter
def u(self, value):
self.view[_U] = value
@property
def v(self):
return self.view[_V]
@v.setter
def v(self, value):
self.view[_V] = value
class Shape:
__slots__ = '_array', '_view', '_size', '_cutouts'
@classmethod
def rectangle(cls, geometry):
shape = cls(size = 4)
tl = Vertex(shape[0])
tl.xy = tl.uv = (0.0, 0.0)
tr = Vertex(shape[1])
tr.xy = tr.uv = (geometry._width, 0.0)
br = Vertex(shape[2])
br.xy = br.uv = (geometry._width, geometry._height)
bl = Vertex(shape[3])
bl.xy = bl.uv = (0.0, geometry._height)
return shape
def __init__(self, size = 0, cutouts = None):
self._array = array(_Type, bytes(size * _Size))
self._view = memoryview(self._array)
self._size = size
self._cutouts = list(cutouts) if cutouts else None
def __del__(self):
del self._view
del self._array
del self._cutouts
def __len__(self):
return self._size
def __getitem__(self, index):
index *= _Channels
return self._view[index:(index + _Channels)]
@property
def size(self):
return self._size
@property
def view(self):
return self._view
@property
def cutouts(self):
return list(self._cutouts) if self._cutouts else []
@cutouts.setter
def cutouts(self, value):
self._cutouts = list(value) if value else None
def append(self, count = 1):
index = self._size
self._view.release()
self._array.frombytes(bytes(count * _Size))
self._view = memoryview(self._array)
self._size += count
return index
def insert(self, index, count = 1):
index *= _Channels
self._view.release()
self._array[index:index] = array(_Type, bytes(count * _Size))
self._view = memoryview(self._array)
self._size += count
def remove(self, index, count = 1):
index *= _Channels
self._view.release()
del self._array[index:(index + count * _Channels)]
self._view = memoryview(self._array)
self._size -= count
def clear(self):
self._view.release()
self._array = array(_Type)
self._view = memoryview(self._array)
self._size = 0