From e1472c5ee70fb95e15461de6d7f7f37ecf647c94 Mon Sep 17 00:00:00 2001
From: Philipp Stadler <hello@phstadler.com>
Date: Mon, 29 Jul 2024 18:23:20 +0200
Subject: [PATCH] =?UTF-8?q?fix:=20add=20=E2=BB=8F=20SVG=20and=20stroke=20d?=
 =?UTF-8?q?ata?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 build/gen-hanzi-data/global-overrides.ts      | 26 +++++++++++++++++
 build/gen-hanzi-data/patched-hanzi-writer.ts  | 28 ++++++++++++++++++-
 build/gen-hanzi-data/stroke-type-overrides.ts |  5 ++++
 build/gen-hanzi-data/stroke-type.ts           |  8 ++++++
 4 files changed, 66 insertions(+), 1 deletion(-)
 create mode 100644 build/gen-hanzi-data/global-overrides.ts

diff --git a/build/gen-hanzi-data/global-overrides.ts b/build/gen-hanzi-data/global-overrides.ts
new file mode 100644
index 0000000..6adcd73
--- /dev/null
+++ b/build/gen-hanzi-data/global-overrides.ts
@@ -0,0 +1,26 @@
+
+export interface AssembleInput {
+  char: string
+  from: number
+  to: number
+  deltaRight?: number
+  deltaUp?: number,
+  dropRadStrokes?: true
+}
+
+/**
+ * Characters that are not defined but have parts that occur in other
+ * characters can be assembled here.
+ *
+ * In contrast to patched Hanzi Writer, this will also get stroke types from
+ * components.
+ */
+export const globalAssembleFrom: Map<string, Array<AssembleInput>> = new Map()
+globalAssembleFrom.set('⻏', [
+  {
+    char: '都',
+    from: 8,
+    to: 10,
+    dropRadStrokes: true
+  }
+])
diff --git a/build/gen-hanzi-data/patched-hanzi-writer.ts b/build/gen-hanzi-data/patched-hanzi-writer.ts
index 0aead14..eb1162b 100644
--- a/build/gen-hanzi-data/patched-hanzi-writer.ts
+++ b/build/gen-hanzi-data/patched-hanzi-writer.ts
@@ -2,6 +2,7 @@ import fs from 'fs'
 import { applyOverridesInPlace } from './overrides'
 import { animDataConcat, animDataSlice, animDataTranslate } from './anim-data'
 import { compat } from './blocks/index'
+import { AssembleInput, globalAssembleFrom } from './global-overrides'
 
 export interface HanziWriterData {
   strokes: string[]
@@ -13,6 +14,10 @@ const noHanziWriterData: HanziWriterData = { strokes: [], medians: [] }
 export async function queryPatchedHanziWriterData (
   char: string
 ): Promise<HanziWriterData> {
+  const assembleFrom = globalAssembleFrom.get(char)
+  if (assembleFrom !== undefined) {
+    return await fromParts(assembleFrom)
+  }
   // kangxi radicals are often not defined, but CJK ideograms have a good
   // chance, so use that data instead
   const hanziWriterCompatChar = compat(char)
@@ -23,6 +28,27 @@ export async function queryPatchedHanziWriterData (
   )
 }
 
+async function fromParts(assembleFrom: AssembleInput[]): Promise<HanziWriterData> {
+  const parts = await Promise.all(assembleFrom.map(
+    async ({ char, from, to, deltaRight, deltaUp, dropRadStrokes }) => {
+      const dataFull = await queryHanziWriterData(char)
+      const extracted = animDataSlice(dataFull, from, to)
+      const positioned = animDataTranslate(extracted, deltaRight ?? 0, deltaUp ?? 0)
+      if (dropRadStrokes === true) {
+        delete positioned.radStrokes
+      }
+      return positioned
+    }
+  ))
+  if (parts.length === 0) {
+    throw new Error('why zero parts?')
+  }
+  return parts.slice(1).reduce(
+    (acc, next) => animDataConcat(acc, next),
+    parts[0]
+  )
+}
+
 export function loadHanziWriterDataWithoutOverridesSync (
   char: string
 ): Omit<HanziWriterData, 'trad'> {
@@ -254,7 +280,7 @@ const hanziWriterOverrides = new Map<string, Partial<HanziWriterData>>(
         -25,
         -25
       )
-    )
+    ),
   })
 )
 
diff --git a/build/gen-hanzi-data/stroke-type-overrides.ts b/build/gen-hanzi-data/stroke-type-overrides.ts
index 3760e92..0c044bf 100644
--- a/build/gen-hanzi-data/stroke-type-overrides.ts
+++ b/build/gen-hanzi-data/stroke-type-overrides.ts
@@ -1,5 +1,10 @@
 import { StrokeType } from '../../src-common/stroke-encodings'
 
+/**
+ * Custom values for the stroke types, without affecting SVG data.
+ * 
+ * Can be used to repair broken cnchar entries.
+ */
 export const strokeTypeOverrides = new Map<string, StrokeType[]>(
   Object.entries({
     艸: [
diff --git a/build/gen-hanzi-data/stroke-type.ts b/build/gen-hanzi-data/stroke-type.ts
index e6e3b93..15d9d0f 100644
--- a/build/gen-hanzi-data/stroke-type.ts
+++ b/build/gen-hanzi-data/stroke-type.ts
@@ -8,6 +8,7 @@ import {
 import { strokeTypeOverrides } from './stroke-type-overrides'
 import { compat } from './blocks/index'
 import { normalizeStroke } from './stroke-normalize'
+import { globalAssembleFrom } from './global-overrides'
 
 cnchar.use(cncharOrder, cncharTrad)
 
@@ -29,6 +30,13 @@ export function queryStrokeTypes (
   expectedLen?: number
 ): StrokeType[] {
   const compatChar = compat(char)
+  const assembleFrom = globalAssembleFrom.get(char)
+  if (assembleFrom !== undefined) {
+    return assembleFrom.reduce(
+      (acc, next) => acc.concat(queryStrokeTypes(next.char).slice(next.from, next.to)),
+      [] as StrokeType[]
+    )
+  }
   const override =
     strokeTypeOverrides.get(char) ?? strokeTypeOverrides.get(compatChar)
   if (override !== undefined) {
-- 
GitLab