@coderline/alphatab 1.6.0-alpha.1415 → 1.6.0-alpha.1418

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/dist/alphaTab.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * alphaTab v1.6.0-alpha.1415 (develop, build 1415)
2
+ * alphaTab v1.6.0-alpha.1418 (develop, build 1418)
3
3
  *
4
4
  * Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -1419,7 +1419,7 @@
1419
1419
  this.barOccurence = 0;
1420
1420
  /**
1421
1421
  * The modified tempo at which the cursor should move (aka. the tempo played within the external audio track).
1422
- * This information is used together with the {@link originalTempo} to calculate how much faster/slower the
1422
+ * This information is used together with normal tempo changes to calculate how much faster/slower the
1423
1423
  * cursor playback is performed to align with the audio track.
1424
1424
  */
1425
1425
  this.modifiedTempo = 0;
@@ -29076,7 +29076,7 @@
29076
29076
  }
29077
29077
  switch (typeof v) {
29078
29078
  case 'undefined':
29079
- return null;
29079
+ return undefined;
29080
29080
  case 'object': {
29081
29081
  const m = v;
29082
29082
  const families = m.get('families');
@@ -29156,10 +29156,13 @@
29156
29156
  return Font.withFamilyList(families, fontSize, fontStyle, fontWeight);
29157
29157
  }
29158
29158
  default:
29159
- return null;
29159
+ return undefined;
29160
29160
  }
29161
29161
  }
29162
29162
  static toJson(font) {
29163
+ if (!font) {
29164
+ return undefined;
29165
+ }
29163
29166
  const o = new Map();
29164
29167
  o.set('families', font.families);
29165
29168
  o.set('size', font.size);
@@ -30166,6 +30169,14 @@
30166
30169
  /*@target web*/
30167
30170
  o.set("fontdirectory", obj.fontDirectory);
30168
30171
  /*@target web*/
30172
+ if (obj.smuflFontSources !== null) {
30173
+ const m = new Map();
30174
+ o.set("smuflfontsources", m);
30175
+ for (const [k, v] of obj.smuflFontSources) {
30176
+ m.set(k.toString(), v);
30177
+ }
30178
+ }
30179
+ /*@target web*/
30169
30180
  o.set("file", obj.file);
30170
30181
  /*@target web*/
30171
30182
  o.set("tex", obj.tex);
@@ -30189,6 +30200,13 @@
30189
30200
  obj.fontDirectory = v;
30190
30201
  return true;
30191
30202
  /*@target web*/
30203
+ case "smuflfontsources":
30204
+ obj.smuflFontSources = new Map();
30205
+ JsonHelper.forEach(v, (v, k) => {
30206
+ obj.smuflFontSources.set(JsonHelper.parseEnum(k, exports.FontFileFormat), v);
30207
+ });
30208
+ return true;
30209
+ /*@target web*/
30192
30210
  case "file":
30193
30211
  obj.file = v;
30194
30212
  return true;
@@ -30232,6 +30250,7 @@
30232
30250
  return null;
30233
30251
  }
30234
30252
  const o = new Map();
30253
+ o.set("smuflfont", Font.toJson(obj.smuflFont));
30235
30254
  o.set("copyrightfont", Font.toJson(obj.copyrightFont));
30236
30255
  o.set("titlefont", Font.toJson(obj.titleFont));
30237
30256
  o.set("subtitlefont", Font.toJson(obj.subTitleFont));
@@ -30258,6 +30277,9 @@
30258
30277
  }
30259
30278
  static setProperty(obj, property, v) {
30260
30279
  switch (property) {
30280
+ case "smuflfont":
30281
+ obj.smuflFont = Font.fromJson(v);
30282
+ return true;
30261
30283
  case "copyrightfont":
30262
30284
  obj.copyrightFont = Font.fromJson(v);
30263
30285
  return true;
@@ -34235,15 +34257,6 @@
34235
34257
  this._color = new Color(0, 0, 0, 0xff);
34236
34258
  this._font = new Font('Arial', 10, FontStyle.Plain);
34237
34259
  this._lineWidth = 0;
34238
- const fontElement = document.createElement('span');
34239
- fontElement.classList.add('at');
34240
- document.body.appendChild(fontElement);
34241
- const style = window.getComputedStyle(fontElement);
34242
- let family = style.fontFamily;
34243
- if (family.startsWith('"') || family.startsWith("'")) {
34244
- family = family.substr(1, family.length - 2);
34245
- }
34246
- this._musicFont = new Font(family, Number.parseFloat(style.fontSize), FontStyle.Plain);
34247
34260
  this._measureCanvas = document.createElement('canvas');
34248
34261
  this._measureCanvas.width = 10;
34249
34262
  this._measureCanvas.height = 10;
@@ -34258,6 +34271,7 @@
34258
34271
  return null;
34259
34272
  }
34260
34273
  beginRender(width, height) {
34274
+ this._musicFont = this.settings.display.resources.smuflFont;
34261
34275
  const scale = this.settings.display.scale;
34262
34276
  this._canvas = document.createElement('canvas');
34263
34277
  this._canvas.width = (width * Environment.HighDpiFactor) | 0;
@@ -38715,7 +38729,11 @@
38715
38729
  */
38716
38730
  class AlphaTabApiBase {
38717
38731
  /**
38718
- * The actual player mode which is currently active (e.g. allows determining whether a backing track or the synthesizer is active).
38732
+ * The actual player mode which is currently active.
38733
+ * @remarks
38734
+ * Allows determining whether a backing track or the synthesizer is active in case automatic detection is enabled.
38735
+ * @category Properties - Player
38736
+ * @since 1.6.0
38719
38737
  */
38720
38738
  get actualPlayerMode() {
38721
38739
  return this._actualPlayerMode;
@@ -43845,10 +43863,6 @@
43845
43863
  return this.areAllFontsLoaded();
43846
43864
  }
43847
43865
  areAllFontsLoaded() {
43848
- Environment.bravuraFontChecker.checkForFontAvailability();
43849
- if (!Environment.bravuraFontChecker.isFontLoaded) {
43850
- return false;
43851
- }
43852
43866
  let isAnyNotLoaded = false;
43853
43867
  for (const checker of this._fontCheckers.values()) {
43854
43868
  if (!checker.isFontLoaded) {
@@ -43885,7 +43899,6 @@
43885
43899
  rootElement.classList.add('alphaTab');
43886
43900
  this.rootContainer = new HtmlElementContainer(rootElement);
43887
43901
  this.areWorkersSupported = 'Worker' in window;
43888
- Environment.bravuraFontChecker.fontLoaded.on(this.onFontLoaded.bind(this));
43889
43902
  this._intersectionObserver = new IntersectionObserver(this.onElementVisibilityChanged.bind(this), {
43890
43903
  threshold: [0, 0.01, 1]
43891
43904
  });
@@ -43953,7 +43966,7 @@
43953
43966
  this._contents = element.element.innerHTML;
43954
43967
  element.element.innerHTML = '';
43955
43968
  }
43956
- this.createStyleElement(settings);
43969
+ this.createStyleElements(settings);
43957
43970
  this._file = settings.core.file;
43958
43971
  }
43959
43972
  setupFontCheckers(settings) {
@@ -43979,10 +43992,15 @@
43979
43992
  }
43980
43993
  destroy() {
43981
43994
  this.rootContainer.element.innerHTML = '';
43995
+ const webFont = this._webFont;
43996
+ webFont.usages--;
43997
+ if (webFont.usages <= 0) {
43998
+ webFont.element.remove();
43999
+ }
43982
44000
  }
43983
44001
  createCanvasElement() {
43984
44002
  const canvasElement = document.createElement('div');
43985
- canvasElement.className = 'at-surface';
44003
+ canvasElement.classList.add('at-surface', `at${this._webFont.fontSuffix}`);
43986
44004
  canvasElement.style.fontSize = '0';
43987
44005
  canvasElement.style.overflow = 'hidden';
43988
44006
  canvasElement.style.lineHeight = '0';
@@ -44080,9 +44098,132 @@
44080
44098
  initialRender();
44081
44099
  }
44082
44100
  }
44083
- createStyleElement(settings) {
44084
- const elementDocument = this._api.container.element.ownerDocument;
44085
- Environment.createStyleElement(elementDocument, settings.core.fontDirectory);
44101
+ createStyleElements(settings) {
44102
+ const root = this._api.container.element.ownerDocument;
44103
+ BrowserUiFacade.createSharedStyleElement(root);
44104
+ // SmuFl Font Specific style
44105
+ const smuflFontSources = settings.core.smuflFontSources ?? CoreSettings.buildDefaultSmuflFontSources(settings.core.fontDirectory);
44106
+ // create a simple unique hash for the font source definition
44107
+ // as data urls might be used we don't want to just use the plain strings.
44108
+ const hash = BrowserUiFacade.cyrb53(smuflFontSources.values());
44109
+ // reuse existing style if available
44110
+ const registeredWebFonts = BrowserUiFacade._registeredWebFonts;
44111
+ if (registeredWebFonts.has(hash)) {
44112
+ const webFont = registeredWebFonts.get(hash);
44113
+ webFont.usages++;
44114
+ webFont.checker.fontLoaded.on(this.onFontLoaded.bind(this));
44115
+ this._webFont = webFont;
44116
+ return;
44117
+ }
44118
+ const fontSuffix = registeredWebFonts.size === 0 ? '' : String(registeredWebFonts.size);
44119
+ const familyName = `alphaTab${fontSuffix}`;
44120
+ const src = Array.from(smuflFontSources.entries())
44121
+ .map(e => `url(${JSON.stringify(e[1])}) format('${BrowserUiFacade.cssFormat(e[0])}')`)
44122
+ .join(',');
44123
+ const css = `
44124
+ @font-face {
44125
+ font-display: block;
44126
+ font-family: '${familyName}';
44127
+ src: ${src};
44128
+ font-weight: normal;
44129
+ font-style: normal;
44130
+ }
44131
+ .at-surface.at${fontSuffix} .at {
44132
+ font-family: '${familyName}';
44133
+ speak: none;
44134
+ font-style: normal;
44135
+ font-weight: normal;
44136
+ font-variant: normal;
44137
+ text-transform: none;
44138
+ line-height: 1;
44139
+ line-height: 1;
44140
+ -webkit-font-smoothing: antialiased;
44141
+ -moz-osx-font-smoothing: grayscale;
44142
+ font-size: ${Environment.MusicFontSize}px;
44143
+ overflow: visible !important;
44144
+ }`;
44145
+ const styleElement = root.createElement('style');
44146
+ styleElement.id = `alphaTabStyle${fontSuffix}`;
44147
+ styleElement.innerHTML = css;
44148
+ root.getElementsByTagName('head').item(0).appendChild(styleElement);
44149
+ const checker = new FontLoadingChecker([familyName]);
44150
+ checker.fontLoaded.on(this.onFontLoaded.bind(this));
44151
+ this._fontCheckers.set(familyName, checker);
44152
+ checker.checkForFontAvailability();
44153
+ settings.display.resources.smuflFont = new Font(familyName, Environment.MusicFontSize, FontStyle.Plain, FontWeight.Regular);
44154
+ const webFont = {
44155
+ element: styleElement,
44156
+ fontSuffix,
44157
+ usages: 1,
44158
+ checker
44159
+ };
44160
+ registeredWebFonts.set(hash, webFont);
44161
+ this._webFont = webFont;
44162
+ }
44163
+ static cssFormat(format) {
44164
+ switch (format) {
44165
+ case exports.FontFileFormat.EmbeddedOpenType:
44166
+ return 'embedded-opentype';
44167
+ case exports.FontFileFormat.Woff:
44168
+ return 'woff';
44169
+ case exports.FontFileFormat.Woff2:
44170
+ return 'woff2';
44171
+ case exports.FontFileFormat.OpenType:
44172
+ return 'opentype';
44173
+ case exports.FontFileFormat.TrueType:
44174
+ return 'truetype';
44175
+ case exports.FontFileFormat.Svg:
44176
+ return 'svg';
44177
+ }
44178
+ }
44179
+ /**
44180
+ * cyrb53 (c) 2018 bryc (github.com/bryc)
44181
+ * License: Public domain (or MIT if needed). Attribution appreciated.
44182
+ * A fast and simple 53-bit string hash function with decent collision resistance.
44183
+ * Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity
44184
+ * @param str
44185
+ * @param seed
44186
+ * @returns
44187
+ */
44188
+ static cyrb53(strings, seed = 0) {
44189
+ let h1 = 0xdeadbeef ^ seed;
44190
+ let h2 = 0x41c6ce57 ^ seed;
44191
+ for (const str of strings) {
44192
+ for (let i = 0; i < str.length; i++) {
44193
+ const ch = str.charCodeAt(i);
44194
+ h1 = Math.imul(h1 ^ ch, 2654435761);
44195
+ h2 = Math.imul(h2 ^ ch, 1597334677);
44196
+ }
44197
+ }
44198
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
44199
+ h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
44200
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
44201
+ h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
44202
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0);
44203
+ }
44204
+ /**
44205
+ * Creates the default CSS styles used across all alphaTab instances.
44206
+ * @target web
44207
+ * @internal
44208
+ */
44209
+ static createSharedStyleElement(root) {
44210
+ let styleElement = root.getElementById('alphaTabStyle');
44211
+ if (!styleElement) {
44212
+ styleElement = document.createElement('style');
44213
+ styleElement.id = 'alphaTabStyleShared';
44214
+ const css = `
44215
+ .at-surface * {
44216
+ cursor: default;
44217
+ vertical-align: top;
44218
+ overflow: visible;
44219
+ }
44220
+ .at-surface-svg text {
44221
+ dominant-baseline: central;
44222
+ white-space:pre;
44223
+ }`;
44224
+ styleElement.innerHTML = css;
44225
+ document.getElementsByTagName('head').item(0).appendChild(styleElement);
44226
+ }
44086
44227
  }
44087
44228
  parseTracks(tracksData) {
44088
44229
  if (!tracksData) {
@@ -44464,6 +44605,7 @@
44464
44605
  return new BackingTrackPlayer(new AudioElementBackingTrackSynthOutput(), this._api.settings.player.bufferTimeInMilliseconds);
44465
44606
  }
44466
44607
  }
44608
+ BrowserUiFacade._registeredWebFonts = new Map();
44467
44609
 
44468
44610
  /**
44469
44611
  * Represents the progress of any data being loaded.
@@ -60721,9 +60863,9 @@
60721
60863
  print(`build date: ${VersionInfo.date}`);
60722
60864
  }
60723
60865
  }
60724
- VersionInfo.version = '1.6.0-alpha.1415';
60725
- VersionInfo.date = '2025-05-19T16:08:22.342Z';
60726
- VersionInfo.commit = '459db69f8896a2ea8822ce5d49dcc824edd36521';
60866
+ VersionInfo.version = '1.6.0-alpha.1418';
60867
+ VersionInfo.date = '2025-05-21T02:08:19.492Z';
60868
+ VersionInfo.commit = '1f6342282295a9544ebc36ddd38d73d220d2caab';
60727
60869
 
60728
60870
  /**
60729
60871
  * A factory for custom layout engines.
@@ -60755,59 +60897,6 @@
60755
60897
  * @partial
60756
60898
  */
60757
60899
  class Environment {
60758
- /**
60759
- * @target web
60760
- * @internal
60761
- */
60762
- static createStyleElement(elementDocument, fontDirectory) {
60763
- let styleElement = elementDocument.getElementById('alphaTabStyle');
60764
- if (!styleElement) {
60765
- if (!fontDirectory) {
60766
- Logger.error('AlphaTab', 'Font directory could not be detected, cannot create style element');
60767
- return;
60768
- }
60769
- styleElement = elementDocument.createElement('style');
60770
- styleElement.id = 'alphaTabStyle';
60771
- const css = `
60772
- @font-face {
60773
- font-display: block;
60774
- font-family: 'alphaTab';
60775
- src: url('${fontDirectory}Bravura.eot');
60776
- src: url('${fontDirectory}Bravura.eot?#iefix') format('embedded-opentype')
60777
- , url('${fontDirectory}Bravura.woff') format('woff')
60778
- , url('${fontDirectory}Bravura.otf') format('opentype')
60779
- , url('${fontDirectory}Bravura.svg#Bravura') format('svg');
60780
- font-weight: normal;
60781
- font-style: normal;
60782
- }
60783
- .at-surface * {
60784
- cursor: default;
60785
- vertical-align: top;
60786
- overflow: visible;
60787
- }
60788
- .at-surface-svg text {
60789
- dominant-baseline: central;
60790
- white-space:pre;
60791
- }
60792
- .at {
60793
- font-family: 'alphaTab';
60794
- speak: none;
60795
- font-style: normal;
60796
- font-weight: normal;
60797
- font-variant: normal;
60798
- text-transform: none;
60799
- line-height: 1;
60800
- line-height: 1;
60801
- -webkit-font-smoothing: antialiased;
60802
- -moz-osx-font-smoothing: grayscale;
60803
- font-size: ${Environment.MusicFontSize}px;
60804
- overflow: visible !important;
60805
- }`;
60806
- styleElement.innerHTML = css;
60807
- elementDocument.getElementsByTagName('head').item(0).appendChild(styleElement);
60808
- Environment.bravuraFontChecker.checkForFontAvailability();
60809
- }
60810
- }
60811
60900
  /**
60812
60901
  * @target web
60813
60902
  * @internal
@@ -60883,7 +60972,9 @@
60883
60972
  catch (e) {
60884
60973
  }
60885
60974
  // normal browser include as <script>
60886
- if ('document' in Environment.globalThis && document.currentScript) {
60975
+ if ('document' in Environment.globalThis &&
60976
+ document.currentScript &&
60977
+ document.currentScript instanceof HTMLScriptElement) {
60887
60978
  return document.currentScript.src;
60888
60979
  }
60889
60980
  return null;
@@ -61361,11 +61452,6 @@
61361
61452
  * @target web
61362
61453
  */
61363
61454
  Environment.fontDirectory = Environment.detectFontDirectory();
61364
- /**
61365
- * @target web
61366
- * @internal
61367
- */
61368
- Environment.bravuraFontChecker = new FontLoadingChecker(['alphaTab']);
61369
61455
  Environment.renderEngines = Environment.createDefaultRenderEngines();
61370
61456
  /**
61371
61457
  * @internal
@@ -61376,12 +61462,58 @@
61376
61462
  */
61377
61463
  Environment.staveProfiles = Environment.createDefaultStaveProfiles();
61378
61464
 
61465
+ /**
61466
+ * Lists the known file formats for font files.
61467
+ * @target web
61468
+ */
61469
+ exports.FontFileFormat = void 0;
61470
+ (function (FontFileFormat) {
61471
+ /**
61472
+ * .eot
61473
+ */
61474
+ FontFileFormat[FontFileFormat["EmbeddedOpenType"] = 0] = "EmbeddedOpenType";
61475
+ /**
61476
+ * .woff
61477
+ */
61478
+ FontFileFormat[FontFileFormat["Woff"] = 1] = "Woff";
61479
+ /**
61480
+ * .woff2
61481
+ */
61482
+ FontFileFormat[FontFileFormat["Woff2"] = 2] = "Woff2";
61483
+ /**
61484
+ * .otf
61485
+ */
61486
+ FontFileFormat[FontFileFormat["OpenType"] = 3] = "OpenType";
61487
+ /**
61488
+ * .ttf
61489
+ */
61490
+ FontFileFormat[FontFileFormat["TrueType"] = 4] = "TrueType";
61491
+ /**
61492
+ * .svg
61493
+ */
61494
+ FontFileFormat[FontFileFormat["Svg"] = 5] = "Svg";
61495
+ })(exports.FontFileFormat || (exports.FontFileFormat = {}));
61379
61496
  /**
61380
61497
  * All main settings of alphaTab controlling rather general aspects of its behavior.
61381
61498
  * @json
61382
61499
  * @json_declaration
61383
61500
  */
61384
61501
  class CoreSettings {
61502
+ /**
61503
+ * Builds the default SMuFL font sources for the usage with alphaTab in cases
61504
+ * where no custom {@link smuflFontSources} are provided.
61505
+ * @param fontDirectory The {@link fontDirectory} configured.
61506
+ * @target web
61507
+ */
61508
+ static buildDefaultSmuflFontSources(fontDirectory) {
61509
+ const map = new Map();
61510
+ // WOFF, WOFF2 and OTF should cover all our platform needs
61511
+ const prefix = fontDirectory ?? '';
61512
+ map.set(exports.FontFileFormat.Woff2, `${prefix}Bravura.woff2`);
61513
+ map.set(exports.FontFileFormat.Woff, `${prefix}Bravura.woff`);
61514
+ map.set(exports.FontFileFormat.OpenType, `${prefix}Bravura.otf`);
61515
+ return map;
61516
+ }
61385
61517
  /**
61386
61518
  * @target web
61387
61519
  */
@@ -61407,12 +61539,27 @@
61407
61539
  * where the Web Font files of [Bravura](https://github.com/steinbergmedia/bravura) are. Normally alphaTab expects
61408
61540
  * them to be in a `font` subfolder beside the script file. If this is not the case, this setting must be used to configure the path.
61409
61541
  * Alternatively also a global variable `ALPHATAB_FONT` can be set on the page before initializing alphaTab.
61542
+ *
61543
+ * Use {@link smuflFontSources} for more flexible font configuration.
61410
61544
  * @defaultValue `"${AlphaTabScriptFolder}/font/"`
61411
61545
  * @category Core - JavaScript Specific
61412
61546
  * @target web
61413
61547
  * @since 0.9.6
61414
61548
  */
61415
61549
  this.fontDirectory = null;
61550
+ /**
61551
+ * Defines the URLs from which to load the SMuFL compliant font files.
61552
+ * @remarks
61553
+ * These sources will be used to load and register the webfonts on the page so
61554
+ * they are available for rendering the music sheet. The sources can be set to any
61555
+ * CSS compatible URL which can be passed into `url()`.
61556
+ * See https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src#url
61557
+ * @defaultValue Bravura files located at {@link fontDirectory} .
61558
+ * @category Core - JavaScript Specific
61559
+ * @target web
61560
+ * @since 1.6.0
61561
+ */
61562
+ this.smuflFontSources = null;
61416
61563
  /**
61417
61564
  * The full URL to the input file to be loaded.
61418
61565
  * @remarks
@@ -65037,9 +65184,11 @@
65037
65184
  ActiveBeatsChangedEventArgs,
65038
65185
  AlphaSynth,
65039
65186
  AlphaSynthAudioWorkletOutput,
65187
+ AlphaSynthBase,
65040
65188
  AlphaSynthScriptProcessorOutput,
65041
65189
  AlphaSynthWebAudioOutputBase,
65042
65190
  AlphaSynthWebWorkerApi,
65191
+ BackingTrackSyncPoint,
65043
65192
  CircularSampleBuffer,
65044
65193
  MidiEventsPlayedEventArgs,
65045
65194
  PlaybackRange,