From 6b1a9d56158b44d5a0d5206164b7f0525040ecc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E5=A4=8F=E5=B0=A7?= <3446798488@qq.com> Date: Sun, 7 Jan 2024 17:51:37 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(analyze):=20=E5=88=86=E6=9E=90?= =?UTF-8?q?=E5=99=A8=E6=B7=BB=E5=8A=A0=20feature=20=E5=92=8C=20svg=20?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/font-analyze/package.json | 4 +- .../font-analyze/src/Charset/FontSetMatch.ts | 4 +- .../src/Charset/defaultCharsetLoader.ts | 3 + .../src/Charset/getCharsetReport.ts | 13 +- .../font-analyze/src/Feature/FeatureList.ts | 147 ++++++++++++++++++ packages/font-analyze/src/Feature/index.ts | 17 ++ packages/font-analyze/src/index.ts | 24 ++- 7 files changed, 199 insertions(+), 13 deletions(-) create mode 100644 packages/font-analyze/src/Feature/FeatureList.ts create mode 100644 packages/font-analyze/src/Feature/index.ts diff --git a/packages/font-analyze/package.json b/packages/font-analyze/package.json index 81d6f01f..8422d2d2 100644 --- a/packages/font-analyze/package.json +++ b/packages/font-analyze/package.json @@ -1,6 +1,6 @@ { "name": "font-analyze", - "version": "1.3.1", + "version": "1.3.2", "description": "", "main": "dist/index.js", "type": "module", @@ -17,7 +17,7 @@ "license": "ISC", "dependencies": { "@types/opentype.js": "^1.3.4", - "@konghayao/opentype.js": "^2023.10.5" + "@konghayao/opentype.js": "^2023.11.20" }, "devDependencies": { "compressing": "^1.9.0", diff --git a/packages/font-analyze/src/Charset/FontSetMatch.ts b/packages/font-analyze/src/Charset/FontSetMatch.ts index 9249c749..7976d3bd 100644 --- a/packages/font-analyze/src/Charset/FontSetMatch.ts +++ b/packages/font-analyze/src/Charset/FontSetMatch.ts @@ -12,12 +12,12 @@ export const calcCharset = (charset: Charset) => { }, 0); }; -/** 字符集判断 */ +/** 判断字体中是否包含 json 文件的 unicode 字符 */ export const FontSetMatch = ( font: Font, items: Set, charset: Charset, - name: string + name: string, ): CharsetReporter => { let support_count = 0; let area_count = 0; diff --git a/packages/font-analyze/src/Charset/defaultCharsetLoader.ts b/packages/font-analyze/src/Charset/defaultCharsetLoader.ts index 7937b753..8b8964af 100644 --- a/packages/font-analyze/src/Charset/defaultCharsetLoader.ts +++ b/packages/font-analyze/src/Charset/defaultCharsetLoader.ts @@ -1,6 +1,7 @@ import { Charset } from './FontSetMatch.js'; import { UnicodeCharset } from './UnicodeMatch.js'; +/** 字符集支持报告的表格 */ export interface CharsetReporter { name: string; cn?: string; @@ -11,6 +12,8 @@ export interface CharsetReporter { coverage: string; in_set_rate: string; } + +/** 从远程加载数据 json 文件 */ export type CharsetLoader = (path: string) => Promise; export const defaultCharsetLoader: CharsetLoader = async (path) => { const { default: D } = await import('../data/' + path); diff --git a/packages/font-analyze/src/Charset/getCharsetReport.ts b/packages/font-analyze/src/Charset/getCharsetReport.ts index 3cb3facb..f4c86e78 100644 --- a/packages/font-analyze/src/Charset/getCharsetReport.ts +++ b/packages/font-analyze/src/Charset/getCharsetReport.ts @@ -1,3 +1,4 @@ +import { Font } from '@konghayao/opentype.js'; import { Charset, FontSetMatch } from './FontSetMatch.js'; import { UnicodeCharset, UnicodeMatch } from './UnicodeMatch.js'; import { CharsetLoader } from './defaultCharsetLoader.js'; @@ -5,8 +6,8 @@ import { CharsetLoader } from './defaultCharsetLoader.js'; /** 获取 unicode 字符集检测报告 */ export async function getCharsetReport( charsetLoader: CharsetLoader, - font: any, - unicodeSet: Set + font: Font, + unicodeSet: Set, ) { const standard = await getCharsetStandard(charsetLoader, font, unicodeSet); // console.table(standard); @@ -14,15 +15,15 @@ export async function getCharsetReport( const unicodeReport = UnicodeMatch( font, unicodeSet, - Unicode as UnicodeCharset + Unicode as UnicodeCharset, ); return { unicodeReport, standard }; } /** 获取标准字符集数据 */ async function getCharsetStandard( charsetLoader: CharsetLoader, - font: any, - unicodeSet: Set + font: Font, + unicodeSet: Set, ) { return await Promise.all( [ @@ -45,6 +46,6 @@ async function getCharsetStandard( ].map(async ([_path, name]) => { const set = await charsetLoader(_path); return FontSetMatch(font, unicodeSet, set as Charset, name); - }) + }), ); } diff --git a/packages/font-analyze/src/Feature/FeatureList.ts b/packages/font-analyze/src/Feature/FeatureList.ts new file mode 100644 index 00000000..15100ed3 --- /dev/null +++ b/packages/font-analyze/src/Feature/FeatureList.ts @@ -0,0 +1,147 @@ +export const FeatureList = [ + 'aalt', + 'abvf', + 'abvm', + 'abvs', + 'afrc', + 'akhn', + 'blwf', + 'blwm', + 'blws', + 'calt', + 'case', + 'ccmp', + 'cfar', + 'chws', + 'cjct', + 'clig', + 'cpct', + 'cpsp', + 'cswh', + 'curs', + ...[...Array(99).keys()].map( + (i) => 'cv' + (i + 1).toString().padStart(2, '0'), + ), + 'c2pc', + 'c2sc', + 'dist', + 'dlig', + 'dnom', + 'dtls', + 'expt', + 'falt', + 'fin2', + 'fin3', + 'fina', + 'flac', + 'frac', + 'fwid', + 'half', + 'haln', + 'halt', + 'hist', + 'hkna', + 'hlig', + 'hngl', + 'hojo', + 'hwid', + 'init', + 'isol', + 'ital', + 'jalt', + 'jp78', + 'jp83', + 'jp90', + 'jp04', + 'kern', + 'lfbd', + 'liga', + 'ljmo', + 'lnum', + 'locl', + 'ltra', + 'ltrm', + 'mark', + 'med2', + 'medi', + 'mgrk', + 'mkmk', + 'mset', + 'nalt', + 'nlck', + 'nukt', + 'numr', + 'onum', + 'opbd', + 'ordn', + 'ornm', + 'palt', + 'pcap', + 'pkna', + 'pnum', + 'pref', + 'pres', + 'pstf', + 'psts', + 'pwid', + 'qwid', + 'rand', + 'rclt', + 'rkrf', + 'rlig', + 'rphf', + 'rtbd', + 'rtla', + 'rtlm', + 'ruby', + 'rvrn', + 'salt', + 'sinf', + 'size', + 'smcp', + 'smpl', + 'ss01', + 'ss02', + 'ss03', + 'ss04', + 'ss05', + 'ss06', + 'ss07', + 'ss08', + 'ss09', + 'ss10', + 'ss11', + 'ss12', + 'ss13', + 'ss14', + 'ss15', + 'ss16', + 'ss17', + 'ss18', + 'ss19', + 'ss20', + 'ssty', + 'stch', + 'subs', + 'sups', + 'swsh', + 'titl', + 'tjmo', + 'tnam', + 'tnum', + 'trad', + 'twid', + 'unic', + 'valt', + 'vatu', + 'vchw', + 'vert', + 'vhal', + 'vjmo', + 'vkna', + 'vkrn', + 'vpal', + 'vrt2', + 'vrtr', + 'zero', +]; diff --git a/packages/font-analyze/src/Feature/index.ts b/packages/font-analyze/src/Feature/index.ts new file mode 100644 index 00000000..45a6c153 --- /dev/null +++ b/packages/font-analyze/src/Feature/index.ts @@ -0,0 +1,17 @@ +import { Font } from '@konghayao/opentype.js'; +import { FeatureList } from './FeatureList'; + +/** Opentype 的 feature 报告 */ +export const getFeatureReport = (font: Font, unicodeSet: Set) => { + return FeatureList.reduce( + (col, i) => { + const arr = (font.substitution as any).getFeature(i); + if (arr && arr.length) col[i] = arr; + return col; + }, + {} as Record< + string, + { sub: number | number[]; by: number | number[] }[] + >, + ); +}; diff --git a/packages/font-analyze/src/index.ts b/packages/font-analyze/src/index.ts index bfbf3ce5..2e14caaf 100644 --- a/packages/font-analyze/src/index.ts +++ b/packages/font-analyze/src/index.ts @@ -1,14 +1,17 @@ -import { parse, type Font } from '@konghayao/opentype.js'; +import { RenderOptions, parse } from '@konghayao/opentype.js'; import { getCharsetReport } from './Charset/getCharsetReport.js'; import { defaultCharsetLoader, CharsetLoader, } from './Charset/defaultCharsetLoader.js'; +import { getFeatureReport } from './Feature/index.js'; + +export * from './Charset/defaultCharsetLoader.js'; /** 分析字体中的字符集和字型相关信息 */ export const FontAnalyze = async ( input: Buffer | ArrayBuffer, - { charsetLoader = defaultCharsetLoader }: { charsetLoader: CharsetLoader } + { charsetLoader = defaultCharsetLoader }: { charsetLoader: CharsetLoader }, ) => { const font = parse(input); @@ -22,8 +25,9 @@ export const FontAnalyze = async ( const { unicodeReport, standard } = await getCharsetReport( charsetLoader, font, - unicodeSet + unicodeSet, ); + const features = getFeatureReport(font, unicodeSet); return { file: { size: input.byteLength, @@ -35,5 +39,19 @@ export const FontAnalyze = async ( unicode: unicodeReport, /** 各大标准字符集检测 */ standard, + /** opentype feature 的替换表 */ + features, + /** 将文本绘制成图片 */ + drawTextToSVG( + text: string, + x: number, + y: number, + fontSize: number, + options?: RenderOptions, + ) { + return font + .getPaths(text, x, y, fontSize, options) + .map((i) => i.toSVG(1)); + }, }; }; From 71e1a82d7f0a52279567eb38e0a3e0165954be9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E5=A4=8F=E5=B0=A7?= <3446798488@qq.com> Date: Sun, 7 Jan 2024 19:13:45 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(analyze):=20=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E7=9A=84=20feature=20=E6=95=B0=E6=8D=AE=E9=9D=9E=20un?= =?UTF-8?q?icode=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/font-analyze/package.json | 2 +- packages/font-analyze/src/Feature/index.ts | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/font-analyze/package.json b/packages/font-analyze/package.json index 8422d2d2..5fb8005a 100644 --- a/packages/font-analyze/package.json +++ b/packages/font-analyze/package.json @@ -1,6 +1,6 @@ { "name": "font-analyze", - "version": "1.3.2", + "version": "1.3.4", "description": "", "main": "dist/index.js", "type": "module", diff --git a/packages/font-analyze/src/Feature/index.ts b/packages/font-analyze/src/Feature/index.ts index 45a6c153..972a8e2c 100644 --- a/packages/font-analyze/src/Feature/index.ts +++ b/packages/font-analyze/src/Feature/index.ts @@ -5,13 +5,23 @@ import { FeatureList } from './FeatureList'; export const getFeatureReport = (font: Font, unicodeSet: Set) => { return FeatureList.reduce( (col, i) => { - const arr = (font.substitution as any).getFeature(i); - if (arr && arr.length) col[i] = arr; + const arr: { sub: number | number[]; by: number | number[] }[] = ( + font.substitution as any + ).getFeature(i); + const idToUnicode = (id: number) => font.glyphs.get(id).unicodes; + if (arr && arr.length) + col[i] = arr.map((i) => { + return { + sub: (typeof i.sub === 'number' ? [i.sub] : i.sub).map( + (i) => idToUnicode(i), + ), + by: (typeof i.by === 'number' ? [i.by] : i.by).map( + (i) => idToUnicode(i), + ), + }; + }); return col; }, - {} as Record< - string, - { sub: number | number[]; by: number | number[] }[] - >, + {} as Record, ); };