|  | @@ -19,8 +19,6 @@ import { AbstractExpression } from "../MusicalScore/VoiceData/Expressions/Abstra
 | 
	
		
			
				|  |  |  import { Dictionary } from "typescript-collections";
 | 
	
		
			
				|  |  |  import { NoteEnum } from "..";
 | 
	
		
			
				|  |  |  import { AutoColorSet, GraphicalMusicPage } from "../MusicalScore";
 | 
	
		
			
				|  |  | -import jspdf = require("jspdf-yworks/dist/jspdf.min");
 | 
	
		
			
				|  |  | -import svg2pdf = require("svg2pdf.js/dist/svg2pdf.min");
 | 
	
		
			
				|  |  |  import { MusicPartManagerIterator } from "../MusicalScore/MusicParts";
 | 
	
		
			
				|  |  |  import { ITransposeCalculator } from "../MusicalScore/Interfaces";
 | 
	
		
			
				|  |  |  /**
 | 
	
	
		
			
				|  | @@ -29,7 +27,7 @@ import { ITransposeCalculator } from "../MusicalScore/Interfaces";
 | 
	
		
			
				|  |  |   * After the constructor, use load() and render() to load and render a MusicXML file.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  export class OpenSheetMusicDisplay {
 | 
	
		
			
				|  |  | -    private version: string = "0.8.1-release"; // getter: this.Version
 | 
	
		
			
				|  |  | +    private version: string = "0.8.2-release"; // getter: this.Version
 | 
	
		
			
				|  |  |      // at release, bump version and change to -release, afterwards to -dev again
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
	
		
			
				|  | @@ -112,21 +110,25 @@ export class OpenSheetMusicDisplay {
 | 
	
		
			
				|  |  |                  // UTF with BOM detected, truncate first three bytes and pass along
 | 
	
		
			
				|  |  |                  return self.load(str.substr(3));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            if (str.substr(0, 6).includes("<?xml")) { // first character is sometimes null, making first five characters '<?xm'.
 | 
	
		
			
				|  |  | -                log.debug("[OSMD] Finally parsing XML content, length: " + str.length);
 | 
	
		
			
				|  |  | +            let trimmedStr: string = str;
 | 
	
		
			
				|  |  | +            if (/^\s/.test(trimmedStr)) { // only trim if we need to. (end of string is irrelevant)
 | 
	
		
			
				|  |  | +                trimmedStr = trimmedStr.trim(); // trim away empty lines at beginning etc
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (trimmedStr.substr(0, 6).includes("<?xml")) { // first character is sometimes null, making first five characters '<?xm'.
 | 
	
		
			
				|  |  | +                log.debug("[OSMD] Finally parsing XML content, length: " + trimmedStr.length);
 | 
	
		
			
				|  |  |                  // Parse the string representing an xml file
 | 
	
		
			
				|  |  |                  const parser: DOMParser = new DOMParser();
 | 
	
		
			
				|  |  | -                content = parser.parseFromString(str, "application/xml");
 | 
	
		
			
				|  |  | -            } else if (str.length < 2083) { // TODO do proper URL format check
 | 
	
		
			
				|  |  | -                log.debug("[OSMD] Retrieve the file at the given URL: " + str);
 | 
	
		
			
				|  |  | +                content = parser.parseFromString(trimmedStr, "application/xml");
 | 
	
		
			
				|  |  | +            } else if (trimmedStr.length < 2083) { // TODO do proper URL format check
 | 
	
		
			
				|  |  | +                log.debug("[OSMD] Retrieve the file at the given URL: " + trimmedStr);
 | 
	
		
			
				|  |  |                  // Assume now "str" is a URL
 | 
	
		
			
				|  |  |                  // Retrieve the file at the given URL
 | 
	
		
			
				|  |  | -                return AJAX.ajax(str).then(
 | 
	
		
			
				|  |  | +                return AJAX.ajax(trimmedStr).then(
 | 
	
		
			
				|  |  |                      (s: string) => { return self.load(s); },
 | 
	
		
			
				|  |  |                      (exc: Error) => { throw exc; }
 | 
	
		
			
				|  |  |                  );
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  | -                console.error("[OSMD] osmd.load(string): Could not process string. Missing else branch?");
 | 
	
		
			
				|  |  | +                console.error("[OSMD] osmd.load(string): Could not process string. Did not find <?xml at beginning.");
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -779,59 +781,6 @@ export class OpenSheetMusicDisplay {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /**
 | 
	
		
			
				|  |  | -     * Creates a Pdf of the currently rendered MusicXML
 | 
	
		
			
				|  |  | -     * @param pdfName if no name is given, the composer and title of the piece will be used
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | -    public createPdf(pdfName: string = undefined): void {
 | 
	
		
			
				|  |  | -        if (this.backendType !== BackendType.SVG) {
 | 
	
		
			
				|  |  | -            console.log("[OSMD] osmd.createPdf(): Warning: createPDF is only supported for SVG background for now, not for Canvas." +
 | 
	
		
			
				|  |  | -                " Please use osmd.setOptions({backendType: SVG}).");
 | 
	
		
			
				|  |  | -            return;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if (pdfName === undefined) {
 | 
	
		
			
				|  |  | -            pdfName = this.sheet.FullNameString + ".pdf";
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        const backends: VexFlowBackend[] = this.drawer.Backends;
 | 
	
		
			
				|  |  | -        let svgElement: SVGElement = (<SvgVexFlowBackend>backends[0]).getSvgElement();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        let pageWidth: number = 210;
 | 
	
		
			
				|  |  | -        let pageHeight: number = 297;
 | 
	
		
			
				|  |  | -        const engravingRulesPageFormat: PageFormat = this.rules.PageFormat;
 | 
	
		
			
				|  |  | -        if (engravingRulesPageFormat && !engravingRulesPageFormat.IsUndefined) {
 | 
	
		
			
				|  |  | -            pageWidth = engravingRulesPageFormat.width;
 | 
	
		
			
				|  |  | -            pageHeight = engravingRulesPageFormat.height;
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -            pageHeight = pageWidth * svgElement.clientHeight / svgElement.clientWidth;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        const orientation: string = pageHeight > pageWidth ? "p" : "l";
 | 
	
		
			
				|  |  | -        // create a new jsPDF instance
 | 
	
		
			
				|  |  | -        const pdf: any = new jspdf(orientation, "mm", [pageWidth, pageHeight]);
 | 
	
		
			
				|  |  | -        const scale: number = pageWidth / svgElement.clientWidth;
 | 
	
		
			
				|  |  | -        for (let idx: number = 0, len: number = backends.length; idx < len; ++idx) {
 | 
	
		
			
				|  |  | -            if (idx > 0) {
 | 
	
		
			
				|  |  | -                pdf.addPage();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            svgElement = (<SvgVexFlowBackend>backends[idx]).getSvgElement();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // render the svg element
 | 
	
		
			
				|  |  | -            svg2pdf(svgElement, pdf, {
 | 
	
		
			
				|  |  | -                scale: scale,
 | 
	
		
			
				|  |  | -                xOffset: 0,
 | 
	
		
			
				|  |  | -                yOffset: 0
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // simply save the created pdf
 | 
	
		
			
				|  |  | -        pdf.save(pdfName);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // note that using jspdf with svg2pdf creates unnecessary console warnings "AcroForm-Classes are not populated into global-namespace..."
 | 
	
		
			
				|  |  | -        // this will hopefully be fixed with a new jspdf release, see https://github.com/yWorks/jsPDF/pull/32
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      //#region GETTER / SETTER
 | 
	
		
			
				|  |  |      public set DrawSkyLine(value: boolean) {
 | 
	
		
			
				|  |  |          this.drawSkyLine = value;
 |