def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None: """Build `GoogleDot` cursor theme for only `Windows` platforms. :param config: `GoogleDot` configuration. :type config: ``Dict`` :param win_out_dir: Path to the output directory,\ Where the `Windows` cursor theme package will generate.\ It also creates a directory if not exists. :type win_out_dir: ``pathlib.Path`` :param info: Content theme name & comment. :type info: Info """ for _, item in config.items(): with CursorAlias.from_bitmap(item["png"], item["hotspot"]) as alias: alias.create(item["x_sizes"], item["delay"]) if item.get("win_key"): win_cfg = alias.reproduce( size=item["win_size"], canvas_size=item["canvas_size"], position=item["position"], delay=item["win_delay"], ).rename(item["win_key"]) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir) WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)
def win_build(item: Any, alias: CursorAlias) -> None: position = item["position"] size = item["size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_cfg = alias.reproduce(size, canvas_size, position, delay=3).rename(win_key) WindowsCursor.create(win_cfg, win_out_dir)
def test_WindowsCursor_generate_with_animated_config(animated_config, image_dir) -> None: """Testing WindowsCursor generate method for generating animated (.ani) \ cursor. """ win = WindowsCursor(animated_config, image_dir, options=Options()) win.generate() assert win.out.exists() is True assert win.out.suffix == ".ani" assert win.out.__sizeof__() > 0
def test_WindowsCursor_generate_with_static_config(static_config, image_dir) -> None: """Testing WindowsCursor generate method for generating static (.cur) \ cursor. """ win = WindowsCursor(static_config, image_dir, options=Options()) win.generate() assert win.out.exists() is True assert win.out.suffix == ".cur" assert win.out.__sizeof__() > 0
def win_build(item: Dict[str, Any], alias: CursorAlias) -> None: position = item["position"] win_size = item["win_size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_delay = item["win_delay"] win_cfg = alias.reproduce(win_size, canvas_size, position, delay=win_delay).rename(win_key) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir)
def test_WindowsCursor(static_config, image_dir) -> None: """Testing WindowsCursor members value.""" win = WindowsCursor(static_config, image_dir, options=Options()) assert win.config_file == static_config # We know 'out_dir' is not exists assert win.out_dir.exists() is True
def test_WindowsCursor_create_with_static_config(static_config, image_dir) -> None: """Testing WindowsCursor generate static (.cur) cursor with ``create`` \ classmethod. """ with WindowsCursor.create(static_config, image_dir) as win: assert win.exists() is True assert win.suffix == ".cur" assert win.__sizeof__() > 0
def test_WindowsCursor_from_bitmap_with_static_png(static_png, hotspot, image_dir) -> None: """Testing WindowsCursor `form_bitmap` classmethod for generating **static** cursor.""" win = WindowsCursor.from_bitmap( png=static_png, hotspot=hotspot, size=(5, 5), canvas_size=(10, 10), out_dir=image_dir, ) assert win.exists() is True assert win.__sizeof__() > 0
def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None: """Build `Bibata Rainbow` cursor theme for only `Windows` platforms. :param config: `Bibata` configuration. :type config: Dict[str, Dict[str, Any]] :param win_out_dir: Path to the output directory,\ Where the `Windows` cursor theme package will \ generate. It also creates a directory if not exists. :type win_out_dir: Path :param info: Content theme name & comment :type info: Dict """ for _, item in config.items(): png = item["png"] hotspot = item["hotspot"] x_sizes = item["x_sizes"] delay = item["delay"] with CursorAlias.from_bitmap(png, hotspot) as alias: alias.create(x_sizes, delay) if item.get("win_key"): position = item["position"] win_size = item["win_size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_delay = item["win_delay"] win_cfg = alias.reproduce(win_size, canvas_size, position, delay=win_delay).rename(win_key) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir) WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)
def test_WindowsCursor_create_with_animated_config(hotspot, image_dir) -> None: """Testing WindowsCursor generate animated (.ani) cursor with ``create`` \ classmethod. """ animated_png = create_test_image(image_dir, 4) with CursorAlias.from_bitmap(animated_png, hotspot) as alias: cfg = alias.create((10, 10), delay=999999999) # Cover more than one delay sets new_lines = [] with cfg.open("r") as f: lines = f.readlines() for l in lines: new_lines.append(l.replace("999999999", str(randint(20, 30)))) with cfg.open("w") as f: f.writelines(new_lines) with WindowsCursor.create(cfg, image_dir) as win: assert win.exists() is True assert win.suffix == ".ani" assert win.__sizeof__() > 0
def test_WindowsCursor_from_bitmap_with_animated_png_exceptions( animated_png, hotspot, image_dir) -> None: """Testing WindowsCursor `form_bitmap` classmethod exceptions for generating **animated** \ cursor. """ with pytest.raises(KeyError) as excinfo1: WindowsCursor.from_bitmap() assert str(excinfo1.value) == "\"argument 'png' required\"" with pytest.raises(KeyError) as excinfo2: WindowsCursor.from_bitmap(png=animated_png) assert str(excinfo2.value) == "\"argument 'hotspot' required\"" with pytest.raises(KeyError) as excinfo3: WindowsCursor.from_bitmap(png=animated_png, hotspot=hotspot) assert str(excinfo3.value) == "\"argument 'size' required\"" with pytest.raises(KeyError) as excinfo4: WindowsCursor.from_bitmap(png=animated_png, hotspot=hotspot, size=(5, 5)) assert str(excinfo4.value) == "\"argument 'canvas_size' required\"" with pytest.raises(KeyError) as excinfo5: WindowsCursor.from_bitmap(png=animated_png, hotspot=hotspot, size=(5, 5), canvas_size=(10, 10)) assert str(excinfo5.value) == "\"argument 'out_dir' required\"" with pytest.raises(KeyError) as excinfo6: WindowsCursor.from_bitmap( png=animated_png, hotspot=hotspot, canvas_size=(10, 10), size=(5, 5), out_dir=image_dir, ) assert str(excinfo6.value) == "\"argument 'delay' required\"" WindowsCursor.from_bitmap( png=animated_png, hotspot=hotspot, canvas_size=(10, 10), size=(5, 5), out_dir=image_dir, position="top_left", delay=2, ) WindowsCursor.from_bitmap( png=animated_png, hotspot=hotspot, canvas_size=(10, 10), size=(5, 5), out_dir=image_dir, position="top_left", delay=2, options=Options(add_shadows=True), )
def test_WindowsCursor_exceptions(static_config, image_dir) -> None: """Testing WindowsCursor `framesets` Exceptions.""" win = WindowsCursor(static_config, image_dir, options=Options()) f1 = [ (10, -1, -1, "test-0.png", 10), (9, -1, -1, "test-0.png", 10), (10, -1, -1, "test-1.png", 10), (9, -1, -1, "test-1.png", 10), (10, -1, -1, "test-2.png", 10), (9, -1, -1, "test-2.png", 10), (10, -1, -1, "test-3.png", 10), (9, -1, -1, "test-3.png", 10), ] with pytest.raises(ValueError) as excinfo: win.make_framesets(f1) assert ( str(excinfo.value) == "Frames are not sorted: frame 2 has size 10, but we have seen that already" ) f2 = [ (10, -1, -1, "test-0.png", 10), (10, -1, -1, "test-1.png", 10), (10, -1, -1, "test-2.png", 10), (10, -1, -1, "test-3.png", 10), (9, -1, -1, "test-0.png", 10), (9, -1, -1, "test-1.png", 10), (9, -1, -1, "test-2.png", 10), ] with pytest.raises(ValueError) as excinfo: win.make_framesets(f2) assert str(excinfo.value) == "Frameset 3 has size 1, expected 2" f3 = [ (10, -1, -1, "test-0.png", 10), (10, -1, -1, "test-1.png", 10), (10, -1, -1, "test-2.png", 10), (10, -1, -1, "test-3.png", 10), (9, -1, -1, "test-0.png", 10), (9, -1, -1, "test-1.png", 10), (9, -1, -1, "test-2.png", 10), (9, -1, -1, "test-3.png", 1), ] with pytest.raises(ValueError) as excinfo: win.make_framesets(f3) assert (str( excinfo.value ) == "Frameset 1 has duration 1 for framesize 9, but 10 for framesize 10") f4 = [ (10, -1, -1, "test-0.png", 10), (10, -1, -1, "test-1.png", 10), (10, -1, -1, "test-2.png", 10), (10, -1, -1, "test-3.png", 10), (9, -1, -1, "test-0.png", 10), (9, -1, -1, "test-1.png", 10), (9, -1, -1, "test-2.png", 10), (9, -1, -1, "test-3.png", 10), ] framesets = win.make_framesets(f4) ff = framesets[0][0] print(ff[0])
def main() -> None: parser = argparse.ArgumentParser( prog="clickgen", description="The hassle-free cursor building toolbox", ) # Positional Args. parser.add_argument( "png", metavar="PNG", type=str, nargs="+", help= "Path to .png file. If animated, Try to mask frame-number using asterisk( * ). For Example 'wait-*.png'", ) parser.add_argument( "-o", "--out-dir", dest="out_dir", metavar="OUT", type=str, default="./", help="To change output directory. (default: %(default)s)", ) # Optional Args. parser.add_argument( "-hot", "--hotspot", dest="hotspot", metavar="cord", nargs=2, default=(0, 0), type=int, help= "To set 'x' & 'y' coordinates of cursor's hotspot. (default: %(default)s)", ) parser.add_argument( "-t", "--type", dest="type", choices=("windows", "xcursor", "all"), default="all", help= "Set cursor type, Which you want to build. (default: '%(default)s')", ) parser.add_argument( "-s", "--sizes", dest="sizes", metavar="size", nargs="+", default=[22], type=int, help="Set pixel-size for cursor. (default: %(default)s)", ) parser.add_argument( "-d", "--delay", dest="delay", metavar="ms", default=50, type=int, help= "Set animated cursor's frames delay in 'micro-second'. (default: %(default)s)", ) args = parser.parse_args() hotspot = (args.hotspot[0], args.hotspot[1]) sizes = [(s, s) for s in args.sizes] out_dir = Path(args.out_dir) if not out_dir.exists(): out_dir.mkdir(parents=True, exist_ok=True) with CursorAlias.from_bitmap(args.png, hotspot) as alias: cfg = alias.create(sizes) if args.type == "windows": WindowsCursor.create(cfg, out_dir) elif args.type == "xcursor": # Using Temporary directory, Because 'XCursor' create inside 'cursors' directory. tmp_dir = Path(tempfile.mkdtemp()) try: xcursor = XCursor.create(cfg, tmp_dir) shutil.move(str(xcursor.absolute()), str(out_dir.absolute())) finally: shutil.rmtree(tmp_dir) else: tmp_dir = Path(tempfile.mkdtemp()) try: xcursor = XCursor.create(cfg, tmp_dir) win_cursor = WindowsCursor.create(cfg, tmp_dir) shutil.move(str(xcursor.absolute()), str(out_dir.absolute())) shutil.move(str(win_cursor.absolute()), str(out_dir.absolute())) finally: shutil.rmtree(tmp_dir)