# People's Video Editor: high quality, GPU accelerated mp4 editor # Copyright (C) 2025 Roz K # # 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 . #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