增加 psd2ui 源码

This commit is contained in:
onvia
2023-07-28 14:23:31 +08:00
parent 38357d6d80
commit 9174aea6e1
59 changed files with 6683 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
import fs from 'fs-extra';
import path from 'path';
import crypto from "crypto";
class FileUtils {
// 深度遍历
DFS(root: string, callback?: (options: {isDirectory: boolean,fullPath: string, fileName: string,depth: number}) => void,depth = 0) {
let exists = fs.existsSync(root);
if (!exists) {
console.log(`FileUtils-> ${root} is not exists`);
return;
}
let files = fs.readdirSync(root);
let _cacheDepth = depth;
depth ++;
files.forEach((file) => {
let fullPath = path.join(root, file);
let stat = fs.lstatSync(fullPath);
let isDirectory = stat.isDirectory();
callback?.({isDirectory,fullPath,fileName: file,depth: _cacheDepth});
if (!isDirectory) {
} else {
this.DFS(fullPath,callback,depth);
}
});
}
filterFile(root: string, filter?: (fileName: string) => boolean) {
let exists = fs.existsSync(root);
if (!exists) {
console.log(`FileUtils-> ${root} is not exists`);
return;
}
var res: string[] = [];
let files = fs.readdirSync(root);
files.forEach((file) => {
let pathName = path.join(root, file);
let stat = fs.lstatSync(pathName);
let isDirectory = stat.isDirectory();
// 只对文件进行判断
if(!isDirectory){
let isPass = filter(file);
if(!isPass){
return;
}
}
if (!isDirectory) {
res.push(pathName);
} else {
res = res.concat(this.filterFile(pathName,filter));
}
});
return res
}
getFolderFiles(dir: string,type: "folder" | "file"){
let exists = fs.existsSync(dir);
if (!exists) {
console.log(`FileUtils-> ${dir} is not exists`);
return;
}
let res: {fullPath: string,basename: string}[] = [];
let files = fs.readdirSync(dir);
files.forEach((file) => {
let fullPath = path.join(dir, file);
let stat = fs.lstatSync(fullPath);
let isDirectory = stat.isDirectory();
if (isDirectory) {
if(type === 'folder'){
res.push({fullPath,basename: file});
}
}else{
if(type === 'file'){
res.push({fullPath,basename: file});
}
}
});
return res;
}
async writeFile(fullPath: string, data: any) {
if(typeof data !== 'string'){
try {
data = JSON.stringify(data,null,2);
} catch (error) {
console.log(`FileUtils->writeFile `,error);
return;
}
}
console.log(`写入文件 ${fullPath}`);
let dir = path.dirname(fullPath);
await fs.mkdirp(dir);
await fs.writeFile(fullPath, data);
console.log(`写入完成 ${fullPath} `);
}
/** 获取文件的 md5 */
getMD5(buffer: Buffer | string){
if(typeof buffer === 'string'){
buffer = fs.readFileSync(buffer);
}
let md5 = crypto.createHash("md5").update(buffer).digest("hex");
return md5;
}
}
export let fileUtils = new FileUtils();

View File

@@ -0,0 +1,60 @@
import canvas from 'canvas';
export interface Border {
l?: number;
r?: number;
t?: number;
b?: number;
}
export class Texture9Utils {
static safeBorder(_canvas: canvas.Canvas, border: Border) {
border.l = (border.l ?? border.r) || 0;
border.r = (border.r ?? border.l) || 0;
border.t = (border.t ?? border.b) || 0;
border.b = (border.b ?? border.t) || 0;
return border;
}
static split(_canvas: canvas.Canvas, border: Border): canvas.Canvas {
this.safeBorder(_canvas, border);
let cw = _canvas.width;
let ch = _canvas.height;
let space = 4;
let left = border.l || cw;
let right = border.r || cw;
let top = border.t || ch;
let bottom = border.b || ch;
if (border.b == 0 && border.t == 0 && border.l == 0 && border.r == 0) {
return _canvas;
}
if (border.l + border.r > cw + space) {
console.log(`Texture9Utils-> 设置的九宫格 left right 数据不合理,请重新设置`);
return _canvas;
}
if (border.b + border.t > ch + space) {
console.log(`Texture9Utils-> 设置的九宫格 bottom top 数据不合理,请重新设置`);
return _canvas;
}
let newCanvas = canvas.createCanvas(Math.min(cw, border.l + border.r + space) || cw, Math.min(ch, border.b + border.t + space) || ch);
let ctx = newCanvas.getContext("2d");
// 左上
ctx.drawImage(_canvas, 0, 0, left + space, top + space, 0, 0, left + space, top + space);
// 左下
ctx.drawImage(_canvas, 0, ch - bottom, left + space, bottom, 0, top + space, left + space, bottom);
// 右上
ctx.drawImage(_canvas, cw - left, 0, right, top + space, left + space, 0, right, top + space);
// 右下
ctx.drawImage(_canvas, cw - left, ch - bottom, right, bottom, left + space, top + space, right, bottom);
return newCanvas;
}
}

View File

@@ -0,0 +1,98 @@
import canvas from 'canvas';
import { PsdLayer } from "../psd/PsdLayer";
import fs from 'fs-extra';
import path from 'path';
import { PsdDocument } from '../psd/PsdDocument';
import { PsdImage } from '../psd/PsdImage';
// ------------decode-uuid
const BASE64_KEYS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const values = new Array(123); // max char code in base64Keys
for (let i = 0; i < 123; ++i) { values[i] = 64; } // fill with placeholder('=') index
for (let i = 0; i < 64; ++i) { values[BASE64_KEYS.charCodeAt(i)] = i; }
// decoded value indexed by base64 char code
const BASE64_VALUES = values;
const HexChars = '0123456789abcdef'.split('');
const _t = ['', '', '', ''];
const UuidTemplate = _t.concat(_t, '-', _t, '-', _t, '-', _t, '-', _t, _t, _t);
const Indices = UuidTemplate.map((x, i) => x === '-' ? NaN : i).filter(isFinite);
let HexMap = {}
{
for (let i = 0; i < HexChars.length; i++) {
let char = HexChars[i]
HexMap[char] = i
}
}
class Utils {
uuid() {
var d = new Date().getTime();
if (globalThis.performance && typeof globalThis.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
decodeUuid(base64) {
const strs = base64.split('@');
const uuid = strs[0];
if (uuid.length !== 22) {
return base64;
}
UuidTemplate[0] = base64[0];
UuidTemplate[1] = base64[1];
for (let i = 2, j = 2; i < 22; i += 2) {
const lhs = BASE64_VALUES[base64.charCodeAt(i)];
const rhs = BASE64_VALUES[base64.charCodeAt(i + 1)];
UuidTemplate[Indices[j++]] = HexChars[lhs >> 2];
UuidTemplate[Indices[j++]] = HexChars[((lhs & 3) << 2) | rhs >> 4];
UuidTemplate[Indices[j++]] = HexChars[rhs & 0xF];
}
return base64.replace(uuid, UuidTemplate.join(''));
}
// 压缩uuid
compressUuid(fullUuid) {
const strs = fullUuid.split('@');
const uuid: string = strs[0];
if (uuid.length !== 36) {
return fullUuid;
}
let zipUuid = []
zipUuid[0] = uuid[0];
zipUuid[1] = uuid[1];
let cleanUuid = uuid.replace('-', '').replace('-', '').replace('-', '').replace('-', '')
for (let i = 2, j = 2; i < 32; i += 3) {
const left = HexMap[String.fromCharCode(cleanUuid.charCodeAt(i))];
const mid = HexMap[String.fromCharCode(cleanUuid.charCodeAt(i + 1))];
const right = HexMap[String.fromCharCode(cleanUuid.charCodeAt(i + 2))];
zipUuid[j++] = BASE64_KEYS[(left << 2) + (mid >> 2)]
zipUuid[j++] = BASE64_KEYS[((mid & 3) << 4) + right]
}
return fullUuid.replace(uuid, zipUuid.join(''));
}
isNumber(val){
return (!isNaN(parseFloat(val)) && isFinite(val));
}
}
export const utils = new Utils();

View File

@@ -0,0 +1,98 @@
var Uuid = require('node-uuid');
var Base64KeyChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var AsciiTo64 = new Array(128);
for (var i = 0; i < 128; ++i) { AsciiTo64[i] = 0; }
for (i = 0; i < 64; ++i) { AsciiTo64[Base64KeyChars.charCodeAt(i)] = i; }
var Reg_Dash = /-/g;
var Reg_Uuid = /^[0-9a-fA-F-]{36}$/;
var Reg_NormalizedUuid = /^[0-9a-fA-F]{32}$/;
var Reg_CompressedUuid = /^[0-9a-zA-Z+/]{22,23}$/;
export class UuidUtils {
// 加了这个标记后,字符串就不可能会是 uuid 了。
static NonUuidMark: '.'
// 压缩后的 uuid 可以减小保存时的尺寸,但不能做为文件名(因为无法区分大小写并且包含非法字符)。
// 默认将 uuid 的后面 27 位压缩成 18 位,前 5 位保留下来,方便调试。
// fc991dd7-0033-4b80-9d41-c8a86a702e59 -> fc9913XADNLgJ1ByKhqcC5Z
// 如果启用 min 则将 uuid 的后面 30 位压缩成 20 位,前 2 位保留不变。
// fc991dd7-0033-4b80-9d41-c8a86a702e59 -> fcmR3XADNLgJ1ByKhqcC5Z
/*
* @param {Boolean} [min=false]
*/
static compressUuid (uuid, min) {
if (Reg_Uuid.test(uuid)) {
uuid = uuid.replace(Reg_Dash, '');
}
else if (!Reg_NormalizedUuid.test(uuid)) {
return uuid;
}
var reserved = (min === true) ? 2 : 5;
return UuidUtils.compressHex(uuid, reserved);
}
static compressHex (hexString, reservedHeadLength) {
var length = hexString.length;
var i;
if (typeof reservedHeadLength !== 'undefined') {
i = reservedHeadLength;
}
else {
i = length % 3;
}
var head = hexString.slice(0, i);
var base64Chars = [];
while (i < length) {
var hexVal1 = parseInt(hexString[i], 16);
var hexVal2 = parseInt(hexString[i + 1], 16);
var hexVal3 = parseInt(hexString[i + 2], 16);
base64Chars.push(Base64KeyChars[(hexVal1 << 2) | (hexVal2 >> 2)]);
base64Chars.push(Base64KeyChars[((hexVal2 & 3) << 4) | hexVal3]);
i += 3;
}
return head + base64Chars.join('');
}
static decompressUuid (str) {
if (str.length === 23) {
// decode base64
var hexChars = [];
for (var i = 5; i < 23; i += 2) {
var lhs = AsciiTo64[str.charCodeAt(i)];
var rhs = AsciiTo64[str.charCodeAt(i + 1)];
hexChars.push((lhs >> 2).toString(16));
hexChars.push((((lhs & 3) << 2) | rhs >> 4).toString(16));
hexChars.push((rhs & 0xF).toString(16));
}
//
str = str.slice(0, 5) + hexChars.join('');
}
else if (str.length === 22) {
// decode base64
var hexChars = [];
for (var i = 2; i < 22; i += 2) {
var lhs = AsciiTo64[str.charCodeAt(i)];
var rhs = AsciiTo64[str.charCodeAt(i + 1)];
hexChars.push((lhs >> 2).toString(16));
hexChars.push((((lhs & 3) << 2) | rhs >> 4).toString(16));
hexChars.push((rhs & 0xF).toString(16));
}
//
str = str.slice(0, 2) + hexChars.join('');
}
return [str.slice(0, 8), str.slice(8, 12), str.slice(12, 16), str.slice(16, 20), str.slice(20)].join('-');
}
static isUuid (str) {
return Reg_CompressedUuid.test(str) || Reg_NormalizedUuid.test(str) || Reg_Uuid.test(str);
}
static uuid () {
var uuid = Uuid.v4();
return UuidUtils.compressUuid(uuid, true);
}
};