MusicSheetDrawer.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. import {EngravingRules} from "./EngravingRules";
  2. import {ITextMeasurer} from "../Interfaces/ITextMeasurer";
  3. import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
  4. import {BoundingBox} from "./BoundingBox";
  5. import {GraphicalLayers, OutlineAndFillStyleEnum} from "./DrawingEnums";
  6. import {DrawingParameters} from "./DrawingParameters";
  7. import {GraphicalLine} from "./GraphicalLine";
  8. import {RectangleF2D} from "../../Common/DataObjects/RectangleF2D";
  9. import {PointF2D} from "../../Common/DataObjects/PointF2D";
  10. import {GraphicalRectangle} from "./GraphicalRectangle";
  11. import {GraphicalLabel} from "./GraphicalLabel";
  12. import {Label} from "../Label";
  13. import {TextAlignment} from "../../Common/Enums/TextAlignment";
  14. import {ArgumentOutOfRangeException} from "../Exceptions";
  15. import {SelectionStartSymbol} from "./SelectionStartSymbol";
  16. import {SelectionEndSymbol} from "./SelectionEndSymbol";
  17. import {MusicSystem} from "./MusicSystem";
  18. import {StaffMeasure} from "./StaffMeasure";
  19. import {StaffLine} from "./StaffLine";
  20. import {SystemLine} from "./SystemLine";
  21. import {MusicSymbol} from "./MusicSymbol";
  22. import {GraphicalMusicPage} from "./GraphicalMusicPage";
  23. import {Instrument} from "../Instrument";
  24. import {MusicSymbolDrawingStyle, PhonicScoreModes} from "./DrawingMode";
  25. import {GraphicalOctaveShift} from "./GraphicalOctaveShift";
  26. import {GraphicalObject} from "./GraphicalObject";
  27. /**
  28. * Class used to draw a GraphicalMusicSheet (with the .drawSheet method)
  29. */
  30. export abstract class MusicSheetDrawer {
  31. public drawingParameters: DrawingParameters = new DrawingParameters();
  32. public splitScreenLineColor: number;
  33. public midiPlaybackAvailable: boolean;
  34. protected rules: EngravingRules;
  35. protected graphicalMusicSheet: GraphicalMusicSheet;
  36. protected textMeasurer: ITextMeasurer;
  37. private phonicScoreMode: PhonicScoreModes = PhonicScoreModes.Manual;
  38. constructor(textMeasurer: ITextMeasurer,
  39. isPreviewImageDrawer: boolean = false) {
  40. this.textMeasurer = textMeasurer;
  41. this.splitScreenLineColor = -1;
  42. if (isPreviewImageDrawer) {
  43. this.drawingParameters.setForThumbmail();
  44. } else {
  45. this.drawingParameters.setForAllOn();
  46. }
  47. }
  48. public set Mode(value: PhonicScoreModes) {
  49. this.phonicScoreMode = value;
  50. }
  51. public drawSheet(graphicalMusicSheet: GraphicalMusicSheet): void {
  52. this.graphicalMusicSheet = graphicalMusicSheet;
  53. this.rules = graphicalMusicSheet.ParentMusicSheet.Rules;
  54. this.drawSplitScreenLine();
  55. if (this.drawingParameters.drawCursors) {
  56. for (let line of graphicalMusicSheet.Cursors) {
  57. let psi: BoundingBox = new BoundingBox(line);
  58. psi.AbsolutePosition = line.Start;
  59. psi.BorderBottom = line.End.y - line.Start.y;
  60. psi.BorderRight = line.Width / 2.0;
  61. psi.BorderLeft = -line.Width / 2.0;
  62. if (this.isVisible(psi)) {
  63. this.drawLineAsVerticalRectangle(line, <number>GraphicalLayers.Cursor);
  64. }
  65. }
  66. }
  67. if (this.drawingParameters.drawScrollIndicator) {
  68. this.drawScrollIndicator();
  69. }
  70. for (let page of this.graphicalMusicSheet.MusicPages) {
  71. this.drawPage(page);
  72. }
  73. }
  74. public drawLineAsHorizontalRectangle(line: GraphicalLine, layer: number): void {
  75. let rectangle: RectangleF2D = new RectangleF2D(line.Start.x, line.End.y - line.Width / 2, line.End.x - line.Start.x, line.Width);
  76. rectangle = this.applyScreenTransformationForRect(rectangle);
  77. this.renderRectangle(rectangle, layer, line.styleId);
  78. }
  79. public drawLineAsVerticalRectangle(line: GraphicalLine, layer: number): void {
  80. let lineStart: PointF2D = line.Start;
  81. let lineWidth: number = line.Width;
  82. let rectangle: RectangleF2D = new RectangleF2D(lineStart.x - lineWidth / 2, lineStart.y, lineWidth, line.End.y - lineStart.y);
  83. rectangle = this.applyScreenTransformationForRect(rectangle);
  84. this.renderRectangle(rectangle, layer, line.styleId);
  85. }
  86. public drawLineAsHorizontalRectangleWithOffset(line: GraphicalLine, offset: PointF2D, layer: number): void {
  87. let start: PointF2D = new PointF2D(line.Start.x + offset.x, line.Start.y + offset.y);
  88. let end: PointF2D = new PointF2D(line.End.x + offset.x, line.End.y + offset.y);
  89. let width: number = line.Width;
  90. let rectangle: RectangleF2D = new RectangleF2D(start.x, end.y - width / 2, end.x - start.x, width);
  91. rectangle = this.applyScreenTransformationForRect(rectangle);
  92. this.renderRectangle(rectangle, layer, line.styleId);
  93. }
  94. public drawLineAsVerticalRectangleWithOffset(line: GraphicalLine, offset: PointF2D, layer: number): void {
  95. let start: PointF2D = new PointF2D(line.Start.x + offset.x, line.Start.y + offset.y);
  96. let end: PointF2D = new PointF2D(line.End.x + offset.x, line.End.y + offset.y);
  97. let width: number = line.Width;
  98. let rectangle: RectangleF2D = new RectangleF2D(start.x, start.y, width, end.y - start.y);
  99. rectangle = this.applyScreenTransformationForRect(rectangle);
  100. this.renderRectangle(rectangle, layer, line.styleId);
  101. }
  102. public drawRectangle(rect: GraphicalRectangle, layer: number): void {
  103. let psi: BoundingBox = rect.PositionAndShape;
  104. let rectangle: RectangleF2D = new RectangleF2D(psi.AbsolutePosition.x, psi.AbsolutePosition.y, psi.BorderRight, psi.BorderBottom);
  105. rectangle = this.applyScreenTransformationForRect(rectangle);
  106. this.renderRectangle(rectangle, layer, <number>rect.style);
  107. }
  108. public calculatePixelDistance(unitDistance: number): number {
  109. throw new Error("not implemented");
  110. }
  111. public drawLabel(graphicalLabel: GraphicalLabel, layer: number): void {
  112. if (!this.isVisible(graphicalLabel.PositionAndShape)) {
  113. return;
  114. }
  115. let label: Label = graphicalLabel.Label;
  116. if (label.text.trim() === "") {
  117. return;
  118. }
  119. let screenPosition: PointF2D = this.applyScreenTransformation(graphicalLabel.PositionAndShape.AbsolutePosition);
  120. let heightInPixel: number = this.calculatePixelDistance(label.fontHeight);
  121. let widthInPixel: number = heightInPixel * this.textMeasurer.computeTextWidthToHeightRatio(label.text, label.font, label.fontStyle);
  122. let bitmapWidth: number = <number>Math.ceil(widthInPixel);
  123. let bitmapHeight: number = <number>Math.ceil(heightInPixel * 1.2);
  124. switch (label.textAlignment) {
  125. case TextAlignment.LeftTop:
  126. break;
  127. case TextAlignment.LeftCenter:
  128. screenPosition.y -= <number>bitmapHeight / 2;
  129. break;
  130. case TextAlignment.LeftBottom:
  131. screenPosition.y -= bitmapHeight;
  132. break;
  133. case TextAlignment.CenterTop:
  134. screenPosition.x -= <number>bitmapWidth / 2;
  135. break;
  136. case TextAlignment.CenterCenter:
  137. screenPosition.x -= <number>bitmapWidth / 2;
  138. screenPosition.y -= <number>bitmapHeight / 2;
  139. break;
  140. case TextAlignment.CenterBottom:
  141. screenPosition.x -= <number>bitmapWidth / 2;
  142. screenPosition.y -= bitmapHeight;
  143. break;
  144. case TextAlignment.RightTop:
  145. screenPosition.x -= bitmapWidth;
  146. break;
  147. case TextAlignment.RightCenter:
  148. screenPosition.x -= bitmapWidth;
  149. screenPosition.y -= <number>bitmapHeight / 2;
  150. break;
  151. case TextAlignment.RightBottom:
  152. screenPosition.x -= bitmapWidth;
  153. screenPosition.y -= bitmapHeight;
  154. break;
  155. default:
  156. throw new ArgumentOutOfRangeException("");
  157. }
  158. this.renderLabel(graphicalLabel, layer, bitmapWidth, bitmapHeight, heightInPixel, screenPosition);
  159. }
  160. protected applyScreenTransformation(point: PointF2D): PointF2D {
  161. throw new Error("not implemented");
  162. }
  163. protected applyScreenTransformations(points: PointF2D[]): PointF2D[] {
  164. let transformedPoints: PointF2D[] = [];
  165. for (let point of points) {
  166. transformedPoints.push(this.applyScreenTransformation(point));
  167. }
  168. return transformedPoints;
  169. }
  170. protected applyScreenTransformationForRect(rectangle: RectangleF2D): RectangleF2D {
  171. throw new Error("not implemented");
  172. }
  173. protected drawSplitScreenLine(): void {
  174. // empty
  175. }
  176. protected renderRectangle(rectangle: RectangleF2D, layer: number, styleId: number): void {
  177. throw new Error("not implemented");
  178. }
  179. protected drawScrollIndicator(): void {
  180. // empty
  181. }
  182. protected drawSelectionStartSymbol(symbol: SelectionStartSymbol): void {
  183. // empty
  184. }
  185. protected drawSelectionEndSymbol(symbol: SelectionEndSymbol): void {
  186. // empty
  187. }
  188. protected renderLabel(graphicalLabel: GraphicalLabel, layer: number, bitmapWidth: number,
  189. bitmapHeight: number, heightInPixel: number, screenPosition: PointF2D): void {
  190. throw new Error("not implemented");
  191. }
  192. protected renderSystemToScreen(system: MusicSystem, systemBoundingBoxInPixels: RectangleF2D,
  193. absBoundingRectWithMargin: RectangleF2D): void {
  194. // empty
  195. }
  196. protected drawMeasure(measure: StaffMeasure): void {
  197. throw new Error("not implemented");
  198. }
  199. protected drawSkyLine(staffLine: StaffLine): void {
  200. // empty
  201. }
  202. protected drawBottomLine(staffLine: StaffLine): void {
  203. // empty
  204. }
  205. protected drawInstrumentBracket(bracket: GraphicalObject, system: MusicSystem): void {
  206. // empty
  207. }
  208. protected drawGroupBracket(bracket: GraphicalObject, system: MusicSystem): void {
  209. // empty
  210. }
  211. protected isVisible(psi: BoundingBox): boolean {
  212. return true;
  213. }
  214. protected drawMusicSystem(system: MusicSystem): void {
  215. let absBoundingRectWithMargin: RectangleF2D = this.getSystemAbsBoundingRect(system);
  216. let systemBoundingBoxInPixels: RectangleF2D = this.getSytemBoundingBoxInPixels(absBoundingRectWithMargin);
  217. this.drawMusicSystemComponents(system, systemBoundingBoxInPixels, absBoundingRectWithMargin);
  218. }
  219. protected getSytemBoundingBoxInPixels(absBoundingRectWithMargin: RectangleF2D): RectangleF2D {
  220. let systemBoundingBoxInPixels: RectangleF2D = this.applyScreenTransformationForRect(absBoundingRectWithMargin);
  221. systemBoundingBoxInPixels.x = Math.round(systemBoundingBoxInPixels.x);
  222. systemBoundingBoxInPixels.y = Math.round(systemBoundingBoxInPixels.y);
  223. return systemBoundingBoxInPixels;
  224. }
  225. protected getSystemAbsBoundingRect(system: MusicSystem): RectangleF2D {
  226. let relBoundingRect: RectangleF2D = system.PositionAndShape.BoundingRectangle;
  227. let absBoundingRectWithMargin: RectangleF2D = new RectangleF2D(
  228. system.PositionAndShape.AbsolutePosition.x + system.PositionAndShape.BorderLeft - 1,
  229. system.PositionAndShape.AbsolutePosition.y + system.PositionAndShape.BorderTop - 1,
  230. (relBoundingRect.width + 6), (relBoundingRect.height + 2)
  231. );
  232. return absBoundingRectWithMargin;
  233. }
  234. protected drawMusicSystemComponents(musicSystem: MusicSystem, systemBoundingBoxInPixels: RectangleF2D,
  235. absBoundingRectWithMargin: RectangleF2D): void {
  236. let selectStartSymb: SelectionStartSymbol = this.graphicalMusicSheet.SelectionStartSymbol;
  237. let selectEndSymb: SelectionEndSymbol = this.graphicalMusicSheet.SelectionEndSymbol;
  238. if (this.drawingParameters.drawSelectionStartSymbol) {
  239. if (selectStartSymb !== undefined && this.isVisible(selectStartSymb.PositionAndShape)) {
  240. this.drawSelectionStartSymbol(selectStartSymb);
  241. }
  242. }
  243. if (this.drawingParameters.drawSelectionEndSymbol) {
  244. if (selectEndSymb !== undefined && this.isVisible(selectEndSymb.PositionAndShape)) {
  245. this.drawSelectionEndSymbol(selectEndSymb);
  246. }
  247. }
  248. for (let staffLine of musicSystem.StaffLines) {
  249. this.drawStaffLine(staffLine);
  250. }
  251. for (let systemLine of musicSystem.SystemLines) {
  252. this.drawSystemLineObject(systemLine);
  253. }
  254. if (musicSystem === musicSystem.Parent.MusicSystems[0] && musicSystem.Parent === musicSystem.Parent.Parent.MusicPages[0]) {
  255. for (let label of musicSystem.Labels) {
  256. this.drawLabel(label, <number>GraphicalLayers.Notes);
  257. }
  258. }
  259. for (let bracket of musicSystem.InstrumentBrackets) {
  260. this.drawInstrumentBracket(bracket, musicSystem);
  261. }
  262. for (let bracket of musicSystem.GroupBrackets) {
  263. this.drawGroupBracket(bracket, musicSystem);
  264. }
  265. if (!this.leadSheet) {
  266. for (let measureNumberLabel of musicSystem.MeasureNumberLabels) {
  267. this.drawLabel(measureNumberLabel, <number>GraphicalLayers.Notes);
  268. }
  269. }
  270. for (let staffLine of musicSystem.StaffLines) {
  271. this.drawStaffLineSymbols(staffLine);
  272. }
  273. if (this.drawingParameters.drawMarkedAreas) {
  274. this.drawMarkedAreas(musicSystem);
  275. }
  276. if (this.drawingParameters.drawComments) {
  277. this.drawComment(musicSystem);
  278. }
  279. }
  280. protected activateSystemRendering(systemId: number, absBoundingRect: RectangleF2D,
  281. systemBoundingBoxInPixels: RectangleF2D, createNewImage: boolean): boolean {
  282. return true;
  283. }
  284. protected drawSystemLineObject(systemLine: SystemLine): void {
  285. // empty
  286. }
  287. protected drawStaffLine(staffLine: StaffLine): void {
  288. for (let measure of staffLine.Measures) {
  289. this.drawMeasure(measure);
  290. }
  291. }
  292. // protected drawSlur(slur: GraphicalSlur, abs: PointF2D): void {
  293. //
  294. // }
  295. protected drawOctaveShift(staffLine: StaffLine, graphicalOctaveShift: GraphicalOctaveShift): void {
  296. this.drawSymbol(graphicalOctaveShift.octaveSymbol, MusicSymbolDrawingStyle.Normal, graphicalOctaveShift.PositionAndShape.AbsolutePosition);
  297. let absolutePos: PointF2D = staffLine.PositionAndShape.AbsolutePosition;
  298. if (graphicalOctaveShift.dashesStart.x < graphicalOctaveShift.dashesEnd.x) {
  299. let horizontalLine: GraphicalLine = new GraphicalLine(graphicalOctaveShift.dashesStart, graphicalOctaveShift.dashesEnd,
  300. this.rules.OctaveShiftLineWidth);
  301. this.drawLineAsHorizontalRectangleWithOffset(horizontalLine, absolutePos, <number>GraphicalLayers.Notes);
  302. }
  303. if (!graphicalOctaveShift.endsOnDifferentStaffLine || graphicalOctaveShift.isSecondPart) {
  304. let verticalLine: GraphicalLine;
  305. let dashEnd: PointF2D = graphicalOctaveShift.dashesEnd;
  306. let octShiftVertLineLength: number = this.rules.OctaveShiftVerticalLineLength;
  307. let octShiftLineWidth: number = this.rules.OctaveShiftLineWidth;
  308. if (graphicalOctaveShift.octaveSymbol === MusicSymbol.VA8 || graphicalOctaveShift.octaveSymbol === MusicSymbol.MA15) {
  309. verticalLine = new GraphicalLine(dashEnd, new PointF2D(dashEnd.x, dashEnd.y + octShiftVertLineLength), octShiftLineWidth);
  310. } else {
  311. verticalLine = new GraphicalLine(new PointF2D(dashEnd.x, dashEnd.y - octShiftVertLineLength), dashEnd, octShiftLineWidth);
  312. }
  313. this.drawLineAsVerticalRectangleWithOffset(verticalLine, absolutePos, <number>GraphicalLayers.Notes);
  314. }
  315. }
  316. protected drawStaffLines(staffLine: StaffLine): void {
  317. if (staffLine.StaffLines !== undefined) {
  318. let position: PointF2D = staffLine.PositionAndShape.AbsolutePosition;
  319. for (let i: number = 0; i < 5; i++) {
  320. this.drawLineAsHorizontalRectangleWithOffset(staffLine.StaffLines[i], position, <number>GraphicalLayers.Notes);
  321. }
  322. }
  323. }
  324. // protected drawEnding(ending: GraphicalRepetitionEnding, absolutePosition: PointF2D): void {
  325. // if (undefined !== ending.Left)
  326. // drawLineAsVerticalRectangle(ending.Left, absolutePosition, <number>GraphicalLayers.Notes);
  327. // this.drawLineAsHorizontalRectangle(ending.Top, absolutePosition, <number>GraphicalLayers.Notes);
  328. // if (undefined !== ending.Right)
  329. // drawLineAsVerticalRectangle(ending.Right, absolutePosition, <number>GraphicalLayers.Notes);
  330. // this.drawLabel(ending.Label, <number>GraphicalLayers.Notes);
  331. // }
  332. // protected drawInstantaniousDynamic(expression: GraphicalInstantaniousDynamicExpression): void {
  333. // expression.ExpressionSymbols.forEach(function (expressionSymbol) {
  334. // let position: PointF2D = expressionSymbol.PositionAndShape.AbsolutePosition;
  335. // let symbol: MusicSymbol = expressionSymbol.GetSymbol;
  336. // drawSymbol(symbol, MusicSymbolDrawingStyle.Normal, position);
  337. // });
  338. // }
  339. // protected drawContinuousDynamic(expression: GraphicalContinuousDynamicExpression,
  340. // absolute: PointF2D): void {
  341. // throw new Error("not implemented");
  342. // }
  343. protected drawSymbol(symbol: MusicSymbol, symbolStyle: MusicSymbolDrawingStyle, position: PointF2D,
  344. scalingFactor: number = 1, layer: number = <number>GraphicalLayers.Notes): void {
  345. //empty
  346. }
  347. protected get leadSheet(): boolean {
  348. return this.graphicalMusicSheet.LeadSheet;
  349. }
  350. protected set leadSheet(value: boolean) {
  351. this.graphicalMusicSheet.LeadSheet = value;
  352. }
  353. private drawPage(page: GraphicalMusicPage): void {
  354. if (!this.isVisible(page.PositionAndShape)) {
  355. return;
  356. }
  357. for (let system of page.MusicSystems) {
  358. if (this.isVisible(system.PositionAndShape)) {
  359. this.drawMusicSystem(system);
  360. }
  361. }
  362. if (page === page.Parent.MusicPages[0]) {
  363. for (let label of page.Labels) {
  364. this.drawLabel(label, <number>GraphicalLayers.Notes);
  365. }
  366. }
  367. }
  368. private drawMarkedAreas(system: MusicSystem): void {
  369. for (let markedArea of system.GraphicalMarkedAreas) {
  370. if (markedArea !== undefined) {
  371. if (markedArea.systemRectangle !== undefined) {
  372. this.drawRectangle(markedArea.systemRectangle, <number>GraphicalLayers.Background);
  373. }
  374. if (markedArea.settings !== undefined) {
  375. this.drawLabel(markedArea.settings, <number>GraphicalLayers.Comment);
  376. }
  377. if (markedArea.labelRectangle !== undefined) {
  378. this.drawRectangle(markedArea.labelRectangle, <number>GraphicalLayers.Background);
  379. }
  380. if (markedArea.label !== undefined) {
  381. this.drawLabel(markedArea.label, <number>GraphicalLayers.Comment);
  382. }
  383. }
  384. }
  385. }
  386. private drawComment(system: MusicSystem): void {
  387. for (let comment of system.GraphicalComments) {
  388. if (comment !== undefined) {
  389. if (comment.settings !== undefined) {
  390. this.drawLabel(comment.settings, <number>GraphicalLayers.Comment);
  391. }
  392. if (comment.label !== undefined) {
  393. this.drawLabel(comment.label, <number>GraphicalLayers.Comment);
  394. }
  395. }
  396. }
  397. }
  398. private drawStaffLineSymbols(staffLine: StaffLine): void {
  399. let parentInst: Instrument = staffLine.ParentStaff.ParentInstrument;
  400. let absX: number = staffLine.PositionAndShape.AbsolutePosition.x;
  401. let absY: number = staffLine.PositionAndShape.AbsolutePosition.y + 2;
  402. let borderRight: number = staffLine.PositionAndShape.BorderRight;
  403. if (parentInst.highlight && this.drawingParameters.drawHighlights) {
  404. this.drawLineAsHorizontalRectangle(
  405. new GraphicalLine(
  406. new PointF2D(absX, absY),
  407. new PointF2D(absX + borderRight, absY),
  408. 4,
  409. OutlineAndFillStyleEnum.Highlighted
  410. ),
  411. <number>GraphicalLayers.Highlight
  412. );
  413. }
  414. let style: MusicSymbolDrawingStyle = MusicSymbolDrawingStyle.Disabled;
  415. let symbol: MusicSymbol = MusicSymbol.PLAY;
  416. let drawSymbols: boolean = this.drawingParameters.drawActivitySymbols;
  417. switch (this.phonicScoreMode) {
  418. case PhonicScoreModes.Midi:
  419. symbol = MusicSymbol.PLAY;
  420. if (this.midiPlaybackAvailable && staffLine.ParentStaff.audible) {
  421. style = MusicSymbolDrawingStyle.PlaybackSymbols;
  422. }
  423. break;
  424. case PhonicScoreModes.Following:
  425. symbol = MusicSymbol.MIC;
  426. if (staffLine.ParentStaff.following) {
  427. style = MusicSymbolDrawingStyle.FollowSymbols;
  428. }
  429. break;
  430. default:
  431. drawSymbols = false;
  432. break;
  433. }
  434. if (drawSymbols) {
  435. let p: PointF2D = new PointF2D(absX + borderRight + 2, absY);
  436. this.drawSymbol(symbol, style, p);
  437. }
  438. if (this.drawingParameters.drawErrors) {
  439. for (let measure of staffLine.Measures) {
  440. let measurePSI: BoundingBox = measure.PositionAndShape;
  441. let absXPSI: number = measurePSI.AbsolutePosition.x;
  442. let absYPSI: number = measurePSI.AbsolutePosition.y + 2;
  443. if (measure.hasError && this.graphicalMusicSheet.ParentMusicSheet.DrawErroneousMeasures) {
  444. this.drawLineAsHorizontalRectangle(
  445. new GraphicalLine(
  446. new PointF2D(absXPSI, absYPSI),
  447. new PointF2D(absXPSI + measurePSI.BorderRight, absYPSI),
  448. 4,
  449. OutlineAndFillStyleEnum.ErrorUnderlay
  450. ),
  451. <number>GraphicalLayers.MeasureError
  452. );
  453. }
  454. }
  455. }
  456. }
  457. }