diff --git a/README.md b/README.md index 46569f1..ebb5c35 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ For example, if you want to convert DMZ-White to Windows: are using unconventional distros (e.g. Alpine) and are getting errors related to `wand`, please see the [Wand documentation on installation][wand-install]. - [wand-install]: https://docs.wand-py.org/en/0.6.7/guide/install.html +[wand-install]: https://docs.wand-py.org/en/0.6.7/guide/install.html diff --git a/win2xcur/cursor.py b/win2xcur/cursor.py index 2925153..a46d683 100644 --- a/win2xcur/cursor.py +++ b/win2xcur/cursor.py @@ -16,6 +16,10 @@ class CursorImage: def __repr__(self) -> str: return f'CursorImage(image={self.image!r}, hotspot={self.hotspot!r}, nominal={self.nominal!r})' + def scale(self, width: int, height: int) -> None: + self.image.scale(width, height) + self.nominal = max(width, height) + class CursorFrame: images: List[CursorImage] diff --git a/win2xcur/main/win2xcur.py b/win2xcur/main/win2xcur.py index 211b0cb..506662d 100644 --- a/win2xcur/main/win2xcur.py +++ b/win2xcur/main/win2xcur.py @@ -7,7 +7,7 @@ from multiprocessing.pool import ThreadPool from threading import Lock from typing import BinaryIO -from win2xcur import scale, shadow +from win2xcur import scale, shadow, multiscale from win2xcur.parser import open_blob from win2xcur.writer import to_x11 @@ -34,6 +34,10 @@ def main() -> None: help='color of the shadow') parser.add_argument('--scale', default=None, type=float, help='Scale the cursor by the specified factor.') + parser.add_argument('--multiscale', action='store_true', + help='Generate multiple sizes for each cursor.') + parser.add_argument('--multiscale-min', type=int, default=12, + help='Minimum size to generate.') args = parser.parse_args() print_lock = Lock() @@ -48,7 +52,9 @@ def main() -> None: print(f'Error occurred while processing {name}:', file=sys.stderr) traceback.print_exc() else: - if args.scale: + if args.multiscale: + multiscale.generates_frames(cursor=cursor, min_size=args.multiscale_min) + elif args.scale: scale.apply_to_frames(cursor.frames, scale=args.scale) if args.shadow: shadow.apply_to_frames(cursor.frames, color=args.shadow_color, radius=args.shadow_radius, diff --git a/win2xcur/multiscale.py b/win2xcur/multiscale.py new file mode 100644 index 0000000..4b0e8bc --- /dev/null +++ b/win2xcur/multiscale.py @@ -0,0 +1,32 @@ +from win2xcur.cursor import CursorFrame, CursorImage + +MULTSCALE = [16, 24, 32, 48, 64, 96, 128, 192, 256] + +def generates_frames(cursor, min_size: int) -> None: + """Generates multiple sizes for each cursor. + + Args: + cursor (Cursor): The cursor to generate sizes for. + min_size (int): The minimum size to generate. + + Returns: + List[Cursor]: The generated cursors. + """ + frames = cursor.frames + new_frames = [] + image_size = frames[0].images[0].nominal + for size in MULTSCALE: + if size > image_size: + continue + if size < min_size: + break + for frame in frames: + new_images = [] + for cur in frame: + new_cur = CursorImage(cur.image.clone(), cur.hotspot, cur.nominal) + new_cur.scale(size, size) + new_images.append(new_cur) + new_frame = CursorFrame(new_images, frame.delay) + new_frames.append(new_frame) + del cursor.frames[:] + cursor.frames.extend(new_frames) diff --git a/win2xcur/scale.py b/win2xcur/scale.py index b25793e..58d4edf 100644 --- a/win2xcur/scale.py +++ b/win2xcur/scale.py @@ -6,7 +6,7 @@ from win2xcur.cursor import CursorFrame def apply_to_frames(frames: List[CursorFrame], *, scale: float) -> None: for frame in frames: for cursor in frame: - cursor.image.scale( + cursor.scale( int(round(cursor.image.width * scale)), int(round(cursor.image.height) * scale), )