Skip to content

Commit 23aaf54

Browse files
authored
feat: Add alphaTex exporter (#2262)
1 parent 46464de commit 23aaf54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+5396
-979
lines changed

src.compiler/csharp/CSharpAstTransformer.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,6 +2347,10 @@ export default class CSharpAstTransformer {
23472347
};
23482348
csParameter.type!.parent = csParameter;
23492349

2350+
if (p.questionToken) {
2351+
(csParameter.type! as cs.UnresolvedTypeNode).isNullable = true;
2352+
}
2353+
23502354
if (p.initializer) {
23512355
csParameter.initializer = this.visitExpression(csParameter, p.initializer) ?? undefined;
23522356
if (csParameter.initializer && cs.isNullLiteral(csParameter.initializer)) {
@@ -3952,9 +3956,9 @@ export default class CSharpAstTransformer {
39523956
// Enum[enumValue] => value.toString()
39533957
// Enum[string] => TypeHelper.parseEnum<Type>(value, Type)
39543958
if (this.isEnumFromOrToString(expression)) {
3955-
const elementType = this._context.typeChecker.getTypeAtLocation(expression.argumentExpression);
3959+
const elementType = this._context.typeChecker.getTypeAtLocation(expression);
39563960

3957-
if (this._context.isEnum(elementType)) {
3961+
if (elementType === this._context.typeChecker.getStringType()) {
39583962
const callExpr = {
39593963
parent: parent,
39603964
arguments: [],

src.csharp/AlphaTab/Core/EcmaScript/Math.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34

45
namespace AlphaTab.Core.EcmaScript;
@@ -23,6 +24,11 @@ public static double Max(params double[] items)
2324
return items.Max();
2425
}
2526

27+
public static double Max(IEnumerable<double> items)
28+
{
29+
return items.Max();
30+
}
31+
2632
public static double Min(params double[] items)
2733
{
2834
return items.Min();
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
namespace AlphaTab.Core.EcmaScript;
1+
using System.Text;
2+
3+
namespace AlphaTab.Core.EcmaScript;
24

35
internal static class String
46
{
57
public static string FromCharCode(double code)
68
{
79
return "" + (char) (int) code;
810
}
9-
}
11+
12+
public static string FromCodePoint(double code)
13+
{
14+
return char.ConvertFromUtf32((int)code);
15+
}
16+
}

src.csharp/AlphaTab/Core/TypeHelper.cs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ public static void Add<T>(this IList<T> list, IList<T> newItems)
3535
}
3636
}
3737

38+
public static void Add<T>(this IList<T> list, params T[] newItems)
39+
{
40+
if (list is List<T> l)
41+
{
42+
l.AddRange(newItems);
43+
}
44+
else
45+
{
46+
foreach (var i in newItems)
47+
{
48+
list.Add(i);
49+
}
50+
}
51+
}
52+
public static void Add<T>(this IList<T> list, IEnumerator<T> newItems)
53+
{
54+
foreach (var i in newItems)
55+
{
56+
list.Add(i);
57+
}
58+
}
59+
3860
public static T Find<T>(this IList<T> list, Func<T, bool> predicate)
3961
{
4062
return list.FirstOrDefault(predicate);
@@ -322,7 +344,7 @@ public static string ToInvariantString(this double num, int radix)
322344
{
323345
if (radix == 16)
324346
{
325-
return ((int)num).ToString("X");
347+
return ((int)num).ToString("x");
326348
}
327349

328350
return num.ToString(CultureInfo.InvariantCulture);
@@ -357,7 +379,8 @@ public static string Replace(this string input, RegExp pattern, string replaceme
357379
}
358380

359381
[MethodImpl(MethodImplOptions.AggressiveInlining)]
360-
public static string Replace(this string input, RegExp pattern, Func<string, string, string> replacer)
382+
public static string Replace(this string input, RegExp pattern,
383+
Func<string, string, string> replacer)
361384
{
362385
return pattern.Replace(input, replacer);
363386
}
@@ -407,7 +430,8 @@ public static string SubstringIndex(this string s, double startIndex)
407430
}
408431

409432
[MethodImpl(MethodImplOptions.AggressiveInlining)]
410-
public static IList<TResult> Map<TKey, TValue, TResult>(this IEnumerable<AlphaTab.Collections.MapEntry<TKey, TValue>> source,
433+
public static IList<TResult> Map<TKey, TValue, TResult>(
434+
this IEnumerable<AlphaTab.Collections.MapEntry<TKey, TValue>> source,
411435
Func<ArrayTuple<TKey, TValue>, TResult> func)
412436
{
413437
return source.Select(i => func(new ArrayTuple<TKey, TValue>(i.Key, i.Value))).ToList();
@@ -474,6 +498,7 @@ public static object ToTemplate<T>(this T value)
474498
return value switch
475499
{
476500
bool b => b.ToTemplate(),
501+
double b => b.ToTemplate(),
477502
Enum e => e.ToTemplate(),
478503
_ => value
479504
};
@@ -491,6 +516,12 @@ public static object ToTemplate(this bool value)
491516
return value ? "true" : "false";
492517
}
493518

519+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
520+
public static object ToTemplate(this double value)
521+
{
522+
return value.ToInvariantString();
523+
}
524+
494525
public static string TypeOf(object? actual)
495526
{
496527
switch (actual)
@@ -545,7 +576,7 @@ public static IList<T> MapInitializer<T>(params T[] items)
545576
[MethodImpl(MethodImplOptions.AggressiveInlining)]
546577
public static string ToFixed(this double value, int decimals)
547578
{
548-
return value.ToString("F" + decimals);
579+
return value.ToString("F" + decimals, CultureInfo.InvariantCulture);
549580
}
550581

551582
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -608,6 +639,34 @@ public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> enumerator)
608639
{
609640
return enumerator;
610641
}
642+
643+
644+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
645+
private static uint GetScalarFromUtf16SurrogatePair(char highSurrogateCodePoint,
646+
char lowSurrogateCodePoint)
647+
{
648+
return (((uint)highSurrogateCodePoint << 10) + lowSurrogateCodePoint -
649+
((0xD800U << 10) + 0xDC00U - (1 << 16)));
650+
}
651+
652+
public static double? CodePointAt(this string s, double position)
653+
{
654+
if (position < 0 || position >= s.Length)
655+
{
656+
return null;
657+
}
658+
659+
var i = (int)position;
660+
if (char.IsHighSurrogate(s, i) && i + 1 < s.Length &&
661+
char.IsLowSurrogate(s, i + 1))
662+
{
663+
return GetScalarFromUtf16SurrogatePair(
664+
s[i], s[i + 1]
665+
);
666+
}
667+
668+
return s[i];
669+
}
611670
}
612671
}
613672

src.csharp/AlphaTab/Environment.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
using System;
2+
using System.Runtime.CompilerServices;
23
using System.Runtime.InteropServices;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using AlphaTab.Collections;
7+
using AlphaTab.Platform;
68
using AlphaTab.Platform.CSharp;
79

810
namespace AlphaTab;
911

1012
partial class Environment
1113
{
1214
public const bool SupportsTextDecoder = true;
15+
1316
public static void PlatformInit()
1417
{
15-
1618
}
1719

1820
private static void PrintPlatformInfo(System.Action<string> print)
@@ -40,7 +42,8 @@ public static Action Throttle(Action action, double delay)
4042
};
4143
}
4244

43-
private static void CreatePlatformSpecificRenderEngines(IMap<string, RenderEngineFactory> renderEngines)
45+
private static void CreatePlatformSpecificRenderEngines(
46+
IMap<string, RenderEngineFactory> renderEngines)
4447
{
4548
renderEngines.Set(
4649
"gdi",
@@ -49,5 +52,9 @@ private static void CreatePlatformSpecificRenderEngines(IMap<string, RenderEngin
4952
renderEngines.Set("default", renderEngines.Get("skia")!);
5053
}
5154

52-
55+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
56+
public static string QuoteJsonString(string value)
57+
{
58+
return Json.QuoteJsonString(value);
59+
}
5360
}

src.kotlin/alphaTab/android/src/main/java/alphaTab/EnvironmentPartials.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package alphaTab
22

3+
import alphaTab.platform.Json
34
import alphaTab.platform.android.AndroidCanvas
45
import alphaTab.platform.android.AndroidEnvironment
56
import android.os.Build
@@ -48,5 +49,8 @@ internal class EnvironmentPartials {
4849
}
4950
}
5051
}
52+
53+
@Suppress("NOTHING_TO_INLINE")
54+
internal inline fun quoteJsonString(string: String) = Json.quoteJsonString(string)
5155
}
5256
}

src.kotlin/alphaTab/android/src/main/java/alphaTab/collections/DoubleDoubleMap.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,23 @@ public class DoubleDoubleMapEntryInternal : DoubleDoubleMapEntry(), IMapEntryInt
4444
}
4545
}
4646

47-
public class DoubleDoubleMap : MapBase<DoubleDoubleMapEntry, DoubleDoubleMapEntryInternal>() {
47+
public class DoubleDoubleMap : MapBase<DoubleDoubleMapEntry, DoubleDoubleMapEntryInternal> {
48+
public constructor()
49+
public constructor(items: Iterable<alphaTab.core.DoubleDoubleArrayTuple>) {
50+
for ((k, v) in items) {
51+
set(k, v)
52+
}
53+
}
54+
4855
public fun has(key: Double): Boolean {
49-
return findEntryInternal(key,
56+
return findEntryInternal(
57+
key,
5058
{ entry, k -> entry.key == k }) >= 0
5159
}
5260

5361
public fun get(key: Double): Double? {
54-
val i = findEntryInternal(key,
62+
val i = findEntryInternal(
63+
key,
5564
{ entry, k -> entry.key == k })
5665
if (i >= 0) {
5766
return entries[i].value
@@ -64,7 +73,8 @@ public class DoubleDoubleMap : MapBase<DoubleDoubleMapEntry, DoubleDoubleMapEntr
6473
}
6574

6675
private fun insert(key: Double, value: Double) {
67-
insertInternal(key, value,
76+
insertInternal(
77+
key, value,
6878
{ entry, k -> entry.key = k },
6979
{ entry, v -> entry.value = v },
7080
{ entry, k -> entry.key == k }

src.kotlin/alphaTab/android/src/main/java/alphaTab/collections/List.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package alphaTab.collections
22

3+
import alphaTab.core.toTemplate
4+
35
internal class ArrayListWithRemoveRange<T> : ArrayList<T> {
46

57
constructor() : super()
68
constructor(c: Collection<T>) : super(c)
79

810

9-
public override fun removeRange(startIndex:Int, endIndex:Int) {
11+
public override fun removeRange(startIndex: Int, endIndex: Int) {
1012
super.removeRange(startIndex, endIndex);
1113
}
1214
}
@@ -127,7 +129,7 @@ public class List<T> : Iterable<T> {
127129
}
128130

129131

130-
internal fun reduce(operation: (acc: Double, v: T) -> Double, initial:Double): Double {
132+
internal fun reduce(operation: (acc: Double, v: T) -> Double, initial: Double): Double {
131133
var accumulator = initial
132134
for (element in _data) accumulator = operation(accumulator, element)
133135
return accumulator
@@ -161,10 +163,10 @@ public class List<T> : Iterable<T> {
161163
}
162164

163165
public fun join(separator: String): String {
164-
return _data.joinToString(separator)
166+
return _data.map { it.toTemplate() }.joinToString(separator)
165167
}
166168
}
167169

168-
internal inline fun <reified T> List<T>.toArray(): Array<T> {
170+
internal inline fun <reified T> List<T>.toArray(): Array<T> {
169171
return this._data.toTypedArray()
170172
}

src.kotlin/alphaTab/android/src/main/java/alphaTab/core/Globals.kt

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import alphaTab.collections.List
77
import alphaTab.collections.MapEntry
88
import alphaTab.core.ecmaScript.ArrayBuffer
99
import alphaTab.core.ecmaScript.RegExp
10+
import alphaTab.core.ecmaScript.Set
1011
import kotlinx.coroutines.CoroutineScope
1112
import kotlinx.coroutines.Deferred
1213
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -181,8 +182,11 @@ internal inline fun Double?.toTemplate(): String {
181182
return this?.toInvariantString() ?: ""
182183
}
183184

184-
internal inline fun Any?.toTemplate(): Any? {
185-
return this
185+
internal fun Any?.toTemplate(): String = when(this) {
186+
null -> ""
187+
is IAlphaTabEnum -> this.toInvariantString()
188+
is Double -> this.toTemplate()
189+
else -> this.toString()
186190
}
187191

188192
internal fun Any?.toDouble(): Double {
@@ -313,8 +317,43 @@ internal inline fun <reified T> List<T>.spread(): Array<T> {
313317
return _data.toTypedArray();
314318
}
315319

316-
internal inline fun <reified TKey, reified TValue, reified TResult> List<MapEntry<TKey, TValue>>.map(func: (v: ArrayTuple<TKey, TValue>) -> TResult): List<TResult> {
317-
return List(_data.map { func(ArrayTuple(it.key, it.value)) }.toCollection(
318-
ArrayListWithRemoveRange()
319-
))
320+
internal inline fun <reified TKey, reified TValue, reified TResult> List<MapEntry<TKey, TValue>>.map(
321+
func: (v: ArrayTuple<TKey, TValue>) -> TResult
322+
): List<TResult> {
323+
return List(
324+
_data.map { func(ArrayTuple(it.key, it.value)) }.toCollection(
325+
ArrayListWithRemoveRange()
326+
)
327+
)
328+
}
329+
330+
internal inline fun Set<Double>.spread(): DoubleArray {
331+
val empty = DoubleArray(this.size.toInt())
332+
for ((i, v) in this.withIndex()) {
333+
empty[i] = v
334+
}
335+
return empty
336+
}
337+
338+
internal inline fun <reified T> Set<T>.spread(): kotlin.Array<T> {
339+
val empty = arrayOfNulls<T>(this.size.toInt())
340+
for ((i, v) in this.withIndex()) {
341+
empty[i] = v
342+
}
343+
@Suppress("UNCHECKED_CAST")
344+
return empty as kotlin.Array<T>
345+
}
346+
347+
internal class IteratorIterable<T>(private val iterator: Iterator<T>) : Iterable<T> {
348+
override fun iterator(): Iterator<T> {
349+
return iterator
350+
}
351+
}
352+
353+
internal inline fun Iterator<Double>.spread(): DoubleArray {
354+
return IteratorIterable(this).toList().toDoubleArray()
355+
}
356+
357+
internal inline fun <reified T> Iterator<T>.spread(): kotlin.Array<T> {
358+
return IteratorIterable(this).toList().toTypedArray()
320359
}

src.kotlin/alphaTab/android/src/main/java/alphaTab/core/ecmaScript/CoreString.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ internal class CoreString {
55
public fun fromCharCode(code:Double): String {
66
return code.toInt().toChar().toString();
77
}
8+
9+
public fun fromCodePoint(code:Double): String {
10+
return String(intArrayOf(code.toInt()), 0, 1);
11+
}
812
}
913
}

0 commit comments

Comments
 (0)