Spaces:
Sleeping
Sleeping
import sha1 from "sha1"; | |
import {GLYPH_BASE_SCALE, POS_PRECISION, roundNumber} from "./utils"; | |
import pathSymbols from "./path-symbols.json"; | |
import glyphHash from "./glyph-hash.json"; | |
type Element = {[key: string]: any}; | |
interface SymbolizeResult { | |
symbol?: string; | |
glyph?: string; | |
[key: string]: any; | |
}; | |
type SymbolizeRule = (elem: Element) => SymbolizeResult; | |
type PostSymbolizeRule = (elem: Element, result: SymbolizeResult) => void; | |
const identityHash = obj => { | |
const identityArray = Object.entries(obj).sort(([k1], [k2]) => k1 > k2 ? 1 : -1); | |
return sha1(JSON.stringify(identityArray)); | |
}; | |
const identitySymbol = (symbol, obj) => { | |
const hash = identityHash(obj); | |
return elem => { | |
if (elem.hash === hash) | |
return {symbol}; | |
}; | |
}; | |
const simplifyPath = (d: string): string => d.replace(/\s+/g, " ").replace(/\d/g, ""); | |
const skeletonizePath = (d: string): string => d.replace(/\s+/g, " ").replace(/-?[.\d]+/g, "."); | |
const pointsSize = (points: string): number => points.split(" ").length; | |
const pathFrameSymbol = (symbol: string, frame: string): SymbolizeRule => elem => { | |
if (elem.identity.type === "path" && simplifyPath(elem.identity.d) === frame) | |
return {symbol}; | |
}; | |
const pathFramesSymbol = (symbol: string, frames: string[]): SymbolizeRule => elem => { | |
if (elem.identity.type === "path" && frames.includes(simplifyPath(elem.identity.d))) | |
return {symbol}; | |
}; | |
const pathSkeletonsSymbol = (symbol: string, skeletons: string[]): SymbolizeRule => elem => { | |
if (elem.identity.type === "path" && skeletons.includes(skeletonizePath(elem.identity.d))) | |
return {symbol}; | |
}; | |
const elemScale = (elem: Element, scale: number): boolean => elem.identity.scale | |
&& (Math.abs(elem.identity.scale.x) === scale) | |
&& (Math.abs(elem.identity.scale.y) === scale); | |
const conditionSymbol = (symbol: string, condition: (elem: Element) => boolean, fields: (x: any) => object = () => ({})) => elem => { | |
if (condition(elem)) | |
return {symbol, ...fields(elem)}; | |
}; | |
const glyphSymbol = (symbol: string, glyph: string) => elem => { | |
if (elem.glyph === glyph) | |
return {symbol}; | |
}; | |
const symbolRules: SymbolizeRule[] = [ | |
pathFramesSymbol("NOTE NOTEHEAD CROSS", [ | |
"M163 31l125 101c2 2 5 3 8 3s6 -1 8 -3l18 -14c3 -2 4 -6 4 -10s-1 -8 -4 -10l-121 -98l121 -98c3 -2 4 -6 4 -10s-1 -8 -4 -10l-18 -14c-2 -2 -5 -3 -8 -3s-6 1 -8 3l-125 101l-125 -101c-2 -2 -5 -3 -8 -3s-6 1 -8 3l-17 14c-3 2 -5 6 -5 10s2 8 5 10l120 98l-120 98 c-3 2 -5 6 -5 10s2 8 5 10l17 14c2 2 5 3 8 3s6 -1 8 -3z", | |
].map(simplifyPath)), | |
pathFramesSymbol("NOTE NOTEHEAD DIAMOND WHOLE", [ | |
"M206 75c-29 0 -27 -45 -27 -74c0 -47 25 -56 61 -67c13 -4 28 -9 40 -9c29 0 26 45 26 74c0 47 -25 56 -61 67c-13 4 -27 9 -39 9zM485 0c0 -57 -78 -42 -122 -67c-41 -23 -72 -68 -120 -68s-80 45 -121 68c-44 25 -122 10 -122 67s78 42 122 67c41 23 73 68 121 68 s79 -45 120 -68c44 -25 122 -10 122 -67z", | |
].map(simplifyPath)), | |
pathFramesSymbol("NOTE NOTEHEAD DIAMOND HALF", [ | |
"M290 55c0 17 -15 27 -30 27c-4 0 -8 -1 -12 -2c-25 -8 -60 -30 -89 -49s-65 -42 -82 -62c-6 -7 -10 -16 -10 -24c0 -17 14 -27 29 -27c4 0 9 1 13 2c25 8 60 30 89 49s65 42 82 62c6 7 10 16 10 24zM316 135c18 0 41 -17 41 -40c0 -28 -33 -54 -42 -84 c-11 -36 3 -84 -30 -106c-15 -10 -33 -13 -51 -13c-25 0 -50 6 -76 6c-43 0 -83 -33 -118 -33c-18 0 -40 17 -40 40c0 28 33 54 42 84c11 36 -3 84 30 106c15 10 32 13 50 13c25 0 51 -6 77 -6c43 0 82 33 117 33z", | |
].map(simplifyPath)), | |
pathFramesSymbol("NOTE NOTEHEAD DIAMOND SOLID", [ | |
"M325 135c19 0 36 -18 36 -38c0 -36 -61 -62 -84 -100c-25 -41 -32 -95 -72 -123c-9 -6 -18 -8 -28 -8c-23 0 -48 12 -72 12c-23 0 -47 -13 -68 -13c-19 0 -37 18 -37 38c0 36 61 62 84 100c25 41 33 95 73 123c9 6 17 8 27 8c23 0 48 -12 72 -12c23 0 48 13 69 13z", | |
].map(simplifyPath)), | |
pathFramesSymbol("NOTE REST", [ | |
"M510 -22h-645c-12 0 -21 10 -21 22s9 22 21 22h135v126c0 4 4 8 8 8h359c4 0 8 -4 8 -8v-126h135c12 0 21 -10 21 -22s-9 -22 -21 -22z", | |
].map(simplifyPath)), | |
pathFramesSymbol("TR", [ | |
"M-300 227c0 -23 18 -32 41 -32c40 0 72 14 104 28l5 28c-23 17 -50 29 -82 29c-33 0 -68 -17 -68 -53zM-26 103c0 -61 -47 -113 -98 -113c-39 0 -56 43 -56 90c0 14 1 28 4 41l16 78c-32 -13 -63 -25 -103 -25c-34 0 -59 17 -59 49c0 50 47 78 94 78c31 0 59 -10 83 -25 l47 234c6 -3 13 -5 20 -5c22 0 48 16 68 35l-54 -268l66 36c26 14 51 21 74 21c29 0 53 -11 64 -30c17 21 44 32 70 32c35 0 67 -20 67 -66c0 -44 -27 -89 -64 -89c-25 0 -37 22 -37 48c0 41 28 63 59 63h4c-8 14 -23 21 -38 21c-25 0 -51 -16 -57 -45l-53 -269 c-11 7 -25 10 -39 10s-29 -3 -43 -10l54 269v6c0 16 -13 27 -30 27c-7 0 -15 -2 -23 -6l-79 -44l-7 -35c27 -31 50 -66 50 -108zM-84 39c23 0 36 33 36 61c0 31 -15 57 -34 81l-6 -30c-4 -18 -12 -54 -12 -81c0 -18 4 -31 16 -31z", | |
"M-299 227c0 -22 18 -31 41 -31c40 0 71 14 103 28l5 26c-23 17 -51 29 -82 29c-32 0 -67 -16 -67 -52zM-26 104c0 -61 -47 -114 -98 -114c-39 0 -56 43 -56 90c0 14 1 28 4 41l16 77c-31 -13 -63 -25 -103 -25c-35 0 -59 17 -59 50c0 51 48 79 95 79c31 0 58 -10 82 -25 l47 233c6 -3 13 -5 20 -5c22 0 48 16 68 35l-54 -267l66 36c26 14 51 21 74 21c29 0 52 -11 63 -30c18 20 45 31 70 31c35 0 68 -21 68 -67c0 -45 -28 -89 -65 -89c-25 0 -37 21 -37 47c0 41 29 64 60 64h3c-8 14 -22 21 -37 21c-24 0 -51 -17 -57 -45l-53 -269 c-11 7 -25 11 -39 11s-29 -4 -43 -11l53 269c0 2 1 5 1 7c0 16 -13 27 -30 27c-7 0 -15 -3 -23 -7l-79 -44l-7 -33c27 -31 50 -66 50 -108zM-85 39c23 0 35 33 35 61c0 30 -14 56 -32 79l-6 -28c-4 -18 -12 -55 -12 -82c0 -17 4 -30 15 -30z", | |
"M-295 228c0 -21 17 -30 38 -30c39 0 71 14 102 28l5 22c-23 17 -50 29 -81 29s-64 -15 -64 -49zM-26 104c0 -62 -47 -114 -98 -114c-39 0 -56 43 -56 90c0 14 1 28 4 41l15 75c-31 -13 -62 -24 -101 -24c-35 0 -60 17 -60 50c0 52 49 82 97 82c30 0 57 -9 81 -24l46 230 c6 -3 13 -5 20 -5c22 0 48 16 68 35l-53 -265l64 35c26 14 51 21 74 21c28 0 52 -10 63 -28c18 19 43 29 68 29c36 0 70 -22 70 -70c0 -46 -27 -91 -65 -91c-25 0 -39 22 -39 48c0 42 30 64 61 64h3c-8 14 -23 21 -38 21c-23 0 -49 -16 -54 -42l-54 -270 c-11 7 -24 11 -38 11s-30 -4 -44 -11l54 270c0 2 1 5 1 7c0 15 -13 25 -29 25c-7 0 -15 -3 -23 -7l-81 -44l-5 -29c27 -31 49 -68 49 -110zM-87 39c22 0 34 34 34 61c0 29 -13 54 -30 76l-5 -25c-4 -19 -14 -57 -14 -84c0 -16 4 -28 15 -28z", | |
].map(simplifyPath)), | |
conditionSymbol("MEASURE_SEPARATOR", elem => elem.identity.type === "rect" | |
&& elem.sw === 0.19 && elem.identity.rh >= 4 && elem.identity.rh <= 4.35), | |
conditionSymbol("MEASURE_SEPARATOR BOLD", elem => elem.identity.type === "rect" | |
&& elem.sw === 0.6 && elem.identity.rh >= 4 && elem.identity.rh <= 4.35), | |
pathFramesSymbol("BRACE", [ | |
"M- -c - - - - -c - - -c - - - - -c- - - c c - - c- - - s c c - - c c - -c- - - - - -c - - -c - - - - -c - - -z", | |
"M- -c - - - - -c - - -c - - - - -c- - - c c - - vvc c - - c c - - c- - - - - -c - - -c - - - - -c - - -z", | |
"M- -c - - - - -c - - -c - - - - -c- - - c c - - c - - s c c - - c c - -c- - - - - -c - - -c - - - - -c - - -z", | |
"M- -c - - - - -c - - -c - - - - -c- - - c c - - c- - - s c c - - c c - -c- - - - - -c - - -c - - - - -c - - -z", | |
]), | |
pathSkeletonsSymbol("BRACE", [ | |
"M-15 -495c0 -261 -102 -516 -102 -762c0 -135 30 -258 129 -357c3 -3 3 -9 3 -12c0 -9 -6 -15 -15 -15c-3 0 -9 0 -12 3c-132 132 -177 312 -177 498c0 267 108 525 108 777c0 135 -33 258 -129 357c-3 3 -3 3 -3 6s0 3 3 6c96 99 129 222 129 357 c0 252 -108 510 -108 777c0 186 45 366 177 498c3 3 9 3 12 3c9 0 15 -6 15 -15c0 -3 0 -9 -3 -12c-99 -99 -129 -222 -129 -357c0 -246 102 -501 102 -762c0 -186 -48 -363 -174 -495c126 -132 174 -309 174 -495z", | |
"M-15 -537c0 -285 -111 -561 -111 -831c0 -147 36 -282 138 -390c3 -3 6 -9 6 -12c0 -9 -9 -18 -18 -18c-3 0 -9 3 -12 6c-138 147 -186 339 -186 540c0 291 114 570 114 846c0 144 -33 279 -135 387c-3 3 -3 6 -3 9s0 6 3 9c102 108 135 243 135 387 c0 276 -114 555 -114 846c0 201 48 393 186 540c3 3 9 6 12 6c9 0 18 -9 18 -18c0 -3 -3 -9 -6 -12c-102 -108 -138 -243 -138 -390c0 -270 111 -546 111 -831c0 -198 -45 -390 -180 -537c135 -147 180 -339 180 -537z", | |
"M-18 -471c0 -246 -96 -489 -96 -723c0 -129 33 -246 126 -339c3 -3 3 -9 3 -12c0 -9 -6 -15 -15 -15c-3 0 -9 0 -12 3c-126 126 -171 294 -171 474c0 252 102 501 102 738c0 129 -30 246 -123 339c-3 3 -3 3 -3 6s0 3 3 6c93 93 123 210 123 339c0 237 -102 486 -102 738 c0 180 45 348 171 474c3 3 9 3 12 3c9 0 15 -6 15 -15c0 -3 0 -9 -3 -12c-93 -93 -126 -210 -126 -339c0 -234 96 -477 96 -723c0 -177 -42 -345 -165 -471c123 -126 165 -294 165 -471z", | |
"M-12 -636c0 -340 -128 -672 -128 -996c0 -172 36 -336 152 -468c4 -4 8 -8 8 -12c0 -8 -12 -20 -20 -20c-4 0 -8 4 -12 8c-156 176 -212 400 -212 636c0 348 136 684 136 1016c0 172 -36 332 -152 464c0 4 -4 4 -4 8s4 4 4 8c116 132 152 292 152 464 c0 332 -136 668 -136 1016c0 236 56 460 212 636c4 4 8 8 12 8c8 0 20 -12 20 -20c0 -4 -4 -8 -8 -12c-116 -132 -152 -296 -152 -468c0 -324 128 -656 128 -996c0 -232 -52 -460 -204 -636c152 -176 204 -404 204 -636z", | |
"M-12 -656c0 -352 -132 -696 -132 -1032c0 -180 36 -344 156 -484c4 -4 8 -8 8 -12c0 -8 -12 -16 -20 -16c-4 0 -8 0 -12 4c-160 184 -216 416 -216 656c0 360 140 712 140 1052c0 176 -40 344 -160 480v8v8c120 136 160 304 160 480c0 340 -140 692 -140 1052 c0 240 56 472 216 656c4 4 8 4 12 4c8 0 20 -8 20 -16c0 -4 -4 -8 -8 -12c-120 -140 -156 -304 -156 -484c0 -336 132 -680 132 -1032c0 -240 -52 -472 -208 -656c156 -184 208 -416 208 -656z", | |
"M-208 -1352c0 316 124 624 124 924c0 156 -36 300 -144 420c0 4 -4 4 -4 8s4 4 4 8c108 120 144 264 144 420c0 300 -124 608 -124 924c0 216 52 420 196 580c16 16 40 -8 24 -24c-108 -120 -144 -268 -144 -424c0 -292 116 -596 116 -904c0 -216 -48 -420 -188 -580 c140 -160 188 -364 188 -580c0 -308 -116 -612 -116 -904c0 -156 36 -304 144 -424c16 -16 -8 -40 -24 -24c-144 160 -196 364 -196 580z", | |
"M-255 -1860c0 435 160 855 160 1270c0 210 -45 410 -180 580c0 0 -5 5 -5 10s5 10 5 10c135 170 180 370 180 580c0 415 -160 835 -160 1270c0 285 60 560 240 785c15 20 45 -5 30 -25c-135 -170 -180 -370 -180 -585c0 -410 155 -820 155 -1250 c0 -285 -65 -560 -240 -785c175 -225 240 -500 240 -785c0 -430 -155 -840 -155 -1250c0 -215 45 -415 180 -585c15 -20 -15 -45 -30 -25c-180 225 -240 500 -240 785z", | |
"M-240 -1668c0 392 148 768 148 1140c0 192 -40 368 -168 520v8v8c128 152 168 328 168 520c0 372 -148 748 -148 1140c0 260 56 508 224 708c16 20 48 -4 32 -24c-128 -152 -168 -332 -168 -524c0 -364 140 -736 140 -1120c0 -260 -56 -508 -220 -708 c164 -200 220 -448 220 -708c0 -384 -140 -756 -140 -1120c0 -192 40 -372 168 -524c16 -20 -16 -44 -32 -24c-168 200 -224 448 -224 708z", | |
].map(skeletonizePath)), | |
pathFramesSymbol("SLUR DOWN", [ | |
"M1.5028 -0.8074C2.4307 0.0391 5.9413 0.0391 6.8692 -0.8074L6.8692 -0.8074C5.9413 -0.0896 2.4307 -0.0896 1.5028 -0.8074z", | |
"M1.5806 -0.0000C2.6617 0.9012 7.7937 0.9012 8.8748 -0.0000L8.8748 -0.0000C7.7937 0.7724 2.6617 0.7724 1.5806 -0.0000z", | |
"M0.1358 4.1918C3.1384 5.5006 23.9261 1.8052 26.2937 -0.4582L26.2937 -0.4582C23.9068 1.6964 3.1190 5.3918 0.1358 4.1918z", | |
"M5.4000 -1.4582C7.2084 0.4248 16.2728 1.8025 18.5590 0.5418L18.5590 0.5418C16.2894 1.6932 7.2250 0.3156 5.4000 -1.4582z", | |
"M0.6840 -0.9582C3.3097 0.6061 19.0586 -0.5325 21.4320 -2.4582L21.4320 -2.4582C19.0506 -0.6428 3.3018 0.4958 0.6840 -0.9582z", | |
"M0.7359 -0.8082C2.1046 0.0164 4.9041 -0.5297 5.8626 -1.8082L5.8626 -1.8082C4.8830 -0.6382 2.0835 -0.0921 0.7359 -0.8082z", | |
"M-0.0038 2.7489C1.0356 4.0058 3.9703 4.4396 5.3289 3.5372L5.3289 3.5372C3.9865 4.3303 1.0518 3.8964 -0.0038 2.7489z", | |
"M0.4158 -0.8186C0.9635 -0.1463 2.0441 0.0143 2.7712 -0.4686L2.7712 -0.4686C2.0598 -0.0914 0.9792 -0.2520 0.4158 -0.8186z", | |
"M0.4367 -5.4611C-1.1373 3.6241 33.0534 23.1887 40.0887 17.2285L40.0887 17.2285C33.1065 23.0960 -1.0842 3.5314 0.4367 -5.4611z", | |
"M0.2462 -1.1121C0.2563 -0.2493 0.9868 0.5033 1.8489 0.5389L1.8489 0.5389C1.0635 0.4288 0.3329 -0.3237 0.2462 -1.1121z", | |
"M0.6586 -1.4611C3.4185 0.3179 24.8011 0.0392 27.5138 -1.8111L27.5138 -1.8111C24.7997 -0.0676 3.4171 0.2111 0.6586 -1.4611z", | |
"M0.5814 4.0389C2.0266 5.6914 7.6905 6.6341 9.5930 5.5389L9.5930 5.5389C7.7037 6.5547 2.0398 5.6119 0.5814 4.0389z", | |
"M0.4463 -1.8051C1.2147 -0.5286 3.6343 0.1911 4.9850 -0.4551L4.9850 -0.4551C3.6728 0.0617 1.2532 -0.6580 0.4463 -1.8051z", | |
].map(simplifyPath)), | |
pathFramesSymbol("SLUR UP", [ | |
"M1.6331 0.7750C2.7048 -0.1232 7.7198 -0.1232 8.7915 0.7750L8.7915 0.7750C7.7198 0.0055 2.7048 0.0055 1.6331 0.7750z", | |
"M1.2172 -3.2497C3.8915 -5.3756 29.8558 -8.0703 32.9096 -6.5389L32.9096 -6.5389C29.8641 -7.9902 3.8998 -5.2954 1.2172 -3.2497z", | |
"M0.8860 0.2500C1.9483 -0.6211 6.8471 -0.6211 7.9093 0.2500L7.9093 0.2500C6.8471 -0.5405 1.9483 -0.5405 0.8860 0.2500z", | |
"M8.8571 -2.1918C12.2053 -7.7623 37.6503 -5.5978 40.0096 0.4582L40.0096 0.4582C37.6407 -5.4854 12.1958 -7.6498 8.8571 -2.1918z", | |
"M5.4000 0.8082C8.8706 -1.2527 91.8062 -3.0964 95.3650 -1.1918L95.3650 -1.1918C91.8086 -2.9859 8.8731 -1.1422 5.4000 0.8082z", | |
"M0.3581 2.9514C0.5936 0.9531 3.9709 -2.1395 5.9821 -2.1986L5.9821 -2.1986C4.0579 -2.0445 0.6806 1.0481 0.3581 2.9514z", | |
"M0.5939 1.7682C2.2579 -0.0946 9.4770 -1.0830 11.5491 0.2682L11.5491 0.2682C9.4914 -0.9772 2.2724 0.0113 0.5939 1.7682z", | |
].map(simplifyPath)), | |
pathFramesSymbol("SLUR",[ | |
"M. -.C. -. . -. . -.C. -. . -. . -.z", | |
"M. .C. . . . . .C. . . . . .z", | |
]), | |
/*pathFramesSymbol("ATTACHED FERMATA", [ | |
"M-69 -48c0 38 31 68 69 68s69 -30 69 -68s-31 -69 -69 -69s-69 31 -69 69zM0 -364c-157 0 -333 176 -333 367c0 10 10 17 20 17c9 0 19 -6 21 -20c26 -147 145 -261 292 -261s266 114 292 261c2 14 12 20 21 20c10 0 20 -7 20 -17c0 -191 -175 -367 -333 -367z", | |
].map(simplifyPath)),*/ | |
conditionSymbol("STAVES_CONNECTION", | |
elem => elem.identity.type === "rect" && elem.sw === 0.16 && elem.identity.height >= 10, | |
elem => ({height: elem.identity.height})), | |
conditionSymbol("BRACE BRACE_BAR", elem => elem.identity.type === "rect" && elem.identity.width === 0.45 && elem.identity.height >= 4), | |
/*pathFramesSymbol("BRACE BRACE_WING", [ | |
"M0 -56v91c0 12 10 21 22 21h43c164 0 281 136 377 272c10 14 32 -1 22 -15c-103 -145 -222 -369 -399 -369h-65z", | |
"M0 56h65c177 0 296 -224 399 -369c10 -14 -12 -29 -22 -15c-96 136 -213 272 -377 272h-43c-12 0 -22 9 -22 21v91z", | |
"M437 328c14 0 24 -12 24 -24c0 -4 -1 -8 -3 -12c-82 -141 -184 -348 -344 -348h-114v74c0 21 17 38 38 38h76c142 0 230 134 303 260c4 8 12 12 20 12z", | |
"M461 -304c0 -12 -10 -24 -24 -24c-8 0 -16 4 -20 12c-73 126 -161 260 -303 260h-76c-21 0 -38 17 -38 38v74h114c160 0 262 -207 344 -348c2 -4 3 -8 3 -12z", | |
"M0 -56v83c0 16 13 29 29 29h59c154 0 257 136 342 267c13 20 44 0 31 -20c-93 -143 -204 -359 -373 -359h-88z", | |
"M452 333c8 0 14 -7 14 -14c0 -3 0 -6 -2 -9c-101 -145 -219 -366 -394 -366h-70v89c0 13 10 23 23 23h47c162 0 276 136 370 271c3 4 7 6 12 6z", | |
].map(simplifyPath)),*/ | |
conditionSymbol("VERTICAL_LINE", elem => elem.identity.type === "rect" | |
&& (elem.sw === 0.19 || elem.sw === 0.6) && elem.identity.height >= 1), | |
conditionSymbol("NOTE_STEM", elem => elem.identity.type === "rect" | |
&& elem.sw === 0.13 && elem.identity.height >= 1), | |
conditionSymbol("TEMPO_NOTE_STEM", elem => elem.identity.type === "rect" | |
&& elem.sw === 0.12 && elem.identity.height >= 1), | |
conditionSymbol("NOTETAIL JOINT BEAM", elem => elem.identity.type === "polygon" && pointsSize(elem.identity.points) === 8), | |
conditionSymbol("STAFF_LINE", elem => elem.identity.type === "line" && elem.identity.height === 0 && elem.identity.width > 2 && elem.sw === 0.1 && !elem.identity["stroke-dasharray"]), | |
conditionSymbol("ADDITIONAL_LINE", elem => elem.identity.type === "rect" && elem.sw2 === 0.2 && elem.identity.rw >= 1.25 && elem.identity.rw < 5), | |
conditionSymbol("OCTAVE A _8", elem => elem.identity.type === "text" && /8va/.test(elem.identity.text)), | |
conditionSymbol("OCTAVE B _8", elem => elem.identity.type === "text" && /8vb/.test(elem.identity.text)), | |
conditionSymbol("OCTAVE _8", elem => elem.identity.type === "text" && elem.identity.text === "8" && elem.identity["font-style"] === "italic" && elem.identity["font-weight"] === "bold"), | |
conditionSymbol("OCTAVE A _15", elem => elem.identity.type === "text" && /15ma/.test(elem.identity.text)), | |
conditionSymbol("OCTAVE B _15", elem => elem.identity.type === "text" && /15mb/.test(elem.identity.text)), | |
conditionSymbol("OCTAVE _15", elem => elem.identity.type === "text" && elem.identity.text === "15" && elem.identity["font-style"] === "italic" && elem.identity["font-weight"] === "bold"), | |
identitySymbol("OCTAVE CLOSE LINE", { | |
type: "line", | |
width: 0, | |
height: 1.25, | |
"stroke-width": 0.0924, | |
"stroke-dasharray": "0.362351432995067,0.537648567004933", | |
}), | |
conditionSymbol("OCTAVE CLOSE LINE", elem => elem.identity.type === "line" && Math.abs(elem.identity.height) === 0.8 | |
&& elem.identity.width === 0 /*&& elem.identity["stroke-dasharray"] === "1.0,0.0"*/ && elem.identity["stroke-width"] < 0.2), | |
pathFrameSymbol("DOT", "M c s - -s- - - -s- - z"), | |
conditionSymbol("LINE", elem => elem.identity.type === "line"), | |
conditionSymbol("NULL LARGE_RECT", elem => elem.identity.type === "rect" && elem.identity.height > 1 && elem.identity.width >= 2 && elem.rx <= 0 && elem.ry <= 0), | |
conditionSymbol("NULL GENERAL_RECT", elem => elem.identity.type === "rect" && (elem.identity.height * elem.identity.width >= 0.3)), | |
conditionSymbol("NULL ENGRAVER_SIG", elem => elem.identity.type === "text" && /www\.lilypond\.org/.test(elem.identity.text)), | |
conditionSymbol("TEXT", elem => elem.identity.type === "text"), | |
glyphSymbol("ALTER FLAT", "accidentals.flat"), | |
glyphSymbol("ALTER FLATFLAT", "accidentals.flatflat"), | |
glyphSymbol("ALTER SHARP", "accidentals.sharp"), | |
glyphSymbol("ALTER SHARPSHARP", "accidentals.doublesharp"), | |
glyphSymbol("CLEF TREBLE", "clefs.G"), | |
glyphSymbol("CLEF TREBLE", "clefs.G_change"), | |
glyphSymbol("CLEF BASS", "clefs.F"), | |
glyphSymbol("CLEF BASS", "clefs.F_change"), | |
glyphSymbol("NOTETAIL FLAG UP EIGHTH", "flags.u3"), | |
glyphSymbol("NOTETAIL FLAG UP SIXTEENTH", "flags.u4"), | |
glyphSymbol("NOTETAIL FLAG UP THIRTYSECOND", "flags.u5"), | |
glyphSymbol("NOTETAIL FLAG UP SIXTYFOURTH", "flags.u6"), | |
glyphSymbol("NOTETAIL FLAG UP HUNDREDTWENTYEIGHTH", "flags.u7"), | |
glyphSymbol("NOTETAIL FLAG UP TWOHUNDREDSFIFTYSIXTH", "flags.u8"), | |
glyphSymbol("NOTETAIL FLAG DOWN EIGHTH", "flags.d3"), | |
glyphSymbol("NOTETAIL FLAG DOWN SIXTEENTH", "flags.d4"), | |
glyphSymbol("NOTETAIL FLAG DOWN THIRTYSECOND", "flags.d5"), | |
glyphSymbol("NOTETAIL FLAG DOWN SIXTYFOURTH", "flags.d6"), | |
glyphSymbol("NOTETAIL FLAG DOWN HUNDREDTWENTYEIGHTH", "flags.d7"), | |
glyphSymbol("NOTETAIL FLAG DOWN TWOHUNDREDSFIFTYSIXTH", "flags.d8"), | |
glyphSymbol("NOTE REST", "rests.0"), | |
glyphSymbol("NOTE REST", "rests.1"), | |
glyphSymbol("NOTE REST", "rests.2"), | |
glyphSymbol("NOTE REST", "rests.3"), | |
glyphSymbol("NOTE REST", "rests.4"), | |
glyphSymbol("NOTE REST", "rests.5"), | |
glyphSymbol("NOTE REST", "rests.6"), | |
glyphSymbol("NOTE REST", "rests.7"), | |
glyphSymbol("NOTE REST", "rests.8"), | |
glyphSymbol("TIME_SIG C_BAR", "timesig.C22"), | |
glyphSymbol("SUSTAIN ON", "pedal.Ped"), | |
glyphSymbol("SUSTAIN OFF", "pedal.*"), | |
glyphSymbol("ATTACHED PORTATO UP", "scripts.dportato"), // 'portato' glyph direction seems inversed in emmentaler v2017 | |
glyphSymbol("ATTACHED PORTATO DOWN", "scripts.uportato"), | |
glyphSymbol("ATTACHED DMARCATO DOWN", "scripts.dmarcato"), | |
glyphSymbol("ATTACHED DMARCATO UP", "scripts.umarcato"), | |
glyphSymbol("ATTACHED TENUTO", "scripts.tenuto"), | |
glyphSymbol("ATTACHED PRALL", "scripts.prall"), | |
glyphSymbol("ATTACHED MORDENT", "scripts.mordent"), | |
glyphSymbol("ATTACHED FERMATA UP", "scripts.ufermata"), | |
glyphSymbol("ATTACHED FERMATA DOWN", "scripts.dfermata"), | |
glyphSymbol("ATTACHED SHORTFERMATA UP", "scripts.ushortfermata"), | |
glyphSymbol("ATTACHED SHORTFERMATA DOWN", "scripts.dshortfermata"), | |
glyphSymbol("ATTACHED SFORZATO", "scripts.sforzato"), | |
glyphSymbol("BRACE BRACE_WING", "brackettips.up"), | |
glyphSymbol("BRACE BRACE_WING", "brackettips.down"), | |
]; | |
pathSymbols.forEach(({symbol, ds}) => symbolRules.push(pathFramesSymbol(symbol, ds))); | |
const postSymbolProcess = (symbol: string, process: PostSymbolizeRule): PostSymbolizeRule => (elem, result) => { | |
const symbols = result.symbol && result.symbol.split(" "); | |
if (symbols && symbols.includes(symbol)) | |
process(elem, result); | |
}; | |
const postConditionSymbol = (symbol: string, condition: (elem: Element) => boolean, addSymbol: string): PostSymbolizeRule => (elem, result) => { | |
const symbols = result.symbol && result.symbol.split(" "); | |
if (symbols && symbols.includes(symbol) && condition(elem)) | |
result.symbol = [...symbols, addSymbol].join(" "); | |
}; | |
const postSymbolRules: PostSymbolizeRule[] = [ | |
postConditionSymbol("NUMBER", elem => elemScale(elem, 0.004), "TIME_SIG"), | |
postConditionSymbol("NUMBER", elem => elemScale(elem, 0.0025), "ALTERNATIVE"), | |
postConditionSymbol("CLOSE", elem => elem.identity.height > 0, "UP"), | |
postConditionSymbol("CLOSE", elem => elem.identity.height < 0, "DOWN"), | |
postSymbolProcess("BEAM", (elem, result) => { | |
const floats = elem.identity.points.split(" ").map(Number); | |
const x1 = floats[4]; | |
const x2 = floats[0]; | |
const y1 = (floats[5] + floats[7]) / 2; | |
const y2 = (floats[1] + floats[3]) / 2; | |
result.start = {x: x1, y: y1}; | |
result.target = {x: x2, y: y2}; | |
}), | |
postSymbolProcess("SLUR", (elem, result) => { | |
const captures = elem.identity.d.match(/M[\d.-]+ ([\d.-]+).*L([\d.-]+) ([\d.-]+)/); | |
if (captures) { | |
const [_, sy, ex, ey] = captures; | |
result.start = {x: 0, y: Number(sy)}; | |
result.target = {x: Number(ex), y: Number(ey)}; | |
//console.log("slur:", result); | |
} | |
}), | |
postSymbolProcess("LINE", (elem, result) => { | |
result.start = {x: 0, y: 0}; | |
result.target = {x: elem.identity.width, y: elem.identity.height}; | |
}), | |
/*postSymbolProcess("NOTEHEAD", (elem, result) => { | |
result.scale = elem.identity.scale.x / GLYPH_BASE_SCALE; | |
}),*/ | |
postSymbolProcess("TEXT", (elem, result) => { | |
result.text = elem.identity.text; | |
}), | |
postSymbolProcess("NOTE_STEM", (elem, result) => { | |
result.width = elem.identity.width; | |
result.height = elem.identity.height; | |
}), | |
postSymbolProcess("ADDITIONAL_LINE", (elem, result) => { | |
result.width = elem.identity.width; | |
result.height = elem.identity.height; | |
// correct ry by stroke width | |
const cy = (elem.y + elem.identity.height / 2); | |
result.ry = roundNumber(cy, POS_PRECISION); | |
}), | |
]; | |
const glyphToSymbols: {[key: string]: string} = { | |
zero: "NUMBER 0", | |
one: "NUMBER 1", | |
two: "NUMBER 2", | |
three: "NUMBER 3", | |
four: "NUMBER 4", | |
five: "NUMBER 5", | |
six: "NUMBER 6", | |
seven: "NUMBER 7", | |
eight: "NUMBER 8", | |
nine: "NUMBER 9", | |
}; | |
const postSymbolize = (elem: Element, result: SymbolizeResult): SymbolizeResult => { | |
result.glyph = result.glyph || elem.glyph; | |
if (result.glyph && elem.identity.scale) { | |
const scale = elem.identity.scale.x / GLYPH_BASE_SCALE; | |
if (scale !== 1) | |
result.scale = scale; | |
} | |
if (result.glyph) { | |
const glyphSymbols = glyphToSymbols[result.glyph]; | |
if (glyphSymbols) | |
result.symbol = [result.symbol, glyphSymbols].filter(Boolean).join(" "); | |
} | |
for (const rule of postSymbolRules) | |
rule(elem, result); | |
return result; | |
}; | |
const symbolize = (elem: Element): SymbolizeResult => { | |
elem.glyph = glyphHash[elem.hash]; | |
let result = {}; | |
for (const rule of symbolRules) { | |
const r = rule(elem); | |
if (r) { | |
result = r; | |
break; | |
} | |
} | |
return postSymbolize(elem, result); | |
}; | |
export { | |
simplifyPath, | |
identityHash, | |
symbolize, | |
}; | |