tegaki 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/FONTS-LICENSE.md +6 -0
- package/README.md +1 -0
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +1 -1
- package/dist/{core-Cbi21OMg.mjs → core-B87FE4Wo.mjs} +147 -12
- package/dist/core-B87FE4Wo.mjs.map +1 -0
- package/dist/fonts/amiri/bundle.mjs.map +1 -1
- package/dist/fonts/caveat/bundle.mjs.map +1 -1
- package/dist/fonts/italianno/bundle.mjs.map +1 -1
- package/dist/fonts/klee-one/bundle.mjs.map +1 -1
- package/dist/fonts/nanum-pen-script/bundle.d.mts +7144 -0
- package/dist/fonts/nanum-pen-script/bundle.mjs +161041 -0
- package/dist/fonts/nanum-pen-script/bundle.mjs.map +1 -0
- package/dist/fonts/nanum-pen-script/nanum-pen-script-38efadb5.ttf +0 -0
- package/dist/fonts/nanum-pen-script/nanum-pen-script.ttf +0 -0
- package/dist/fonts/parisienne/bundle.mjs.map +1 -1
- package/dist/fonts/suez-one/bundle.mjs.map +1 -1
- package/dist/fonts/tangerine/bundle.mjs.map +1 -1
- package/dist/fonts/tillana/bundle.mjs.map +1 -1
- package/dist/{index-BcyoxWKO.d.mts → index-Bbbx_Ck-.d.mts} +4 -5
- package/dist/{index-BRsSO7q7.d.mts → index-H08fD9_Z.d.mts} +49 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/react/index.d.mts +4 -4
- package/dist/react/index.mjs +2 -2
- package/dist/{react-Aw2TTpfu.mjs → react-cKaviQiL.mjs} +3 -2
- package/dist/{react-Aw2TTpfu.mjs.map → react-cKaviQiL.mjs.map} +1 -1
- package/dist/shaper-harfbuzz/index.d.mts +1 -1
- package/dist/shaper-harfbuzz/index.mjs +26 -35
- package/dist/shaper-harfbuzz/index.mjs.map +1 -1
- package/dist/{shaper-registry-DVS5R37Q.d.mts → shaper-registry-DmlJGnE3.d.mts} +2 -2
- package/dist/wc/index.d.mts +3 -3
- package/dist/wc/index.mjs +1 -1
- package/dist/wc/index.mjs.map +1 -1
- package/fonts/nanum-pen-script/bundle.ts +20 -0
- package/fonts/nanum-pen-script/glyphData.json +1 -0
- package/fonts/nanum-pen-script/nanum-pen-script-38efadb5.ttf +0 -0
- package/fonts/nanum-pen-script/nanum-pen-script.ttf +0 -0
- package/package.json +26 -18
- package/src/astro/TegakiRenderer.astro +31 -5
- package/src/core/bundle-registry.ts +3 -0
- package/src/core/engine.ts +1 -0
- package/src/core/index.ts +7 -1
- package/src/env.d.ts +2 -0
- package/src/lib/drawGlyph.ts +12 -2
- package/src/lib/font.ts +1 -1
- package/src/lib/timeline.test.ts +173 -0
- package/src/lib/timeline.ts +179 -10
- package/src/nuxt/module.ts +0 -3
- package/src/shaper-harfbuzz/index.ts +24 -42
- package/src/types.ts +1 -1
- package/src/vue/TegakiRenderer.vue +2 -2
- package/src/vue/index.ts +1 -0
- package/dist/core-Cbi21OMg.mjs.map +0 -1
- package/dist/solid/index.d.mts +0 -20
- package/dist/solid/index.mjs +0 -91
- package/dist/solid/index.mjs.map +0 -1
- package/src/lib/harfbuzzjs.d.ts +0 -71
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# tegaki
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 68ee58f: Support Korean (Hangul) writing system and add Nanum Pen Script as a built-in font. The bundle ships ~650 most-frequent precomposed Hangul syllables (KS X 1001 common band ∪ top-N Korean-Wikipedia-frequency, capped by the Google Fonts subsetting ceiling) plus the 40 modern compatibility jamo (19 consonants ㄱ–ㅎ + 21 vowels ㅏ–ㅣ) and the Latin baseline. Hangul is precomposed in Unicode, so no shaper is required.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 29e111e: Fix Next.js App Router / Turbopack compatibility. Two build/packaging issues prevented `tegaki` from being used in a Next.js (App Router) app:
|
|
12
|
+
|
|
13
|
+
- The bundler dropped the `'use client'` directive from the React adapter's output chunk, so importing `TegakiRenderer` into a Server Component failed with "You're importing a module that depends on `useState` into a React Server Component". The directive is now preserved in the built output.
|
|
14
|
+
- The font subpath exports (`tegaki/fonts/*`) resolved the `node` condition to the raw TypeScript source, which uses `import ... with { type: 'url' }` import attributes that Turbopack/webpack can't process. The `node` condition now points to the pre-built `.mjs` bundle (which loads the font via `new URL('./font.ttf', import.meta.url)`), so it works in any Node-based bundler.
|
|
15
|
+
|
|
16
|
+
## 0.18.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- b6e883b: Update Harfbuzz to v1.1.0
|
|
21
|
+
- d358cbd: Add `stagger` timing mode where each glyph starts a fixed advance (seconds or `"N%"` of the previous glyph's effective duration) after the previous one, with an optional static per-glyph duration that scales strokes to fit. Exposed in the website previewer via the new `st` / `sa` / `sd` URL keys.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 150296e: Fix the Astro adapter so passing `font={bundle}` hydrates without an explicit `bundle` prop and lookups by human-friendly font name resolve correctly. Animations now also re-hydrate after Astro View Transitions navigations.
|
|
26
|
+
- 150296e: Make the Vue adapter's `effects` prop generic so custom effect configs are correctly type-inferred. Also drop a redundant Nuxt config type augmentation.
|
|
27
|
+
|
|
3
28
|
## 0.17.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/FONTS-LICENSE.md
CHANGED
|
@@ -51,6 +51,12 @@ All fonts are licensed under the [SIL Open Font License, Version 1.1](https://op
|
|
|
51
51
|
- **Copyright**: Copyright (c) 2014, Indian Type Foundry (info@indiantypefoundry.com)
|
|
52
52
|
- **License**: SIL Open Font License, Version 1.1
|
|
53
53
|
|
|
54
|
+
## Nanum Pen Script
|
|
55
|
+
|
|
56
|
+
- **Designer**: Sandoll Communications Inc. for NHN Corporation
|
|
57
|
+
- **Copyright**: Copyright © 2010 NHN Corporation. All rights reserved. Font designed by Sandoll Communications Inc.
|
|
58
|
+
- **License**: SIL Open Font License, Version 1.1
|
|
59
|
+
|
|
54
60
|
---
|
|
55
61
|
|
|
56
62
|
## SIL Open Font License, Version 1.1
|
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ Several handwriting fonts are bundled and ready to use:
|
|
|
75
75
|
- **Amiri** — `tegaki/fonts/amiri` _(Arabic + Latin)_
|
|
76
76
|
- **Tillana** — `tegaki/fonts/tillana` _(Devanagari + Latin)_
|
|
77
77
|
- **Klee One** — `tegaki/fonts/klee-one` _(Japanese: kana + Kyōiku grade 1–2 kanji + Latin)_
|
|
78
|
+
- **Nanum Pen Script** — `tegaki/fonts/nanum-pen-script` _(Korean: Hangul syllables + jamo + Latin)_
|
|
78
79
|
|
|
79
80
|
For other fonts, use the [interactive generator](https://gkurt.com/tegaki/generator/) to create a custom bundle.
|
|
80
81
|
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { S as TimedPoint, _ as TegakiEffectName, a as BBox, b as TegakiMultiEffectName, c as CSSLength, d as LineCap, f as PathCommand, g as TegakiEffectConfigs, h as TegakiBundle, i as ShapedGlyph, l as FontOutput, m as Stroke, o as BUNDLE_VERSION, p as Point, r as BundleShaper, s as COMPATIBLE_BUNDLE_VERSIONS, t as ShaperFactory, u as GlyphData, v as TegakiEffects, x as TegakiSingletonEffectName, y as TegakiGlyphData } from "../shaper-registry-
|
|
2
|
-
import { A as TimelineEntry, C as resolveEffects, D as computeTextLayout, E as computeLayoutBbox, O as Timeline, S as hasRenderHooks, T as TextLayout, _ as RenderStageContext, a as CreateElementFn, b as findEffects, c as TimeControlMode, d as getBundle, f as registerBundle, g as EffectDefinition, h as drawGlyph, i as TegakiEngine, j as
|
|
3
|
-
export { BBox, BUNDLE_VERSION, BundleShaper, COMPATIBLE_BUNDLE_VERSIONS, CSSLength, CreateElementFn, EffectDefinition, FontOutput, GlyphData, LayoutBBox, LineCap, PathCommand, Point, RenderStageContext, ResolvedEffect, ShapedGlyph, ShaperFactory, Stroke, TegakiBundle, TegakiEffectConfigs, TegakiEffectName, TegakiEffects, TegakiEngine, TegakiEngineOptions, TegakiGlyphData, TegakiMultiEffectName, TegakiQuality, TegakiSingletonEffectName, TextLayout, TimeControlMode, TimeControlProp, TimedPoint, Timeline, TimelineConfig, TimelineEntry, buildChildren, buildRootProps, computeLayoutBbox, computeTextLayout, computeTimeline, createBundle, domCreateElement, drawGlyph, ensureFontFace, findEffect, findEffects, getBundle, getEffectDefinition, hasRenderHooks, registerBundle, resolveBundle, resolveEffects };
|
|
1
|
+
import { S as TimedPoint, _ as TegakiEffectName, a as BBox, b as TegakiMultiEffectName, c as CSSLength, d as LineCap, f as PathCommand, g as TegakiEffectConfigs, h as TegakiBundle, i as ShapedGlyph, l as FontOutput, m as Stroke, o as BUNDLE_VERSION, p as Point, r as BundleShaper, s as COMPATIBLE_BUNDLE_VERSIONS, t as ShaperFactory, u as GlyphData, v as TegakiEffects, x as TegakiSingletonEffectName, y as TegakiGlyphData } from "../shaper-registry-DmlJGnE3.mjs";
|
|
2
|
+
import { A as TimelineEntry, C as resolveEffects, D as computeTextLayout, E as computeLayoutBbox, M as computeTimeline, O as Timeline, S as hasRenderHooks, T as TextLayout, _ as RenderStageContext, a as CreateElementFn, b as findEffects, c as TimeControlMode, d as getBundle, f as registerBundle, g as EffectDefinition, h as drawGlyph, i as TegakiEngine, j as TimelineStaggerConfig, k as TimelineConfig, l as TimeControlProp, m as ensureFontFace, n as buildRootProps, o as TegakiEngineOptions, p as resolveBundle, r as domCreateElement, s as TegakiQuality, t as buildChildren, u as createBundle, v as ResolvedEffect, w as LayoutBBox, x as getEffectDefinition, y as findEffect } from "../index-H08fD9_Z.mjs";
|
|
3
|
+
export { type BBox, BUNDLE_VERSION, type BundleShaper, COMPATIBLE_BUNDLE_VERSIONS, type CSSLength, type CreateElementFn, type EffectDefinition, type FontOutput, type GlyphData, type LayoutBBox, type LineCap, type PathCommand, type Point, type RenderStageContext, type ResolvedEffect, type ShapedGlyph, type ShaperFactory, type Stroke, type TegakiBundle, type TegakiEffectConfigs, type TegakiEffectName, type TegakiEffects, TegakiEngine, type TegakiEngineOptions, type TegakiGlyphData, type TegakiMultiEffectName, type TegakiQuality, type TegakiSingletonEffectName, type TextLayout, type TimeControlMode, type TimeControlProp, type TimedPoint, type Timeline, type TimelineConfig, type TimelineEntry, type TimelineStaggerConfig, buildChildren, buildRootProps, computeLayoutBbox, computeTextLayout, computeTimeline, createBundle, domCreateElement, drawGlyph, ensureFontFace, findEffect, findEffects, getBundle, getEffectDefinition, hasRenderHooks, registerBundle, resolveBundle, resolveEffects };
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as findEffect, a as createBundle, b as hasRenderHooks, c as resolveBundle, d as computeTimeline, f as computeLayoutBbox, h as drawGlyph, i as domCreateElement, l as BUNDLE_VERSION, m as ensureFontFace, n as buildChildren, o as getBundle, p as computeTextLayout, r as buildRootProps, s as registerBundle, t as TegakiEngine, u as COMPATIBLE_BUNDLE_VERSIONS, v as findEffects, x as resolveEffects, y as getEffectDefinition } from "../core-
|
|
1
|
+
import { _ as findEffect, a as createBundle, b as hasRenderHooks, c as resolveBundle, d as computeTimeline, f as computeLayoutBbox, h as drawGlyph, i as domCreateElement, l as BUNDLE_VERSION, m as ensureFontFace, n as buildChildren, o as getBundle, p as computeTextLayout, r as buildRootProps, s as registerBundle, t as TegakiEngine, u as COMPATIBLE_BUNDLE_VERSIONS, v as findEffects, x as resolveEffects, y as getEffectDefinition } from "../core-B87FE4Wo.mjs";
|
|
2
2
|
export { BUNDLE_VERSION, COMPATIBLE_BUNDLE_VERSIONS, TegakiEngine, buildChildren, buildRootProps, computeLayoutBbox, computeTextLayout, computeTimeline, createBundle, domCreateElement, drawGlyph, ensureFontFace, findEffect, findEffects, getBundle, getEffectDefinition, hasRenderHooks, registerBundle, resolveBundle, resolveEffects };
|
|
@@ -368,8 +368,13 @@ function defaultStrokeEasing(t) {
|
|
|
368
368
|
* delay relative to `localTime = 0`. Used by the timeline scheduler to defer
|
|
369
369
|
* priority-tagged strokes (disconnected marks / i-dots / Arabic nuqṭa) to
|
|
370
370
|
* after every body stroke in the word has drawn.
|
|
371
|
+
*
|
|
372
|
+
* `strokeTimeScale` multiplies both bundled `d` and `a` so a glyph's strokes
|
|
373
|
+
* fit a stretched/compressed time slot (used by stagger mode with a static
|
|
374
|
+
* `duration`). Defaults to `1` (no scaling). `strokeDelays` are already
|
|
375
|
+
* scheduler-relative seconds and are not affected by this scale.
|
|
371
376
|
*/
|
|
372
|
-
function drawGlyph(ctx, glyph, pos, localTime, lineCap, color, effects = [], seed = 0, getSubdivided, strokeEasing = defaultStrokeEasing, strokeScale = 1, strokeStyleOverride, strokeDelays) {
|
|
377
|
+
function drawGlyph(ctx, glyph, pos, localTime, lineCap, color, effects = [], seed = 0, getSubdivided, strokeEasing = defaultStrokeEasing, strokeScale = 1, strokeStyleOverride, strokeDelays, strokeTimeScale = 1) {
|
|
373
378
|
const defaultStrokePaint = strokeStyleOverride ?? color;
|
|
374
379
|
const scale = pos.fontSize / pos.unitsPerEm;
|
|
375
380
|
const ox = pos.x;
|
|
@@ -419,10 +424,11 @@ function drawGlyph(ctx, glyph, pos, localTime, lineCap, color, effects = [], see
|
|
|
419
424
|
};
|
|
420
425
|
for (let si = 0; si < glyph.s.length; si++) {
|
|
421
426
|
const stroke = glyph.s[si];
|
|
422
|
-
const delay = strokeDelays?.[si] ?? stroke.d;
|
|
427
|
+
const delay = strokeDelays?.[si] ?? stroke.d * strokeTimeScale;
|
|
423
428
|
if (localTime < delay) continue;
|
|
424
429
|
const elapsed = localTime - delay;
|
|
425
|
-
const
|
|
430
|
+
const animDuration = stroke.a * strokeTimeScale;
|
|
431
|
+
const linearProgress = animDuration > 0 ? Math.min(elapsed / animDuration, 1) : 1;
|
|
426
432
|
const progress = strokeEasing ? strokeEasing(linearProgress) : linearProgress;
|
|
427
433
|
const rawPts = stroke.p;
|
|
428
434
|
if (rawPts.length === 0) continue;
|
|
@@ -559,7 +565,7 @@ function drawGlyph(ctx, glyph, pos, localTime, lineCap, color, effects = [], see
|
|
|
559
565
|
* explicit enables. (Explicit *disables* are fine — `-fina` suppressing the
|
|
560
566
|
* automatic fina is exactly the user's intent.)
|
|
561
567
|
*/
|
|
562
|
-
const SHAPER_MANAGED_FEATURES = new Set([
|
|
568
|
+
const SHAPER_MANAGED_FEATURES = /* @__PURE__ */ new Set([
|
|
563
569
|
"init",
|
|
564
570
|
"medi",
|
|
565
571
|
"fina",
|
|
@@ -875,6 +881,79 @@ function computeTimeline(text, font, config, shaper) {
|
|
|
875
881
|
if (shaper && font.glyphDataById) return computeShapedTimeline(text, font, config, shaper);
|
|
876
882
|
return computeGraphemeTimeline(text, font, config);
|
|
877
883
|
}
|
|
884
|
+
/** Parse a stagger advance value into seconds, given the previous glyph's bundled duration. */
|
|
885
|
+
function resolveAdvance(advance, prevBundled) {
|
|
886
|
+
if (typeof advance === "number") return Math.max(0, advance);
|
|
887
|
+
const m = /^(-?\d+(?:\.\d+)?)\s*%$/.exec(advance);
|
|
888
|
+
if (m) {
|
|
889
|
+
const pct = Number(m[1]) / 100;
|
|
890
|
+
return Math.max(0, pct * prevBundled);
|
|
891
|
+
}
|
|
892
|
+
const n = Number(advance);
|
|
893
|
+
return Number.isFinite(n) ? Math.max(0, n) : 0;
|
|
894
|
+
}
|
|
895
|
+
var StaggerScheduler = class {
|
|
896
|
+
wordGap;
|
|
897
|
+
lineGap;
|
|
898
|
+
advance;
|
|
899
|
+
staticDuration;
|
|
900
|
+
entries = [];
|
|
901
|
+
offset = 0;
|
|
902
|
+
/**
|
|
903
|
+
* Effective duration of the most recent glyph (= `staticDuration` when set,
|
|
904
|
+
* else its bundled `glyph.t`). Basis for percent advances — so
|
|
905
|
+
* `advance: '100%'` always means "start once the previous glyph finishes",
|
|
906
|
+
* independent of whether the duration was overridden.
|
|
907
|
+
*/
|
|
908
|
+
prevEffective = 0;
|
|
909
|
+
hasPrev = false;
|
|
910
|
+
/** Accumulated word/line gap pending until the next glyph (or finalize). */
|
|
911
|
+
pendingGap = 0;
|
|
912
|
+
constructor(wordGap, lineGap, advance, staticDuration) {
|
|
913
|
+
this.wordGap = wordGap;
|
|
914
|
+
this.lineGap = lineGap;
|
|
915
|
+
this.advance = advance;
|
|
916
|
+
this.staticDuration = staticDuration;
|
|
917
|
+
}
|
|
918
|
+
addGlyph(fields, bundledDuration) {
|
|
919
|
+
if (this.hasPrev) {
|
|
920
|
+
this.offset += resolveAdvance(this.advance, this.prevEffective) + this.pendingGap;
|
|
921
|
+
this.pendingGap = 0;
|
|
922
|
+
}
|
|
923
|
+
const duration = this.staticDuration ?? bundledDuration;
|
|
924
|
+
const strokeTimeScale = bundledDuration > 0 ? duration / bundledDuration : 1;
|
|
925
|
+
this.entries.push({
|
|
926
|
+
...fields,
|
|
927
|
+
offset: this.offset,
|
|
928
|
+
duration,
|
|
929
|
+
...strokeTimeScale !== 1 ? { strokeTimeScale } : {}
|
|
930
|
+
});
|
|
931
|
+
this.prevEffective = duration;
|
|
932
|
+
this.hasPrev = true;
|
|
933
|
+
}
|
|
934
|
+
/** Emit a zero-duration marker (e.g. whitespace) at the current offset without advancing the cursor. */
|
|
935
|
+
addMarker(fields) {
|
|
936
|
+
this.entries.push({
|
|
937
|
+
...fields,
|
|
938
|
+
offset: this.offset,
|
|
939
|
+
duration: 0
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
separator(sep) {
|
|
943
|
+
this.pendingGap += sep === "line" ? this.lineGap : this.wordGap;
|
|
944
|
+
}
|
|
945
|
+
finalize() {
|
|
946
|
+
let total = 0;
|
|
947
|
+
for (const e of this.entries) {
|
|
948
|
+
const end = e.offset + e.duration;
|
|
949
|
+
if (end > total) total = end;
|
|
950
|
+
}
|
|
951
|
+
return {
|
|
952
|
+
entries: this.entries,
|
|
953
|
+
totalDuration: total
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
};
|
|
878
957
|
/** Decompose a glyph into a body phase and an optional dot phase. */
|
|
879
958
|
function partitionGlyph(glyph, fallbackTotal, deferDots) {
|
|
880
959
|
const strokes = glyph.s;
|
|
@@ -916,6 +995,9 @@ function partitionGlyph(glyph, fallbackTotal, deferDots) {
|
|
|
916
995
|
};
|
|
917
996
|
}
|
|
918
997
|
var Scheduler = class {
|
|
998
|
+
glyphGap;
|
|
999
|
+
wordGap;
|
|
1000
|
+
lineGap;
|
|
919
1001
|
entries = [];
|
|
920
1002
|
group = [];
|
|
921
1003
|
offset = 0;
|
|
@@ -1013,6 +1095,40 @@ function computeGraphemeTimeline(text, font, config) {
|
|
|
1013
1095
|
const unknownDuration = config?.unknownDuration ?? DEFAULTS.unknownDuration;
|
|
1014
1096
|
const deferDots = config?.deferDots ?? DEFAULTS.deferDots;
|
|
1015
1097
|
const chars = graphemes(text);
|
|
1098
|
+
if (config?.stagger) {
|
|
1099
|
+
const staticDur = config.stagger.duration === "auto" || config.stagger.duration === void 0 ? void 0 : config.stagger.duration;
|
|
1100
|
+
const sched = new StaggerScheduler(wordGap, lineGap, config.stagger.advance, staticDur);
|
|
1101
|
+
for (let i = 0; i < chars.length; i++) {
|
|
1102
|
+
const char = chars[i];
|
|
1103
|
+
const isLineBreak = char === "\n";
|
|
1104
|
+
const isWhitespace = !isLineBreak && /^\s+$/.test(char);
|
|
1105
|
+
if (isLineBreak) {
|
|
1106
|
+
sched.separator("line");
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
if (isWhitespace) {
|
|
1110
|
+
sched.addMarker({
|
|
1111
|
+
char,
|
|
1112
|
+
graphemeIndex: i,
|
|
1113
|
+
hasGlyph: false
|
|
1114
|
+
});
|
|
1115
|
+
sched.separator("word");
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
const glyph = lookupGlyphData(font, char);
|
|
1119
|
+
if (glyph) sched.addGlyph({
|
|
1120
|
+
char,
|
|
1121
|
+
graphemeIndex: i,
|
|
1122
|
+
hasGlyph: true
|
|
1123
|
+
}, glyph.t ?? unknownDuration);
|
|
1124
|
+
else sched.addGlyph({
|
|
1125
|
+
char,
|
|
1126
|
+
graphemeIndex: i,
|
|
1127
|
+
hasGlyph: false
|
|
1128
|
+
}, unknownDuration);
|
|
1129
|
+
}
|
|
1130
|
+
return sched.finalize();
|
|
1131
|
+
}
|
|
1016
1132
|
const sched = new Scheduler(glyphGap, wordGap, lineGap);
|
|
1017
1133
|
for (let i = 0; i < chars.length; i++) {
|
|
1018
1134
|
const char = chars[i];
|
|
@@ -1079,7 +1195,8 @@ function computeShapedTimeline(text, font, config, shaper) {
|
|
|
1079
1195
|
}
|
|
1080
1196
|
utf16ToGrapheme[text.length] = chars.length;
|
|
1081
1197
|
}
|
|
1082
|
-
const
|
|
1198
|
+
const staggerSched = config?.stagger ? new StaggerScheduler(wordGap, lineGap, config.stagger.advance, config.stagger.duration === "auto" || config.stagger.duration === void 0 ? void 0 : config.stagger.duration) : null;
|
|
1199
|
+
const sched = staggerSched ? null : new Scheduler(glyphGap, wordGap, lineGap);
|
|
1083
1200
|
let lineStart = 0;
|
|
1084
1201
|
for (let i = 0; i <= text.length; i++) {
|
|
1085
1202
|
const atEnd = i === text.length;
|
|
@@ -1102,7 +1219,15 @@ function computeShapedTimeline(text, font, config, shaper) {
|
|
|
1102
1219
|
const data = font.glyphDataById?.[glyph.g] ?? lookupGlyphData(font, firstChar);
|
|
1103
1220
|
const hasGlyph = !!data;
|
|
1104
1221
|
if (isWhitespace) {
|
|
1105
|
-
|
|
1222
|
+
if (staggerSched) {
|
|
1223
|
+
staggerSched.addMarker({
|
|
1224
|
+
char: firstChar,
|
|
1225
|
+
graphemeIndex: graphemeIdx,
|
|
1226
|
+
glyphId: glyph.g,
|
|
1227
|
+
hasGlyph
|
|
1228
|
+
});
|
|
1229
|
+
staggerSched.separator("word");
|
|
1230
|
+
} else sched.separate("word", {
|
|
1106
1231
|
fields: {
|
|
1107
1232
|
char: firstChar,
|
|
1108
1233
|
graphemeIndex: graphemeIdx,
|
|
@@ -1113,7 +1238,15 @@ function computeShapedTimeline(text, font, config, shaper) {
|
|
|
1113
1238
|
});
|
|
1114
1239
|
continue;
|
|
1115
1240
|
}
|
|
1116
|
-
if (
|
|
1241
|
+
if (staggerSched) {
|
|
1242
|
+
const bundled = hasGlyph && data ? data.t ?? unknownDuration : unknownDuration;
|
|
1243
|
+
staggerSched.addGlyph({
|
|
1244
|
+
char: firstChar,
|
|
1245
|
+
graphemeIndex: graphemeIdx,
|
|
1246
|
+
glyphId: glyph.g,
|
|
1247
|
+
hasGlyph: !!(hasGlyph && data)
|
|
1248
|
+
}, bundled);
|
|
1249
|
+
} else if (hasGlyph && data) {
|
|
1117
1250
|
const part = partitionGlyph(data, unknownDuration, deferDots);
|
|
1118
1251
|
sched.add({
|
|
1119
1252
|
fields: {
|
|
@@ -1144,11 +1277,12 @@ function computeShapedTimeline(text, font, config, shaper) {
|
|
|
1144
1277
|
}
|
|
1145
1278
|
}
|
|
1146
1279
|
if (!atEnd) {
|
|
1147
|
-
|
|
1280
|
+
if (staggerSched) staggerSched.separator("line");
|
|
1281
|
+
else sched.separate("line");
|
|
1148
1282
|
lineStart = i + 1;
|
|
1149
1283
|
}
|
|
1150
1284
|
}
|
|
1151
|
-
return sched.finalize();
|
|
1285
|
+
return staggerSched ? staggerSched.finalize() : sched.finalize();
|
|
1152
1286
|
}
|
|
1153
1287
|
//#endregion
|
|
1154
1288
|
//#region src/types.ts
|
|
@@ -1162,7 +1296,7 @@ const BUNDLE_VERSION = 0;
|
|
|
1162
1296
|
* console warning (once per bundle) when it encounters a version outside
|
|
1163
1297
|
* this set.
|
|
1164
1298
|
*/
|
|
1165
|
-
const COMPATIBLE_BUNDLE_VERSIONS = new Set([0]);
|
|
1299
|
+
const COMPATIBLE_BUNDLE_VERSIONS = /* @__PURE__ */ new Set([0]);
|
|
1166
1300
|
//#endregion
|
|
1167
1301
|
//#region src/core/bundle-registry.ts
|
|
1168
1302
|
const bundles = /* @__PURE__ */ new Map();
|
|
@@ -1178,6 +1312,7 @@ function checkBundleVersion(bundle) {
|
|
|
1178
1312
|
function registerBundle(bundle) {
|
|
1179
1313
|
checkBundleVersion(bundle);
|
|
1180
1314
|
bundles.set(bundle.family, bundle);
|
|
1315
|
+
if (bundle.fullFamily && bundle.fullFamily !== bundle.family) bundles.set(bundle.fullFamily, bundle);
|
|
1181
1316
|
}
|
|
1182
1317
|
/** Look up a registered bundle by family name. */
|
|
1183
1318
|
function getBundle(family) {
|
|
@@ -2114,7 +2249,7 @@ var TegakiEngine = class {
|
|
|
2114
2249
|
unitsPerEm: font.unitsPerEm,
|
|
2115
2250
|
ascender: font.ascender,
|
|
2116
2251
|
descender: font.descender
|
|
2117
|
-
}, localTime, font.lineCap, color, this._resolvedEffects, this._seed + charIdx, getSubdivided, this._timing?.strokeEasing, strokeScale, stage?.strokeStyle, entry.strokeDelays);
|
|
2252
|
+
}, localTime, font.lineCap, color, this._resolvedEffects, this._seed + charIdx, getSubdivided, this._timing?.strokeEasing, strokeScale, stage?.strokeStyle, entry.strokeDelays, entry.strokeTimeScale);
|
|
2118
2253
|
} else if (!entry.hasGlyph && currentTime >= entry.offset + entry.duration) {
|
|
2119
2254
|
const baseline = y + halfLeading + font.ascender / font.unitsPerEm * fontSize;
|
|
2120
2255
|
drawFallbackGlyph(ctx, entry.char, x, baseline, fontSize, cssFontFamily(font), color, this._resolvedEffects, this._seed + charIdx);
|
|
@@ -2162,4 +2297,4 @@ var TegakiEngine = class {
|
|
|
2162
2297
|
//#endregion
|
|
2163
2298
|
export { findEffect as _, createBundle as a, hasRenderHooks as b, resolveBundle as c, computeTimeline as d, computeLayoutBbox as f, coerceToString as g, drawGlyph as h, domCreateElement as i, BUNDLE_VERSION as l, ensureFontFace as m, buildChildren as n, getBundle as o, computeTextLayout as p, buildRootProps as r, registerBundle as s, TegakiEngine as t, COMPATIBLE_BUNDLE_VERSIONS as u, findEffects as v, resolveEffects as x, getEffectDefinition as y };
|
|
2164
2299
|
|
|
2165
|
-
//# sourceMappingURL=core-
|
|
2300
|
+
//# sourceMappingURL=core-B87FE4Wo.mjs.map
|