📦 cursor builder package renamed applbuild -> src

This commit is contained in:
ful1e5 2021-08-13 14:41:26 +05:30
parent db1357fdc7
commit 8e70c271ce
7 changed files with 3 additions and 8 deletions

0
builder/src/__init__.py Normal file
View file

102
builder/src/configure.py Normal file
View file

@ -0,0 +1,102 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Any, Dict, Tuple, TypeVar
from clickgen.util import PNGProvider
from .constants import WIN_CURSORS_CFG, WIN_DELAY, X_CURSORS_CFG, X_DELAY
X = TypeVar("X")
def to_tuple(x: X) -> Tuple[X, X]:
return (x, x)
def get_config(bitmaps_dir, **kwargs) -> Dict[str, Any]:
"""Return configuration of `GoogleDot` pointers.
:param bitmaps_dir: Path to .png file's directory.
:type bitmaps_dir: ``str`` or ``pathlib.Path``
:param **kwargs:
See below
:Keyword Arguments:
* *x_sizes* (``List[int]``) --
List of pixel-sizes for xcursors.
* *win_canvas_size* (``int``) --
Windows cursor's canvas pixel-size.
* *win_size* (``int``) --
Pixel-size for Windows cursor.
Example:
```python
get_config(
bitmaps_dir="./bitmaps",
x_sizes=[24, 28, 32],
win_canvas_size=32,
win_size=24,
)
```
"""
w_size = to_tuple(kwargs.pop("win_size"))
w_canvas_size = to_tuple(kwargs.pop("win_canvas_size"))
raw_x_sizes = kwargs.pop("x_sizes")
x_sizes = []
for size in raw_x_sizes:
x_sizes.append(to_tuple(size))
png_provider = PNGProvider(bitmaps_dir)
config: Dict[str, Any] = {}
for key, item in X_CURSORS_CFG.items():
x_hot: int = int(item.get("xhot", 0))
y_hot: int = int(item.get("yhot", 0))
hotspot: Tuple[int, int] = (x_hot, y_hot)
delay: int = int(item.get("delay", X_DELAY))
png = png_provider.get(key)
if not png:
raise FileNotFoundError(f"{key} not found")
data = {
"png": png,
"x_sizes": x_sizes,
"hotspot": hotspot,
"delay": delay,
}
win_data = WIN_CURSORS_CFG.get(key)
if win_data:
win_key: str = str(win_data.get("to"))
position: str = str(win_data.get("position", "center"))
win_delay: int = int(win_data.get("delay", WIN_DELAY))
canvas_size = win_data.get("canvas_size", w_canvas_size)
win_size = win_data.get("size", w_size)
# Because provided cursor size is bigger than cursor's canvas.
# Also, "position" settings will not effect on cursor because the
# cursor's canvas and cursor sizes are equals.
if (win_size[0] > canvas_size[0]) | (win_size[1] > canvas_size[1]):
canvas_size = win_size
config[key] = {
**data,
"win_key": win_key,
"position": position,
"canvas_size": canvas_size,
"win_size": win_size,
"win_delay": win_delay,
}
else:
config[key] = data
return config

95
builder/src/constants.py Normal file
View file

@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Dict
# Info
THEME_NAME = "macOSBigSur"
COMMENT = "macOS Big Sur Pointers"
AUTHOR = "Kaiz Khatri"
URL = "https://github.com/ful1e5/apple_cursor"
# XCursor
X_DELAY: int = 10
# Windows Cursor
WIN_DELAY = 1
X_CURSORS_CFG: Dict[str, Dict[str, int]] = {
##########
# Static #
##########
"all-scroll.png": {"xhot": 100, "yhot": 100},
"bottom_left_corner.png": {"xhot": 100, "yhot": 100},
"bottom_right_corner.png": {"xhot": 100, "yhot": 100},
"bottom_tee.png": {"xhot": 98, "yhot": 137},
"center_ptr.png": {"xhot": 100, "yhot": 70},
"context-menu.png": {"xhot": 29, "yhot": 28},
"copy.png": {"xhot": 54, "yhot": 13},
"cross.png": {"xhot": 100, "yhot": 100},
"crossed_circle.png": {"xhot": 54, "yhot": 13},
"crosshair.png": {"xhot": 100, "yhot": 100},
"dnd_no_drop.png": {"xhot": 100, "yhot": 100},
"dotbox.png": {"xhot": 100, "yhot": 100},
"hand1.png": {"xhot": 94, "yhot": 72},
"hand2.png": {"xhot": 67, "yhot": 46},
"left_ptr.png": {"xhot": 53, "yhot": 13},
"left_side.png": {"xhot": 100, "yhot": 100},
"left_tee.png": {"xhot": 100, "yhot": 100},
"link.png": {"xhot": 120, "yhot": 55},
"ll_angle.png": {"xhot": 100, "yhot": 100},
"lr_angle.png": {"xhot": 100, "yhot": 100},
"move.png": {"xhot": 80, "yhot": 71},
"pencil.png": {"xhot": 81, "yhot": 117},
"plus.png": {"xhot": 98, "yhot": 100},
"question_arrow.png": {"xhot": 99, "yhot": 99},
"right_ptr.png": {"xhot": 154, "yhot": 24},
"right_tee.png": {"xhot": 98, "yhot": 99},
"sb_down_arrow.png": {"xhot": 100, "yhot": 100},
"sb_h_double_arrow.png": {"xhot": 100, "yhot": 100},
"sb_left_arrow.png": {"xhot": 100, "yhot": 100},
"sb_right_arrow.png": {"xhot": 100, "yhot": 100},
"sb_up_arrow.png": {"xhot": 100, "yhot": 100},
"sb_v_double_arrow.png": {"xhot": 100, "yhot": 100},
"top_side.png": {"xhot": 100, "yhot": 100},
"top_tee.png": {"xhot": 100, "yhot": 100},
"ul_angle.png": {"xhot": 100, "yhot": 100},
"ur_angle.png": {"xhot": 100, "yhot": 100},
"vertical-text.png": {"xhot": 96, "yhot": 99},
"wayland-cursor.png": {"xhot": 100, "yhot": 100},
"X_cursor.png": {"xhot": 100, "yhot": 100},
"xterm.png": {"xhot": 100, "yhot": 104},
"zoom-in.png": {"xhot": 100, "yhot": 100},
"zoom-out.png": {"xhot": 100, "yhot": 100},
############
# Animated #
############
# Note: Animated cursors don't need an extension and frame numbers.
"left_ptr_watch": {"xhot": 54, "yhot": 13},
"wait": {"xhot": 100, "yhot": 100},
}
WIN_CURSORS_CFG: Dict[str, Dict[str, str]] = {
##########
# Static #
##########
"right_ptr.png": {"to": "Alternate", "position": "top_left"},
"cross.png": {"to": "Cross"},
"left_ptr.png": {"to": "Default", "position": "top_left"},
"bottom_right_corner.png": {"to": "Diagonal_1"},
"bottom_left_corner.png": {"to": "Diagonal_2"},
"pencil.png": {"to": "Handwriting"},
"question_arrow.png": {"to": "Help", "position.png": "top_left"},
"sb_h_double_arrow.png": {"to": "Horizontal"},
"xterm.png": {"to": "IBeam", "position": "top_left"},
"hand2.png": {"to": "Link", "position": "top_left"},
"hand1.png": {"to": "Move"},
"crossed_circle.png": {"to": "Unavailiable", "position": "top_left"},
"sb_v_double_arrow.png": {"to": "Vertical"},
############
# Animated #
############
# Note: Animated cursors don't need frame numbers.
"left_ptr_watch": {"to": "Work", "position": "top_left"},
"wait": {"to": "Busy"},
}

120
builder/src/generator.py Normal file
View file

@ -0,0 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This module provides build methods for ``macOSBigSur``."""
from pathlib import Path
from typing import Any, Dict
from clickgen.builders import WindowsCursor, XCursor
from clickgen.core import CursorAlias
from clickgen.packagers import WindowsPackager, XPackager
from .constants import AUTHOR, COMMENT, THEME_NAME, URL
from .symlinks import add_missing_xcursor
def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path) -> None:
"""Build `macOSBigSur` cursor theme for only `X11`(UNIX) platform.
:param config: `macOSBigSur` configuration.
:type config: Dict
:param x_out_dir: Path to the output directory,\
Where the `X11` cursor theme package will generate.\
It also creates a directory if not exists.
:type x_out_dir: 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:
x_cfg = alias.create(item["x_sizes"], item["delay"])
print(f"Building '{x_cfg.stem}' XCursor...")
XCursor.create(x_cfg, x_out_dir)
add_missing_xcursor(x_out_dir / "cursors")
XPackager(x_out_dir, THEME_NAME, COMMENT)
def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path) -> None:
"""Build `macOSBigSur` cursor theme for only `Windows` platforms.
:param config: `macOSBigSur` 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: 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, THEME_NAME, COMMENT, AUTHOR, URL)
def build(
config: Dict[str, Dict[str, Any]], x_out_dir: Path, win_out_dir: Path
) -> None:
"""Build `macOSBigSur` cursor theme for `X11` & `Windows` platforms.
:param config: `macOSBigSur` configuration.
:type config: Dict
:param x_out_dir: Path to the output directory,\
Where the `X11` cursor theme package will generate.\
It also creates a directory if not exists.
:type x_out_dir: Path
: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: Info
"""
for _, item in config.items():
with CursorAlias.from_bitmap(item["png"], item["hotspot"]) as alias:
x_cfg = alias.create(item["x_sizes"], item["delay"])
print(f"Building '{x_cfg.stem}' XCursor...")
XCursor.create(x_cfg, x_out_dir)
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)
add_missing_xcursor(x_out_dir / "cursors")
XPackager(x_out_dir, THEME_NAME, COMMENT)
WindowsPackager(win_out_dir, THEME_NAME, COMMENT, AUTHOR, URL)

168
builder/src/symlinks.py Normal file
View file

@ -0,0 +1,168 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from pathlib import Path
from typing import Dict, List, Union
from clickgen.util import chdir
def add_missing_xcursor(directory: Union[str, Path]) -> None:
"""Add missing `XCursor` to the Unix cursor package.
:param directory: directory where XCursors are available.
:type directory: ``str`` or ``pathlib.Path``
"""
symlinks: List[Dict[str, Union[str, List[str]]]] = [
{"src": "all-scroll", "links": ["fleur", "size_all"]},
{
"src": "bottom_left_corner",
"links": [
"fcf1c3c7cd4491d801f1e1c78f100000",
"sw-resize",
"ne-resize",
"size_bdiag",
"nesw-resize",
"top_right_corner",
"fd_double_arrow",
],
},
{
"src": "bottom_right_corner",
"links": [
"c7088f0f3e6c8088236ef8e1e3e70000",
"top_left_corner",
"se-resize",
"nw-resize",
"size_fdiag",
"nwse-resize",
"bd_double_arrow",
],
},
{
"src": "copy",
"links": [
"1081e37283d90000800003c07f3ef6bf",
"6407b0e94181790501fd1e167b474872",
"b66166c04f8c3109214a4fbd64a50fc8",
"dnd-copy",
],
},
{
"src": "cross",
"links": ["cross_reverse", "diamond_cross", "tcross", "color-picker"],
},
{
"src": "crossed_circle",
"links": [
"03b6e0fcb3499374a867c041f52298f0",
"not-allowed",
"forbidden",
"circle",
],
},
{"src": "dnd_no_drop", "links": ["no-drop"]},
{"src": "dotbox", "links": ["dot_box_mask", "draped_box", "icon", "target"]},
{"src": "hand1", "links": ["grab", "openhand"]},
{
"src": "hand2",
"links": [
"9d800788f1b08800ae810202380a0822",
"e29285e634086352946a0e7090d73106",
"pointer",
"pointing_hand",
],
},
{"src": "left_ptr", "links": ["arrow", "default"]},
{
"src": "left_ptr_watch",
"links": [
"00000000000000020006000e7e9ffc3f",
"08e8e1c95fe2fc01f976f1e063a24ccd",
"3ecb610c1bf2410f44200f48c40d3599",
"progress",
],
},
{"src": "left_side", "links": ["w-resize", "right_side", "e-resize"]},
{
"src": "link",
"links": [
"3085a0e285430894940527032f8b26df",
"640fb0e74195791501fd1ed57b41487f",
"a2a266d0498c3104214a47bd64ab0fc8",
"alias",
"dnd-link",
],
},
{
"src": "move",
"links": [
"4498f0e0c1937ffe01fd06f973665830",
"9081237383d90e509aa00f00170e968f",
"fcf21c00b30f7e3f83fe0dfd12e71cff",
"grabbing",
"pointer_move",
"dnd-move",
"closedhand",
"dnd-none",
],
},
{"src": "pencil", "links": ["draft"]},
{"src": "plus", "links": ["cell"]},
{
"src": "question_arrow",
"links": [
"5c6cd98b3f3ebcb1f9c7f1c204630408",
"d9ce0ab605698f320427677b458ad60b",
"help",
"left_ptr_help",
"whats_this",
"dnd-ask",
],
},
{"src": "right_ptr", "links": ["draft_large", "draft_small"]},
{"src": "sb_down_arrow", "links": ["down-arrow"]},
{
"src": "sb_h_double_arrow",
"links": [
"028006030e0e7ebffc7f7070c0600140",
"14fef782d02440884392942c1120523",
"col-resize",
"ew-resize",
"h_double_arrow",
"size-hor",
"size_hor",
"split_h",
],
},
{"src": "sb_left_arrow", "links": ["left-arrow"]},
{"src": "sb_right_arrow", "links": ["right-arrow"]},
{"src": "sb_up_arrow", "links": ["up-arrow"]},
{
"src": "sb_v_double_arrow",
"links": [
"00008160000006810000408080010102",
"2870a09082c103050810ffdffffe0204",
"double_arrow",
"ns-resize",
"row-resize",
"size-ver",
"size_ver",
"split_v",
"v_double_arrow",
],
},
{"src": "top_side", "links": ["s-resize", "n-resize", "bottom_side"]},
{"src": "wait", "links": ["watch"]},
{"src": "X_cursor", "links": ["pirate", "x-cursor"]},
{"src": "xterm", "links": ["ibeam", "text"]},
]
with chdir(directory):
for item in symlinks:
src: str = str(item["src"])
for link in item.get("links"):
print(f"Creating symlink {src} -> {link}")
os.symlink(src, link)