UNPKG

@stringsync/vexml

Version:

MusicXML to Vexflow

154 lines (153 loc) 6.09 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Label = void 0; const util = __importStar(require("../util")); const spatial_1 = require("../spatial"); const pen_1 = require("./pen"); const textmeasurer_1 = require("./textmeasurer"); class Label { config; log; lines; font; rect; ctx = null; constructor(config, log, lines, font, rect) { this.config = config; this.log = log; this.lines = lines; this.font = font; this.rect = rect; } static singleLine(config, log, textContent, position, padding, font) { const fragments = Label.split(textContent, font, Infinity); const pen = new pen_1.Pen(position); const lines = new Array(); for (const fragment of fragments) { const paddingLeft = padding.left ?? 0; const paddingRight = padding.right ?? 0; const paddingTop = padding.top ?? 0; const paddingBottom = padding.bottom ?? 0; const x = pen.x - paddingLeft; const y = pen.y - paddingTop - fragment.height; const w = fragment.width + paddingLeft + paddingRight; const h = fragment.height + paddingTop + paddingBottom; const rect = new spatial_1.Rect(x, y, w, h); lines.push({ text: fragment.text, rect }); } const rect = spatial_1.Rect.merge(lines.map((line) => line.rect)); return new Label(config, log, lines, font, rect); } static centerAligned(config, log, maxWidth, textContent, position, padding, font) { const fragments = Label.split(textContent, font, maxWidth); const pen = new pen_1.Pen(position); const lines = new Array(); for (const fragment of fragments) { const paddingLeft = padding.left ?? 0; const paddingRight = padding.right ?? 0; const paddingTop = padding.top ?? 0; const paddingBottom = padding.bottom ?? 0; const x = position.x + (maxWidth - fragment.width) / 2 - paddingLeft; const y = pen.y - paddingTop - fragment.height; const w = fragment.width + paddingLeft + paddingRight; const h = fragment.height + paddingTop + paddingBottom; const rect = new spatial_1.Rect(x, y, w, h); lines.push({ text: fragment.text, rect }); const lineHeight = font.lineHeight ?? fragment.height; pen.moveTo({ x: position.x, y: pen.y + lineHeight }); } const rect = spatial_1.Rect.merge(lines.map((line) => line.rect)); return new Label(config, log, lines, font, rect); } static split(textContent, font, maxWidth) { const words = textContent.split(/\s+/); const fragments = new Array(); const textMeasurer = new textmeasurer_1.TextMeasurer(font); const spaceWidth = textMeasurer.measure(' ').width; let texts = new Array(); let width = 0; let height = 0; // Break down the words into fragments that fit within the maxWidth. for (let index = 0; index < words.length; index++) { const word = words[index]; const wordMetrics = textMeasurer.measure(word); const wordWidth = wordMetrics.width; const wordHeight = wordMetrics.approximateHeight; const remainingWidth = maxWidth - width; if (remainingWidth < wordWidth && texts.length > 0) { fragments.push({ text: texts.join(' '), width, height }); texts = []; width = 0; height = 0; } texts.push(word); width += wordWidth + spaceWidth; height = Math.max(height, wordHeight); if (index === words.length - 1 && texts.length > 0) { fragments.push({ text: texts.join(' '), width, height }); } } return fragments; } setContext(ctx) { this.ctx = ctx; return this; } draw() { const ctx = this.ctx; util.assertNotNull(ctx); ctx.save(); if (this.font.color) { ctx.setFillStyle(this.font.color); } const fontInfo = {}; if (this.font.family) { fontInfo.family = this.font.family; } if (this.font.size) { fontInfo.size = this.font.size; } if (Object.keys(fontInfo).length > 0) { ctx.setFont(fontInfo); } for (const line of this.lines) { ctx.fillText(line.text, line.rect.x, line.rect.y + line.rect.h); } ctx.restore(); return this; } } exports.Label = Label;