@lightningjs/blits 1.51.0 → 2.0.0-beta.10

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.
Files changed (45) hide show
  1. package/element-test-full.txt +0 -0
  2. package/index.d.ts +35 -50
  3. package/package.json +6 -6
  4. package/scripts/lint.js +17 -0
  5. package/scripts/prepublishOnly.js +2 -2
  6. package/scripts/prepush.js +4 -6
  7. package/src/component/base/methods.js +16 -76
  8. package/src/component/base/utils.js +18 -4
  9. package/src/component/setup/props.js +37 -28
  10. package/src/component/setup/state.js +5 -5
  11. package/src/component.js +28 -19
  12. package/src/components/Circle.js +52 -9
  13. package/src/components/FPScounter.js +224 -88
  14. package/src/components/RouterView.js +58 -6
  15. package/src/components/Sprite.js +72 -8
  16. package/src/constants.js +17 -0
  17. package/src/engine.js +17 -0
  18. package/src/engines/L3/element.js +109 -86
  19. package/src/engines/L3/fontLoader.js +43 -31
  20. package/src/engines/L3/index.js +17 -0
  21. package/src/engines/L3/launch.js +1 -0
  22. package/src/engines/L3/shaderLoader.js +73 -6
  23. package/src/engines/index.js +17 -0
  24. package/src/focus/focus.js +7 -7
  25. package/src/focus/helpers.js +4 -2
  26. package/src/focus/hover.js +7 -6
  27. package/src/helpers/fetchJson.js +4 -6
  28. package/src/launch.js +1 -2
  29. package/src/lib/codegenerator/generator.js +127 -16
  30. package/src/lib/colors/colors.js +0 -1
  31. package/src/lib/lifecycle.js +8 -10
  32. package/src/lib/log.js +4 -4
  33. package/src/lib/reactivityguard/computedprops.js +27 -13
  34. package/src/lib/shaders/shaders.js +164 -0
  35. package/src/lib/symbols.js +25 -0
  36. package/src/lib/templateparser/parser.js +6 -2
  37. package/src/lib/utils.js +53 -0
  38. package/src/plugin.js +17 -0
  39. package/src/plugins/storage/localCookie.js +4 -6
  40. package/src/router/router.js +23 -15
  41. package/test-output.txt +0 -0
  42. package/vite/blitsTips.js +57 -0
  43. package/vite/inject-dev-config.js +17 -0
  44. package/vite/msdfGenerator.js +52 -6
  45. package/vscode/data/template-attributes.json +112 -0
@@ -25,6 +25,48 @@ export default () =>
25
25
  code: {
26
26
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
27
27
  const elms = []
28
+ const validAttributes = [
29
+ 'parent',
30
+ 'rotation',
31
+ 'w',
32
+ 'width',
33
+ 'h',
34
+ 'height',
35
+ 'x',
36
+ 'y',
37
+ 'z',
38
+ 'zIndex',
39
+ 'color',
40
+ 'src',
41
+ 'texture',
42
+ 'fit',
43
+ 'rtt',
44
+ 'mount',
45
+ 'pivot',
46
+ 'scale',
47
+ 'show',
48
+ 'alpha',
49
+ 'rounded',
50
+ 'border',
51
+ 'shadow',
52
+ 'shader',
53
+ 'clipping',
54
+ 'overflow',
55
+ 'font',
56
+ 'size',
57
+ 'maxwidth',
58
+ 'maxheight',
59
+ 'maxlines',
60
+ 'textoverflow',
61
+ 'letterspacing',
62
+ 'lineheight',
63
+ 'contain',
64
+ 'align',
65
+ 'content',
66
+ 'placement',
67
+ 'inspector-data',
68
+ 'holder',
69
+ ]
28
70
  const elementConfigs = []
29
71
  const forloops = []
30
72
  const props = []
@@ -46,11 +88,13 @@ export default () =>
46
88
  inSlot === true ? slotComponent : component
47
89
  )
48
90
 
49
- elementConfigs[0]['w'] = parent.node.width * (100 / 100)
50
- elementConfigs[0]['h'] = parent.node.height * (100 / 100)
91
+ elementConfigs[0]['w'] = parent.node.w * (100 / 100)
92
+ elementConfigs[0]['h'] = parent.node.h * (100 / 100)
51
93
  elementConfigs[0]['texture'] = component.texture
52
94
  elementConfigs[0]['color'] = component.color
53
- elementConfigs[0]['effects'] = component.effects
95
+ elementConfigs[0]['rounded'] = component.rounded
96
+ elementConfigs[0]['border'] = component.border
97
+ elementConfigs[0]['shadow'] = component.shadow
54
98
  elms[0].populate(elementConfigs[0])
55
99
 
56
100
  if (inSlot === true) {
@@ -73,19 +117,39 @@ export default () =>
73
117
  props.length = 0
74
118
  skips.length = 0
75
119
  },
120
+ skips,
76
121
  }
77
122
  },
78
123
  effects: [
79
- function anonymous(component, elms, context, components, rootComponent, effect) {
124
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
80
125
  elms[0].set('texture', component.texture)
81
126
  },
82
- function anonymous(component, elms, context, components, rootComponent, effect) {
127
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
83
128
  elms[0].set('color', component.color)
84
129
  },
130
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
131
+ elms[0].set('rounded', component.rounded)
132
+ },
133
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
134
+ elms[0].set('border', component.border)
135
+ },
136
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
137
+ elms[0].set('shadow', component.shadow)
138
+ },
85
139
  ],
86
140
  context: {},
87
141
  },
88
- props: ['image', 'map', 'frame', 'color', 'effects', '@loaded', '@error'],
142
+ props: {
143
+ image: undefined,
144
+ map: undefined,
145
+ frame: undefined,
146
+ color: undefined,
147
+ rounded: undefined,
148
+ border: undefined,
149
+ shadow: undefined,
150
+ '@loaded': undefined,
151
+ '@error': undefined,
152
+ },
89
153
  state() {
90
154
  return {
91
155
  spriteTexture: null,
@@ -182,8 +246,8 @@ export default () =>
182
246
  texture: this.spriteTexture,
183
247
  x: options.x,
184
248
  y: options.y,
185
- width: options.w,
186
- height: options.h,
249
+ w: options.w,
250
+ h: options.h,
187
251
  })
188
252
  }
189
253
 
package/src/constants.js CHANGED
@@ -1,3 +1,20 @@
1
+ /*
2
+ * Copyright 2023 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
1
18
  export const DEFAULT_HOLD_TIMEOUT_MS = 50
2
19
 
3
20
  export const DEFAULT_KEYMAP = {
package/src/engine.js CHANGED
@@ -1 +1,18 @@
1
+ /*
2
+ * Copyright 2023 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
1
18
  export { L3 as default } from './engines/index.js'
@@ -16,11 +16,13 @@
16
16
  */
17
17
 
18
18
  import { renderer } from './launch.js'
19
+ import { parseToObject, isObjectString, isArrayString, isTransition } from '../../lib/utils.js'
19
20
  import colors from '../../lib/colors/colors.js'
20
21
 
21
22
  import { Log } from '../../lib/log.js'
22
23
  import symbols from '../../lib/symbols.js'
23
24
  import Settings from '../../settings.js'
25
+ import shaders from '../../lib/shaders/shaders.js'
24
26
 
25
27
  const holderComponentMap = new WeakMap()
26
28
 
@@ -81,8 +83,8 @@ const layoutFn = function (config) {
81
83
  const position = config.direction === 'vertical' ? 'y' : 'x'
82
84
  const oppositePosition = config.direction === 'vertical' ? 'x' : 'y'
83
85
  const oppositeMount = config.direction === 'vertical' ? 'mountX' : 'mountY'
84
- const dimension = config.direction === 'vertical' ? 'height' : 'width'
85
- const oppositeDimension = config.direction === 'vertical' ? 'width' : 'height'
86
+ const dimension = config.direction === 'vertical' ? 'h' : 'w'
87
+ const oppositeDimension = config.direction === 'vertical' ? 'w' : 'h'
86
88
  const padding = createPaddingObject(config.padding, config.direction)
87
89
 
88
90
  let offset = padding.start
@@ -100,17 +102,10 @@ const layoutFn = function (config) {
100
102
  node[position] = offset
101
103
  node[oppositePosition] = padding.oppositeStart
102
104
  // todo: temporary text check, due to 1px width of empty text node
103
- if (dimension === 'width') {
104
- offset += node.width + (node.width !== ('text' in node ? 1 : 0) ? gap : 0)
105
+ if (dimension === 'w') {
106
+ offset += node.w + (node.w !== ('text' in node ? 1 : 0) ? gap : 0)
105
107
  } else {
106
- offset +=
107
- 'text' in node
108
- ? node.width > 1
109
- ? node.height + gap
110
- : 0
111
- : node.height !== 0
112
- ? node.height + gap
113
- : 0
108
+ offset += 'text' in node ? (node.w > 1 ? node.h + gap : 0) : node.h !== 0 ? node.h + gap : 0
114
109
  }
115
110
  otherDimension = Math.max(
116
111
  otherDimension,
@@ -137,7 +132,7 @@ const layoutFn = function (config) {
137
132
 
138
133
  // emit an updated event
139
134
  if (config['@updated'] !== undefined) {
140
- config['@updated']({ w: this.node.width, h: this.node.height }, this)
135
+ config['@updated']({ w: this.node.w, h: this.node.h }, this)
141
136
  }
142
137
 
143
138
  // trigger layout on parent if parent is a layout
@@ -146,33 +141,6 @@ const layoutFn = function (config) {
146
141
  }
147
142
  }
148
143
 
149
- /**
150
- * Checks if a value is a transition object.
151
- * @param {any} value - The value to check.
152
- * @returns {boolean} True if the value is a transition object, false otherwise.
153
- */
154
- const isTransition = (value) => {
155
- return value !== null && typeof value === 'object' && 'transition' in value === true
156
- }
157
-
158
- /**
159
- * Checks if a string is an object string (starts and ends with curly braces).
160
- * @param {string} str - The string to check.
161
- * @returns {boolean} True if the string is an object string, false otherwise.
162
- */
163
- const isObjectString = (str) => {
164
- return typeof str === 'string' && str.startsWith('{') && str.endsWith('}')
165
- }
166
-
167
- /**
168
- * Parses a string into an object, converting single quotes to double and adding quotes to keys.
169
- * @param {string} str - The string to parse.
170
- * @returns {object} The parsed object.
171
- */
172
- const parseToObject = (str) => {
173
- return JSON.parse(str.replace(/'/g, '"').replace(/([{,]\s*)([\w-_]+)(\s*:)/g, '$1"$2"$3'))
174
- }
175
-
176
144
  /**
177
145
  * Parses a percentage string or returns the value as-is.
178
146
  * @param {string|number} v - The value to parse (may be a percentage string).
@@ -244,36 +212,38 @@ const propsTransformer = {
244
212
  this.props['rotation'] = v * (Math.PI / 180)
245
213
  },
246
214
  set w(v) {
247
- this.props['width'] = parsePercentage.call(this, v, 'width')
215
+ const parsed = parsePercentage.call(this, v, 'w')
216
+ this.props['w'] = parsed
248
217
  if (
249
218
  this.___wrapper === true &&
250
219
  this.element.component.eol !== true &&
251
220
  this.element.component[symbols.holder] !== undefined
252
221
  ) {
253
- this.element.component[symbols.holder].set('w', this.props['width'])
222
+ this.element.component[symbols.holder].set('w', parsed)
254
223
  }
255
224
  },
256
225
  set width(v) {
257
226
  this.w = v
258
227
  },
259
228
  set h(v) {
260
- this.props['height'] = parsePercentage.call(this, v, 'height')
229
+ const parsed = parsePercentage.call(this, v, 'h')
230
+ this.props['h'] = parsed
261
231
  if (
262
232
  this.___wrapper === true &&
263
233
  this.element.component.eol !== true &&
264
234
  this.element.component[symbols.holder] !== undefined
265
235
  ) {
266
- this.element.component[symbols.holder].set('h', this.props['height'])
236
+ this.element.component[symbols.holder].set('h', parsed)
267
237
  }
268
238
  },
269
239
  set height(v) {
270
240
  this.h = v
271
241
  },
272
242
  set x(v) {
273
- this.props['x'] = parsePercentage.call(this, v, 'width')
243
+ this.props['x'] = parsePercentage.call(this, v, 'w')
274
244
  },
275
245
  set y(v) {
276
- this.props['y'] = parsePercentage.call(this, v, 'height')
246
+ this.props['y'] = parsePercentage.call(this, v, 'h')
277
247
  },
278
248
  set z(v) {
279
249
  this.props['zIndex'] = v
@@ -303,7 +273,7 @@ const propsTransformer = {
303
273
  this.props['color'] = this.props['src'] ? 0xffffffff : 0x00000000
304
274
  }
305
275
  // apply auto sizing when no width or height specified
306
- if (!('w' in this.raw) && !('w' in this.raw) && !('h' in this.raw) && !('height' in this.raw)) {
276
+ if (!('w' in this.raw) && !('h' in this.raw)) {
307
277
  this.props['autosize'] = true
308
278
  }
309
279
  },
@@ -395,37 +365,68 @@ const propsTransformer = {
395
365
  this.props['alpha'] = v
396
366
  }
397
367
  },
368
+ set rounded(v) {
369
+ this.props['rounded'] = v
370
+ if (this.element.node !== undefined && this.elementShader === true) {
371
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
372
+ this.element.node.props['shader'].props = v
373
+ } else {
374
+ if (isArrayString(v) === true) {
375
+ v = JSON.parse(v)
376
+ }
377
+ this.element.node.props['shader'].props.radius = v
378
+ }
379
+ }
380
+ },
381
+ set border(v) {
382
+ this.props['border'] = v
383
+ if (
384
+ this.element.node !== undefined &&
385
+ this.elementShader === true &&
386
+ (typeof v === 'object' || isObjectString(v) === true)
387
+ ) {
388
+ v = shaders.parseProps(v)
389
+ for (const key in v) {
390
+ this.element.node.props['shader'].props[`border-${key}`] = v[key]
391
+ }
392
+ }
393
+ },
394
+ set shadow(v) {
395
+ this.props['shadow'] = v
396
+ if (
397
+ this.element.node !== undefined &&
398
+ this.elementShader === true &&
399
+ (typeof v === 'object' || isObjectString(v) === true)
400
+ ) {
401
+ v = shaders.parseProps(v)
402
+ for (const key in v) {
403
+ this.element.node.props['shader'].props[`shadow-${key}`] = v[key]
404
+ }
405
+ }
406
+ },
398
407
  set shader(v) {
408
+ let type = v
409
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
410
+ type = v.type
411
+ v = shaders.parseProps(v)
412
+ }
399
413
  const target = this.element.node !== undefined ? this.element.node : this.props
400
-
401
- if (v === null) {
402
- target['shader'] = null
414
+ //if v remains a string we can change shader types
415
+ if (typeof v === 'string') {
416
+ target['shader'] = renderer.createShader(type)
403
417
  return
404
418
  }
405
419
 
406
- if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
407
- if (target.shader !== undefined && target.shader.type === v.type) {
408
- for (const prop in v.props) {
409
- target.shader.props[prop] = v.props[prop]
410
- }
420
+ //check again if v is an object since it could have been an object string
421
+ if (typeof v === 'object') {
422
+ if (target.shader !== undefined && type === target.shader.shaderKey) {
423
+ target['shader'].props = v
411
424
  return
412
425
  }
413
- target['shader'] = renderer.createShader(v.type, v.props)
414
- }
415
- },
416
- set effects(v) {
417
- for (let i = 0; i < v.length; i++) {
418
- if (v[i].props && v[i].props.color) {
419
- v[i].props.color = colors.normalize(v[i].props.color)
420
- }
421
- }
422
- if (this.element.node === undefined) {
423
- this.props['shader'] = renderer.createShader('DynamicShader', {
424
- effects: v.map((effect) => {
425
- return renderer.createEffect(effect.type, effect.props)
426
- }),
427
- })
426
+ target['shader'] = renderer.createShader(type, v)
427
+ return
428
428
  }
429
+ target['shader'] = renderer.createShader('DefaultShader')
429
430
  },
430
431
  set clipping(v) {
431
432
  this.props['clipping'] = v
@@ -439,21 +440,27 @@ const propsTransformer = {
439
440
  set size(v) {
440
441
  this.props['fontSize'] = v
441
442
  },
442
- set wordwrap(v) {
443
- Log.warn('The wordwrap attribute is deprecated, use maxwidth instead')
444
- this.props['width'] = v
445
- this.props['contain'] = 'width'
446
- },
447
443
  set maxwidth(v) {
448
- this.props['width'] = v
444
+ this.props['maxWidth'] = v
445
+ if (this.manualTextContain === true) {
446
+ return
447
+ }
448
+ if (this.props['contain'] === 'height') {
449
+ this.props['contain'] = 'both'
450
+ return
451
+ }
449
452
  this.props['contain'] = 'width'
450
453
  },
451
454
  set maxheight(v) {
452
- this.props['height'] = v
453
- this.props['contain'] = 'both'
454
- },
455
- set contain(v) {
456
- this.props['contain'] = v
455
+ this.props['maxHeight'] = v
456
+ if (this.manualTextContain === true) {
457
+ return
458
+ }
459
+ if (this.props['contain'] === 'width') {
460
+ this.props['contain'] = 'both'
461
+ return
462
+ }
463
+ this.props['contain'] = 'height'
457
464
  },
458
465
  set maxlines(v) {
459
466
  this.props['maxLines'] = v
@@ -467,6 +474,10 @@ const propsTransformer = {
467
474
  set lineheight(v) {
468
475
  this.props['lineHeight'] = v
469
476
  },
477
+ set contain(v) {
478
+ this.props['contain'] = v
479
+ this.manualTextContain = true
480
+ },
470
481
  set align(v) {
471
482
  this.props['textAlign'] = v
472
483
  },
@@ -519,13 +530,14 @@ const propsTransformer = {
519
530
  },
520
531
  }
521
532
 
533
+ export const elementAttributes = Object.keys(propsTransformer)
534
+
522
535
  const Element = {
523
536
  /**
524
537
  * Populates the element with data
525
- * @param {import('../../component.js').BlitsElementProps} data
538
+ * @param {import('../../component.js').BlitsElementProps} props
526
539
  */
527
- populate(data) {
528
- const props = data
540
+ populate(props) {
529
541
  props['node'] = this.config.node
530
542
 
531
543
  if (props[symbols.isSlot] === true) {
@@ -538,11 +550,22 @@ const Element = {
538
550
  //@ts-ignore This might be a left over from the old code?
539
551
  delete props.parent
540
552
 
541
- this.props.raw = data
553
+ this.props.raw = props
554
+ this.props.elementShader = false
542
555
 
543
556
  const propKeys = Object.keys(props)
544
557
  const length = propKeys.length
545
558
 
559
+ if (
560
+ props['shader'] === undefined &&
561
+ (props['rounded'] !== undefined ||
562
+ props['border'] !== undefined ||
563
+ props['shadow'] !== undefined)
564
+ ) {
565
+ this.props.elementShader = true
566
+ this.props.props['shader'] = shaders.createElementShader(props)
567
+ }
568
+
546
569
  for (let i = 0; i < length; i++) {
547
570
  const key = propKeys[i]
548
571
  const value = props[key]
@@ -566,7 +589,7 @@ const Element = {
566
589
 
567
590
  if (props['@loaded'] !== undefined && typeof props['@loaded'] === 'function') {
568
591
  this.node.on('loaded', (el, { type, dimensions }) => {
569
- props['@loaded']({ w: dimensions.width, h: dimensions.height, type }, this)
592
+ props['@loaded']({ w: dimensions.w, h: dimensions.h, type }, this)
570
593
  })
571
594
  }
572
595
 
@@ -1,38 +1,50 @@
1
- import { SdfTrFontFace, WebTrFontFace } from '@lightningjs/renderer'
1
+ /*
2
+ * Copyright 2023 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
2
18
  import Settings from '../../settings.js'
3
19
  import { renderer } from './launch.js'
4
20
 
21
+ const fontTypeMapping = {
22
+ sdf: 'sdf',
23
+ msdf: 'sdf',
24
+ canvas: 'canvas',
25
+ web: 'canvas',
26
+ }
27
+
5
28
  export default () => {
6
29
  const stage = renderer.stage
7
- Settings.get('fonts', []).forEach((font) => {
8
- if (font.type === 'sdf' || font.type === 'msdf') {
9
- // automatically map png key to file name
10
- if (!font.png && font.file) {
11
- font.png = font.file.replace(/\.[^.]+$/, `.${font.type}.png`)
12
- }
13
- // automatically map json to file name
14
- if (!font.json && font.file) {
15
- font.json = font.file.replace(/\.[^.]+$/, `.${font.type}.json`)
16
- }
17
- stage.fontManager.addFontFace(
18
- new SdfTrFontFace(font.type, {
19
- fontFamily: font.family,
20
- descriptors: {},
21
- atlasUrl: font.png,
22
- atlasDataUrl: font.json,
23
- stage,
24
- metrics: font.metrics,
25
- })
26
- )
27
- } else if (font.type === 'web') {
28
- stage.fontManager.addFontFace(
29
- new WebTrFontFace({
30
- fontFamily: font.family,
31
- fontUrl: font.file,
32
- descriptors: {},
33
- metrics: font.metrics,
34
- })
35
- )
30
+
31
+ const fonts = Settings.get('fonts', [])
32
+ for (let i = 0; i < fonts.length; i++) {
33
+ const font = fonts[i]
34
+ const type = fontTypeMapping[font.type] || 'sdf'
35
+
36
+ if (type === 'sdf') {
37
+ stage.loadFont('sdf', {
38
+ fontFamily: font.family,
39
+ atlasUrl: font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.png`)),
40
+ atlasDataUrl:
41
+ font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.json`)),
42
+ })
43
+ } else {
44
+ stage.loadFont('canvas', {
45
+ fontFamily: font.family,
46
+ fontUrl: font.file,
47
+ })
36
48
  }
37
- })
49
+ }
38
50
  }
@@ -1,3 +1,20 @@
1
+ /*
2
+ * Copyright 2023 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
1
18
  import Element from './element.js'
2
19
  import Launch from './launch.js'
3
20
 
@@ -100,6 +100,7 @@ export default (App, target, settings = {}) => {
100
100
  textureMemory: textureMemorySettings(settings),
101
101
  createImageBitmapSupport: 'auto',
102
102
  targetFPS: 'maxFPS' in settings ? settings.maxFPS : 0,
103
+ platform: 'platform' in settings ? settings.platform : null,
103
104
  },
104
105
  ...(settings.advanced || {}),
105
106
  },