Merge pull request #1 from ful1e5/dev

👷 Builder & `.svg` Init
This commit is contained in:
Kaiz Khatri
2021-04-24 17:10:39 +05:30
committed by GitHub
32 changed files with 2576 additions and 1 deletions
+52
View File
@@ -0,0 +1,52 @@
all: clean render build
clean:
@rm -rf bitmaps themes
render: bitmapper svg
@cd bitmapper && $(MAKE)
build: bitmaps
@cd builder && make build clean
.PHONY: all
unix: clean render bitmaps
@cd builder && make build_unix clean
windows: clean render bitmaps
@cd builder && make build_windows clean
# Installation
.ONESHELL:
SHELL:=/bin/bash
src = ./themes/BreezeX-*
local := ~/.icons
local_dest := $(local)/BreezeX-*
root := /usr/share/icons
root_dest := $(root)/BreezeX-*
install: themes
@if [[ $EUID -ne 0 ]]; then
@echo "> Installing 'BreezeX' cursors inside $(local)/..."
@mkdir -p $(local)
@cp -r $(src) $(local)/ && echo "> Installed!"
@else
@echo "> Installing 'BreezeX' cursors inside $(root)/..."
@mkdir -p $(root)
@sudo cp -r $(src) $(root)/ && echo "> Installed!"
@fi
uninstall:
@if [[ $EUID -ne 0 ]]; then
@echo "> Removing 'BreezeX' cursors from '$(local)'..."
@rm -rf $(local_dest)
@else
@echo "> Removing 'BreezeX' cursors from '$(root)'..."
@sudo rm -rf $(root_dest)
@fi
reinstall: uninstall install
+3 -1
View File
@@ -1 +1,3 @@
# BreezeX_Cursor
# BreezeX_Cursor
extended KDE cursor 💙
+18
View File
@@ -0,0 +1,18 @@
all: install render
.PHONY: all
install: node_modules package.json
@yarn install
render:
@yarn render
watch:
@yarn watch
node_modules:
@mkdir -p $@
clean:
@rm -rf node_modules yarn.lock
+26
View File
@@ -0,0 +1,26 @@
{
"name": "breezex-bitmapper",
"version": "1.0.0",
"description": "extended KDE cursor 💙",
"main": "index.js",
"repository": "git@github.com:ful1e5/BreezeX_Cursor.git",
"author": "Kaiz Khatri",
"license": "GPL-3.0",
"private": true,
"scripts": {
"render": "npx ts-node src/index.ts"
},
"devDependencies": {
"@types/pixelmatch": "^5.2.2",
"@types/pngjs": "^3.4.2",
"@types/puppeteer": "^5.4.2",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
},
"dependencies": {
"pixelmatch": "^5.2.1",
"pngjs": "^6.0.0",
"puppeteer": "^5.5.0"
}
}
+28
View File
@@ -0,0 +1,28 @@
import { Colors } from "./core/types";
interface Config {
themeName: string;
color: Colors;
}
const breeze = "#4D4D4D";
const white = "#FFFFFF";
const config: Config[] = [
{
themeName: "BreezeX-Dark",
color: {
base: breeze,
outline: white,
},
},
{
themeName: "BreezeX-Light",
color: {
base: white,
outline: breeze,
},
},
];
export { config };
+155
View File
@@ -0,0 +1,155 @@
import fs from "fs";
import path from "path";
import puppeteer, { Browser, ElementHandle, Page } from "puppeteer";
import { frameNumber } from "./util/frameNumber";
import { matchImages } from "./util/matchImages";
import { toHTML } from "./util/toHTML";
class BitmapsGenerator {
/**
* Generate Png files from svg code.
* @param themeName Give name, So all bitmaps files are organized in one directory.
* @param bitmapsDir `absolute` or `relative` path, Where `.png` files will store.
*/
constructor(private bitmapsDir: string) {
this.bitmapsDir = path.resolve(bitmapsDir);
this.createDir(this.bitmapsDir);
}
/**
* Create directory if it doesn't exists.
* @param dirPath directory `absolute` path.
*/
private createDir(dirPath: string) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
}
/**
* Prepare headless browser.
*/
public async getBrowser(): Promise<Browser> {
return await puppeteer.launch({
ignoreDefaultArgs: ["--no-sandbox"],
headless: true,
});
}
private async getSvgElement(
page: Page,
content: string
): Promise<ElementHandle<Element>> {
if (!content) {
throw new Error(`${content} File Read error`);
}
const html = toHTML(content);
await page.setContent(html, { timeout: 0 });
const svg = await page.$("#container svg");
if (!svg) {
throw new Error("svg element not found!");
}
return svg;
}
public async generateStatic(browser: Browser, content: string, key: string) {
const page = await browser.newPage();
const svg = await this.getSvgElement(page, content);
const out = path.resolve(this.bitmapsDir, `${key}.png`);
await svg.screenshot({ omitBackground: true, path: out });
await page.close();
}
private async screenshot(
element: ElementHandle<Element>
): Promise<Buffer | string> {
const buffer = await element.screenshot({
encoding: "binary",
omitBackground: true,
});
if (!buffer) {
throw new Error("SVG element screenshot not working");
}
return buffer;
}
private async stopAnimation(page: Page) {
const client = await page.target().createCDPSession();
await client.send("Animation.setPlaybackRate", {
playbackRate: 0,
});
}
private async resumeAnimation(page: Page, playbackRate: number) {
const client = await page.target().createCDPSession();
await client.send("Animation.setPlaybackRate", {
playbackRate,
});
}
private async saveFrameImage(key: string, frame: Buffer | string) {
const out_path = path.resolve(this.bitmapsDir, key);
fs.writeFileSync(out_path, frame);
}
public async generateAnimated(
browser: Browser,
content: string,
key: string,
options?: {
playbackRate?: number;
diff?: number;
frameLimit?: number;
framePadding?: number;
}
) {
const opt = Object.assign(
{ playbackRate: 0.1, diff: 0, frameLimit: 300, framePadding: 4 },
options
);
const page = await browser.newPage();
const svg = await this.getSvgElement(page, content);
await this.stopAnimation(page);
let index = 1;
let breakRendering = false;
let prevImg: Buffer | string;
// Rendering frames till `imgN` matched to `imgN-1` (When Animation is done)
while (!breakRendering) {
if (index > opt.frameLimit) {
throw new Error("Reached the frame limit.");
}
await this.resumeAnimation(page, opt.playbackRate);
const img: string | Buffer = await this.screenshot(svg);
await this.stopAnimation(page);
if (index > 1) {
// @ts-ignore
const diff = matchImages(prevImg, img);
if (diff <= opt.diff) {
breakRendering = !breakRendering;
}
}
const number = frameNumber(index, opt.framePadding);
const frame = `${key}-${number}.png`;
this.saveFrameImage(frame, img);
prevImg = img;
++index;
}
await page.close();
}
}
export { BitmapsGenerator };
@@ -0,0 +1,77 @@
import fs from "fs";
import path from "path";
interface Svg {
key: string;
content: string;
}
class SvgDirectoryParser {
/**
* Manage and Parse SVG file path in `absolute` fashion.
* This Parser look svg files as below fashion:
* `
* <@svgDir>/static
* <@svgDir>/animated
* `
* @param svgDir is relative/absolute path, Where `SVG` files are stored.
*/
semiAnimated: boolean = false;
constructor(private svgDir: string) {
if (!fs.existsSync(this.svgDir)) {
throw new Error(`SVG files not found in ${this.svgDir}`);
}
}
private readData(f: string): Svg {
const content = fs.readFileSync(f, "utf-8");
const key = path.basename(f, ".svg");
return { content, key };
}
/**
* Return absolute paths array of SVG files data located inside '@svgDir/static'
*/
public getStatic(): Svg[] {
const staticDir = path.resolve(this.svgDir, "static");
if (!fs.existsSync(staticDir)) {
console.log(`${this.svgDir} contains semi-animated .svg files`);
this.semiAnimated = true;
return [];
} else {
const svgs = fs
.readdirSync(staticDir)
.map((f) => this.readData(path.resolve(staticDir, f)));
if (svgs.length == 0) {
throw new Error("Static Cursors directory is empty");
}
return svgs;
}
}
/**
* Return absolute paths array of SVG files data located inside '@svgDir/animated'
*/
public getAnimated(): Svg[] {
const animatedDir = path.resolve(this.svgDir, "animated");
if (!fs.existsSync(animatedDir)) {
throw new Error("Animated Cursors directory not found");
}
const svgs = fs
.readdirSync(animatedDir)
.map((f) => this.readData(path.resolve(animatedDir, f)));
if (svgs.length == 0 && this.semiAnimated) {
throw new Error(
`Can't parse svg directory ${this.svgDir} as semi-animated theme`
);
}
return svgs;
}
}
export { SvgDirectoryParser };
+52
View File
@@ -0,0 +1,52 @@
import { Colors } from "../types";
/**
* Default Key Colors for generating colored svg.
* base="#00FF00" (Green)
* outline="#0000FF" (Blue)
* watch.background="#FF0000" (Red)
* */
const defaultKeyColors: Colors = {
base: "#00FF00",
outline: "#0000FF",
watch: {
background: "#FF0000",
},
};
/**
* Customize colors of svg code.
* @param {string} content SVG code.
* @param {Colors} colors Customize colors.
* @param {Colors} [keys] Colors Key, That was written SVG code.
* @returns {string} SVG code with colors.
*/
const colorSvg = (
content: string,
colors: Colors,
keys: Colors = defaultKeyColors
): string => {
content = content
.replace(new RegExp(keys.base, "ig"), colors.base)
.replace(new RegExp(keys.outline, "ig"), colors.outline);
try {
// === trying to replace `watch` color ===
if (!colors.watch?.background) {
throw new Error("");
}
const { background: b } = colors.watch;
content = content.replace(new RegExp(keys.watch!.background, "ig"), b); // Watch Background
} catch (error) {
// === on error => replace `watch` color as `base` ===
content = content.replace(
new RegExp(keys.watch!.background, "ig"),
colors.base
);
}
return content;
};
export { colorSvg };
+4
View File
@@ -0,0 +1,4 @@
import { colorSvg } from "./colorSvg";
import { SvgDirectoryParser } from "./SvgDirectoryParser";
export { colorSvg, SvgDirectoryParser };
+4
View File
@@ -0,0 +1,4 @@
import { BitmapsGenerator } from "./BitmapsGenerator";
import * as SVGHandler from "./SVGHandler";
export { BitmapsGenerator, SVGHandler };
+20
View File
@@ -0,0 +1,20 @@
/**
* Hex Colors in string Format.
*
* `Example: `"#FFFFFF"
*/
type HexColor = string;
/**
* @Colors expect `base`, `outline` & `watch-background` colors in **HexColor** Format.
* @default background is `base` color.
*/
type Colors = {
base: HexColor;
outline: HexColor;
watch?: {
background: HexColor;
};
};
export { Colors };
+7
View File
@@ -0,0 +1,7 @@
export const frameNumber = (index: number, padding: number) => {
let result = "" + index;
while (result.length < padding) {
result = "0" + result;
}
return result;
};
+11
View File
@@ -0,0 +1,11 @@
import Pixelmatch from "pixelmatch";
import { PNG } from "pngjs";
export const matchImages = (img1: Buffer, img2: Buffer): number => {
const { data: img1Data, width, height } = PNG.sync.read(img1);
const { data: imgNData } = PNG.sync.read(img2);
return Pixelmatch(img1Data, imgNData, null, width, height, {
threshold: 0.1,
});
};
+19
View File
@@ -0,0 +1,19 @@
export const template = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Render Template</title>
</head>
<body>
<div id="container">
<svginjection>
</div>
</body>
</html>
`;
export const toHTML = (svgData: string): string =>
template.replace("<svginjection>", svgData);
+37
View File
@@ -0,0 +1,37 @@
import path from "path";
import { BitmapsGenerator, SVGHandler } from "./core";
import { config } from "./config";
const root = path.resolve(__dirname, "../../");
const svgDir = path.resolve(root, "svg");
const main = async () => {
for (const { themeName, color } of config) {
console.log("=>", themeName);
const bitmapsDir = path.resolve(root, "bitmaps", themeName);
const svg = new SVGHandler.SvgDirectoryParser(svgDir);
const png = new BitmapsGenerator(bitmapsDir);
const browser = await png.getBrowser();
for (let { key, content } of svg.getStatic()) {
console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color);
await png.generateStatic(browser, content, key);
}
for (let { key, content } of svg.getAnimated()) {
console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color);
await png.generateAnimated(browser, content, key);
}
await browser.close();
}
};
main();
+12
View File
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"strictNullChecks": true,
"esModuleInterop": true,
"target": "ES2015",
"module": "commonjs",
"lib": ["es2015", "dom"],
"noUnusedParameters": true
}
}
+1195
View File
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
bitmaps_dir = "../bitmaps"
.PHONY: all
all: clean setup build
.ONESHELL:
SHELL:=/bin/bash
THEMES = Dark Light
X_SIZES ?=22 24 28 32 40 48 56 64 72 80 88 96
WIN_CANVAS_SIZE ?= 32
WIN_SIZE ?= 24
clean:
@rm -rf bxbuild/__pycache__
setup:
@python3 -m pip install clickgen --user
build: setup build.py
@$(foreach theme,$(THEMES), python3 build.py -p "$(bitmaps_dir)/BreezeX-$(theme)" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
build_unix: setup build.py
@$(foreach theme,$(THEMES), python3 build.py unix -p "$(bitmaps_dir)/BreezeX-$(theme)" --xsizes $(X_SIZES);)
build_windows: setup build.py
@$(foreach theme,$(THEMES), python3 build.py windows -p "$(bitmaps_dir)/BreezeX-$(theme)" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
from pathlib import Path
from bxbuild.configure import get_config
from bxbuild.generator import Info, build, wbuild, xbuild
parser = argparse.ArgumentParser(
prog="breezex_builder",
description="'BreezeX' cursor build python script.",
)
# Positional Args.
parser.add_argument(
"platform",
choices=("windows", "unix", "all"),
default="all",
const="all",
nargs="?",
help="Set package type, Which you want to build. (default: '%(default)s')",
)
# Optional Args.
parser.add_argument(
"-p",
"--png-dir",
dest="png_dir",
metavar="PNG",
type=str,
default="../bitmaps",
help="To change pngs directory. (default: %(default)s)",
)
parser.add_argument(
"-o",
"--out-dir",
dest="out_dir",
metavar="OUT",
type=str,
default="../themes",
help="To change output directory. (default: %(default)s)",
)
parser.add_argument(
"-xs",
"--xsizes",
dest="xsizes",
metavar="INT",
nargs="+",
default=[
22,
24,
28,
32,
40,
48,
56,
64,
72,
80,
88,
96,
],
type=int,
help="Set pixel-size for xcursor. (default: %(default)s)",
)
parser.add_argument(
"-ws",
"--win-size",
dest="win_size",
metavar="INT",
default=24,
type=int,
help="Set pixel-size for Windows cursors. (default: %(default)s)",
)
parser.add_argument(
"-wcs",
"--win-canvas-size",
dest="win_canvas_size",
metavar="INT",
default=32,
type=int,
help="Set pixel-size for Windows cursor's canvas. (default: %(default)s)",
)
# Preparing build
args = parser.parse_args()
bitmaps_dir = Path(args.png_dir)
name = bitmaps_dir.stem
x_out_dir = Path(args.out_dir) / name
win_out_dir = Path(args.out_dir) / f"{name}-Windows"
print(f"Getting '{name}' bitmaps ready for build...")
config = get_config(
bitmaps_dir,
x_sizes=args.xsizes,
win_canvas_size=args.win_canvas_size,
win_size=args.win_size,
)
info = Info(name=name, comment=f"{name} Cursors")
if args.platform == "unix":
xbuild(config, x_out_dir, info)
elif args.platform == "windows":
wbuild(config, win_out_dir, info)
else:
build(config, x_out_dir, win_out_dir, info)
View File
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pathlib import Path
from typing import Any, Dict, Tuple, TypeVar, Union
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: Union[str, Path], **kwargs) -> Dict[str, Any]:
"""Return configuration of `BreezeX` 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
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Dict
# Info
AUTHOR = "Kaiz Khatri"
URL = "https://github.com/ful1e5/BreezeX_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": 100, "yhot": 100},
"context-menu.png": {"xhot": 100, "yhot": 100},
"copy.png": {"xhot": 100, "yhot": 100},
"cross.png": {"xhot": 100, "yhot": 100},
"dnd_no_drop.png": {"xhot": 100, "yhot": 100},
"dotbox.png": {"xhot": 100, "yhot": 100},
"hand1.png": {"xhot": 100, "yhot": 100},
"hand2.png": {"xhot": 100, "yhot": 100},
"left_ptr.png": {"xhot": 100, "yhot": 100},
"left_tee.png": {"xhot": 100, "yhot": 100},
"link.png": {"xhot": 100, "yhot": 100},
"ll_angle.png": {"xhot": 100, "yhot": 100},
"lr_angle.png": {"xhot": 100, "yhot": 100},
"move.png": {"xhot": 100, "yhot": 100},
"pencil.png": {"xhot": 100, "yhot": 100},
"plus.png": {"xhot": 100, "yhot": 100},
"question_arrow.png": {"xhot": 100, "yhot": 100},
"right_ptr.png": {"xhot": 100, "yhot": 100},
"right_tee.png": {"xhot": 100, "yhot": 100},
"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_tee.png": {"xhot": 100, "yhot": 100},
"ul_angle.png": {"xhot": 100, "yhot": 100},
"ur_angle.png": {"xhot": 100, "yhot": 100},
"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": 89},
"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": 100, "yhot": 100},
"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"},
}
+123
View File
@@ -0,0 +1,123 @@
#!/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 .constants import AUTHOR, URL
from .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 `BreezeX` cursor theme for only `X11`(UNIX) platform.
:param config: `BreezeX` 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, info.name, info.comment)
def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None:
"""Build `BreezeX` cursor theme for only `Windows` platforms.
:param config: `BreezeX` 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(
item["win_size"],
item["canvas_size"],
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 build(
config: Dict[str, Dict[str, Any]], x_out_dir: Path, win_out_dir: Path, info: Info
) -> None:
"""Build `BreezeX` cursor theme for `X11` & `Windows` platforms.
:param config: `BreezeX` 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(
item["win_size"],
item["canvas_size"],
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, info.name, info.comment)
WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)
+188
View File
@@ -0,0 +1,188 @@
#!/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.
:param directory: directory where XCursors are available.
:type directory: Union[str, 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",
"crosshair",
],
},
{
"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",
],
},
{
"src": "left_ptr_watch",
"links": [
"00000000000000020006000e7e9ffc3f",
"08e8e1c95fe2fc01f976f1e063a24ccd",
"3ecb610c1bf2410f44200f48c40d3599",
"progress",
],
},
{
"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",
"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",
"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(item["src"])
for link in item.get("links"):
print(f"Creating symlink {src} -> {link}")
os.symlink(src, link)
+31
View File
@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M120.282 99.5C120.282 110.978 110.978 120.282 99.5 120.282C88.0222 120.282 78.7177 110.978 78.7177 99.5C78.7177 88.0223 88.0222 78.7178 99.5 78.7178C110.978 78.7178 120.282 88.0223 120.282 99.5Z" fill="white"/>
<path d="M94.4038 23.0608C96.5756 18.9797 102.424 18.9797 104.596 23.0608L123.467 58.5204C124.891 61.1981 123.992 64.5108 121.308 65.9235C115.869 68.7863 106.724 72.9449 99.5 72.9449C92.2761 72.9449 83.1314 68.7863 77.692 65.9235C75.0078 64.5108 74.1084 61.1981 75.5334 58.5204L94.4038 23.0608Z" fill="white"/>
<path d="M23.0608 104.538C18.9797 102.366 18.9797 96.5176 23.0608 94.3457L58.5204 75.4753C61.1981 74.0504 64.5108 74.9497 65.9235 77.6339C68.7863 83.0733 72.9449 92.2181 72.9449 99.4419C72.9449 106.666 68.7863 115.811 65.9235 121.25C64.5108 123.934 61.1981 124.833 58.5204 123.408L23.0608 104.538Z" fill="white"/>
<path d="M104.538 175.939C102.366 180.02 96.5175 180.02 94.3457 175.939L75.4753 140.48C74.0503 137.802 74.9496 134.489 77.6338 133.077C83.0732 130.214 92.218 126.055 99.4418 126.055C106.666 126.055 115.81 130.214 121.25 133.077C123.934 134.489 124.833 137.802 123.408 140.48L104.538 175.939Z" fill="white"/>
<path d="M175.939 104.538C180.02 102.366 180.02 96.5176 175.939 94.3457L140.48 75.4753C137.802 74.0504 134.489 74.9497 133.077 77.6339C130.214 83.0733 126.055 92.2181 126.055 99.4419C126.055 106.666 130.214 115.811 133.077 121.25C134.489 123.934 137.802 124.833 140.48 123.408L175.939 104.538Z" fill="white"/>
<path d="M120.282 99.5C120.282 110.978 110.978 120.282 99.5 120.282C88.0222 120.282 78.7177 110.978 78.7177 99.5C78.7177 88.0223 88.0222 78.7178 99.5 78.7178C110.978 78.7178 120.282 88.0223 120.282 99.5Z" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M94.4038 23.0608C96.5756 18.9797 102.424 18.9797 104.596 23.0608L123.467 58.5204C124.891 61.1981 123.992 64.5108 121.308 65.9235C115.869 68.7863 106.724 72.9449 99.5 72.9449C92.2761 72.9449 83.1314 68.7863 77.692 65.9235C75.0078 64.5108 74.1084 61.1981 75.5334 58.5204L94.4038 23.0608Z" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M23.0608 104.538C18.9797 102.366 18.9797 96.5176 23.0608 94.3457L58.5204 75.4753C61.1981 74.0504 64.5108 74.9497 65.9235 77.6339C68.7863 83.0733 72.9449 92.2181 72.9449 99.4419C72.9449 106.666 68.7863 115.811 65.9235 121.25C64.5108 123.934 61.1981 124.833 58.5204 123.408L23.0608 104.538Z" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M104.538 175.939C102.366 180.02 96.5175 180.02 94.3457 175.939L75.4753 140.48C74.0503 137.802 74.9496 134.489 77.6338 133.077C83.0732 130.214 92.218 126.055 99.4418 126.055C106.666 126.055 115.81 130.214 121.25 133.077C123.934 134.489 124.833 137.802 123.408 140.48L104.538 175.939Z" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M175.939 104.538C180.02 102.366 180.02 96.5176 175.939 94.3457L140.48 75.4753C137.802 74.0504 134.489 74.9497 133.077 77.6339C130.214 83.0733 126.055 92.2181 126.055 99.4419C126.055 106.666 130.214 115.811 133.077 121.25C134.489 123.934 137.802 124.833 140.48 123.408L175.939 104.538Z" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<path d="M99.7871 25L119.308 61.915C119.308 61.915 107.902 69.084 99.7871 69.084C91.6719 69.084 80.2662 61.915 80.2662 61.915L99.7871 25Z" fill="#4D4D4D"/>
<path d="M99.7871 175L80.2662 138.085C80.2662 138.085 91.6719 130.916 99.7871 130.916C107.902 130.916 119.308 138.085 119.308 138.085L99.7871 175Z" fill="#4D4D4D"/>
<path d="M24 100L61.0198 80.5343C61.0198 80.5343 68.2091 91.9078 68.2091 100C68.2091 108.092 61.0198 119.466 61.0198 119.466L24 100Z" fill="#4D4D4D"/>
<path d="M175 100L137.98 80.5343C137.98 80.5343 130.791 91.9078 130.791 100C130.791 108.092 137.98 119.466 137.98 119.466L175 100Z" fill="#4D4D4D"/>
<circle cx="100" cy="100" r="16" fill="#F67400"/>
<defs>
<filter id="filter0_d" x="14.5" y="18.5" width="170" height="172" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M99.7344 30.4801L55.3856 129.857C54.715 131.36 55.3687 133.127 56.8356 133.873C63.0168 137.013 78.4017 145.521 86.0678 155.921C91.821 163.726 90.3303 168.935 100.027 168.965C109.723 168.996 107.765 163.777 113.568 156.008C121.289 145.67 136.386 137.267 142.472 134.155C143.927 133.41 144.581 131.657 143.924 130.16L100.192 30.4816C100.104 30.2829 99.8228 30.282 99.7344 30.4801Z" fill="white"/>
<path d="M100.203 30.4768L103.855 28.8745L147.587 128.553C149.12 132.048 147.576 136.037 144.293 137.716C141.341 139.226 136.209 142.017 130.899 145.668C125.543 149.351 120.251 153.744 116.772 158.401C115.523 160.075 114.68 161.622 113.951 163.091C113.8 163.395 113.642 163.724 113.478 164.066C112.928 165.208 112.306 166.501 111.631 167.561C110.629 169.134 109.269 170.64 107.14 171.656C105.116 172.622 102.749 172.974 100.014 172.965C97.2694 172.956 94.9035 172.586 92.8692 171.635C90.7457 170.642 89.3352 169.181 88.2657 167.615C87.4812 166.466 86.7852 165.098 86.1653 163.879C86.0264 163.606 85.8913 163.34 85.7598 163.086C84.9804 161.58 84.106 160.001 82.848 158.294C79.4059 153.625 74.07 149.197 68.6347 145.475C63.2502 141.787 58.0235 138.963 55.0236 137.439C51.7129 135.756 50.1685 131.733 51.7328 128.227L96.0816 28.85L99.7344 30.4801L96.0816 28.85C97.5851 25.4811 102.372 25.4962 103.855 28.8745L100.203 30.4768ZM100.203 30.4768L100.194 30.4804L100.203 30.4768Z" stroke="white" stroke-width="8"/>
</g>
<path d="M99.9644 29.9644L54.9818 130.762C54.5348 131.764 54.9638 132.938 55.9461 133.426C61.3914 136.132 78.0019 144.979 86.0676 155.921C91.8208 163.726 90.3301 168.935 100.027 168.965C109.723 168.996 107.765 163.777 113.567 156.008C121.694 145.127 137.991 136.391 143.353 133.709C144.328 133.221 144.756 132.057 144.318 131.059L99.9644 29.9644Z" fill="#4D4D4D"/>
<defs>
<filter id="filter0_d" x="43.1163" y="22.332" width="113.069" height="164.633" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M57.4358 30.6757L57.3085 139.5C57.3065 141.145 58.622 142.494 60.2653 142.579C67.1894 142.936 84.7041 144.456 95.9356 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C123.949 127.16 134.328 113.346 138.623 108.029C139.651 106.757 139.535 104.89 138.326 103.789L57.8541 30.4912C57.6937 30.3451 57.436 30.4587 57.4358 30.6757Z" fill="white"/>
<path d="M53.4358 30.671V30.6711L53.3085 139.495C53.304 143.333 56.3505 146.382 60.0592 146.573C63.4196 146.747 69.3431 147.203 75.7616 148.383C82.2406 149.575 88.9155 151.452 93.9584 154.319C95.8017 155.367 97.2421 156.454 98.5665 157.514C98.7898 157.692 99.0213 157.88 99.2593 158.073C100.321 158.935 101.513 159.903 102.697 160.633C104.31 161.629 106.193 162.39 108.537 162.435C110.782 162.477 113.094 161.854 115.606 160.746C118.108 159.642 120.128 158.359 121.584 156.654C123.116 154.86 123.746 152.931 124.023 151.087C124.209 149.844 124.252 148.409 124.29 147.143C124.301 146.763 124.312 146.399 124.326 146.059C124.394 144.421 124.536 142.665 124.998 140.628C126.283 134.959 129.332 128.794 132.729 123.252C136.096 117.758 139.651 113.122 141.735 110.543C144.052 107.674 143.841 103.402 141.019 100.832L60.5476 27.534L60.5476 27.534C57.8202 25.0498 53.4401 26.9819 53.4358 30.671Z" stroke="white" stroke-width="8"/>
</g>
<path d="M57.4365 30.1108L57.3074 140.49C57.3061 141.587 58.1752 142.485 59.2712 142.532C65.3462 142.791 84.1186 144.123 95.9357 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C124.099 126.499 135.438 111.893 139.247 107.264C139.94 106.422 139.858 105.184 139.052 104.45L57.4365 30.1108Z" fill="#4D4D4D"/>
<g filter="url(#filter1_d)">
<rect x="77" y="28" width="96" height="96" rx="30" fill="#11D116"/>
</g>
<path d="M120.896 48V71.9117H97V79.8823H120.896V103.794H128.861V79.8823H152.757V71.9117H128.861V48H120.896Z" fill="white"/>
<defs>
<filter id="filter0_d" x="45.3085" y="22.4099" width="106.011" height="154.027" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="73" y="28" width="104" height="106" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M57.4357 30.6757L57.3084 139.5C57.3065 141.145 58.622 142.494 60.2652 142.579C67.1894 142.936 84.704 144.456 95.9356 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C123.949 127.16 134.328 113.346 138.623 108.029C139.65 106.757 139.535 104.89 138.326 103.789L57.854 30.4912C57.6936 30.3451 57.436 30.4587 57.4357 30.6757Z" fill="white"/>
<path d="M53.4357 30.671V30.6711L53.3084 139.495C53.3039 143.333 56.3505 146.382 60.0591 146.573C63.4195 146.747 69.343 147.203 75.7615 148.383C82.2406 149.575 88.9154 151.452 93.9584 154.319C95.8016 155.367 97.242 156.454 98.5664 157.514C98.7898 157.692 99.0212 157.88 99.2593 158.073C100.321 158.935 101.513 159.903 102.697 160.633C104.31 161.629 106.193 162.39 108.537 162.435C110.782 162.477 113.094 161.854 115.606 160.746C118.108 159.642 120.128 158.359 121.584 156.654C123.116 154.86 123.746 152.931 124.023 151.087C124.209 149.844 124.252 148.409 124.29 147.143C124.301 146.763 124.312 146.399 124.326 146.059C124.394 144.421 124.536 142.665 124.998 140.628C126.283 134.959 129.332 128.794 132.729 123.252C136.096 117.758 139.651 113.122 141.735 110.543C144.052 107.674 143.841 103.402 141.019 100.832L60.5476 27.534L60.5476 27.534C57.8202 25.0498 53.44 26.9819 53.4357 30.671Z" stroke="white" stroke-width="8"/>
</g>
<path d="M57.4365 30.1108L57.3074 140.49C57.3061 141.587 58.1752 142.485 59.2712 142.532C65.3462 142.791 84.1186 144.123 95.9357 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C124.099 126.499 135.438 111.893 139.247 107.264C139.94 106.422 139.858 105.184 139.052 104.45L57.4365 30.1108Z" fill="#4D4D4D"/>
<g filter="url(#filter1_d)">
<rect x="77" y="28" width="96" height="96" rx="30" fill="#ED1515"/>
</g>
<path d="M147.632 52.075C137.285 42.2596 121.466 39.9366 108.468 47.4252C95.4704 54.9141 89.5767 69.7472 92.9212 83.5971L147.632 52.075Z" fill="white"/>
<path d="M157.079 68.4033L102.368 99.9254C112.715 109.741 128.534 112.063 141.532 104.575C154.529 97.086 160.423 82.2535 157.079 68.4033Z" fill="white"/>
<defs>
<filter id="filter0_d" x="45.3084" y="22.4099" width="106.011" height="154.027" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="73" y="28" width="104" height="106" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<rect x="20" y="20" width="160" height="160" rx="50" fill="#ED1515"/>
</g>
<path d="M137.72 60.125C120.475 43.766 94.1096 39.8943 72.4468 52.3753C50.7839 64.8568 40.9612 89.5786 46.5353 112.662L137.72 60.125Z" fill="white"/>
<path d="M153.465 87.3388L62.2798 139.876C79.5248 156.235 105.89 160.105 127.553 147.624C149.216 135.143 159.039 110.422 153.465 87.3388Z" fill="white"/>
<defs>
<filter id="filter0_d" x="16" y="20" width="168" height="170" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M57.4356 30.6757L57.3084 139.5C57.3064 141.145 58.6219 142.494 60.2652 142.579C67.1893 142.936 84.7039 144.456 95.9355 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C123.949 127.16 134.328 113.346 138.623 108.029C139.65 106.757 139.535 104.89 138.326 103.789L57.854 30.4912C57.6936 30.3451 57.4359 30.4587 57.4356 30.6757Z" fill="white"/>
<path d="M53.4356 30.671V30.6711L53.3084 139.495C53.3039 143.333 56.3504 146.382 60.0591 146.573C63.4195 146.747 69.343 147.203 75.7614 148.383C82.2405 149.575 88.9154 151.452 93.9583 154.319C95.8016 155.367 97.2419 156.454 98.5664 157.514C98.7897 157.692 99.0212 157.88 99.2592 158.073C100.321 158.935 101.513 159.903 102.697 160.633C104.31 161.629 106.193 162.39 108.537 162.435C110.782 162.477 113.094 161.854 115.606 160.746C118.108 159.642 120.128 158.359 121.584 156.654C123.116 154.86 123.746 152.931 124.023 151.087C124.209 149.844 124.252 148.409 124.29 147.143C124.301 146.763 124.312 146.399 124.326 146.059C124.394 144.421 124.536 142.665 124.998 140.628C126.283 134.959 129.332 128.794 132.729 123.252C136.096 117.758 139.651 113.122 141.734 110.543C144.052 107.674 143.841 103.402 141.019 100.832L60.5475 27.534L60.5475 27.534C57.8201 25.0498 53.44 26.9819 53.4356 30.671Z" stroke="white" stroke-width="8"/>
</g>
<path d="M57.4365 30.1108L57.3074 140.49C57.3061 141.587 58.1752 142.485 59.2712 142.532C65.3462 142.791 84.1186 144.123 95.9357 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C124.099 126.499 135.438 111.893 139.247 107.264C139.94 106.422 139.858 105.184 139.052 104.45L57.4365 30.1108Z" fill="#4D4D4D"/>
<defs>
<filter id="filter0_d" x="45.3083" y="22.4099" width="106.011" height="154.027" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M57.4358 30.6757L57.3085 139.5C57.3065 141.145 58.622 142.494 60.2653 142.579C67.1894 142.936 84.7041 144.456 95.9356 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C123.949 127.16 134.328 113.346 138.623 108.029C139.651 106.757 139.535 104.89 138.326 103.789L57.8541 30.4912C57.6937 30.3451 57.436 30.4587 57.4358 30.6757Z" fill="white"/>
<path d="M53.4358 30.671V30.6711L53.3085 139.495C53.304 143.333 56.3505 146.382 60.0592 146.573C63.4196 146.747 69.3431 147.203 75.7616 148.383C82.2406 149.575 88.9155 151.452 93.9584 154.319C95.8017 155.367 97.2421 156.454 98.5665 157.514C98.7898 157.692 99.0213 157.88 99.2593 158.073C100.321 158.935 101.513 159.903 102.697 160.633C104.31 161.629 106.193 162.39 108.537 162.435C110.782 162.477 113.094 161.854 115.606 160.746C118.108 159.642 120.128 158.359 121.584 156.654C123.116 154.86 123.746 152.931 124.023 151.087C124.209 149.844 124.252 148.409 124.29 147.143C124.301 146.763 124.312 146.399 124.326 146.059C124.394 144.421 124.536 142.665 124.998 140.628C126.283 134.959 129.332 128.794 132.729 123.252C136.096 117.758 139.651 113.122 141.735 110.543C144.052 107.674 143.841 103.402 141.019 100.832L60.5476 27.534L60.5476 27.534C57.8202 25.0498 53.4401 26.9819 53.4358 30.671Z" stroke="white" stroke-width="8"/>
</g>
<path d="M57.4365 30.1108L57.3074 140.49C57.3061 141.587 58.1752 142.485 59.2712 142.532C65.3462 142.791 84.1186 144.123 95.9357 150.842C104.365 155.635 105.12 161 113.991 157.086C122.863 153.173 118.953 149.2 121.097 139.744C124.099 126.499 135.438 111.893 139.247 107.264C139.94 106.422 139.858 105.184 139.052 104.45L57.4365 30.1108Z" fill="#4D4D4D"/>
<g filter="url(#filter1_d)">
<rect x="77" y="28" width="96" height="96" rx="30" fill="#3DAEE9"/>
</g>
<path d="M108.388 59.7898L104.84 50.9975C108.989 39.7743 136.199 36.9465 142.857 50.6589C149.465 64.2676 132.213 73.8233 129.678 79.234C126.136 86.7964 127.988 88.5334 127.988 88.5334H117.851C117.851 88.5334 113.595 79.1399 129.171 64.6931C137.682 56.7992 123.416 41.2626 108.388 59.7898Z" fill="white"/>
<path d="M130.354 103.159C130.354 104.103 130.168 105.037 129.808 105.909C129.447 106.781 128.918 107.573 128.251 108.241C127.584 108.908 126.792 109.437 125.921 109.798C125.05 110.159 124.116 110.345 123.173 110.345C121.268 110.345 119.442 109.588 118.095 108.241C116.749 106.893 115.992 105.065 115.992 103.159C115.992 101.253 116.749 99.4256 118.095 98.078C119.442 96.7303 121.268 95.9733 123.173 95.9733C124.116 95.9733 125.05 96.1591 125.921 96.5202C126.792 96.8813 127.584 97.4107 128.251 98.078C128.918 98.7453 129.447 99.5373 129.808 100.409C130.168 101.281 130.354 102.216 130.354 103.159Z" fill="white"/>
<defs>
<filter id="filter0_d" x="45.3085" y="22.4099" width="106.011" height="154.027" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="73" y="28" width="104" height="106" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none">
<g filter="url(#filter0_d)">
<path d="M137.588 30.6757L137.715 139.5C137.717 141.145 136.402 142.494 134.758 142.579C127.834 142.936 110.32 144.456 99.0879 150.842C90.6588 155.635 89.9039 161 81.0322 157.086C72.1604 153.173 76.0706 149.2 73.9269 139.744C71.0744 127.16 60.6956 113.346 56.4007 108.029C55.373 106.757 55.4887 104.89 56.6977 103.789L137.169 30.4912C137.33 30.3451 137.588 30.4587 137.588 30.6757Z" fill="white"/>
<path d="M141.588 30.671V30.6711L141.715 139.495C141.72 143.333 138.673 146.382 134.964 146.573C131.604 146.747 125.68 147.203 119.262 148.383C112.783 149.575 106.108 151.452 101.065 154.319C99.2219 155.367 97.7815 156.454 96.4571 157.514C96.2337 157.692 96.0023 157.88 95.7642 158.073C94.7024 158.935 93.5103 159.903 92.3267 160.633C90.7132 161.629 88.8306 162.39 86.4867 162.435C84.2412 162.477 81.9292 161.854 79.4178 160.746C76.9152 159.642 74.8959 158.359 73.4393 156.654C71.9072 154.86 71.2771 152.931 71.0007 151.087C70.8144 149.844 70.7716 148.409 70.7337 147.143C70.7224 146.763 70.7115 146.399 70.6973 146.059C70.6291 144.421 70.4876 142.665 70.0259 140.628C68.7409 134.959 65.6914 128.794 62.2943 123.252C58.9271 117.758 55.3721 113.122 53.289 110.543C50.9719 107.674 51.1824 103.402 54.0041 100.832L134.476 27.534L134.476 27.534C137.203 25.0498 141.583 26.9819 141.588 30.671Z" stroke="white" stroke-width="8"/>
</g>
<path d="M137.587 30.1108L137.716 140.49C137.717 141.587 136.848 142.485 135.752 142.532C129.677 142.791 110.905 144.123 99.0879 150.842C90.6588 155.635 89.9039 161 81.0321 157.086C72.1603 153.173 76.0705 149.2 73.9269 139.744C70.9247 126.499 59.5852 111.893 55.7765 107.264C55.0838 106.422 55.1658 105.184 55.9718 104.45L137.587 30.1108Z" fill="#4D4D4D"/>
<defs>
<filter id="filter0_d" x="43.7045" y="22.4099" width="106.011" height="154.027" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB