@lightningjs/blits 0.9.9 → 1.0.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 +27 -0
- package/boilerplate/common/public/fonts/Lato-Regular.ttf +0 -0
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.ttf +0 -0
- package/docs/essentials/displaying_text.md +1 -1
- package/package.json +3 -4
- package/src/component/base/events.js +1 -1
- package/src/component/base/utils.js +34 -1
- package/src/component/setup/props.js +3 -1
- package/src/component/setup/props.test.js +51 -19
- package/src/component.d.ts +2 -1
- package/src/component.js +20 -13
- package/src/components/Circle.js +13 -12
- package/src/components/FPScounter.js +413 -465
- package/src/components/Image.js +7 -9
- package/src/components/Layout.js +49 -0
- package/src/components/Layout.orig.js +34 -0
- package/src/components/RouterView.js +6 -10
- package/src/components/Sprite.js +10 -12
- package/src/components/index.js +2 -2
- package/src/components/index.orig.js +2 -2
- package/src/engine.js +1 -1
- package/src/engines/L3/element.js +193 -180
- package/src/engines/L3/element.test.js +170 -0
- package/src/engines/L3/fontLoader.js +20 -7
- package/src/engines/L3/index.js +2 -2
- package/src/engines/L3/launch.js +7 -13
- package/src/engines/L3/shaderLoader.js +12 -0
- package/src/engines/index.js +1 -1
- package/src/launch.d.ts +19 -2
- package/src/lib/codegenerator/generator.js +214 -77
- package/src/lib/codegenerator/generator.test.js +657 -942
- package/src/lib/colors/colors.js +59 -46
- package/src/lib/precompiler/precompiler.js +2 -1
- package/src/lib/reactivity/effect.js +10 -13
- package/src/lib/reactivity/reactive.js +24 -14
- package/src/lib/symbols.js +1 -0
- package/src/router/router.js +17 -3
- package/vite/msdfGenerator.js +52 -53
- package/boilerplate/common/public/fonts/Lato-Regular.msdf.json +0 -5383
- package/boilerplate/common/public/fonts/Lato-Regular.msdf.png +0 -0
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.json +0 -10838
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.png +0 -0
- package/boilerplate/js/default/src/renderer.js +0 -4
- package/src/components/Text.js +0 -119
- package/src/components/Text.orig.js +0 -81
package/src/lib/colors/colors.js
CHANGED
|
@@ -15,64 +15,77 @@
|
|
|
15
15
|
* SPDX-License-Identifier: Apache-2.0
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
|
|
18
|
+
import colorsMap from './htmlColors.js'
|
|
19
|
+
|
|
20
|
+
const hex = /^#?([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i
|
|
21
|
+
const rgba =
|
|
22
|
+
/^(rgba?)\((\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*),(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*),(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*)(,(\s*(-?\d+(?:\.\d+)?)\s*))?\)$/
|
|
23
|
+
const hsla =
|
|
24
|
+
/^(hsla?)\((\s*(360|3[0-5][0-9]|[12]?[0-9]{1,2})\s*),(\s*(100|[1-9]?[0-9])\s*)%,(\s*(100|[1-9]?[0-9])\s*)%(,(\s*(1|0(?:\.\d+)?)\s*))?\)$/
|
|
25
|
+
|
|
26
|
+
const hexLookup = {}
|
|
27
|
+
|
|
28
|
+
const decimalToHex = (decimal) => {
|
|
29
|
+
if (hexLookup[decimal] !== undefined) {
|
|
30
|
+
return hexLookup[decimal]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const resp = parseInt(decimal).toString(16).padStart(2, '0')
|
|
34
|
+
hexLookup[decimal] = resp
|
|
35
|
+
return resp
|
|
36
|
+
}
|
|
20
37
|
|
|
21
38
|
export default {
|
|
22
|
-
|
|
23
|
-
// Because the template parser evaluates attribute values, even if they are not color codes,
|
|
24
|
-
// to determine whether they represent color values or not.
|
|
25
|
-
normalize(color = '', defaultColor = '0xffffffff') {
|
|
39
|
+
normalize: (color = '', defaultColor = '0xffffffff') => {
|
|
26
40
|
color = color.toString()
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/^(rgba?)\((\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*),(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*),(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\s*)(,(\s*(-?\d+(?:\.\d+)?)\s*))?\)$/
|
|
33
|
-
const hsla =
|
|
34
|
-
/^(hsla?)\((\s*(360|3[0-5][0-9]|[12]?[0-9]{1,2})\s*),(\s*(100|[1-9]?[0-9])\s*)%,(\s*(100|[1-9]?[0-9])\s*)%(,(\s*(1|0(?:\.\d+)?)\s*))?\)$/
|
|
42
|
+
// its mappable, map it
|
|
43
|
+
if (colorsMap[color] !== undefined) {
|
|
44
|
+
return colorsMap[color]
|
|
45
|
+
}
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
// its a 0xRRGGBBAA color, store it and return it
|
|
48
|
+
if (color.startsWith('0x') && color.length === 10) {
|
|
49
|
+
colorsMap[color] = color
|
|
50
|
+
return color
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// check for hex color
|
|
54
|
+
if (hex.test(color)) {
|
|
55
|
+
color = color.replace('#', '').toLowerCase()
|
|
56
|
+
if (color.length === 3) {
|
|
57
|
+
color = color
|
|
58
|
+
.split('')
|
|
59
|
+
.map((c) => c + c)
|
|
60
|
+
.join('')
|
|
38
61
|
}
|
|
39
62
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.split('')
|
|
45
|
-
.map((c) => c + c)
|
|
46
|
-
.join('')
|
|
47
|
-
}
|
|
63
|
+
const colorRGBA = '0x' + color.padEnd(8, 'f')
|
|
64
|
+
colorsMap[color] = colorRGBA
|
|
65
|
+
return colorRGBA
|
|
66
|
+
}
|
|
48
67
|
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
//rgb/a
|
|
69
|
+
const rgbaMatch = rgba.exec(color)
|
|
70
|
+
if (rgbaMatch) {
|
|
71
|
+
const r = decimalToHex(rgbaMatch[3])
|
|
72
|
+
const g = decimalToHex(rgbaMatch[5])
|
|
73
|
+
const b = decimalToHex(rgbaMatch[7])
|
|
74
|
+
let a = 'ff'
|
|
51
75
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
'0x' +
|
|
57
|
-
parseInt(rgbaMatch[3]).toString(16).padStart(2, '0') +
|
|
58
|
-
parseInt(rgbaMatch[5]).toString(16).padStart(2, '0') +
|
|
59
|
-
parseInt(rgbaMatch[7]).toString(16).padStart(2, '0') +
|
|
60
|
-
(rgbaMatch[10] && rgbaMatch[1] === 'rgba'
|
|
61
|
-
? Math.min(Math.max(Math.round(parseFloat(rgbaMatch[10]) * 255), 0), 255)
|
|
62
|
-
.toString(16)
|
|
63
|
-
.padStart(2, '0')
|
|
64
|
-
: 'ff')
|
|
65
|
-
)
|
|
76
|
+
if (rgbaMatch[10] && rgbaMatch[1] === 'rgba') {
|
|
77
|
+
const alpha = Math.min(Math.max(Math.round(parseFloat(rgbaMatch[10]) * 255), 0), 255)
|
|
78
|
+
a = decimalToHex(alpha)
|
|
66
79
|
}
|
|
67
80
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
const resp = '0x' + r + g + b + a
|
|
82
|
+
colorsMap[color] = resp
|
|
83
|
+
return resp
|
|
84
|
+
}
|
|
72
85
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
if (hsla.test(color)) {
|
|
87
|
+
console.warn('HSL(A) color format is not supported yet')
|
|
88
|
+
return '0xffffffff'
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
return defaultColor
|
|
@@ -23,7 +23,8 @@ export default (source, filePath) => {
|
|
|
23
23
|
if (
|
|
24
24
|
source.indexOf('Blits.Component(') > -1 ||
|
|
25
25
|
source.indexOf('Blits.Application(') > -1 ||
|
|
26
|
-
/=>\s*Component\(['"][A-Za-z]+['"],/s.test(source) // blits component
|
|
26
|
+
/=>\s*Component\(['"][A-Za-z]+['"],/s.test(source) || // blits component
|
|
27
|
+
/\{.*?template\s*:\s*(['"`])((?:\\?.)*?)\1.*?\}/s.test(source) // object with template key
|
|
27
28
|
) {
|
|
28
29
|
const templates = source.matchAll(/(?<!\/\/\s*)template\s*:\s*(['"`])((?:\\?.)*?)\1/gs)
|
|
29
30
|
let newSource = source
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
let currentEffect = null
|
|
19
|
+
let currentKey = null
|
|
19
20
|
|
|
20
21
|
let paused = false
|
|
21
22
|
|
|
@@ -25,22 +26,16 @@ export const pauseTracking = () => {
|
|
|
25
26
|
|
|
26
27
|
export const resumeTracking = () => {
|
|
27
28
|
paused = false
|
|
28
|
-
for (let i = 0; i < trackQueue.length; i++) {
|
|
29
|
-
const item = trackQueue[i]
|
|
30
|
-
currentEffect = item.currentEffect
|
|
31
|
-
track(item.target, item.key)
|
|
32
|
-
}
|
|
33
|
-
trackQueue.length = 0
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
const objectMap = new WeakMap()
|
|
37
32
|
|
|
38
|
-
const trackQueue = []
|
|
39
|
-
|
|
40
33
|
export const track = (target, key) => {
|
|
41
34
|
if (currentEffect) {
|
|
42
35
|
if (paused) {
|
|
43
|
-
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (currentKey !== null && key !== currentKey) {
|
|
44
39
|
return
|
|
45
40
|
}
|
|
46
41
|
let effectsMap = objectMap.get(target)
|
|
@@ -58,21 +53,23 @@ export const track = (target, key) => {
|
|
|
58
53
|
}
|
|
59
54
|
|
|
60
55
|
export const trigger = (target, key, force = false) => {
|
|
61
|
-
if (paused) return
|
|
56
|
+
if (paused === true) return
|
|
62
57
|
const effectsMap = objectMap.get(target)
|
|
63
58
|
if (!effectsMap) {
|
|
64
59
|
return
|
|
65
60
|
}
|
|
66
61
|
const effects = effectsMap.get(key)
|
|
67
62
|
if (effects) {
|
|
68
|
-
|
|
63
|
+
for (let effect of effects) {
|
|
69
64
|
effect(force)
|
|
70
|
-
}
|
|
65
|
+
}
|
|
71
66
|
}
|
|
72
67
|
}
|
|
73
68
|
|
|
74
|
-
export const effect = (effect) => {
|
|
69
|
+
export const effect = (effect, key = null) => {
|
|
75
70
|
currentEffect = effect
|
|
71
|
+
currentKey = key
|
|
76
72
|
currentEffect()
|
|
77
73
|
currentEffect = null
|
|
74
|
+
currentKey = null
|
|
78
75
|
}
|
|
@@ -18,27 +18,27 @@
|
|
|
18
18
|
import { track, trigger, pauseTracking, resumeTracking } from './effect.js'
|
|
19
19
|
import symbols from '../symbols.js'
|
|
20
20
|
|
|
21
|
-
const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice']
|
|
21
|
+
const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort']
|
|
22
22
|
|
|
23
23
|
const proxyMap = new WeakMap()
|
|
24
24
|
|
|
25
|
-
const
|
|
26
|
-
return proxyMap.get(obj)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const getRaw = (value) => {
|
|
25
|
+
export const getRaw = (value) => {
|
|
30
26
|
const raw = value && value[symbols.raw]
|
|
31
27
|
return raw ? getRaw(raw) : value
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
const reactiveProxy = (original, _parent = null, _key) => {
|
|
35
|
-
// don't create a proxy when a Blits component
|
|
36
|
-
|
|
31
|
+
// don't create a proxy when a Blits component or an Image Texture
|
|
32
|
+
// is assigned to a state variable
|
|
33
|
+
if (
|
|
34
|
+
(typeof original === 'object' && original[symbols.id]) ||
|
|
35
|
+
original.constructor.name === '_ImageTexture'
|
|
36
|
+
) {
|
|
37
37
|
return original
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// if original object is already a proxy, don't create a new one but return the existing one instead
|
|
41
|
-
const existingProxy =
|
|
41
|
+
const existingProxy = proxyMap.get(original)
|
|
42
42
|
if (existingProxy) {
|
|
43
43
|
return existingProxy
|
|
44
44
|
}
|
|
@@ -52,21 +52,31 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
52
52
|
|
|
53
53
|
// handling arrays
|
|
54
54
|
if (Array.isArray(target)) {
|
|
55
|
+
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
56
|
+
if (Array.isArray(target[key])) {
|
|
57
|
+
track(target, key)
|
|
58
|
+
}
|
|
59
|
+
// create a new reactive proxy
|
|
60
|
+
return reactiveProxy(getRaw(target[key]), target, key)
|
|
61
|
+
}
|
|
55
62
|
// augment array path methods (that change the length of the array)
|
|
56
|
-
if (arrayPatchMethods.indexOf(key)
|
|
63
|
+
if (arrayPatchMethods.indexOf(key) !== -1) {
|
|
57
64
|
return function (...args) {
|
|
58
65
|
pauseTracking()
|
|
59
66
|
const result = target[key].apply(this, args)
|
|
67
|
+
resumeTracking()
|
|
60
68
|
// trigger a change on the parent object and the key
|
|
61
69
|
// i.e. when pushing a new item to `obj.data`, _parent will equal `obj`
|
|
62
70
|
// and _key will equal `data`
|
|
63
|
-
resumeTracking()
|
|
64
71
|
trigger(_parent, _key)
|
|
65
72
|
return result
|
|
66
73
|
}
|
|
67
|
-
} else {
|
|
68
|
-
return Reflect.get(target, key, receiver)
|
|
69
74
|
}
|
|
75
|
+
if (key === 'length') {
|
|
76
|
+
return original.length
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return Reflect.get(target, key, receiver)
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
// handling objects (but not null values, which have object type in JS)
|
|
@@ -75,7 +85,7 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
75
85
|
track(target, key)
|
|
76
86
|
}
|
|
77
87
|
// create a new reactive proxy
|
|
78
|
-
return reactiveProxy(target[key], target, key)
|
|
88
|
+
return reactiveProxy(getRaw(target[key]), target, key)
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
// handling all other types
|
package/src/lib/symbols.js
CHANGED
package/src/router/router.js
CHANGED
|
@@ -259,9 +259,23 @@ const removeView = async (route, view, transition) => {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
const setOrAnimate = (node, transition, shouldAnimate = true) => {
|
|
262
|
-
return
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
return new Promise((resolve) => {
|
|
263
|
+
if (shouldAnimate) {
|
|
264
|
+
// resolve the promise in the transition end-callback
|
|
265
|
+
// ("extending" end callback when one is already specified)
|
|
266
|
+
const existingEndCallback = transition.end
|
|
267
|
+
transition.end = existingEndCallback
|
|
268
|
+
? (...args) => {
|
|
269
|
+
existingEndCallback(...args)
|
|
270
|
+
resolve()
|
|
271
|
+
}
|
|
272
|
+
: resolve
|
|
273
|
+
node.set(transition.prop, { transition })
|
|
274
|
+
} else {
|
|
275
|
+
node.set(transition.prop, transition.value)
|
|
276
|
+
resolve()
|
|
277
|
+
}
|
|
278
|
+
})
|
|
265
279
|
}
|
|
266
280
|
|
|
267
281
|
export const to = (location, data = {}, options = {}) => {
|
package/vite/msdfGenerator.js
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import * as fs from 'fs'
|
|
3
|
-
import
|
|
3
|
+
import { genFont, setGeneratePaths } from '@lightningjs/msdf-generator'
|
|
4
|
+
import { adjustFont } from '@lightningjs/msdf-generator/adjustFont'
|
|
4
5
|
|
|
6
|
+
class TaskQueue {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.currentTask = Promise.resolve()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async enqueue(task) {
|
|
12
|
+
// Wait for the current task to complete before starting a new one
|
|
13
|
+
this.currentTask = this.currentTask.then(task, this.handleError)
|
|
14
|
+
await this.currentTask
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
handleError(error) {
|
|
18
|
+
console.error('Error during task execution:', error)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const fontGenerationQueue = new TaskQueue()
|
|
5
23
|
let config
|
|
6
24
|
|
|
7
25
|
export default function () {
|
|
@@ -15,14 +33,13 @@ export default function () {
|
|
|
15
33
|
config = resolvedConfig
|
|
16
34
|
buildOutputPath = config.build.outDir
|
|
17
35
|
publicDir = path.join(config.root, 'public')
|
|
18
|
-
msdfOutputDir = path.resolve(config.root, 'node_modules', '.tmp-msdf-fonts')
|
|
36
|
+
msdfOutputDir = path.resolve(config.root, 'node_modules', '.tmp-msdf-fonts-v2')
|
|
19
37
|
},
|
|
20
38
|
async configureServer(server) {
|
|
21
39
|
server.middlewareMode = true
|
|
22
40
|
server.middlewares.use('/', async (req, res, next) => {
|
|
23
41
|
const file = req.url.substring(req.url.lastIndexOf('/') + 1)
|
|
24
42
|
const match = file.match(/(.+)\.msdf\.(json|png)/)
|
|
25
|
-
|
|
26
43
|
// msdf font request
|
|
27
44
|
if (match) {
|
|
28
45
|
const fontPath = path.dirname(req.url.split('?')[0]).replace(/^\//, '')
|
|
@@ -42,21 +59,28 @@ export default function () {
|
|
|
42
59
|
)
|
|
43
60
|
const mimeType = ext === 'png' ? 'image/png' : 'application/json'
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
await fontGenerationQueue.enqueue(async () => {
|
|
63
|
+
if (!fs.existsSync(generatedFontFile)) {
|
|
64
|
+
// Check if generation is needed
|
|
65
|
+
console.log(`\nGenerating ${targetDir}/${fontName}.msdf.${ext}`)
|
|
66
|
+
await generateSDF(fontFile, path.join(targetDir))
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
if (fs.existsSync(generatedFontFile)) {
|
|
71
|
+
const fileContent = fs.readFileSync(generatedFontFile)
|
|
72
|
+
|
|
73
|
+
// Check if headers have already been sent
|
|
74
|
+
if (!res.headersSent) {
|
|
75
|
+
res.setHeader('Content-Type', mimeType)
|
|
76
|
+
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
|
|
77
|
+
res.end(fileContent)
|
|
78
|
+
} else {
|
|
79
|
+
// this should never happen except some edge cases
|
|
80
|
+
console.error(`ERROR: Headers already sent for ${req.url}`, res.getHeaders())
|
|
81
|
+
}
|
|
57
82
|
} else {
|
|
58
|
-
//
|
|
59
|
-
console.error(`ERROR: Headers already sent for ${req.url}`, res.getHeaders())
|
|
83
|
+
next() // Handle case where generation might have failed
|
|
60
84
|
}
|
|
61
85
|
} else {
|
|
62
86
|
next() // ttf file does not exist
|
|
@@ -71,7 +95,6 @@ export default function () {
|
|
|
71
95
|
},
|
|
72
96
|
// after build ends, the first hook is renderStart where we can modify the output
|
|
73
97
|
async renderStart() {
|
|
74
|
-
// Find all TTF files under publicDir
|
|
75
98
|
const ttfFiles = findAllTtfFiles(publicDir)
|
|
76
99
|
|
|
77
100
|
for (const ttfFile of ttfFiles) {
|
|
@@ -83,7 +106,7 @@ export default function () {
|
|
|
83
106
|
// Check if MSDF files are generated, if not, generate them
|
|
84
107
|
if (!fs.existsSync(msdfJsonPath) || !fs.existsSync(msdfPngPath)) {
|
|
85
108
|
console.log(`Generating missing MSDF files for ${ttfFile}`)
|
|
86
|
-
await
|
|
109
|
+
await generateSDF(ttfFile, path.join(msdfOutputDir, relativePath))
|
|
87
110
|
}
|
|
88
111
|
}
|
|
89
112
|
|
|
@@ -94,40 +117,16 @@ export default function () {
|
|
|
94
117
|
}
|
|
95
118
|
}
|
|
96
119
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
(err, textures, font) => {
|
|
108
|
-
if (err) {
|
|
109
|
-
console.error(err)
|
|
110
|
-
reject(err)
|
|
111
|
-
} else {
|
|
112
|
-
textures.forEach((texture) => {
|
|
113
|
-
try {
|
|
114
|
-
fs.writeFileSync(path.resolve(fontDir, `${fontName}.msdf.png`), texture.texture)
|
|
115
|
-
} catch (e) {
|
|
116
|
-
console.error(e)
|
|
117
|
-
reject(e)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
try {
|
|
121
|
-
fs.writeFileSync(path.resolve(fontDir, `${fontName}.msdf.json`), font.data)
|
|
122
|
-
resolve()
|
|
123
|
-
} catch (e) {
|
|
124
|
-
console.error(err)
|
|
125
|
-
reject(e)
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
})
|
|
120
|
+
const generateSDF = async (inputFilePath, outputDirPath) => {
|
|
121
|
+
// Ensure the destination directory exists
|
|
122
|
+
fs.mkdirSync(outputDirPath, { recursive: true })
|
|
123
|
+
|
|
124
|
+
setGeneratePaths(path.dirname(inputFilePath), outputDirPath)
|
|
125
|
+
|
|
126
|
+
let font = await genFont(path.basename(inputFilePath), 'msdf')
|
|
127
|
+
|
|
128
|
+
if (font) await adjustFont(font)
|
|
129
|
+
else console.error('Failed to generate MSDF file')
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
// finds all TTF files in a directory
|