👷 Bibata builde init

This commit is contained in:
ful1e5 2021-02-23 17:47:12 +05:30
parent 89eba25a9d
commit 64e50b2eec
6 changed files with 573 additions and 0 deletions

View file

105
builder/bbpkg/configure.py Normal file
View file

@ -0,0 +1,105 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Any, Dict, Tuple, TypeVar
from clickgen.util import PNGProvider
from bbpkg.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.
```
Args:
:bitmaps_dir: (str | Path) Path to .png file's directory.
Keywords Args:
: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",
x_sizes=[(24, 24), (32, 32)],
win_canvas_size=(32, 32),
win_size=(24, 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 in {bitmaps_dir}")
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

109
builder/bbpkg/constants.py Normal file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Dict
# Info
AUTHOR = "Kaiz Khatri"
URL = "https://github.com/ful1e5/Google_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},
"bd_double_arrow.png": {"xhot": 98, "yhot": 100},
"bottom_left_corner.png": {"xhot": 31, "yhot": 172},
"bottom_right_corner.png": {"xhot": 170, "yhot": 172},
"bottom_side.png": {"xhot": 100, "yhot": 164},
"bottom_tee.png": {"xhot": 100, "yhot": 164},
"center_ptr.png": {"xhot": 98, "yhot": 131},
"circle.png": {"xhot": 48, "yhot": 25},
"context-menu.png": {"xhot": 48, "yhot": 25},
"copy.png": {"xhot": 48, "yhot": 25},
"cross.png": {"xhot": 98, "yhot": 96},
"crossed_circle.png": {"xhot": 100, "yhot": 100},
"crosshair.png": {"xhot": 99, "yhot": 99},
"dnd_no_drop.png": {"xhot": 86, "yhot": 79},
"dnd-ask.png": {"xhot": 86, "yhot": 79},
"dnd-copy.png": {"xhot": 86, "yhot": 79},
"dnd-link.png": {"xhot": 86, "yhot": 79},
"dnd-move.png": {"xhot": 86, "yhot": 79},
"dnd-none.png": {"xhot": 99, "yhot": 98},
"dotbox.png": {"xhot": 100, "yhot": 100},
"fd_double_arrow.png": {"xhot": 98, "yhot": 100},
"grabbing.png": {"xhot": 106, "yhot": 79},
"hand1.png": {"xhot": 113, "yhot": 95},
"hand2.png": {"xhot": 88, "yhot": 32},
"left_ptr.png": {"xhot": 53, "yhot": 36},
"left_side.png": {"xhot": 35, "yhot": 100},
"left_tee.png": {"xhot": 165, "yhot": 95},
"link.png": {"xhot": 48, "yhot": 25},
"ll_angle.png": {"xhot": 34, "yhot": 165},
"lr_angle.png": {"xhot": 167, "yhot": 164},
"move.png": {"xhot": 100, "yhot": 100},
"pencil.png": {"xhot": 37, "yhot": 161},
"plus.png": {"xhot": 100, "yhot": 100},
"pointer-move.png": {"xhot": 48, "yhot": 25},
"question_arrow.png": {"xhot": 102, "yhot": 102},
"right_ptr.png": {"xhot": 150, "yhot": 29},
"right_side.png": {"xhot": 163, "yhot": 98},
"right_tee.png": {"xhot": 30, "yhot": 96},
"sb_down_arrow.png": {"xhot": 100, "yhot": 126},
"sb_h_double_arrow.png": {"xhot": 100, "yhot": 100},
"sb_left_arrow.png": {"xhot": 86, "yhot": 100},
"sb_right_arrow.png": {"xhot": 113, "yhot": 100},
"sb_up_arrow.png": {"xhot": 99, "yhot": 86},
"sb_v_double_arrow.png": {"xhot": 100, "yhot": 100},
"tcross.png": {"xhot": 98, "yhot": 100},
"top_left_corner.png": {"xhot": 29, "yhot": 27},
"top_right_corner.png": {"xhot": 170, "yhot": 28},
"top_side.png": {"xhot": 98, "yhot": 34},
"top_tee.png": {"xhot": 98, "yhot": 29},
"ul_angle.png": {"xhot": 34, "yhot": 35},
"ur_angle.png": {"xhot": 164, "yhot": 34},
"vertical-text.png": {"xhot": 100, "yhot": 100},
"wayland-cursor.png": {"xhot": 100, "yhot": 100},
"X_cursor.png": {"xhot": 100, "yhot": 100},
"xterm.png": {"xhot": 100, "yhot": 100},
"zoom-in.png": {"xhot": 90, "yhot": 89},
"zoom-out.png": {"xhot": 93, "yhot": 90},
############
# Animated #
############
# Note: Animated cursors don't need an extension and frame numbers.
"left_ptr_watch": {"xhot": 50, "yhot": 28},
"wait": {"xhot": 100, "yhot": 100},
}
WIN_CURSORS_CFG: Dict[str, Dict[str, str]] = {
##########
# Static #
##########
"right_ptr.png": {"to": "Alternate", "position": "top_right"},
"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"},
"dnd_no_drop.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"},
}

135
builder/bbpkg/generator.py Normal file
View file

@ -0,0 +1,135 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pathlib import Path
from typing import Any, Dict, NamedTuple
from clickgen.builders import WindowsCursor, XCursor
from clickgen.core import CursorAlias
from clickgen.packagers import WindowsPackager, XPackager
from bbpkg.constants import AUTHOR, URL
from bbpkg.symlinks import add_missing_xcursor
class Info(NamedTuple):
name: str
comment: str
def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> None:
"""Build `Bibata` cursor theme for only `X11`(UNIX) platform.
```
:config: (Dict) `Bibata` configuration.
:x_out_dir: (Path) Path to the output directory,
Where the `X11` cursor theme package will generate.
It also creates a directory if not exists.
:info: (Dict) Content theme name & comment
```
"""
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:
x_cfg = alias.create(x_sizes, 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, info.name, info.comment)
def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None:
"""Build `Bibata` cursor theme for only `Windows` platforms.
```
:config: (Dict) `Bibata` configuration.
:win_out_dir: (Path) Path to the output directory,
Where the `Windows` cursor theme package will generate.
It also creates a directory if not exists.
:info: (Dict) Content theme name & comment
```
"""
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 build(
config: Dict[str, Dict[str, Any]], x_out_dir: Path, win_out_dir: Path, info: Info
) -> None:
"""Build `Bibata` cursor theme for `X11` & `Windows` platforms.
```
:config: (Dict) `Bibata` configuration.
:x_out_dir: (Path) Path to the output directory,
Where the `X11` cursor theme package will generate.
It also creates a directory if not exists.
:win_out_dir: (Path) Path to the output directory,
Where the `Windows` cursor theme package will generate.
It also creates a directory if not exists.
:info: (Dict) Content theme name & comment
```
"""
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)
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:
x_cfg = alias.create(x_sizes, delay)
print(f"Building '{x_cfg.stem}' XCursor...")
XCursor.create(x_cfg, x_out_dir)
if item.get("win_key"):
win_build(item, alias)
add_missing_xcursor(x_out_dir / "cursors")
XPackager(x_out_dir, info.name, info.comment)
WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)

202
builder/bbpkg/symlinks.py Normal file
View file

@ -0,0 +1,202 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from typing import Dict, List, Union
from clickgen.util import chdir
def add_missing_xcursor(directory) -> None:
"""Add missing `XCursor` to the Unix cursor package.
:directory: (Path|str) directory where XCursors are available.
"""
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",
# crosshair
"crosshair",
],
},
# {
# "src": "crossed_circle",
# "links": [
# "03b6e0fcb3499374a867c041f52298f0",
# "not-allowed",
# "forbidden",
# "circle",
# ],
# },
{
"src": "dnd_no_drop",
"links": [
"no-drop",
# crossed_circle symlinks
"crossed_circle",
"03b6e0fcb3499374a867c041f52298f0",
"not-allowed",
"forbidden",
"circle",
],
},
{"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",
# center_ptr symlinks
"center_ptr",
],
},
{
"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"]}, # required
{"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",
# left_side symlinks
"left_side",
"w-resize",
"right_side",
"e-resize",
],
},
{"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",
# top_side symlinks
"top_side",
"s-resize",
"n-resize",
"bottom_side",
],
},
# {"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 = item.get("src")
for link in item.get("links"):
print(f"Creating symlink {src} -> {link}")
os.symlink(src, link)

22
builder/setup.py Normal file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup
setup(
name="bbpkg",
version="1.0.4",
description="Generate 'Bibata' cursor theme from PNGs file",
url="https://github.com/ful1e5/Bibata_Cursor",
packages=["bbpkg"],
package_dir={"bbpkg": "bbpkg"},
author="Kaiz Khatri",
author_email="kaizmandhu@gamil.com",
install_requires=["clickgen==1.1.8"],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
],
python_requires=">=3.8",
zip_safe=True,
)