mirror of
https://github.com/ful1e5/apple_cursor.git
synced 2025-05-23 19:47:05 -04:00
💝 Performance tweak & prettier
This commit is contained in:
parent
75bba67132
commit
0fe8b2f1d3
7 changed files with 197 additions and 204 deletions
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": false
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
|
|
118
hotspots.json
118
hotspots.json
|
@ -1,102 +1,102 @@
|
|||
{
|
||||
"all_scroll": { "xhot": 100, "yhot": 100 },
|
||||
"all_scroll": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"bottom_left_corner": { "xhot": 100, "yhot": 100 },
|
||||
"fd_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"top_right_corner": { "xhot": 100, "yhot": 100 },
|
||||
"bottom_left_corner": { "xhot": 100, "yhot": 100 },
|
||||
"fd_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"top_right_corner": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"bottom_right_corner": { "xhot": 100, "yhot": 100 },
|
||||
"bd_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"top_left_corner": { "xhot": 100, "yhot": 100 },
|
||||
"bottom_right_corner": { "xhot": 100, "yhot": 100 },
|
||||
"bd_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"top_left_corner": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"bottom_tee": { "xhot": 141, "yhot": 99 },
|
||||
"bottom_tee": { "xhot": 141, "yhot": 99 },
|
||||
|
||||
"center_ptr": { "xhot": 61, "yhot": 100 },
|
||||
"center_ptr": { "xhot": 61, "yhot": 100 },
|
||||
|
||||
"circle": { "xhot": 47, "yhot": 39 },
|
||||
"crossed_circle": { "xhot": 47, "yhot": 39 },
|
||||
"dnd_no_drop": { "xhot": 47, "yhot": 39 },
|
||||
"circle": { "xhot": 47, "yhot": 39 },
|
||||
"crossed_circle": { "xhot": 47, "yhot": 39 },
|
||||
"dnd_no_drop": { "xhot": 47, "yhot": 39 },
|
||||
|
||||
"context_menu": { "xhot": 61, "yhot": 58 },
|
||||
"context_menu": { "xhot": 61, "yhot": 58 },
|
||||
|
||||
"copy": { "xhot": 47, "yhot": 39 },
|
||||
"dnd_copy": { "xhot": 47, "yhot": 39 },
|
||||
"copy": { "xhot": 47, "yhot": 39 },
|
||||
"dnd_copy": { "xhot": 47, "yhot": 39 },
|
||||
|
||||
"cross": { "xhot": 100, "yhot": 100 },
|
||||
"tcross": { "xhot": 100, "yhot": 100 },
|
||||
"cross": { "xhot": 100, "yhot": 100 },
|
||||
"tcross": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"crosshair": { "xhot": 100, "yhot": 100 },
|
||||
"crosshair": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"dotbox": { "xhot": 100, "yhot": 100 },
|
||||
"dotbox": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"hand1": { "xhot": 94, "yhot": 105 },
|
||||
"hand1": { "xhot": 94, "yhot": 105 },
|
||||
|
||||
"hand2": { "xhot": 66, "yhot": 34 },
|
||||
"hand2": { "xhot": 66, "yhot": 34 },
|
||||
|
||||
"left_ptr": { "xhot": 68, "yhot": 41 },
|
||||
"left_ptr": { "xhot": 68, "yhot": 41 },
|
||||
|
||||
"left_side": { "xhot": 100, "yhot": 100 },
|
||||
"right_side": { "xhot": 100, "yhot": 100 },
|
||||
"left_side": { "xhot": 100, "yhot": 100 },
|
||||
"right_side": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"left_tee": { "xhot": 100, "yhot": 58 },
|
||||
"left_tee": { "xhot": 100, "yhot": 58 },
|
||||
|
||||
"link": { "xhot": 61, "yhot": 105 },
|
||||
"dnd_link": { "xhot": 61, "yhot": 105 },
|
||||
"link": { "xhot": 61, "yhot": 105 },
|
||||
"dnd_link": { "xhot": 61, "yhot": 105 },
|
||||
|
||||
"ll_angle": { "xhot": 141, "yhot": 58 },
|
||||
"ll_angle": { "xhot": 141, "yhot": 58 },
|
||||
|
||||
"lr_angle": { "xhot": 141, "yhot": 138 },
|
||||
"lr_angle": { "xhot": 141, "yhot": 138 },
|
||||
|
||||
"move": { "xhot": 80, "yhot": 106 },
|
||||
"dnd_move": { "xhot": 80, "yhot": 106 },
|
||||
"dnd_none": { "xhot": 80, "yhot": 106 },
|
||||
"grabbing": { "xhot": 80, "yhot": 106 },
|
||||
"pointer_move": { "xhot": 80, "yhot": 106 },
|
||||
"move": { "xhot": 80, "yhot": 106 },
|
||||
"dnd_move": { "xhot": 80, "yhot": 106 },
|
||||
"dnd_none": { "xhot": 80, "yhot": 106 },
|
||||
"grabbing": { "xhot": 80, "yhot": 106 },
|
||||
"pointer_move": { "xhot": 80, "yhot": 106 },
|
||||
|
||||
"pencil": { "xhot": 141, "yhot": 58 },
|
||||
"pencil": { "xhot": 141, "yhot": 58 },
|
||||
|
||||
"plus": { "xhot": 100, "yhot": 100 },
|
||||
"plus": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"question_arrow": { "xhot": 105, "yhot": 105 },
|
||||
"dnd_ask": { "xhot": 105, "yhot": 105 },
|
||||
"question_arrow": { "xhot": 105, "yhot": 105 },
|
||||
"dnd_ask": { "xhot": 105, "yhot": 105 },
|
||||
|
||||
"right_ptr": { "xhot": 61, "yhot": 138 },
|
||||
"right_ptr": { "xhot": 61, "yhot": 138 },
|
||||
|
||||
"right_tee": { "xhot": 100, "yhot": 138 },
|
||||
"right_tee": { "xhot": 100, "yhot": 138 },
|
||||
|
||||
"sb_down_arrow": { "xhot": 133, "yhot": 99 },
|
||||
"sb_down_arrow": { "xhot": 133, "yhot": 99 },
|
||||
|
||||
"sb_h_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"sb_h_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"sb_left_arrow": { "xhot": 100, "yhot": 68 },
|
||||
"sb_left_arrow": { "xhot": 100, "yhot": 68 },
|
||||
|
||||
"sb_right_arrow": { "xhot": 100, "yhot": 138 },
|
||||
"sb_right_arrow": { "xhot": 100, "yhot": 138 },
|
||||
|
||||
"sb_up_arrow": { "xhot": 68, "yhot": 99 },
|
||||
"sb_up_arrow": { "xhot": 68, "yhot": 99 },
|
||||
|
||||
"sb_v_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
"sb_v_double_arrow": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"top_side": { "xhot": 100, "yhot": 100 },
|
||||
"bottom_side": { "xhot": 100, "yhot": 100 },
|
||||
"top_side": { "xhot": 100, "yhot": 100 },
|
||||
"bottom_side": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"top_tee": { "xhot": 61, "yhot": 99 },
|
||||
"top_tee": { "xhot": 61, "yhot": 99 },
|
||||
|
||||
"ul_angle": { "xhot": 61, "yhot": 65 },
|
||||
"ul_angle": { "xhot": 61, "yhot": 65 },
|
||||
|
||||
"ur_angle": { "xhot": 61, "yhot": 138 },
|
||||
"ur_angle": { "xhot": 61, "yhot": 138 },
|
||||
|
||||
"vertical_text": { "xhot": 100, "yhot": 102 },
|
||||
"vertical_text": { "xhot": 100, "yhot": 102 },
|
||||
|
||||
"wait": { "xhot": 104, "yhot": 105 },
|
||||
"left_ptr_watch": { "xhot": 104, "yhot": 105 },
|
||||
"wait": { "xhot": 104, "yhot": 105 },
|
||||
"left_ptr_watch": { "xhot": 104, "yhot": 105 },
|
||||
|
||||
"wayland_cursor": { "xhot": 100, "yhot": 100 },
|
||||
"wayland_cursor": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"x_cursor": { "xhot": 100, "yhot": 100 },
|
||||
"x_cursor": { "xhot": 100, "yhot": 100 },
|
||||
|
||||
"xterm": { "xhot": 97, "yhot": 97 },
|
||||
"xterm": { "xhot": 97, "yhot": 97 },
|
||||
|
||||
"zoom_in": { "xhot": 76, "yhot": 78 },
|
||||
"zoom_in": { "xhot": 76, "yhot": 78 },
|
||||
|
||||
"zoom_out": { "xhot": 76, "yhot": 78 }
|
||||
"zoom_out": { "xhot": 76, "yhot": 78 }
|
||||
}
|
||||
|
|
22
nodemon.json
22
nodemon.json
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"restartable": "rs",
|
||||
"ignore": [".git", "node_modules/**/node_modules"],
|
||||
"verbose": true,
|
||||
"execMap": {
|
||||
"ts": "node --require ts-node/register"
|
||||
},
|
||||
"watch": ["src/"],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"ext": "js,json,ts"
|
||||
"restartable": "rs",
|
||||
"ignore": [".git", "node_modules/**/node_modules"],
|
||||
"verbose": true,
|
||||
"execMap": {
|
||||
"ts": "node --require ts-node/register"
|
||||
},
|
||||
"watch": ["src/"],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"ext": "js,json,ts"
|
||||
}
|
||||
|
|
62
package.json
62
package.json
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"name": "apple_cursor",
|
||||
"version": "1.0.6",
|
||||
"description": "🍎 macOS Cursor Theme",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"clean": "rm -rf bitmaps themes",
|
||||
"dev": "nodemon src/index.ts",
|
||||
"watch": "nodemon --inspect src/index.ts",
|
||||
"py_install": "pip install -r requirements.txt",
|
||||
"render": "yarn ts-node src/index.ts",
|
||||
"build": "python build.py",
|
||||
"compile": "yarn clean && yarn render && yarn build"
|
||||
},
|
||||
"repository": "git@github.com:ful1e5/apple_cursor.git",
|
||||
"author": "Kaiz Khatri",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/pixelmatch": "^5.2.2",
|
||||
"@types/pngjs": "^3.4.2",
|
||||
"@types/puppeteer": "^3.0.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"ts-node": "^8.10.2",
|
||||
"tslint": "^6.1.2",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^6.0.0",
|
||||
"puppeteer": "^5.2.1"
|
||||
}
|
||||
"name": "apple_cursor",
|
||||
"version": "1.0.6",
|
||||
"description": "🍎 macOS Cursor Theme",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"clean": "rm -rf bitmaps themes",
|
||||
"dev": "nodemon src/index.ts",
|
||||
"watch": "nodemon --inspect src/index.ts",
|
||||
"py_install": "pip install -r requirements.txt",
|
||||
"render": "yarn ts-node src/index.ts",
|
||||
"build": "python build.py",
|
||||
"compile": "yarn clean && yarn render && yarn build"
|
||||
},
|
||||
"repository": "git@github.com:ful1e5/apple_cursor.git",
|
||||
"author": "Kaiz Khatri",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/pixelmatch": "^5.2.2",
|
||||
"@types/pngjs": "^3.4.2",
|
||||
"@types/puppeteer": "^3.0.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"ts-node": "^8.10.2",
|
||||
"tslint": "^6.1.2",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^6.0.0",
|
||||
"puppeteer": "^5.2.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,12 @@ import { resolve } from "path";
|
|||
import { readdirSync, existsSync } from "fs";
|
||||
|
||||
// Source Directory
|
||||
const svgsDir = resolve(__dirname, "svg");
|
||||
if (!existsSync(svgsDir)) {
|
||||
console.log("Source .svg files not found");
|
||||
}
|
||||
const staticCursorsDir = resolve(__dirname, "svg", "static");
|
||||
const animatedCursorsDir = resolve(__dirname, "svg", "animated");
|
||||
|
||||
const staticCursorsDir = resolve(svgsDir, "static");
|
||||
const animatedCursorsDir = resolve(svgsDir, "animated");
|
||||
if (!existsSync(staticCursorsDir) || !existsSync(animatedCursorsDir)) {
|
||||
throw new Error("svg directory not found");
|
||||
}
|
||||
|
||||
// Out Directory
|
||||
const bitmapsDir = resolve(__dirname, "../", "bitmaps");
|
||||
|
|
182
src/index.ts
182
src/index.ts
|
@ -1,16 +1,40 @@
|
|||
import "module-alias/register";
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import puppeteer from "puppeteer";
|
||||
import Pixelmatch from "pixelmatch";
|
||||
|
||||
import { htmlTemplate } from "./utils/htmlTemplate";
|
||||
import { staticCursors, bitmapsDir, animatedCursors } from "./config";
|
||||
import { matchImages } from "./utils/matchImages";
|
||||
import { saveFrames, Frames } from "./utils/saveFrames";
|
||||
import { PNG } from "pngjs";
|
||||
import puppeteer, { ElementHandle, Page } from "puppeteer";
|
||||
|
||||
import { animatedCursors, bitmapsDir, staticCursors } from "./config";
|
||||
import { getFrameName } from "./utils/getFrameName";
|
||||
import { toHTML } from "./utils/toHTML";
|
||||
|
||||
const getSVGElement = async (page: Page) => {
|
||||
const svg = await page.$("#container svg");
|
||||
|
||||
if (!svg) {
|
||||
throw new Error("svg element not found!");
|
||||
}
|
||||
return svg;
|
||||
};
|
||||
|
||||
const screenshot = async (element: ElementHandle<Element>): Promise<Buffer> => {
|
||||
return await element.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary",
|
||||
});
|
||||
};
|
||||
|
||||
const saveFrame = (key: string, frame: Buffer) => {
|
||||
const out_path = path.resolve(bitmapsDir, key);
|
||||
fs.writeFileSync(out_path, frame, { encoding: "binary" });
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
const browser = await puppeteer.launch({
|
||||
ignoreDefaultArgs: [" --single-process ", "--no-sandbox"],
|
||||
ignoreDefaultArgs: ["--single-process", "--no-sandbox"],
|
||||
headless: true,
|
||||
});
|
||||
|
||||
|
@ -18,100 +42,70 @@ const main = async () => {
|
|||
fs.mkdirSync(bitmapsDir);
|
||||
}
|
||||
|
||||
try {
|
||||
console.log("📸 Rendering Static Cursors...");
|
||||
|
||||
for (let svgPath of staticCursors) {
|
||||
const buffer = fs.readFileSync(path.resolve(svgPath), "utf8");
|
||||
if (!buffer) throw new Error(`${svgPath} File Read error`);
|
||||
|
||||
// Generating HTML Template
|
||||
const data = buffer.toString();
|
||||
const template = htmlTemplate(data);
|
||||
|
||||
// config
|
||||
const bitmapName = `${path.basename(svgPath, ".svg")}.png`;
|
||||
const out = path.resolve(bitmapsDir, bitmapName);
|
||||
|
||||
// Render
|
||||
const page = await browser.newPage();
|
||||
await page.setContent(template);
|
||||
|
||||
await page.waitForSelector("#container");
|
||||
const svgElement = await page.$("#container svg");
|
||||
if (!svgElement) throw new Error("svg element not found");
|
||||
await svgElement.screenshot({ omitBackground: true, path: out });
|
||||
|
||||
await page.close();
|
||||
for (const svgFilePath of staticCursors) {
|
||||
const svgData = fs.readFileSync(svgFilePath, "utf-8");
|
||||
if (!svgData) {
|
||||
throw new Error(`${svgFilePath} File Read error`);
|
||||
}
|
||||
|
||||
console.log("🎥 Rendering Animated Cursors...");
|
||||
const page = await browser.newPage();
|
||||
const html = toHTML(svgData);
|
||||
|
||||
for (let svgPath of animatedCursors) {
|
||||
const buffer = fs.readFileSync(svgPath, "utf8");
|
||||
if (!buffer) throw new Error(`${svgPath} File Read error`);
|
||||
await page.setContent(html);
|
||||
const svg = await getSVGElement(page);
|
||||
|
||||
// Generating HTML Template
|
||||
const data = buffer.toString();
|
||||
const template = htmlTemplate(data);
|
||||
const key = `${path.basename(svgFilePath, ".svg")}.png`;
|
||||
const out = path.join(bitmapsDir, key);
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setContent(template, { waitUntil: "networkidle2" });
|
||||
|
||||
await page.waitForSelector("#container");
|
||||
const svgElement = await page.$("#container svg");
|
||||
if (!svgElement) throw new Error("svg element not found");
|
||||
|
||||
// Render Config
|
||||
let index = 1;
|
||||
let breakRendering = false;
|
||||
const frames: Frames = {};
|
||||
const firstKey = getFrameName(index, svgPath);
|
||||
|
||||
console.log("Rendering", path.basename(svgPath), "...");
|
||||
console.log(firstKey);
|
||||
|
||||
// 1st Frame
|
||||
frames[firstKey] = {
|
||||
buffer: await svgElement.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary",
|
||||
}),
|
||||
};
|
||||
|
||||
// Pushing frames until it match to 1st frame
|
||||
index++;
|
||||
while (!breakRendering) {
|
||||
const newFrame = await svgElement.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary",
|
||||
});
|
||||
const key = getFrameName(index, svgPath);
|
||||
console.log(key);
|
||||
const diff = matchImages({
|
||||
img1Buff: frames[firstKey].buffer,
|
||||
img2Buff: newFrame,
|
||||
});
|
||||
|
||||
if (!(diff < 700)) {
|
||||
frames[key] = { buffer: newFrame };
|
||||
} else {
|
||||
breakRendering = true;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
saveFrames(frames);
|
||||
|
||||
await page.close();
|
||||
}
|
||||
|
||||
console.log(`\nBitmaps stored at ${bitmapsDir}\n\n🎉 Render Done.`);
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
console.log("Saving", key, "...");
|
||||
await svg.screenshot({ omitBackground: true, path: out });
|
||||
await page.close();
|
||||
}
|
||||
|
||||
for (const svgFilePath of animatedCursors) {
|
||||
const svgData = fs.readFileSync(svgFilePath, "utf8");
|
||||
if (!svgData) {
|
||||
throw new Error(`${svgFilePath} File Read error`);
|
||||
}
|
||||
|
||||
const page = await browser.newPage();
|
||||
const html = toHTML(svgData);
|
||||
|
||||
await page.setContent(html);
|
||||
const svg = await getSVGElement(page);
|
||||
|
||||
let index = 1;
|
||||
let breakRendering = false;
|
||||
|
||||
// Rendering 1st frame
|
||||
const img1 = await screenshot(svg);
|
||||
const key1 = getFrameName(index, svgFilePath);
|
||||
|
||||
console.log("Saving", key1, "...");
|
||||
saveFrame(key1, img1);
|
||||
|
||||
// Rendering frames till `imgN` matched to `img1`
|
||||
while (!breakRendering) {
|
||||
++index;
|
||||
const imgN = await screenshot(svg);
|
||||
const keyN = getFrameName(index, svgFilePath);
|
||||
|
||||
console.log("Saving", keyN, "...");
|
||||
saveFrame(keyN, imgN);
|
||||
|
||||
const { data: img1Data, width, height } = PNG.sync.read(img1);
|
||||
const { data: imgNData } = PNG.sync.read(imgN);
|
||||
|
||||
const diff = Pixelmatch(img1Data, imgNData, null, width, height);
|
||||
|
||||
if (diff <= 100) {
|
||||
breakRendering = !breakRendering;
|
||||
}
|
||||
}
|
||||
|
||||
await page.close();
|
||||
}
|
||||
await browser.close();
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
|
@ -16,4 +16,4 @@ export const template = `
|
|||
`;
|
||||
|
||||
export const toHTML = (svgData: string): string =>
|
||||
template.replace("<svginjection>", svgData);
|
||||
template.replace("<svginjection>", svgData);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue