diff --git a/svg_rendering/page/js-gen/Y_extract.js b/svg_rendering/page/js-gen/Y_extract.js index eaa8456..98b69f6 100644 --- a/svg_rendering/page/js-gen/Y_extract.js +++ b/svg_rendering/page/js-gen/Y_extract.js @@ -13,7 +13,7 @@ Y.Object = {}; * @param {object} sx static properties to add/override. * @return {object} the extended object. */ -Y.extend = function(r, s, px, sx) { +Y.extend = function (r, s, px, sx) { if (!s || !r) { //console.log('extend failed, verify dependencies'); } @@ -45,40 +45,40 @@ Y.extend = function(r, s, px, sx) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** -Mixes _supplier_'s properties into _receiver_. - -Properties on _receiver_ or _receiver_'s prototype will not be overwritten or -shadowed unless the _overwrite_ parameter is `true`, and will not be merged -unless the _merge_ parameter is `true`. - -In the default mode (0), only properties the supplier owns are copied (prototype -properties are not copied). The following copying modes are available: - - * `0`: _Default_. Object to object. - * `1`: Prototype to prototype. - * `2`: Prototype to prototype and object to object. - * `3`: Prototype to object. - * `4`: Object to prototype. - -@method mix -@param {Function|Object} receiver The object or function to receive the mixed - properties. -@param {Function|Object} supplier The object or function supplying the - properties to be mixed. -@param {Boolean} [overwrite=false] If `true`, properties that already exist - on the receiver will be overwritten with properties from the supplier. -@param {String[]} [whitelist] An array of property names to copy. If - specified, only the whitelisted properties will be copied, and all others - will be ignored. -@param {Number} [mode=0] Mix mode to use. See above for available modes. -@param {Boolean} [merge=false] If `true`, objects and arrays that already - exist on the receiver will have the corresponding object/array from the - supplier merged into them, rather than being skipped or overwritten. When - both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. -@return {Function|Object|YUI} The receiver, or the YUI instance if the - specified receiver is falsy. -**/ -Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { + Mixes _supplier_'s properties into _receiver_. + + Properties on _receiver_ or _receiver_'s prototype will not be overwritten or + shadowed unless the _overwrite_ parameter is `true`, and will not be merged + unless the _merge_ parameter is `true`. + + In the default mode (0), only properties the supplier owns are copied (prototype + properties are not copied). The following copying modes are available: + + * `0`: _Default_. Object to object. + * `1`: Prototype to prototype. + * `2`: Prototype to prototype and object to object. + * `3`: Prototype to object. + * `4`: Object to prototype. + + @method mix + @param {Function|Object} receiver The object or function to receive the mixed + properties. + @param {Function|Object} supplier The object or function supplying the + properties to be mixed. + @param {Boolean} [overwrite=false] If `true`, properties that already exist + on the receiver will be overwritten with properties from the supplier. + @param {String[]} [whitelist] An array of property names to copy. If + specified, only the whitelisted properties will be copied, and all others + will be ignored. + @param {Number} [mode=0] Mix mode to use. See above for available modes. + @param {Boolean} [merge=false] If `true`, objects and arrays that already + exist on the receiver will have the corresponding object/array from the + supplier merged into them, rather than being skipped or overwritten. When + both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. + @return {Function|Object|YUI} The receiver, or the YUI instance if the + specified receiver is falsy. + **/ +Y.mix = function (receiver, supplier, overwrite, whitelist, mode, merge) { var alwaysOverwrite, exists, from, i, key, len, to; // If no supplier is given, we return the receiver. If no receiver is given, @@ -94,13 +94,13 @@ Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { // handled later on. if (mode === 2) { Y.mix(receiver.prototype, supplier.prototype, overwrite, - whitelist, 0, merge); + whitelist, 0, merge); } // Depending on which mode is specified, we may be copying from or to // the prototypes of the supplier and receiver. from = mode === 1 || mode === 3 ? supplier.prototype : supplier; - to = mode === 1 || mode === 4 ? receiver.prototype : receiver; + to = mode === 1 || mode === 4 ? receiver.prototype : receiver; // If either the supplier or receiver doesn't actually have a // prototype property, then we could end up with an undefined `from` @@ -110,7 +110,7 @@ Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { } } else { from = supplier; - to = receiver; + to = receiver; } // If `overwrite` is truthy and `merge` is falsy, then we can skip a @@ -189,7 +189,7 @@ Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Y.Array.find = function(a, f, o) { +Y.Array.find = function (a, f, o) { for (var i = 0, l = a.length; i < l; i++) { if (i in a && f.call(o, a[i], i, a)) { return a[i]; @@ -202,21 +202,21 @@ Y.Array.find = function(a, f, o) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Y.Array.dedupe = function (array) { - var hash = Object.create(null), - results = [], - i, item, len; - - for (i = 0, len = array.length; i < len; ++i) { - item = array[i]; - - if (!hash[item]) { - hash[item] = 1; - results.push(item); - } - } - return results; - }; +Y.Array.dedupe = function (array) { + var hash = Object.create(null), + results = [], + i, item, len; + + for (i = 0, len = array.length; i < len; ++i) { + item = array[i]; + + if (!hash[item]) { + hash[item] = 1; + results.push(item); + } + } + return results; +}; diff --git a/svg_rendering/page/js-gen/adhoc-tree.js b/svg_rendering/page/js-gen/adhoc-tree.js index 25b574c..63b42fb 100644 --- a/svg_rendering/page/js-gen/adhoc-tree.js +++ b/svg_rendering/page/js-gen/adhoc-tree.js @@ -17,310 +17,326 @@ * along with this program. If not, see . */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust) { - - var XMLNodeUtils = { - documentOrderSort : function(a,b) { - var aNode = a.data['xml:node'].split('/').reverse().map(function(x){return parseInt(x);}); - var bNode = b.data['xml:node'].split('/').reverse().map(function(x){return parseInt(x);}); - if (bNode[0].length === 0) { - return 1; - } - for (var i=0; true; i++) { - if (!aNode[i]) { - return -1; +(function (Faust) { + + var XMLNodeUtils = { + documentOrderSort: function (a, b) { + var aNode = a.data['xml:node'].split('/').reverse().map(function (x) { + return parseInt(x); + }); + var bNode = b.data['xml:node'].split('/').reverse().map(function (x) { + return parseInt(x); + }); + if (bNode[0].length === 0) { + return 1; + } + for (var i = 0; true; i++) { + if (!aNode[i]) { + return -1; + } + if (!bNode[i]) { + return 1; + } + if (aNode[i] < bNode[i]) { + return -2; + } + if (aNode[i] > bNode[i]) { + return 2; + } + } + }, + + // is a descendant of b in document? + isDescendant: function (a, b) { + var aNode = a.data['xml:node'].split('/').reverse().map(function (x) { + return parseInt(x); + }); + var bNode = b.data['xml:node'].split('/').reverse().map(function (x) { + return parseInt(x); + }); + if (aNode[0].length === 0) { + return false; + } + for (var i = 0; true; i++) { + if (!aNode[i]) { + return false; + } + if (!bNode[i]) { + return true; + } + if (aNode[i] != bNode[i]) { + return false; + } + } + }, + + // is a following b in document order? + isFollowing: function (a, b) { + return XMLNodeUtils.documentOrderSort(a, b) > 0; } - if (!bNode[i]) { - return 1; - } - if (aNode[i] < bNode[i]) { - return -2; - } - if (aNode[i] > bNode[i]) { - return 2; - } - } - }, - - // is a descendant of b in document? - isDescendant : function(a, b) { - var aNode = a.data['xml:node'].split('/').reverse().map(function(x){return parseInt(x);}); - var bNode = b.data['xml:node'].split('/').reverse().map(function(x){return parseInt(x);}); - if (aNode[0].length === 0) { - return false; - } - for (var i=0; true; i++) { - if (!aNode[i]) { - return false; - } - if (!bNode[i]) { - return true; + }; + + + function _sortByRange(a, b) { + if (a.targets[0].range.start === b.targets[0].range.start) { + return a.targets[0].range.end - b.targets[0].range.end; + } else { + return a.targets[0].range.start - b.targets[0].range.start; } - if (aNode[i] != bNode[i]) { - return false; + } + + function _nextOutermostAnnotationCandidates(transcript, start, end, filter, siblings, ancestors, parent, + documentOrderSort, isDescendant) { + + var allAnnotations = transcript.find(start, end, filter); + + var includedAnnotations = allAnnotations.filter(function (annotation) { + + //exclude children of exclude too! + var descendantOrSelfOfExcluded = false; + siblings.forEach(function (sibling) { + descendantOrSelfOfExcluded = isDescendant(annotation, sibling) || descendantOrSelfOfExcluded; + }); + + var exclude = ancestors.concat(siblings); + + return exclude.indexOf(annotation) < 0 && isDescendant(annotation, parent) && !descendantOrSelfOfExcluded; + + // return exclude.indexOf(annotation) < 0 && isDescendant(annotation, parent); + }); + + if (includedAnnotations.length === 0) { + return []; } - } - }, - // is a following b in document order? - isFollowing : function(a,b) { - return XMLNodeUtils.documentOrderSort(a, b) > 0; - } - }; + // assuming annotations ordered by start position + var smallestStart = includedAnnotations[0].targets[0].range.start; + + var firstAnnotations = includedAnnotations.filter(function (annotation) { + return annotation.targets[0].range.start === smallestStart; + }); + + var ends = firstAnnotations.map(function (annotation) { + return annotation.targets[0].range.end; + }); + + var greatestEnd = ends.reduce(function (x, y) { + return Math.max(x, y); + }, start); + + var nextOutermostAnnotationCandidates = firstAnnotations.filter(function (annotation) { + return annotation.targets[0].range.end === greatestEnd; + }); + + //return nextOutermostAnnotationCandidates; + return firstAnnotations.sort(documentOrderSort); - function _sortByRange(a, b) { - if (a.targets[0].range.start === b.targets[0].range.start) { - return a.targets[0].range.end - b.targets[0].range.end; - } else { - return a.targets[0].range.start - b.targets[0].range.start; - } - } - function _nextOutermostAnnotationCandidates(transcript, start, end, filter, siblings, ancestors, parent, - documentOrderSort, isDescendant) { - - var allAnnotations = transcript.find (start, end, filter); - - var includedAnnotations = allAnnotations.filter(function(annotation) { - - //exclude children of exclude too! - var descendantOrSelfOfExcluded = false; - siblings.forEach(function(sibling){ - descendantOrSelfOfExcluded = isDescendant(annotation, sibling) || descendantOrSelfOfExcluded; - }); - - var exclude = ancestors.concat(siblings); - - return exclude.indexOf(annotation) < 0 && isDescendant(annotation, parent) && !descendantOrSelfOfExcluded; - - // return exclude.indexOf(annotation) < 0 && isDescendant(annotation, parent); - }); - - if (includedAnnotations.length === 0) { - return []; } - // assuming annotations ordered by start position + function _nextOutermostAnnotation(transcript, start, end, filter, siblings, ancestors, parent, + documentOrderSort, isDescendant) { - var smallestStart = includedAnnotations[0].targets[0].range.start; + var nextOutermostAnnotationCandidates = _nextOutermostAnnotationCandidates(transcript, start, end, filter, siblings, ancestors, parent, + documentOrderSort, isDescendant); - var firstAnnotations = includedAnnotations.filter(function(annotation) { - return annotation.targets[0].range.start === smallestStart; - }); + var exclude = ancestors.concat(siblings); - var ends = firstAnnotations.map(function(annotation) { - return annotation.targets[0].range.end; - }); + var includedAnnotations = nextOutermostAnnotationCandidates.filter(function (annotation) { + return exclude.indexOf(annotation) < 0; + }); - var greatestEnd = ends.reduce(function(x,y){ - return Math.max(x,y); - }, start); + if (includedAnnotations.length === 0) { + return null; + } - var nextOutermostAnnotationCandidates = firstAnnotations.filter(function(annotation){ - return annotation.targets[0].range.end === greatestEnd; - }); + var descendants = includedAnnotations.filter(function (annotation) { + return isDescendant(annotation, parent); + }); - //return nextOutermostAnnotationCandidates; - return firstAnnotations.sort(documentOrderSort); - } - function _nextOutermostAnnotation(transcript, start, end, filter, siblings, ancestors, parent, - documentOrderSort, isDescendant) { + // filter out descendents of siblings; necessary with empty elements - var nextOutermostAnnotationCandidates = _nextOutermostAnnotationCandidates(transcript, start, end, filter, siblings, ancestors, parent, - documentOrderSort, isDescendant); + var nonDescendantsOfSiblings = descendants.filter(function (annotation) { + for (var i = 0; i < siblings.length; i++) { + if (isDescendant(annotation, siblings[i])) { + return false; + } + } + return true; + }); - var exclude = ancestors.concat(siblings); + var sortedByNesting = nonDescendantsOfSiblings.sort(documentOrderSort); - var includedAnnotations = nextOutermostAnnotationCandidates.filter(function(annotation) { - return exclude.indexOf(annotation) < 0; - }); + return sortedByNesting.length > 0 ? sortedByNesting[0] : null; + } - if (includedAnnotations.length === 0) { - return null; + function AdhocNode(parent) { + this.parent = parent; } - var descendants = includedAnnotations.filter(function(annotation){ - return isDescendant(annotation, parent); - }); - + Y.extend(AdhocNode, Object, { + ancestors: function () { + var node = this; + var result = []; + while (node.parent) { + node = node.parent; + result.push(node); + } + return result; + }, + children: function () { + return []; + }, + _getAncestorProperty: function (property) { + if (this[property]) { + return this[property]; + } else { + if (this.parent) { + return this.parent._getAncestorProperty(property); + } + } + }, + transcript: function () { + return this._getAncestorProperty('_transcript'); + }, + filter: function () { + return this._getAncestorProperty('_filter'); + } + }); - // filter out descendents of siblings; necessary with empty elements + function TextNode(range, parent) { + TextNode.superclass.constructor.call(this, parent); + this.range = range; + } - var nonDescendantsOfSiblings = descendants.filter(function(annotation){ - for (var i=0; i < siblings.length; i++ ) { - if (isDescendant(annotation, siblings[i])) { - return false; + Y.extend(TextNode, AdhocNode, { + content: function () { + return this.range.of(this.transcript().content); + }, + toString: function () { + return this.content(); } - } - return true; - }); - - var sortedByNesting = nonDescendantsOfSiblings.sort(documentOrderSort); - - return sortedByNesting.length > 0 ? sortedByNesting[0] : null; - } - - function AdhocNode(parent) { - this.parent = parent; - } - Y.extend(AdhocNode, Object, { - ancestors : function() { - var node = this; - var result = []; - while (node.parent) { - node = node.parent; - result.push(node); - } - return result; - }, - children : function() { - return []; - }, - _getAncestorProperty: function(property) { - if (this[property]) { - return this[property]; - } else { - if (this.parent) { - return this.parent._getAncestorProperty(property); - } - } - }, - transcript : function() { - return this._getAncestorProperty('_transcript'); - }, - filter : function() { - return this._getAncestorProperty('_filter'); - } - }); - - function TextNode(range, parent) { - TextNode.superclass.constructor.call(this, parent); - this.range = range; - } - - Y.extend(TextNode, AdhocNode, { - content: function() { - return this.range.of(this.transcript().content); - }, - toString : function() { - return this.content(); - } - - }); - - function AnnotationNode(annotation, parent) { - AnnotationNode.superclass.constructor.call(this, parent); - this.annotation = annotation; - } - Y.extend(AnnotationNode, AdhocNode, { - - _textNodesForPartitions: function(start, end, parent) { - var partitions = this.transcript().partition(null, start, end); - var textNodes = partitions.map(function(partition) { - return new TextNode(new Faust.Range(partition.start, partition.end), parent); - }); - return textNodes; - }, - - _iterateChildren: function(start, end, ancestors, documentOrderSort, isDescendant) { - var siblings = []; - var result = []; - var from = start; - var to = end; - while (true) { - var annotation = _nextOutermostAnnotation(this.transcript(), from, end, this.filter(), siblings, - ancestors, this.annotation, - documentOrderSort, isDescendant); - if (annotation) { - - // there is a sibling non-text node - var prefixStart = from; - var prefixEnd = annotation.targets[0].range.start; - var annotationEnd = annotation.targets[0].range.end; - if (prefixEnd > prefixStart) { - // there is text content before the next sibling node - var textNodes = this._textNodesForPartitions(prefixStart, prefixEnd, this); - result = result.concat(textNodes); - } - siblings.push(annotation); - var annotationNode = new AnnotationNode(annotation, this); - result.push(annotationNode); - from = annotationEnd; - } else { - // text node - if (from < end) { - var textNodes = this._textNodesForPartitions(from, end, this); - result = result.concat(textNodes); - } - return result; - } - } - }, - - data: function() { - return this.annotation.data; - }, - children: function() { - var ancestorAnnotationCandidates = [this].concat(this.ancestors()).map(function(node) {return node.annotation;}); - //ancestorAnnotationCandidates = ancestorAnnotationCandidates.push(this.annotation); - var ancestorAnnotations = ancestorAnnotationCandidates.filter(function(annotation){return annotation;}); - var range = this.annotation.targets[0].range; - return this._iterateChildren(range.start, range.end, ancestorAnnotations, - this._getAncestorProperty('_documentOrderSort'), - this._getAncestorProperty('_isDescendant')); - }, - name: function() { - return this.annotation.name; - }, - toString : function() { - var result = ""; - var name = this.name().localName; - var node = this.data()['xml:node'] ? ' ' + this.data()['xml:node'] + ' ' : ''; - result = result + (name ? '<' + name + node + '>': ''); - this.children().forEach(function(child){ - result = result + child.toString(); - }); - result = result + (name ? '': ''); - return result; - } - }); - - function AdhocTree(transcript, filter, documentOrderSort, isDescendant) { - - var mockAnnotation = new Faust.Annotation(new Faust.Name("http://interedition.eu/ns", "treeRoot"), - {'xml:node': ''}, - [new Faust.TextTarget(transcript, - new Faust.Range(0, transcript.content.length))] - ); - - AdhocTree.superclass.constructor.call(this, mockAnnotation); - this._transcript = transcript; - this._filter = filter; - this._documentOrderSort = documentOrderSort; - this._isDescendant = isDescendant; - } - - Y.extend(AdhocTree, AnnotationNode, { - children: function() { - return this._iterateChildren(0, this.transcript().content.length, [], - this._getAncestorProperty('_documentOrderSort'), - this._getAncestorProperty('_isDescendant')); - }, - data: function() { - return {}; - } - - }); - - Faust.AdhocTree = AdhocTree; - Faust.TextNode = TextNode; - Faust.AnnotationNode = AnnotationNode; - Faust.XMLNodeUtils = XMLNodeUtils; + + }); + + function AnnotationNode(annotation, parent) { + AnnotationNode.superclass.constructor.call(this, parent); + this.annotation = annotation; + } + + Y.extend(AnnotationNode, AdhocNode, { + + _textNodesForPartitions: function (start, end, parent) { + var partitions = this.transcript().partition(null, start, end); + var textNodes = partitions.map(function (partition) { + return new TextNode(new Faust.Range(partition.start, partition.end), parent); + }); + return textNodes; + }, + + _iterateChildren: function (start, end, ancestors, documentOrderSort, isDescendant) { + var siblings = []; + var result = []; + var from = start; + var to = end; + while (true) { + var annotation = _nextOutermostAnnotation(this.transcript(), from, end, this.filter(), siblings, + ancestors, this.annotation, + documentOrderSort, isDescendant); + if (annotation) { + + // there is a sibling non-text node + var prefixStart = from; + var prefixEnd = annotation.targets[0].range.start; + var annotationEnd = annotation.targets[0].range.end; + if (prefixEnd > prefixStart) { + // there is text content before the next sibling node + var textNodes = this._textNodesForPartitions(prefixStart, prefixEnd, this); + result = result.concat(textNodes); + } + siblings.push(annotation); + var annotationNode = new AnnotationNode(annotation, this); + result.push(annotationNode); + from = annotationEnd; + } else { + // text node + if (from < end) { + var textNodes = this._textNodesForPartitions(from, end, this); + result = result.concat(textNodes); + } + return result; + } + } + }, + + data: function () { + return this.annotation.data; + }, + children: function () { + var ancestorAnnotationCandidates = [this].concat(this.ancestors()).map(function (node) { + return node.annotation; + }); + //ancestorAnnotationCandidates = ancestorAnnotationCandidates.push(this.annotation); + var ancestorAnnotations = ancestorAnnotationCandidates.filter(function (annotation) { + return annotation; + }); + var range = this.annotation.targets[0].range; + return this._iterateChildren(range.start, range.end, ancestorAnnotations, + this._getAncestorProperty('_documentOrderSort'), + this._getAncestorProperty('_isDescendant')); + }, + name: function () { + return this.annotation.name; + }, + toString: function () { + var result = ""; + var name = this.name().localName; + var node = this.data()['xml:node'] ? ' ' + this.data()['xml:node'] + ' ' : ''; + result = result + (name ? '<' + name + node + '>' : ''); + this.children().forEach(function (child) { + result = result + child.toString(); + }); + result = result + (name ? '' : ''); + return result; + } + }); + + function AdhocTree(transcript, filter, documentOrderSort, isDescendant) { + + var mockAnnotation = new Faust.Annotation(new Faust.Name("http://interedition.eu/ns", "treeRoot"), + {'xml:node': ''}, + [new Faust.TextTarget(transcript, + new Faust.Range(0, transcript.content.length))] + ); + + AdhocTree.superclass.constructor.call(this, mockAnnotation); + this._transcript = transcript; + this._filter = filter; + this._documentOrderSort = documentOrderSort; + this._isDescendant = isDescendant; + } + + Y.extend(AdhocTree, AnnotationNode, { + children: function () { + return this._iterateChildren(0, this.transcript().content.length, [], + this._getAncestorProperty('_documentOrderSort'), + this._getAncestorProperty('_isDescendant')); + }, + data: function () { + return {}; + } + + }); + + Faust.AdhocTree = AdhocTree; + Faust.TextNode = TextNode; + Faust.AnnotationNode = AnnotationNode; + Faust.XMLNodeUtils = XMLNodeUtils; })(Faust); diff --git a/svg_rendering/page/js-gen/faust.js b/svg_rendering/page/js-gen/faust.js index d804f22..ecfc537 100644 --- a/svg_rendering/page/js-gen/faust.js +++ b/svg_rendering/page/js-gen/faust.js @@ -17,90 +17,92 @@ * along with this program. If not, see . */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust){ - Faust.encodePath = function (path) { - var encoded = ""; - var pathComponents = path.split("/"); - for (var pc = 0; pc < pathComponents.length; pc++) - encoded += (encoded.length == 0 ? "" : "/") + encodeURI(pathComponents[pc]); - return encoded; - }; +(function (Faust) { + Faust.encodePath = function (path) { + var encoded = ""; + var pathComponents = path.split("/"); + for (var pc = 0; pc < pathComponents.length; pc++) + encoded += (encoded.length == 0 ? "" : "/") + encodeURI(pathComponents[pc]); + return encoded; + }; - Faust.URI = function(uri) { - this.components = uri.match(/^faust:\/\/([^\/]+)\/(.*)/); - }; + Faust.URI = function (uri) { + this.components = uri.match(/^faust:\/\/([^\/]+)\/(.*)/); + }; - Faust.URI.prototype = { - encodedPath: function() { return Faust.encodePath(this.components[2]); } - }; + Faust.URI.prototype = { + encodedPath: function () { + return Faust.encodePath(this.components[2]); + } + }; -/* REMOVE - Faust.YUI = function() { - return YUI(); - }; -*/ + /* REMOVE + Faust.YUI = function() { + return YUI(); + }; + */ - Faust.io = function(uri, callback, reviver) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", uri, true); - xhr.setRequestHeader("Accept", "application/json"); - if(callback) { - xhr.onreadystatechange = function () { - if(this.readyState === 4) { - callback(JSON.parse(xhr.responseText, reviver)); + Faust.io = function (uri, callback, reviver) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri, true); + xhr.setRequestHeader("Accept", "application/json"); + if (callback) { + xhr.onreadystatechange = function () { + if (this.readyState === 4) { + callback(JSON.parse(xhr.responseText, reviver)); + } + }; } - }; - } - xhr.send(null); - }; - - Faust.xml = function(uri, callback) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", uri, true); - if(callback) { - xhr.onreadystatechange = function () { - if(this.readyState === 4) { - callback(xhr.responseXML); + xhr.send(null); + }; + + Faust.xml = function (uri, callback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri, true); + if (callback) { + xhr.onreadystatechange = function () { + if (this.readyState === 4) { + callback(xhr.responseXML); + } + }; } - }; - } - xhr.send(null); - }; -/* REMOVE - Faust.io = function(uri, callback, reviver) { - Faust.YUI().use("io", "json", function(Y) { - Y.io(Faust.contextPath + "/" + uri, { - method: "GET", - xdr: { responseXML: false }, - headers: { "Accept": "application/json" }, - on: { - success: function(id, o, a) { - callback(Y.JSON.parse(o.responseText, reviver)); - }, - failure: function(id, o, a) { - Y.log("ERROR " + id + " " + a, "info", "Faust") } - } - }); - }); - }; -*/ -/* REMOVE - Faust.xml = function(uri, callback) { - Faust.YUI().use("io", function(Y) { - Y.io(Faust.contextPath + "/" + uri, { - method: "GET", - on: { - success: function(id, o, a) { - callback(o.responseXML); - }, - failure: function(id, o, a) { - Y.log("ERROR " + id + " " + a, "info", "Faust") } - } - }); - }); - }; -*/ + xhr.send(null); + }; + /* REMOVE + Faust.io = function(uri, callback, reviver) { + Faust.YUI().use("io", "json", function(Y) { + Y.io(Faust.contextPath + "/" + uri, { + method: "GET", + xdr: { responseXML: false }, + headers: { "Accept": "application/json" }, + on: { + success: function(id, o, a) { + callback(Y.JSON.parse(o.responseText, reviver)); + }, + failure: function(id, o, a) { + Y.log("ERROR " + id + " " + a, "info", "Faust") } + } + }); + }); + }; + */ + /* REMOVE + Faust.xml = function(uri, callback) { + Faust.YUI().use("io", function(Y) { + Y.io(Faust.contextPath + "/" + uri, { + method: "GET", + on: { + success: function(id, o, a) { + callback(o.responseXML); + }, + failure: function(id, o, a) { + Y.log("ERROR " + id + " " + a, "info", "Faust") } + } + }); + }); + }; + */ })(Faust); diff --git a/svg_rendering/page/js-gen/loadwebfonts.js b/svg_rendering/page/js-gen/loadwebfonts.js index 389bc22..6b8cba1 100644 --- a/svg_rendering/page/js-gen/loadwebfonts.js +++ b/svg_rendering/page/js-gen/loadwebfonts.js @@ -18,50 +18,50 @@ */ if (window.Faust === undefined) { - window.Faust = {}; + window.Faust = {}; } (function (Faust) { - Fonts = {}; - Fonts.active = function (callback) { + Fonts = {}; + Fonts.active = function (callback) { - var fontError = false; - var webFontConfig = { - custom: { - families: ['Ubuntu', 'Ubuntu Monospace', 'Gentium Plus'], - // we don not need to specify urls as they are specified in the css files - urls: ['/css/webfonts.css'] - }, - // do not time out if font can't be loaded - timeout: 10, //Number.MAX_VALUE, - active: function () { - // if we made it this far without 'fontinactive' occurring, then all - // fonts have been loaded - if (!Faust.TranscriptConfiguration.forceFontLoading || !fontError) { - callback(); - } else { - // do not try to render page - } + var fontError = false; + var webFontConfig = { + custom: { + families: ['Ubuntu', 'Ubuntu Monospace', 'Gentium Plus'], + // we don not need to specify urls as they are specified in the css files + urls: ['/css/webfonts.css'] + }, + // do not time out if font can't be loaded + timeout: 10, //Number.MAX_VALUE, + active: function () { + // if we made it this far without 'fontinactive' occurring, then all + // fonts have been loaded + if (!Faust.TranscriptConfiguration.forceFontLoading || !fontError) { + callback(); + } else { + // do not try to render page + } - }, - fontinactive: function (familyName, fvd) { - // font could not be loaded, abort - if (Faust.TranscriptConfiguration.forceFontLoading) { - fontError = true; - var message = "Error: web font could not be loaded: " + familyName + " " + fvd; - var htmlMessage = document.createElement('div'); - htmlMessage.innerHTML = message; - document.body.append(htmlMessage); - throw(message); - } - } - }; + }, + fontinactive: function (familyName, fvd) { + // font could not be loaded, abort + if (Faust.TranscriptConfiguration.forceFontLoading) { + fontError = true; + var message = "Error: web font could not be loaded: " + familyName + " " + fvd; + var htmlMessage = document.createElement('div'); + htmlMessage.innerHTML = message; + document.body.append(htmlMessage); + throw(message); + } + } + }; - WebFont.load(webFontConfig); - }; + WebFont.load(webFontConfig); + }; - Faust.Fonts = Fonts; + Faust.Fonts = Fonts; })(Faust); diff --git a/svg_rendering/page/js-gen/materialunit.js b/svg_rendering/page/js-gen/materialunit.js index ae796de..a05b92b 100644 --- a/svg_rendering/page/js-gen/materialunit.js +++ b/svg_rendering/page/js-gen/materialunit.js @@ -16,71 +16,76 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust){ - var MaterialUnit = function() {}; - MaterialUnit.prototype = { - descendants: function() { - return (function(list, mu) { - for (var cc = 0; cc < mu.contents.length; cc++) { - list.push(mu.contents[cc]); - arguments.callee(list, mu.contents[cc]); - } - return list; - })([], this); - }, - transcription: function(callback) { - if (this.transcript == null) { callback(); return; } - Faust.io("goddag/" + this.transcript.source.encodedPath() + "?snapshot=true", function(data) { - callback(new Goddag.Graph(data)); - }); - }, - - transcriptionFromRanges: function(callback) { - if (this.transcript == null) { - callback(); - return; - } - Faust.io("transcript/source/" + this.id, function(data) { - callback(data); - }); - } - - }; +(function (Faust) { + var MaterialUnit = function () { + }; + MaterialUnit.prototype = { + descendants: function () { + return (function (list, mu) { + for (var cc = 0; cc < mu.contents.length; cc++) { + list.push(mu.contents[cc]); + arguments.callee(list, mu.contents[cc]); + } + return list; + })([], this); + }, + transcription: function (callback) { + if (this.transcript == null) { + callback(); + return; + } + Faust.io("goddag/" + this.transcript.source.encodedPath() + "?snapshot=true", function (data) { + callback(new Goddag.Graph(data)); + }); + }, - var Document = function() {}; - Document.load = function(uri, callback) { - Faust.io(uri, callback, function(key, value) { - if (key === "order") { - // Begin: replacement of Y.augment (which was actually only Y.mix since this has no prototype - var from = MaterialUnit.prototype; - for(key in from) { - if(from.hasOwnProperty(key)) { - if(!(key in this)) { - this[key] = from[key]; + transcriptionFromRanges: function (callback) { + if (this.transcript == null) { + callback(); + return; } - } + Faust.io("transcript/source/" + this.id, function (data) { + callback(data); + }); } - // End: replacement - } - if (key === "source") { - return new Faust.URI(value); - } - if (key === "facsimiles") { - var facsimiles = []; - for (var vc = 0; vc < value.length; vc++) - facsimiles.push(new Faust.URI(value[vc])); - return facsimiles; - } - return value; - }); - }; + + }; + + var Document = function () { + }; + Document.load = function (uri, callback) { + Faust.io(uri, callback, function (key, value) { + if (key === "order") { + // Begin: replacement of Y.augment (which was actually only Y.mix since this has no prototype + var from = MaterialUnit.prototype; + for (key in from) { + if (from.hasOwnProperty(key)) { + if (!(key in this)) { + this[key] = from[key]; + } + } + } + // End: replacement + } + if (key === "source") { + return new Faust.URI(value); + } + if (key === "facsimiles") { + var facsimiles = []; + for (var vc = 0; vc < value.length; vc++) + facsimiles.push(new Faust.URI(value[vc])); + return facsimiles; + } + return value; + }); + }; - Faust.Document = Document; - Faust.MaterialUnit = MaterialUnit; + Faust.Document = Document; + Faust.MaterialUnit = MaterialUnit; })(Faust); diff --git a/svg_rendering/page/js-gen/svg-utils.js b/svg_rendering/page/js-gen/svg-utils.js index 2836bdf..c3d27ba 100644 --- a/svg_rendering/page/js-gen/svg-utils.js +++ b/svg_rendering/page/js-gen/svg-utils.js @@ -17,337 +17,338 @@ * along with this program. If not, see . */ -if(window.SvgUtils === undefined) { - window.SvgUtils = {}; +if (window.SvgUtils === undefined) { + window.SvgUtils = {}; } -(function(SvgUtils){ +(function (SvgUtils) { - var SVG_NS = "http://www.w3.org/2000/svg"; + var SVG_NS = "http://www.w3.org/2000/svg"; - function decodeClassValue(classValue, key) { - var start = classValue.indexOf(key); - if (start < 0) { - return ''; + function decodeClassValue(classValue, key) { + var start = classValue.indexOf(key); + if (start < 0) { + return ''; + } + var rightSide = classValue.substring(start + key.length); + var end = rightSide.search('\\s'); + return end >= 0 ? rightSide.substring(0, end) : rightSide; + } + + + function qscale(degree) { + return function (val) { + return val * Math.pow(2, degree); + }; + } + + function svgElement(name) { + return document.createElementNS(SVG_NS, name); + } + + function svgAttrs(element, attrs) { + Object.keys(attrs).forEach(function (attr) { + element.setAttribute(attr, attrs[attr]); + }); + return element; } - var rightSide = classValue.substring(start + key.length); - var end = rightSide.search('\\s'); - return end >= 0 ? rightSide.substring(0, end) : rightSide; - } - - - function qscale (degree) { - return function (val) { - return val * Math.pow(2, degree); - }; - } - - function svgElement(name) { - return document.createElementNS(SVG_NS, name); - } - - function svgAttrs(element, attrs) { - Object.keys(attrs).forEach(function(attr) { - element.setAttribute(attr, attrs[attr]); - }); - return element; - } - - function hasClass(yuiNode, classValue) { - var classTokens = yuiNode.getDOMNode().getAttribute('class').split(' '); - return classTokens.indexOf(classValue) >= 0; - } - - function addClass(yuiNode, newClass) { - var domNode = yuiNode.getDOMNode(); - var classValue = domNode.getAttribute('class'); - domNode.setAttribute('class', classValue + ' ' + newClass); - } - - function removeClass(yuiNode, removeValue) { - var domNode = yuiNode.getDOMNode(); - var classTokens = domNode.getAttribute('class').split(' '); - var newClassValue = ''; - for (var i = 0; i < classTokens.length; i++) { - if (classTokens[i] !== removeValue) { - newClassValue = newClassValue + classTokens[i] + ' '; - } - } - domNode.setAttribute('class', newClassValue); - } - - function svgStyles(element, styles) { - Object.keys(styles).forEach(function(style) { - element.style[style] = styles[style]; - }); - return element; - } - - function svg(element, attrs, styles) { - return svgStyles(svgAttrs( - svgElement(element), attrs || {}), styles || {}); - } - - function empty(element) { - while (element.firstChild) { - element.removeChild(element.firstChild); - } - } - - // An implementation of getScreenBBox, by Antoine Quint, modiefied by Moritz Wissenbach - // http://the.fuchsia-design.com/2006/12/getting-svg-elementss-full-bounding-box.html - function getScreenBBox(element, svgRoot) { - - // macro to create an SVGPoint object - function createPoint (x, y) { - var point = svgRoot.createSVGPoint(); - point.x = x; - point.y = y; - return point; - } - - // macro to create an SVGRect object - function createRect (x, y, width, height) { - var rect = svgRoot.createSVGRect(); - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - return rect; - } - - // get the complete transformation matrix - //var matrix = element.getTransformToElement(svgRoot); - var matrix = svgRoot.getTransformToElement(element); - // get the bounding box of the target element - var box = element.getBBox(); - - // create an array of SVGPoints for each corner - // of the bounding box and update their location - // with the transform matrix - var corners = []; - var point = createPoint(box.x, box.y); - corners.push( point.matrixTransform(matrix) ); - point.x = box.x + box.width; - point.y = box.y; - corners.push( point.matrixTransform(matrix) ); - point.x = box.x + box.width; - point.y = box.y + box.height; - corners.push( point.matrixTransform(matrix) ); - point.x = box.x; - point.y = box.y + box.height; - corners.push( point.matrixTransform(matrix) ); - var max = createPoint(corners[0].x, corners[0].y); - var min = createPoint(corners[0].x, corners[0].y); - - // identify the new corner coordinates of the - // fully transformed bounding box - for (var i = 1; i < corners.length; i++) { - var x = corners[i].x; - var y = corners[i].y; - if (x < min.x) { - min.x = x; - } - else if (x > max.x) { - max.x = x; - } - if (y < min.y) { - min.y = y; - } - else if (y > max.y) { - max.y = y; - } - } - - // return the bounding box as an SVGRect object - return createRect(min.x, min.y, max.x - min.x, max.y - min.y); - } - - - /** - * Safely get and return the bounding box of element as seen from its local coordinate system. - */ - - function localBoundingBox(element) { - - // Firefox will throw an exception when calling getBBox() on an element with display: none - // see https://bugzilla.mozilla.org/show_bug.cgi?id=612118 - - var visible = true; - var el = element; - if(window.getComputedStyle(el).display === 'none') { - visible = false; + + function hasClass(yuiNode, classValue) { + var classTokens = yuiNode.getDOMNode().getAttribute('class').split(' '); + return classTokens.indexOf(classValue) >= 0; + } + + function addClass(yuiNode, newClass) { + var domNode = yuiNode.getDOMNode(); + var classValue = domNode.getAttribute('class'); + domNode.setAttribute('class', classValue + ' ' + newClass); } - while((el = el.parentNode)) { - if((el.nodeType === 1) && (window.getComputedStyle(el).display === 'none')) { - visible = false; + + function removeClass(yuiNode, removeValue) { + var domNode = yuiNode.getDOMNode(); + var classTokens = domNode.getAttribute('class').split(' '); + var newClassValue = ''; + for (var i = 0; i < classTokens.length; i++) { + if (classTokens[i] !== removeValue) { + newClassValue = newClassValue + classTokens[i] + ' '; + } } + domNode.setAttribute('class', newClassValue); + } + + function svgStyles(element, styles) { + Object.keys(styles).forEach(function (style) { + element.style[style] = styles[style]; + }); + return element; + } + + function svg(element, attrs, styles) { + return svgStyles(svgAttrs( + svgElement(element), attrs || {}), styles || {}); } - // local bounding box in local coordinates - if (visible) { - return element.getBBox(); - } else { - return {x:0, y:0, width:0, height:0}; - } - } - - /** - * Return the bounding box of element as seen from the coordinate system given by matrix. If matrix is not - * given, the local coordinate system of element is assumed. - */ - - function boundingBox(element, matrix) { - - // macro to create an SVGPoint object - function createPoint (x, y) { - var point = element.viewportElement.createSVGPoint(); - point.x = x; - point.y = y; - return point; - } - - // macro to create an SVGRect object - function createRect (x, y, width, height) { - var rect = element.viewportElement.createSVGRect(); - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - return rect; - } - - var box = localBoundingBox(element); - - if (typeof matrix === 'undefined') { - return box; - } - - var inv = matrix.inverse(); - - inv = inv.multiply(element.getCTM()); - - // create an array of SVGPoints for each corner - // of the bounding box and update their location - // with the transform matrix - var corners = []; - var point = createPoint(box.x, box.y); - corners.push(point.matrixTransform(inv) ); - point.x = box.x + box.width; - point.y = box.y; - corners.push( point.matrixTransform(inv) ); - point.x = box.x + box.width; - point.y = box.y + box.height; - corners.push( point.matrixTransform(inv) ); - point.x = box.x; - point.y = box.y + box.height; - corners.push( point.matrixTransform(inv) ); - var max = createPoint(corners[0].x, corners[0].y); - var min = createPoint(corners[0].x, corners[0].y); - - // identify the new corner coordinates of the - // fully transformed bounding box - for (var i = 1; i < corners.length; i++) { - var x = corners[i].x; - var y = corners[i].y; - if (x < min.x) { - min.x = x; - } - else if (x > max.x) { - max.x = x; - } - if (y < min.y) { - min.y = y; - } - else if (y > max.y) { - max.y = y; - } - } - - // return the bounding box as an SVGRect object - return createRect(min.x, min.y, max.x - min.x, max.y - min.y); - } - var containingRect = function (rect1, rect2) { - var x = Math.min(rect1.x, rect2.x); - var y = Math.min(rect1.y, rect2.y); - var width = Math.max(rect1.x + rect1.width, rect2.x + rect2.width) - x; - var height = Math.max(rect1.y + rect1.height, rect2.y + rect2.height) - y; - return {x: x, y: y, width: width, height: height}; - }; - - - var fitTo = function (element, target) { - - function fitToUnitSquare(element, targetBBox) { - var bbox = element.getBBox(); - - // hack: make all lines the same height - bbox.height = targetBBox.height * .15; - bbox.y = -bbox.height; - - var translate1 = element.ownerSVGElement.createSVGTransform(); - var scale1 = element.ownerSVGElement.createSVGTransform(); - var translate2 = element.ownerSVGElement.createSVGTransform(); - var scale2 = element.ownerSVGElement.createSVGTransform(); - - translate2.setTranslate(targetBBox.x, targetBBox.y); - //scale2.setScale(targetBBox.width, targetBBox.height); - scale1.setScale(targetBBox.width / bbox.width, targetBBox.height / bbox.height); - translate1.setTranslate(-bbox.x, -bbox.y); - - element.transform.baseVal.appendItem(translate2); - //element.transform.baseVal.appendItem(scale2); - - element.transform.baseVal.appendItem(scale1); - element.transform.baseVal.appendItem(translate1); - element.transform.baseVal.consolidate(); - } - - // account for the different transforms of the objects - var matrix = target.getTransformToElement(element); - element.transform.baseVal.consolidate(); - var transform = element.transform.baseVal.createSVGTransformFromMatrix(matrix); - element.transform.baseVal.appendItem(transform); - element.transform.baseVal.consolidate(); - - // account for the different local sizes of the objects - var targetBBox = target.getBBox(); - fitToUnitSquare(element, targetBBox); - //Y.SvgUtils.drawBBox(element); - - }; - - var drawBBox = function (element) { - var bbox = element.getBBox(); - var rect = SvgUtils.svgElement('rect'); - rect.setAttribute('x', bbox.x); - rect.setAttribute('y', bbox.y); - rect.setAttribute('width', bbox.width); - rect.setAttribute('height', bbox.height); - rect.setAttribute('stroke', 'gray'); - rect.setAttribute('fill', 'none'); - rect.setAttribute('transform', element.getAttribute('transform')); - element.parentElement.appendChild(rect); - return rect; - }; - - - SvgUtils.SVG_NS = SVG_NS; - SvgUtils.decodeClassValue = decodeClassValue; - SvgUtils.boundingBox = boundingBox; - SvgUtils.qscale = qscale; - SvgUtils.svgElement = svgElement; - SvgUtils.svgAttrs = svgAttrs; - SvgUtils.hasClass = hasClass; - SvgUtils.addClass = addClass; - SvgUtils.removeClass = removeClass; - SvgUtils.svgStyles = svgStyles; - SvgUtils.svg = svg; - SvgUtils.empty = empty; - SvgUtils.getScreenBBox = getScreenBBox; - SvgUtils.containingRect = containingRect; - SvgUtils.fitTo = fitTo; - SvgUtils.drawBBox = drawBBox; + function empty(element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + } + + // An implementation of getScreenBBox, by Antoine Quint, modiefied by Moritz Wissenbach + // http://the.fuchsia-design.com/2006/12/getting-svg-elementss-full-bounding-box.html + function getScreenBBox(element, svgRoot) { + + // macro to create an SVGPoint object + function createPoint(x, y) { + var point = svgRoot.createSVGPoint(); + point.x = x; + point.y = y; + return point; + } + + // macro to create an SVGRect object + function createRect(x, y, width, height) { + var rect = svgRoot.createSVGRect(); + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + return rect; + } + + // get the complete transformation matrix + //var matrix = element.getTransformToElement(svgRoot); + var matrix = svgRoot.getTransformToElement(element); + // get the bounding box of the target element + var box = element.getBBox(); + + // create an array of SVGPoints for each corner + // of the bounding box and update their location + // with the transform matrix + var corners = []; + var point = createPoint(box.x, box.y); + corners.push(point.matrixTransform(matrix)); + point.x = box.x + box.width; + point.y = box.y; + corners.push(point.matrixTransform(matrix)); + point.x = box.x + box.width; + point.y = box.y + box.height; + corners.push(point.matrixTransform(matrix)); + point.x = box.x; + point.y = box.y + box.height; + corners.push(point.matrixTransform(matrix)); + var max = createPoint(corners[0].x, corners[0].y); + var min = createPoint(corners[0].x, corners[0].y); + + // identify the new corner coordinates of the + // fully transformed bounding box + for (var i = 1; i < corners.length; i++) { + var x = corners[i].x; + var y = corners[i].y; + if (x < min.x) { + min.x = x; + } + else if (x > max.x) { + max.x = x; + } + if (y < min.y) { + min.y = y; + } + else if (y > max.y) { + max.y = y; + } + } + + // return the bounding box as an SVGRect object + return createRect(min.x, min.y, max.x - min.x, max.y - min.y); + } + + + /** + * Safely get and return the bounding box of element as seen from its local coordinate system. + */ + + function localBoundingBox(element) { + + // Firefox will throw an exception when calling getBBox() on an element with display: none + // see https://bugzilla.mozilla.org/show_bug.cgi?id=612118 + + var visible = true; + var el = element; + if (window.getComputedStyle(el).display === 'none') { + visible = false; + } + while ((el = el.parentNode)) { + if ((el.nodeType === 1) && (window.getComputedStyle(el).display === 'none')) { + visible = false; + } + } + + // local bounding box in local coordinates + if (visible) { + return element.getBBox(); + } else { + return {x: 0, y: 0, width: 0, height: 0}; + } + } + + /** + * Return the bounding box of element as seen from the coordinate system given by matrix. If matrix is not + * given, the local coordinate system of element is assumed. + */ + + function boundingBox(element, matrix) { + + // macro to create an SVGPoint object + function createPoint(x, y) { + var point = element.viewportElement.createSVGPoint(); + point.x = x; + point.y = y; + return point; + } + + // macro to create an SVGRect object + function createRect(x, y, width, height) { + var rect = element.viewportElement.createSVGRect(); + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + return rect; + } + + var box = localBoundingBox(element); + + if (typeof matrix === 'undefined') { + return box; + } + + var inv = matrix.inverse(); + + inv = inv.multiply(element.getCTM()); + + // create an array of SVGPoints for each corner + // of the bounding box and update their location + // with the transform matrix + var corners = []; + var point = createPoint(box.x, box.y); + corners.push(point.matrixTransform(inv)); + point.x = box.x + box.width; + point.y = box.y; + corners.push(point.matrixTransform(inv)); + point.x = box.x + box.width; + point.y = box.y + box.height; + corners.push(point.matrixTransform(inv)); + point.x = box.x; + point.y = box.y + box.height; + corners.push(point.matrixTransform(inv)); + var max = createPoint(corners[0].x, corners[0].y); + var min = createPoint(corners[0].x, corners[0].y); + + // identify the new corner coordinates of the + // fully transformed bounding box + for (var i = 1; i < corners.length; i++) { + var x = corners[i].x; + var y = corners[i].y; + if (x < min.x) { + min.x = x; + } + else if (x > max.x) { + max.x = x; + } + if (y < min.y) { + min.y = y; + } + else if (y > max.y) { + max.y = y; + } + } + + // return the bounding box as an SVGRect object + return createRect(min.x, min.y, max.x - min.x, max.y - min.y); + } + + var containingRect = function (rect1, rect2) { + var x = Math.min(rect1.x, rect2.x); + var y = Math.min(rect1.y, rect2.y); + var width = Math.max(rect1.x + rect1.width, rect2.x + rect2.width) - x; + var height = Math.max(rect1.y + rect1.height, rect2.y + rect2.height) - y; + return {x: x, y: y, width: width, height: height}; + }; + + + var fitTo = function (element, target) { + + function fitToUnitSquare(element, targetBBox) { + var bbox = element.getBBox(); + + // hack: make all lines the same height + bbox.height = targetBBox.height * .15; + bbox.y = -bbox.height; + + var translate1 = element.ownerSVGElement.createSVGTransform(); + var scale1 = element.ownerSVGElement.createSVGTransform(); + var translate2 = element.ownerSVGElement.createSVGTransform(); + var scale2 = element.ownerSVGElement.createSVGTransform(); + + translate2.setTranslate(targetBBox.x, targetBBox.y); + //scale2.setScale(targetBBox.width, targetBBox.height); + scale1.setScale(targetBBox.width / bbox.width, targetBBox.height / bbox.height); + translate1.setTranslate(-bbox.x, -bbox.y); + + element.transform.baseVal.appendItem(translate2); + //element.transform.baseVal.appendItem(scale2); + + element.transform.baseVal.appendItem(scale1); + element.transform.baseVal.appendItem(translate1); + element.transform.baseVal.consolidate(); + } + + // account for the different transforms of the objects + var matrix = target.getTransformToElement(element); + element.transform.baseVal.consolidate(); + var transform = element.transform.baseVal.createSVGTransformFromMatrix(matrix); + element.transform.baseVal.appendItem(transform); + element.transform.baseVal.consolidate(); + + // account for the different local sizes of the objects + var targetBBox = target.getBBox(); + fitToUnitSquare(element, targetBBox); + //Y.SvgUtils.drawBBox(element); + + }; + + var drawBBox = function (element) { + var bbox = element.getBBox(); + var rect = SvgUtils.svgElement('rect'); + rect.setAttribute('x', bbox.x); + rect.setAttribute('y', bbox.y); + rect.setAttribute('width', bbox.width); + rect.setAttribute('height', bbox.height); + rect.setAttribute('stroke', 'gray'); + rect.setAttribute('fill', 'none'); + rect.setAttribute('transform', element.getAttribute('transform')); + element.parentElement.appendChild(rect); + return rect; + }; + + + SvgUtils.SVG_NS = SVG_NS; + SvgUtils.decodeClassValue = decodeClassValue; + SvgUtils.boundingBox = boundingBox; + SvgUtils.qscale = qscale; + SvgUtils.svgElement = svgElement; + SvgUtils.svgAttrs = svgAttrs; + SvgUtils.hasClass = hasClass; + SvgUtils.addClass = addClass; + SvgUtils.removeClass = removeClass; + SvgUtils.svgStyles = svgStyles; + SvgUtils.svg = svg; + SvgUtils.empty = empty; + SvgUtils.getScreenBBox = getScreenBBox; + SvgUtils.containingRect = containingRect; + SvgUtils.fitTo = fitTo; + SvgUtils.drawBBox = drawBBox; })(SvgUtils); diff --git a/svg_rendering/page/js-gen/text-annotation.js b/svg_rendering/page/js-gen/text-annotation.js index ce1e101..ca39213 100644 --- a/svg_rendering/page/js-gen/text-annotation.js +++ b/svg_rendering/page/js-gen/text-annotation.js @@ -17,265 +17,265 @@ * along with this program. If not, see . */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust) { +(function (Faust) { - var Range = function (start, end) { - this.start = start; - this.end = end; - }; - var Name = function (namespace, localName) { - this.namespace = namespace; - this.localName = localName; - }; - var Text = function (id, type, contentLength, range, content) { - this.id = id; - this.type = type; - this.contentLength = contentLength; - this.range = range || new Range(0, contentLength); - this.content = content || ""; - }; - var TextTarget = function (text, range) { - this.text = text; - this.range = range; - }; + var Range = function (start, end) { + this.start = start; + this.end = end; + }; + var Name = function (namespace, localName) { + this.namespace = namespace; + this.localName = localName; + }; + var Text = function (id, type, contentLength, range, content) { + this.id = id; + this.type = type; + this.contentLength = contentLength; + this.range = range || new Range(0, contentLength); + this.content = content || ""; + }; + var TextTarget = function (text, range) { + this.text = text; + this.range = range; + }; - var UNKNOWN_NAME = new Name(null, ""); - var Annotation = function (name, data, targets, id) { - this.name = name || UNKNOWN_NAME; - this.data = data || {}; - this.targets = targets || []; - this.id = (id !== undefined) ? id : NaN; - }; - Y.extend(Annotation, Object, { - target: function () { - return (this.targets ? this.targets[0] : null); - }, - targetIn: function (text) { - return Y.Array.find(this.targets, function (t) { - return (t.text === text); - }); - } - }); + var UNKNOWN_NAME = new Name(null, ""); + var Annotation = function (name, data, targets, id) { + this.name = name || UNKNOWN_NAME; + this.data = data || {}; + this.targets = targets || []; + this.id = (id !== undefined) ? id : NaN; + }; + Y.extend(Annotation, Object, { + target: function () { + return (this.targets ? this.targets[0] : null); + }, + targetIn: function (text) { + return Y.Array.find(this.targets, function (t) { + return (t.text === text); + }); + } + }); - Y.extend(TextTarget, Object, { - textContent: function () { - return this.range.of(this.text.content); - } - }); - + Y.extend(TextTarget, Object, { + textContent: function () { + return this.range.of(this.text.content); + } + }); - Y.extend(Text, Object, { - partition: function (annotations, start, end) { - var partitioningAnnotations = annotations ? annotations : this.annotations; - var partitionsStart = start ? start : 0; - var partitionsEnd = end ? end : this.content.length; - var offsets = [partitionsStart, partitionsEnd]; - partitioningAnnotations.forEach(function (a) { - a.targets.forEach(function (t) { - if (t.text == this) { - var range = t.range; - if(range.start > partitionsStart && range.start < partitionsEnd) { - offsets.push(range.start); - } - if(range.end > partitionsStart && range.end < partitionsEnd) { - offsets.push(range.end); - } - } - }, this); - }, this); + Y.extend(Text, Object, { + partition: function (annotations, start, end) { + var partitioningAnnotations = annotations ? annotations : this.annotations; + var partitionsStart = start ? start : 0; + var partitionsEnd = end ? end : this.content.length; + var offsets = [partitionsStart, partitionsEnd]; - offsets = Y.Array.dedupe(offsets); - offsets.sort(function (a, b) { - return a - b; - }); + partitioningAnnotations.forEach(function (a) { + a.targets.forEach(function (t) { + if (t.text == this) { + var range = t.range; + if (range.start > partitionsStart && range.start < partitionsEnd) { + offsets.push(range.start); + } + if (range.end > partitionsStart && range.end < partitionsEnd) { + offsets.push(range.end); + } + } + }, this); + }, this); - //if (offsets.length == 0 || offsets[0] > this.range.start) offsets.unshift(this.range.start); - //if (offsets.length == 1 || offsets[offsets.length - 1] < this.range.end) offsets.push(this.range.end); + offsets = Y.Array.dedupe(offsets); + offsets.sort(function (a, b) { + return a - b; + }); - var partitions = []; - var rangeStart = -1; - offsets.forEach(function (rangeEnd) { - if (rangeStart >= 0) { - partitions.push(new Range(rangeStart, rangeEnd)); - } - rangeStart = rangeEnd; - }); + //if (offsets.length == 0 || offsets[0] > this.range.start) offsets.unshift(this.range.start); + //if (offsets.length == 1 || offsets[offsets.length - 1] < this.range.end) offsets.push(this.range.end); - - return partitions; - }, + var partitions = []; + var rangeStart = -1; + offsets.forEach(function (rangeEnd) { + if (rangeStart >= 0) { + partitions.push(new Range(rangeStart, rangeEnd)); + } + rangeStart = rangeEnd; + }); - /** - * Find all annotations applying (partly) to [start, end] optionally filtered by filter. - * @param start Integer - * @param end Integer - * @param filter Annotation filter. - * If String, this is matched against the annotations local name, - * if [String], this must contain the annotations local name, - * if function(Annotation) this is used as predicate. - */ - find: function (start, end, filter) { - var result = [], - nameFilter = null, - range = new Range( - ((typeof start === 'number' && isFinite(start)) ? start : 0), - ((typeof end === 'number' && isFinite(end)) ? end : this.contentLength) - ); - if (typeof filter === 'function') { - nameFilter = filter; - } else if (Array.isArray(filter)) { - nameFilter = function (a) { - return (filter.indexOf(a.name.localName) >= 0); - }; - } else if (typeof filter === 'string') { - nameFilter = function (a) { - return filter == a.name.localName; - }; - } else { - nameFilter = function () { - return true; - }; - } + return partitions; + }, - this._searchRange(this.rangeIndex._root, range, nameFilter, result); - return result; - }, - _searchRange: function (node, range, annotationFilter, result) { - // Don't search nodes that don't exist - if (node === null) { - return; - } + /** + * Find all annotations applying (partly) to [start, end] optionally filtered by filter. + * @param start Integer + * @param end Integer + * @param filter Annotation filter. + * If String, this is matched against the annotations local name, + * if [String], this must contain the annotations local name, + * if function(Annotation) this is used as predicate. + */ + find: function (start, end, filter) { + var result = [], + nameFilter = null, + range = new Range( + ((typeof start === 'number' && isFinite(start)) ? start : 0), + ((typeof end === 'number' && isFinite(end)) ? end : this.contentLength) + ); - // If range is to the right of the rightmost point of any interval - // in this node and all children, there won't be any matches. - if (range.start > node.maxEnd) { - return; - } + if (typeof filter === 'function') { + nameFilter = filter; + } else if (Array.isArray(filter)) { + nameFilter = function (a) { + return (filter.indexOf(a.name.localName) >= 0); + }; + } else if (typeof filter === 'string') { + nameFilter = function (a) { + return filter == a.name.localName; + }; + } else { + nameFilter = function () { + return true; + }; + } - // Search left children - if (node.left !== null) { - this._searchRange(node.left, range, annotationFilter, result); - } + this._searchRange(this.rangeIndex._root, range, nameFilter, result); + return result; + }, + _searchRange: function (node, range, annotationFilter, result) { + // Don't search nodes that don't exist + if (node === null) { + return; + } + + // If range is to the right of the rightmost point of any interval + // in this node and all children, there won't be any matches. + if (range.start > node.maxEnd) { + return; + } + + // Search left children + if (node.left !== null) { + this._searchRange(node.left, range, annotationFilter, result); + } - // Check this node - if (node.key.overlapsWith(range) || range.includes(node.key)) { - node.values.filter(annotationFilter).forEach(function (v) { - result.push(v); - }); - } + // Check this node + if (node.key.overlapsWith(range) || range.includes(node.key)) { + node.values.filter(annotationFilter).forEach(function (v) { + result.push(v); + }); + } - // If range is to the left of the start of this interval, - // then it can't be in any child to the right. - if (range.end < node.key.start) { - return; - } + // If range is to the left of the start of this interval, + // then it can't be in any child to the right. + if (range.end < node.key.start) { + return; + } - // Otherwise, search right children - if (node.right !== null) { - this._searchRange(node.right, range, annotationFilter, result); - } - }, - _setupRangeIndexNode: function (node) { - if (node === null) { - return 0; - } else { - node.maxEnd = Math.max(node.key.end, this._setupRangeIndexNode(node.left), this._setupRangeIndexNode(node.right)); - return node.maxEnd; - } - } - }, { - create: function (data) { - var text = new Text(data.text.id, data.text.t, data.text.l, data.textRange, data.textContent), names = {}; - Object.keys(data.names).forEach(function(name) { - names[name] = new Name(data.names[name][0], data.names[name][1]); - }); - text.rangeIndex = new Faust.RBTree(Range.sort, function (a) { - return a.targetIn(text).range; - }); - text.localNameIndex = {}; - text.annotations = data.annotations.map(function (a) { - var annotation = new Annotation(names[a.n], a.d, a.t.map(function (target) { - return new TextTarget((target[2] == text.id ? text : target[2]), new Range(target[0], target[1])); - }), a.id); + // Otherwise, search right children + if (node.right !== null) { + this._searchRange(node.right, range, annotationFilter, result); + } + }, + _setupRangeIndexNode: function (node) { + if (node === null) { + return 0; + } else { + node.maxEnd = Math.max(node.key.end, this._setupRangeIndexNode(node.left), this._setupRangeIndexNode(node.right)); + return node.maxEnd; + } + } + }, { + create: function (data) { + var text = new Text(data.text.id, data.text.t, data.text.l, data.textRange, data.textContent), names = {}; + Object.keys(data.names).forEach(function (name) { + names[name] = new Name(data.names[name][0], data.names[name][1]); + }); + text.rangeIndex = new Faust.RBTree(Range.sort, function (a) { + return a.targetIn(text).range; + }); + text.localNameIndex = {}; + text.annotations = data.annotations.map(function (a) { + var annotation = new Annotation(names[a.n], a.d, a.t.map(function (target) { + return new TextTarget((target[2] == text.id ? text : target[2]), new Range(target[0], target[1])); + }), a.id); - text.rangeIndex.insert(annotation); + text.rangeIndex.insert(annotation); - var ln = annotation.name.localName; - text.localNameIndex[ln] = (text.localNameIndex[ln] || []).concat(annotation); + var ln = annotation.name.localName; + text.localNameIndex[ln] = (text.localNameIndex[ln] || []).concat(annotation); - return annotation; - }); - text._setupRangeIndexNode(text.rangeIndex._root); + return annotation; + }); + text._setupRangeIndexNode(text.rangeIndex._root); - return text; - } - }); - Y.extend(Name, Object, { - toString: function () { - return (this.namespace == null ? "" : "{" + this.namespace + "}") + this.localName; - }, - fromString: function (str) { - var firstBrace = str.indexOf("{"); - if (firstBrace < 0) { - return new NS.Name(null, str); - } - var secondBrace = str.indexOf("}"); - if (secondBrace < firstBrace || secondBrace >= (str.length - 1)) { - //Y.error("Invalid Name", str, { throwFail: true }); - } + return text; + } + }); + Y.extend(Name, Object, { + toString: function () { + return (this.namespace == null ? "" : "{" + this.namespace + "}") + this.localName; + }, + fromString: function (str) { + var firstBrace = str.indexOf("{"); + if (firstBrace < 0) { + return new NS.Name(null, str); + } + var secondBrace = str.indexOf("}"); + if (secondBrace < firstBrace || secondBrace >= (str.length - 1)) { + //Y.error("Invalid Name", str, { throwFail: true }); + } - return new NS.Name(str.substring(firstBrace + 1, secondBrace), str.substring(secondBrace + 1)) - } - }); - Y.extend(Range, Object, { - length: function () { - return (this.end - this.start); - }, - precedes: function (other) { - return (this.end <= other.start); - }, - overlapsWith: function (other) { - return ((this.start < other.end) && (this.end > other.start)); - }, - includes: function (other) { - return (this.start <= other.start && this.end >= other.end); - }, - of: function (text) { - return text.substring(this.start, this.end); - }, - equalsStartOf: function (other) { - return (this.start == other.start) && (this.end == other.start); - }, - amountOfOverlapWith: function (other) { - return (Math.min(this.end, other.end) - Math.max(this.start, other.start)); - }, - fromId: function (str) { - var components = str.replace("r", "").split("-"); - return new Range(parseInt(components[0]), parseInt(components[1])); - }, - toId: function () { - return "r" + this.start.toString() + "-" + this.end.toString(); - }, - toString: function () { - return "[" + this.start + ", " + this.end + "]"; - } - }, { - sort: function (ra, rb) { - return (ra.start == rb.start ? (rb.end - ra.end) : (ra.start - rb.start)); - } - }); + return new NS.Name(str.substring(firstBrace + 1, secondBrace), str.substring(secondBrace + 1)) + } + }); + Y.extend(Range, Object, { + length: function () { + return (this.end - this.start); + }, + precedes: function (other) { + return (this.end <= other.start); + }, + overlapsWith: function (other) { + return ((this.start < other.end) && (this.end > other.start)); + }, + includes: function (other) { + return (this.start <= other.start && this.end >= other.end); + }, + of: function (text) { + return text.substring(this.start, this.end); + }, + equalsStartOf: function (other) { + return (this.start == other.start) && (this.end == other.start); + }, + amountOfOverlapWith: function (other) { + return (Math.min(this.end, other.end) - Math.max(this.start, other.start)); + }, + fromId: function (str) { + var components = str.replace("r", "").split("-"); + return new Range(parseInt(components[0]), parseInt(components[1])); + }, + toId: function () { + return "r" + this.start.toString() + "-" + this.end.toString(); + }, + toString: function () { + return "[" + this.start + ", " + this.end + "]"; + } + }, { + sort: function (ra, rb) { + return (ra.start == rb.start ? (rb.end - ra.end) : (ra.start - rb.start)); + } + }); - Faust.Text = Text; - Faust.Name = Name; - Faust.Range = Range; - Faust.TextTarget = TextTarget; - Faust.Annotation = Annotation; + Faust.Text = Text; + Faust.Name = Name; + Faust.Range = Range; + Faust.TextTarget = TextTarget; + Faust.Annotation = Annotation; })(Faust); diff --git a/svg_rendering/page/js-gen/text-index.js b/svg_rendering/page/js-gen/text-index.js index a77423c..ccfa18e 100644 --- a/svg_rendering/page/js-gen/text-index.js +++ b/svg_rendering/page/js-gen/text-index.js @@ -17,377 +17,379 @@ * along with this program. If not, see . */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust) { - - var Iterator = function (tree) { - this._tree = tree; - this._cursor = null; - }; - Y.extend(Iterator, Object, { - data: function () { - return this._cursor; - }, - // if null-iterator, returns first node - // otherwise, returns next node - next: function () { - if (this._cursor === null) { - var root = this._tree._root; - if (root !== null) { - this._minNode(root); - } - } else { - if (this._cursor.right === null) { - // no greater node in subtree, go up to parent - // if coming from a right child, continue up the stack - var save; - do { - save = this._cursor; - this._cursor = this._cursor.parent; - if (this._cursor === null) { - break; - } - } while (this._cursor.right === save); - } else { - // get the next node from the subtree - this._minNode(this._cursor.right); - } - } - return this._cursor; - }, - // if null-iterator, returns last node - // otherwise, returns previous node - prev: function () { - if (this._cursor === null) { - var root = this._tree._root; - if (root !== null) { - this._maxNode(root); - } - } - else { - if (this._cursor.left === null) { - var save; - do { - save = this._cursor; - this._cursor = this._cursor.parent; - if (this._cursor === null) { - break; - } - } while (this._cursor.left === save); - } else { - this._maxNode(this._cursor.left); - } - } - return this._cursor; - }, - _minNode: function (start) { - while (start.left !== null) { - start = start.left; - } - this._cursor = start; - }, - _maxNode: function (start) { - while (start.right !== null) { - start = start.right; - } - this._cursor = start; - } - }); - - var TreeBase = function () { - }; - Y.extend(TreeBase, Object, { - // removes all nodes from the tree - clear: function () { - this._root = null; - this.size = 0; - }, - // returns node if found, null otherwise - find: function (key) { - var res = this._root; - - while (res !== null) { - var c = this._comparator(key, res.key); - if (c === 0) { - return res; - } else { - res = res.get_child(c > 0); - } - } - - return null; - }, - // returns null if tree is empty - min: function () { - var res = this._root; - if (res === null) { - return null; - } - - while (res.left !== null) { - res = res.left; - } - - return res; - }, - // returns null if tree is empty - max: function () { - var res = this._root; - if (res === null) { - return null; - } - - while (res.right !== null) { - res = res.right; - } - - return res; - }, - // returns a null iterator, call next() or prev() to point to an element - iterator: function () { - return new Iterator(this); - }, - // calls cb on each node, in order - each: function (cb) { - var it = this.iterator(), node; - while ((node = it.next()) !== null) { - cb(node); - } - }, - // calls cb on each node, in reverse order - reach: function (cb) { - var it = this.iterator(), node; - while ((node = it.prev()) !== null) { - cb(node); - } - } - }); - - var Node = function (key) { - this.key = key; - this.values = []; - this.parent = null; - this.left = null; - this.right = null; - this.red = true; - }; - Y.extend(Node, Object, { - get_child: function (dir) { - return dir ? this.right : this.left; - }, - set_child: function (dir, val) { - if (dir) { - this.right = val; - } else { - this.left = val; - } - if (val !== null) { - val.parent = this; - } - } - }); - - function is_red(node) { - return node !== null && node.red; - } - - function single_rotate(root, dir) { - var save = root.get_child(!dir); - - root.set_child(!dir, save.get_child(dir)); - save.set_child(dir, root); - - root.red = true; - save.red = false; - - return save; - } - - function double_rotate(root, dir) { - root.set_child(!dir, single_rotate(root.get_child(!dir), !dir)); - return single_rotate(root, dir); - } - - var RBTree = function (comparator, keyFunction) { - this._root = null; - this._comparator = comparator; - this._keyFunction = keyFunction || function(d) { return d; }; - this.size = 0; - }; - Y.extend(RBTree, TreeBase, { - // returns true if inserted, false if duplicate - insert: function (data) { - var key = this._keyFunction(data); - var ret = false; - - if (this._root === null) { - // empty tree - this._root = new Node(key); - this._root.values.push(data); - ret = true; - this.size++; - } else { - var head = new Node(undefined); // fake tree root - - var dir = 0; - var last = 0; - - // setup - var gp = null; // grandparent - var ggp = head; // grand-grand-parent - var p = null; // parent - var node = this._root; - ggp.right = this._root; - - // search down - while (true) { - if (node === null) { - // insert new node at the bottom - node = new Node(key); - p.set_child(dir, node); - ret = true; - this.size++; - } else if (is_red(node.left) && is_red(node.right)) { - // color flip - node.red = true; - node.left.red = false; - node.right.red = false; - } - - // fix red violation - if (is_red(node) && is_red(p)) { - var dir2 = ggp.right === gp; - - if (node === p.get_child(last)) { - ggp.set_child(dir2, single_rotate(gp, !last)); - } - else { - ggp.set_child(dir2, double_rotate(gp, !last)); - } - } - - var cmp = this._comparator(node.key, key); - - // stop if found - if (cmp === 0) { - node.values.push(data); - break; - } - - last = dir; - dir = cmp < 0; - - // update helpers - if (gp !== null) { - ggp = gp; - } - gp = p; - p = node; - node = node.get_child(dir); - } - - // update root - this._root = head.right; - } - - // make root black - this._root.red = false; - - return ret; - }, - // returns true if removed, false if not found - remove: function (data) { - if (this._root === null) { - return false; - } - - var key = this._keyFunction(data); - var head = new Node(undefined); // fake tree root - var node = head; - node.right = this._root; - var p = null; // parent - var gp = null; // grand parent - var found = null; // found item - var dir = 1; - - while (node.get_child(dir) !== null) { - var last = dir; - - // update helpers - gp = p; - p = node; - node = node.get_child(dir); - - var cmp = this._comparator(key, node.key); - - dir = cmp > 0; - - // save found node - if (cmp === 0) { - var valIndex = node.values.indexOf(data), valFound = (valIndex >= 0); - if (valFound) { - node.values.splice(valIndex, 1); - } - if (node.values.length > 0) { - return valFound; - } - found = node; - } - - // push the red node down - if (!is_red(node) && !is_red(node.get_child(dir))) { - if (is_red(node.get_child(!dir))) { - var sr = single_rotate(node, dir); - p.set_child(last, sr); - p = sr; - } else if (!is_red(node.get_child(!dir))) { - var sibling = p.get_child(!last); - if (sibling !== null) { - if (!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) { - // color flip - p.red = false; - sibling.red = true; - node.red = true; - } else { - var dir2 = gp.right === p; - - if (is_red(sibling.get_child(last))) { - gp.set_child(dir2, double_rotate(p, last)); - } else if (is_red(sibling.get_child(!last))) { - gp.set_child(dir2, single_rotate(p, last)); - } - - // ensure correct coloring - var gpc = gp.get_child(dir2); - gpc.red = true; - node.red = true; - gpc.left.red = false; - gpc.right.red = false; - } - } - } - } - } - - // replace and remove if found - if (found !== null) { - p.set_child(p.right === node, node.get_child(node.left === null)); - this.size--; - } - - // update root and make it black - this._root = head.right; - if (this._root !== null) { - this._root.red = false; - } - - return found !== null; - } - }); - - Faust.RBTree = RBTree; +(function (Faust) { + + var Iterator = function (tree) { + this._tree = tree; + this._cursor = null; + }; + Y.extend(Iterator, Object, { + data: function () { + return this._cursor; + }, + // if null-iterator, returns first node + // otherwise, returns next node + next: function () { + if (this._cursor === null) { + var root = this._tree._root; + if (root !== null) { + this._minNode(root); + } + } else { + if (this._cursor.right === null) { + // no greater node in subtree, go up to parent + // if coming from a right child, continue up the stack + var save; + do { + save = this._cursor; + this._cursor = this._cursor.parent; + if (this._cursor === null) { + break; + } + } while (this._cursor.right === save); + } else { + // get the next node from the subtree + this._minNode(this._cursor.right); + } + } + return this._cursor; + }, + // if null-iterator, returns last node + // otherwise, returns previous node + prev: function () { + if (this._cursor === null) { + var root = this._tree._root; + if (root !== null) { + this._maxNode(root); + } + } + else { + if (this._cursor.left === null) { + var save; + do { + save = this._cursor; + this._cursor = this._cursor.parent; + if (this._cursor === null) { + break; + } + } while (this._cursor.left === save); + } else { + this._maxNode(this._cursor.left); + } + } + return this._cursor; + }, + _minNode: function (start) { + while (start.left !== null) { + start = start.left; + } + this._cursor = start; + }, + _maxNode: function (start) { + while (start.right !== null) { + start = start.right; + } + this._cursor = start; + } + }); + + var TreeBase = function () { + }; + Y.extend(TreeBase, Object, { + // removes all nodes from the tree + clear: function () { + this._root = null; + this.size = 0; + }, + // returns node if found, null otherwise + find: function (key) { + var res = this._root; + + while (res !== null) { + var c = this._comparator(key, res.key); + if (c === 0) { + return res; + } else { + res = res.get_child(c > 0); + } + } + + return null; + }, + // returns null if tree is empty + min: function () { + var res = this._root; + if (res === null) { + return null; + } + + while (res.left !== null) { + res = res.left; + } + + return res; + }, + // returns null if tree is empty + max: function () { + var res = this._root; + if (res === null) { + return null; + } + + while (res.right !== null) { + res = res.right; + } + + return res; + }, + // returns a null iterator, call next() or prev() to point to an element + iterator: function () { + return new Iterator(this); + }, + // calls cb on each node, in order + each: function (cb) { + var it = this.iterator(), node; + while ((node = it.next()) !== null) { + cb(node); + } + }, + // calls cb on each node, in reverse order + reach: function (cb) { + var it = this.iterator(), node; + while ((node = it.prev()) !== null) { + cb(node); + } + } + }); + + var Node = function (key) { + this.key = key; + this.values = []; + this.parent = null; + this.left = null; + this.right = null; + this.red = true; + }; + Y.extend(Node, Object, { + get_child: function (dir) { + return dir ? this.right : this.left; + }, + set_child: function (dir, val) { + if (dir) { + this.right = val; + } else { + this.left = val; + } + if (val !== null) { + val.parent = this; + } + } + }); + + function is_red(node) { + return node !== null && node.red; + } + + function single_rotate(root, dir) { + var save = root.get_child(!dir); + + root.set_child(!dir, save.get_child(dir)); + save.set_child(dir, root); + + root.red = true; + save.red = false; + + return save; + } + + function double_rotate(root, dir) { + root.set_child(!dir, single_rotate(root.get_child(!dir), !dir)); + return single_rotate(root, dir); + } + + var RBTree = function (comparator, keyFunction) { + this._root = null; + this._comparator = comparator; + this._keyFunction = keyFunction || function (d) { + return d; + }; + this.size = 0; + }; + Y.extend(RBTree, TreeBase, { + // returns true if inserted, false if duplicate + insert: function (data) { + var key = this._keyFunction(data); + var ret = false; + + if (this._root === null) { + // empty tree + this._root = new Node(key); + this._root.values.push(data); + ret = true; + this.size++; + } else { + var head = new Node(undefined); // fake tree root + + var dir = 0; + var last = 0; + + // setup + var gp = null; // grandparent + var ggp = head; // grand-grand-parent + var p = null; // parent + var node = this._root; + ggp.right = this._root; + + // search down + while (true) { + if (node === null) { + // insert new node at the bottom + node = new Node(key); + p.set_child(dir, node); + ret = true; + this.size++; + } else if (is_red(node.left) && is_red(node.right)) { + // color flip + node.red = true; + node.left.red = false; + node.right.red = false; + } + + // fix red violation + if (is_red(node) && is_red(p)) { + var dir2 = ggp.right === gp; + + if (node === p.get_child(last)) { + ggp.set_child(dir2, single_rotate(gp, !last)); + } + else { + ggp.set_child(dir2, double_rotate(gp, !last)); + } + } + + var cmp = this._comparator(node.key, key); + + // stop if found + if (cmp === 0) { + node.values.push(data); + break; + } + + last = dir; + dir = cmp < 0; + + // update helpers + if (gp !== null) { + ggp = gp; + } + gp = p; + p = node; + node = node.get_child(dir); + } + + // update root + this._root = head.right; + } + + // make root black + this._root.red = false; + + return ret; + }, + // returns true if removed, false if not found + remove: function (data) { + if (this._root === null) { + return false; + } + + var key = this._keyFunction(data); + var head = new Node(undefined); // fake tree root + var node = head; + node.right = this._root; + var p = null; // parent + var gp = null; // grand parent + var found = null; // found item + var dir = 1; + + while (node.get_child(dir) !== null) { + var last = dir; + + // update helpers + gp = p; + p = node; + node = node.get_child(dir); + + var cmp = this._comparator(key, node.key); + + dir = cmp > 0; + + // save found node + if (cmp === 0) { + var valIndex = node.values.indexOf(data), valFound = (valIndex >= 0); + if (valFound) { + node.values.splice(valIndex, 1); + } + if (node.values.length > 0) { + return valFound; + } + found = node; + } + + // push the red node down + if (!is_red(node) && !is_red(node.get_child(dir))) { + if (is_red(node.get_child(!dir))) { + var sr = single_rotate(node, dir); + p.set_child(last, sr); + p = sr; + } else if (!is_red(node.get_child(!dir))) { + var sibling = p.get_child(!last); + if (sibling !== null) { + if (!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) { + // color flip + p.red = false; + sibling.red = true; + node.red = true; + } else { + var dir2 = gp.right === p; + + if (is_red(sibling.get_child(last))) { + gp.set_child(dir2, double_rotate(p, last)); + } else if (is_red(sibling.get_child(!last))) { + gp.set_child(dir2, single_rotate(p, last)); + } + + // ensure correct coloring + var gpc = gp.get_child(dir2); + gpc.red = true; + node.red = true; + gpc.left.red = false; + gpc.right.red = false; + } + } + } + } + } + + // replace and remove if found + if (found !== null) { + p.set_child(p.right === node, node.get_child(node.left === null)); + this.size--; + } + + // update root and make it black + this._root = head.right; + if (this._root !== null) { + this._root.red = false; + } + + return found !== null; + } + }); + + Faust.RBTree = RBTree; })(Faust); diff --git a/svg_rendering/page/js-gen/transcript-adhoc-tree.js b/svg_rendering/page/js-gen/transcript-adhoc-tree.js index e12e418..dd02316 100644 --- a/svg_rendering/page/js-gen/transcript-adhoc-tree.js +++ b/svg_rendering/page/js-gen/transcript-adhoc-tree.js @@ -17,45 +17,48 @@ * along with this program. If not, see . */ -if(window.FaustTranscript === undefined) { - window.FaustTranscript = {}; +if (window.FaustTranscript === undefined) { + window.FaustTranscript = {}; } -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust){ - - var TranscriptLayout = { - // Text factory; the current model only delivers text nodes, some additional elements (gaps, insertion marks) need - // to be delivered to know their tree context (hands...) for visualisation - createText : function(content, start, end, text, layoutState){ - if (content.length < 1) { - throw "Cannot create empty text!"; - } - var textAttrs = {}; - var annotations = text.find(start, end) - //ignore empty annotations at the borders - .filter(function(x){var r = x.target().range; return r.start !== r.end; }); - - var textVC = new FaustTranscript.Text(content, textAttrs); - - // reset custom state of current text representation - if (typeof layoutState !== 'undefined') - layoutState.textState = {}; - annotations.forEach(function(annotation) { - if (annotation.name.localName in Faust.TranscriptConfiguration.names - && Faust.TranscriptConfiguration.names[annotation.name.localName].text) { - Faust.TranscriptConfiguration.names[annotation.name.localName].text(annotation, textVC, layoutState); - } - }); - - return textVC; - } - - }; - - Faust.TranscriptLayout = TranscriptLayout; +(function (Faust) { + + var TranscriptLayout = { + // Text factory; the current model only delivers text nodes, some additional elements (gaps, insertion marks) need + // to be delivered to know their tree context (hands...) for visualisation + createText: function (content, start, end, text, layoutState) { + if (content.length < 1) { + throw "Cannot create empty text!"; + } + var textAttrs = {}; + var annotations = text.find(start, end) + //ignore empty annotations at the borders + .filter(function (x) { + var r = x.target().range; + return r.start !== r.end; + }); + + var textVC = new FaustTranscript.Text(content, textAttrs); + + // reset custom state of current text representation + if (typeof layoutState !== 'undefined') + layoutState.textState = {}; + annotations.forEach(function (annotation) { + if (annotation.name.localName in Faust.TranscriptConfiguration.names + && Faust.TranscriptConfiguration.names[annotation.name.localName].text) { + Faust.TranscriptConfiguration.names[annotation.name.localName].text(annotation, textVC, layoutState); + } + }); + + return textVC; + } + + }; + + Faust.TranscriptLayout = TranscriptLayout; })(Faust); @@ -63,176 +66,196 @@ if(window.Faust === undefined) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -(function(FaustTranscript){ - - var TranscriptAdhocTree = function() { - this.mainZone = null; - this.idMap = {}; - this.postBuildDeferred = []; - }; - - Y.extend(TranscriptAdhocTree, Object, { - - buildVC: function(parent, node, text, layoutState) { - - if (node == null) { - return null; - } - - var vc = null; - - - var ancestorNames = node.ancestors().map(function(node){return node.annotation.name.localName}); - if ((node instanceof Faust.TextNode) && (parent != null) && (ancestorNames.indexOf('line') >= 0)) { - if (Faust.TranscriptConfiguration.stripWhitespace.indexOf(node.parent.name().localName) >= 0 && node.content().trim() == "") { - //only whitespace to be stripped, do not return a text representation - } else { - vc = Faust.TranscriptLayout.createText(node.content(), node.range.start, node.range.end, text, layoutState); - } - } else if (node instanceof Faust.AnnotationNode) { - - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - - //ioc: configurable modules handle the construction of the view - - // 'start' callback before the construction of any view components - - if (node.name().localName in Faust.TranscriptConfiguration.names) { - var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; - if (nameHandler.start) { - nameHandler.start.call(node, text, layoutState); - } - } - - if (node.name().localName in Faust.TranscriptConfiguration.names - && 'vc' in Faust.TranscriptConfiguration.names[node.name().localName]) { - var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; - if (nameHandler.vc) { - vc = nameHandler.vc(node, text, layoutState); - } else { - vc = new FaustTranscript.InlineViewComponent(); - } - } - - var aligningAttributes = ["f:at", "f:left", "f:left-right", "f:right", "f:right-left", "f:top", "f:top-bottom", "f:bottom", "f:bottom-top"]; - - var that = this; - - aligningAttributes.forEach(function(a){ - if (a in node.data()) { - if (!vc) { - vc = new FaustTranscript.InlineViewComponent(); - } - //FIXME id hash hack; do real resolution of references - var anchorId = node.data()[a].substring(1); - var coordRot = a in {"f:at":1, "f:left":1, "f:left-right":1, "f:right":1, "f:right-left":1}? 0 : 90; - var alignName = coordRot == 0 ? "hAlign" : "vAlign"; - var myJoint = a in {"f:left":1, "f:left-right":1, "f:top":1, "f:top-bottom":1}? 0 : 1; - var yourJoint = a in {"f:at":1, "f:left":1, "f:right-left":1, "f:top":1, "f:bottom-top":1}? 0 : 1; - - if ("f:orient" in node.data()) - myJoint = node.data()["f:orient"] == "left" ? 1 : 0; - - that.postBuildDeferred.push( - function(){ - var anchor = that.idMap[anchorId]; - if (!anchor) - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Reference to #" + anchorId + " cannot be resolved!"); - var globalCoordRot = coordRot + anchor.globalRotation(); - vc.setAlign(alignName, new FaustTranscript.Align(vc, anchor, globalCoordRot, myJoint, yourJoint, FaustTranscript.Align.EXPLICIT)); - }); - } - }); - - // TODO special treatment of zones - if ("rend" in node.data()) { - if (node.data()["rend"] == "right") { - vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 1, 1, FaustTranscript.Align.REND_ATTR)); - } else if (node.data()["rend"] == "left") { - vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 0, 0, FaustTranscript.Align.REND_ATTR)); - } else if (node.data()["rend"] == "centered") { - vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 0.5, 0.5, FaustTranscript.Align.REND_ATTR)); - } - - - } - } - - if (vc != null) { - - // annotate the vc with the original element name - vc.elementName = node.name ? node.name().localName : ""; - - if (parent != null ) { // && parent !== this) { - parent.add(vc); - vc.parent = parent; - } - parent = vc; - } - - if (node instanceof Faust.AnnotationNode) { - var xmlId = node.data()["xml:id"]; - if (xmlId) { - this.idMap[xmlId] = vc; - vc.xmlId = xmlId; - } - } - - var that = this; - - node.children().forEach(function(c) { that.buildVC(parent, c, text, layoutState); }); - - if (node instanceof Faust.AnnotationNode) { - - // space at the beginning of each line, to give empty lines height - if (node.name().localName == "line") { - var emptyProp = new FaustTranscript.Text("\u00a0", {noBackground: true}); - emptyProp.classes.push('noBackground'); - vc.add (emptyProp); - } - - // 'end' callback after all children are constructed - // with the vc for 'this' - - if (node.name().localName in Faust.TranscriptConfiguration.names) { - var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; - if (nameHandler.end) { - nameHandler.end.call(vc, node, text, layoutState); - } - } - } - return vc; - }, - - transcriptVC: function(jsonRepresentation) { - - var structuralNames = Object.keys(Faust.TranscriptConfiguration.names) - .filter(function(name){return 'vc' in Faust.TranscriptConfiguration.names[name]}); - - var text = Faust.Text.create(jsonRepresentation); - - var tree = new Faust.AdhocTree(text, structuralNames, - Faust.XMLNodeUtils.documentOrderSort, - Faust.XMLNodeUtils.isDescendant - ); - - var surfaceVC = new FaustTranscript.Surface(); - - - var layoutState = { - rootVC : surfaceVC - }; - - Faust.TranscriptConfiguration.initialize(layoutState); - this.buildVC(surfaceVC, tree, text, layoutState); - - this.postBuildDeferred.forEach(function(f) {f.apply(this);}); - - return surfaceVC; - } - }); - - FaustTranscript.TranscriptAdhocTree = TranscriptAdhocTree; +(function (FaustTranscript) { + + var TranscriptAdhocTree = function () { + this.mainZone = null; + this.idMap = {}; + this.postBuildDeferred = []; + }; + + Y.extend(TranscriptAdhocTree, Object, { + + buildVC: function (parent, node, text, layoutState) { + + if (node == null) { + return null; + } + + var vc = null; + + + var ancestorNames = node.ancestors().map(function (node) { + return node.annotation.name.localName + }); + if ((node instanceof Faust.TextNode) && (parent != null) && (ancestorNames.indexOf('line') >= 0)) { + if (Faust.TranscriptConfiguration.stripWhitespace.indexOf(node.parent.name().localName) >= 0 && node.content().trim() == "") { + //only whitespace to be stripped, do not return a text representation + } else { + vc = Faust.TranscriptLayout.createText(node.content(), node.range.start, node.range.end, text, layoutState); + } + } else if (node instanceof Faust.AnnotationNode) { + + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + + //ioc: configurable modules handle the construction of the view + + // 'start' callback before the construction of any view components + + if (node.name().localName in Faust.TranscriptConfiguration.names) { + var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; + if (nameHandler.start) { + nameHandler.start.call(node, text, layoutState); + } + } + + if (node.name().localName in Faust.TranscriptConfiguration.names + && 'vc' in Faust.TranscriptConfiguration.names[node.name().localName]) { + var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; + if (nameHandler.vc) { + vc = nameHandler.vc(node, text, layoutState); + } else { + vc = new FaustTranscript.InlineViewComponent(); + } + } + + var aligningAttributes = ["f:at", "f:left", "f:left-right", "f:right", "f:right-left", "f:top", "f:top-bottom", "f:bottom", "f:bottom-top"]; + + var that = this; + + aligningAttributes.forEach(function (a) { + if (a in node.data()) { + if (!vc) { + vc = new FaustTranscript.InlineViewComponent(); + } + //FIXME id hash hack; do real resolution of references + var anchorId = node.data()[a].substring(1); + var coordRot = a in { + "f:at": 1, + "f:left": 1, + "f:left-right": 1, + "f:right": 1, + "f:right-left": 1 + } ? 0 : 90; + var alignName = coordRot == 0 ? "hAlign" : "vAlign"; + var myJoint = a in {"f:left": 1, "f:left-right": 1, "f:top": 1, "f:top-bottom": 1} ? 0 : 1; + var yourJoint = a in { + "f:at": 1, + "f:left": 1, + "f:right-left": 1, + "f:top": 1, + "f:bottom-top": 1 + } ? 0 : 1; + + if ("f:orient" in node.data()) + myJoint = node.data()["f:orient"] == "left" ? 1 : 0; + + that.postBuildDeferred.push( + function () { + var anchor = that.idMap[anchorId]; + if (!anchor) + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Reference to #" + anchorId + " cannot be resolved!"); + var globalCoordRot = coordRot + anchor.globalRotation(); + vc.setAlign(alignName, new FaustTranscript.Align(vc, anchor, globalCoordRot, myJoint, yourJoint, FaustTranscript.Align.EXPLICIT)); + }); + } + }); + + // TODO special treatment of zones + if ("rend" in node.data()) { + if (node.data()["rend"] == "right") { + vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 1, 1, FaustTranscript.Align.REND_ATTR)); + } else if (node.data()["rend"] == "left") { + vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 0, 0, FaustTranscript.Align.REND_ATTR)); + } else if (node.data()["rend"] == "centered") { + vc.setAlign("hAlign", new FaustTranscript.Align(vc, parent, parent.globalRotation(), 0.5, 0.5, FaustTranscript.Align.REND_ATTR)); + } + + + } + } + + if (vc != null) { + + // annotate the vc with the original element name + vc.elementName = node.name ? node.name().localName : ""; + + if (parent != null) { // && parent !== this) { + parent.add(vc); + vc.parent = parent; + } + parent = vc; + } + + if (node instanceof Faust.AnnotationNode) { + var xmlId = node.data()["xml:id"]; + if (xmlId) { + this.idMap[xmlId] = vc; + vc.xmlId = xmlId; + } + } + + var that = this; + + node.children().forEach(function (c) { + that.buildVC(parent, c, text, layoutState); + }); + + if (node instanceof Faust.AnnotationNode) { + + // space at the beginning of each line, to give empty lines height + if (node.name().localName == "line") { + var emptyProp = new FaustTranscript.Text("\u00a0", {noBackground: true}); + emptyProp.classes.push('noBackground'); + vc.add(emptyProp); + } + + // 'end' callback after all children are constructed + // with the vc for 'this' + + if (node.name().localName in Faust.TranscriptConfiguration.names) { + var nameHandler = Faust.TranscriptConfiguration.names[node.name().localName]; + if (nameHandler.end) { + nameHandler.end.call(vc, node, text, layoutState); + } + } + } + return vc; + }, + + transcriptVC: function (jsonRepresentation) { + + var structuralNames = Object.keys(Faust.TranscriptConfiguration.names) + .filter(function (name) { + return 'vc' in Faust.TranscriptConfiguration.names[name] + }); + + var text = Faust.Text.create(jsonRepresentation); + + var tree = new Faust.AdhocTree(text, structuralNames, + Faust.XMLNodeUtils.documentOrderSort, + Faust.XMLNodeUtils.isDescendant + ); + + var surfaceVC = new FaustTranscript.Surface(); + + + var layoutState = { + rootVC: surfaceVC + }; + + Faust.TranscriptConfiguration.initialize(layoutState); + this.buildVC(surfaceVC, tree, text, layoutState); + + this.postBuildDeferred.forEach(function (f) { + f.apply(this); + }); + + return surfaceVC; + } + }); + + FaustTranscript.TranscriptAdhocTree = TranscriptAdhocTree; })(FaustTranscript); diff --git a/svg_rendering/page/js-gen/transcript-configuration-faust.js b/svg_rendering/page/js-gen/transcript-configuration-faust.js index ad58ca5..6534d5b 100644 --- a/svg_rendering/page/js-gen/transcript-configuration-faust.js +++ b/svg_rendering/page/js-gen/transcript-configuration-faust.js @@ -18,121 +18,139 @@ */ -if(window.Faust === undefined) { - window.Faust = {}; +if (window.Faust === undefined) { + window.Faust = {}; } -(function(Faust){ +(function (Faust) { + + function classesFromHandValue(hand) { + var tokens = hand.substring(1).split('_'); + + var writer = tokens[0]; + var material = tokens[1]; + var script = tokens[2]; + + var classes = []; + if (writer) { + classes.push("hand-" + writer); + } + if (material) { + classes.push("material-" + material); + } + if (script) { + classes.push("script-" + script); + } + return classes; + } - function classesFromHandValue(hand) { - var tokens = hand.substring(1).split('_'); + // A configuration defines how markup is rendered by providing handler + // functions in Y.Faust.TranscriptConfiguration. + + Faust.TranscriptConfiguration = { + // should overlapping stuff be rendered on top of each other? + // overlay : "overlay", + overlay: "none", + stripWhitespace: ['overw'], + // distance from top of one line to top of the following line + lineSpacingValue: "20", + lineSpacingUnit: "pt", + initialize: function (layoutState) { + layoutState.idMap = {}; + }, + forceFontLoading: false, + names: { + 'anchor': { + vc: function (node, text, layoutState) { + //use empty text element as an anchor + // FIXME make proper phrase/block context differentiation + if (node.parent.name().localName === "zone") { + return new FaustTranscript.Line([]); + } else { + return new FaustTranscript.Text("", {}); + } + } + }, - var writer = tokens[0]; - var material = tokens[1]; - var script = tokens[2]; + 'choice': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, - var classes = []; - if (writer) { - classes.push("hand-" + writer); - } - if (material) { - classes.push("material-" + material); - } - if (script) { - classes.push("script-" + script); - } - return classes; - } - - // A configuration defines how markup is rendered by providing handler - // functions in Y.Faust.TranscriptConfiguration. - - Faust.TranscriptConfiguration = { - // should overlapping stuff be rendered on top of each other? - // overlay : "overlay", - overlay : "none", - stripWhitespace : ['overw'], - // distance from top of one line to top of the following line - lineSpacingValue: "20", - lineSpacingUnit: "pt", - initialize : function (layoutState) { - layoutState.idMap = {}; - }, - forceFontLoading: false, - names: { - 'anchor': { - vc: function(node, text, layoutState) { - //use empty text element as an anchor - // FIXME make proper phrase/block context differentiation - if (node.parent.name().localName === "zone") { - return new FaustTranscript.Line([]); - } else { - return new FaustTranscript.Text("", {}); - } - } - }, - - 'choice' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'corr' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'document': { - - vc: function(node, text, layoutState) { - return new FaustTranscript.Surface(); - } - }, - - 'ex' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'expan' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'gap': { - text: function(annotation, textVC, layoutState) { - 1+1; - var annotationStart = annotation.target().range.start; - var annotationEnd = annotation.target().range.end; - var representation; - var nrChars; - var gapChar = '\u00d7'; - var gapUncertainChar = '.'; - switch (annotation.data["unit"]) { - case "chars": - if (annotation.data['quantity'] && annotation.data['precision'] && - annotation.data['precision'] === 'medium') { - representation = gapChar; - for (nrChars=2; nrChars < annotation.data["quantity"]; nrChars++) { - representation += gapUncertainChar; - } - representation += gapChar; - textVC.text = representation; - } else if (annotation.data['quantity']) { - representation = ''; - for (nrChars=0; nrChars < annotation.data["quantity"]; nrChars++) { - //representation += '\u2715'; //capital X - representation += gapChar; // small X - } - textVC.text = representation; - } else if(annotation.data['atLeast']) { - representation = gapChar; - for (nrChars=2; nrChars < annotation.data["atLeast"]; nrChars++) { - representation += gapUncertainChar; - } - representation += gapChar; - textVC.text = representation; - } else { - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Please specify either @qunatity or @atLeast"); - } - break; - default: - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for gap element! Use 'chars'!"); - } - }}, - - 'grBrace': { - - vc: function() {} - }, + 'corr': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, + + 'document': { + + vc: function (node, text, layoutState) { + return new FaustTranscript.Surface(); + } + }, + + 'ex': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, + + 'expan': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, + + 'gap': { + text: function (annotation, textVC, layoutState) { + 1 + 1; + var annotationStart = annotation.target().range.start; + var annotationEnd = annotation.target().range.end; + var representation; + var nrChars; + var gapChar = '\u00d7'; + var gapUncertainChar = '.'; + switch (annotation.data["unit"]) { + case "chars": + if (annotation.data['quantity'] && annotation.data['precision'] && + annotation.data['precision'] === 'medium') { + representation = gapChar; + for (nrChars = 2; nrChars < annotation.data["quantity"]; nrChars++) { + representation += gapUncertainChar; + } + representation += gapChar; + textVC.text = representation; + } else if (annotation.data['quantity']) { + representation = ''; + for (nrChars = 0; nrChars < annotation.data["quantity"]; nrChars++) { + //representation += '\u2715'; //capital X + representation += gapChar; // small X + } + textVC.text = representation; + } else if (annotation.data['atLeast']) { + representation = gapChar; + for (nrChars = 2; nrChars < annotation.data["atLeast"]; nrChars++) { + representation += gapUncertainChar; + } + representation += gapChar; + textVC.text = representation; + } else { + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Please specify either @qunatity or @atLeast"); + } + break; + default: + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for gap element! Use 'chars'!"); + } + } + }, + + 'grBrace': { + + vc: function () { + } + }, // vc: function(node, text, layoutState) { // var imgPath = './img/'; // var imgFilename = 'grLineDiagonalFalling.svg#img'; @@ -143,220 +161,234 @@ if(window.Faust === undefined) { // } // }, - 'grLine': { - vc: function(node, text, layoutState) { - var ancestorNames = node.ancestors().map(function(node){return node.annotation.name.localName}); - var inline = ancestorNames.indexOf('line') >= 0; - // TODO figure outh the number of pixels per em dynamically - var EM = 10; - var width = node.data()['width'] ? Number(node.data()['width']) * EM: null; - var height = node.data()['height'] ? Number(node.data()['height']) * EM : null; - var imgPath = './img/'; - if (node.data()['f:style'] === 'curly') { - if (node.data()['f:orient'] === 'horiz') { - if (inline) { - return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineCurlyHorizontal.svg#img', 100, 100, 20 * EM, 2 * EM); - } else { - //return new Y.FaustTranscript.SpanningVC('grLine',imgPath + 'grLineCurlyHorizontal.svg#img', 100, 100, width, height); - return null; - } - } else if (node.data()['f:orient'] === 'vert') { - if (inline) { - return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineCurlyVertical.svg#img', 100, 100, width, height); - } else { - //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineCurlyVertical.svg#img', 100, 100, width, height); - return null; - } - } - } else if (node.data()['f:style'] === 'linear') { - if (node.data()['f:orient'] === 'horiz') { - if (inline) { - return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineStraightHorizontal.svg#img', 100, 20, 10 * EM, 2 * EM); - } else { - //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineStraightHorizontal.svg#img', 100, 20, null, 2 * EM); - return null; - } - } else if (node.data()['f:orient'] === 'vert') { - if (inline) { - return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineStraightVertical.svg#img', 20, 100, 1 * EM, 2 * EM); - } else { - //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineStraightVertical.svg#img', 20, 100, null, 2 * EM); - return null; - } - } - } else if (node.data()['f:style'] === 's-left-right') { - if (inline) { - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "S-curve can't be inline!"); - } else { - //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineSLeftRight.svg#img', 100, 100, null, null); - return null; - } - } - } - }, - - 'hand' : { - - text: function(annotation, textVC, layoutState) { - var hand = annotation.data["value"]; - var classes = classesFromHandValue(hand); - textVC.classes = textVC.classes.concat(classes); - } - }, - - 'hi' : { - vc: function(node, text, layoutState) { - - var handClasses = []; - if (node.data["hand"]) { - var hand = node.data["hand"]; - handClasses = classesFromHandValue(hand); - } - - if (node.data()["rend"]) { - var rendTokens = node.data()["rend"].split(' '); - if (rendTokens.indexOf("frame") >= 0) { - return new FaustTranscript.RectInlineDecoration(handClasses); - } else if (rendTokens.indexOf("circle") >= 0) { - return new FaustTranscript.CircleInlineDecoration(handClasses); - } - } - }, - - text: function (annotation, textVC, layoutState) { - if (annotation.data["rend"]) { - var rendTokens = annotation.data["rend"].split(' '); - - var handClasses = []; - if (annotation.data["hand"]) { - var hand = annotation.data["hand"]; - handClasses = classesFromHandValue(hand); - } - - if (rendTokens.indexOf("underline") >= 0) { - var underline = new FaustTranscript.LineDecoration(textVC, handClasses, 'underline', 0.1); - textVC.decorations.push(underline); - } - if (rendTokens.indexOf("underdots") >= 0) { - var underdots = new FaustTranscript.LineDecoration(textVC, handClasses, 'underdots', 0.2); - textVC.decorations.push(underdots); - } - if (rendTokens.indexOf("overline") >= 0) { - var overline = new FaustTranscript.LineDecoration(textVC, handClasses, 'overline', -0.7); - textVC.decorations.push(overline); - } - - if (rendTokens.indexOf('sup') >= 0) { - textVC.classes.push('sup'); - } - if (rendTokens.indexOf('sub') >= 0) { - textVC.classes.push('sub'); - } - } - } - }, - - 'hspace': { - vc: function(node, text, layoutState) { - switch (node.data()["unit"]) { - case "chars": - if (node.data()['quantity']) { - var width = String(node.data()['quantity']); - return new FaustTranscript.HSpace(width); - } else { - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "f:hspace: Please specify @qunatity"); + 'grLine': { + vc: function (node, text, layoutState) { + var ancestorNames = node.ancestors().map(function (node) { + return node.annotation.name.localName + }); + var inline = ancestorNames.indexOf('line') >= 0; + // TODO figure outh the number of pixels per em dynamically + var EM = 10; + var width = node.data()['width'] ? Number(node.data()['width']) * EM : null; + var height = node.data()['height'] ? Number(node.data()['height']) * EM : null; + var imgPath = './img/'; + if (node.data()['f:style'] === 'curly') { + if (node.data()['f:orient'] === 'horiz') { + if (inline) { + return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineCurlyHorizontal.svg#img', 100, 100, 20 * EM, 2 * EM); + } else { + //return new Y.FaustTranscript.SpanningVC('grLine',imgPath + 'grLineCurlyHorizontal.svg#img', 100, 100, width, height); + return null; + } + } else if (node.data()['f:orient'] === 'vert') { + if (inline) { + return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineCurlyVertical.svg#img', 100, 100, width, height); + } else { + //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineCurlyVertical.svg#img', 100, 100, width, height); + return null; + } + } + } else if (node.data()['f:style'] === 'linear') { + if (node.data()['f:orient'] === 'horiz') { + if (inline) { + return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineStraightHorizontal.svg#img', 100, 20, 10 * EM, 2 * EM); + } else { + //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineStraightHorizontal.svg#img', 100, 20, null, 2 * EM); + return null; + } + } else if (node.data()['f:orient'] === 'vert') { + if (inline) { + return new FaustTranscript.InlineGraphic('grLine', imgPath + 'grLineStraightVertical.svg#img', 20, 100, 1 * EM, 2 * EM); + } else { + //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineStraightVertical.svg#img', 20, 100, null, 2 * EM); + return null; + } + } + } else if (node.data()['f:style'] === 's-left-right') { + if (inline) { + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "S-curve can't be inline!"); + } else { + //return new Y.FaustTranscript.SpanningVC('grLine', imgPath + 'grLineSLeftRight.svg#img', 100, 100, null, null); + return null; + } + } } - break; - default: - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for hspace element! Use 'chars'!"); - } - } - }, - - 'ins': { - vc: function(node, text, layoutState) { - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - var vc = new FaustTranscript.InlineViewComponent(); - // insertion mark - if (node.data()["f:orient"] === "right") { - var insertionSign = node.data()['f:at'].substring(1) in layoutState.idMap ? "\u230a" : "\u2308"; - vc.add (Faust.TranscriptLayout.createText(insertionSign, annotationStart, annotationEnd, - text, layoutState)); - } - return vc; - }, - end: function(node, text, layoutState) { - if (node.data()["f:orient"] === "left") { - // insertion mark - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - var insertionSign = node.data()['f:at'].substring(1) in layoutState.idMap ? "\u230b" : "\u2309"; - this.add (Faust.TranscriptLayout.createText(insertionSign, annotationStart, annotationEnd, - text, layoutState)); - } - } - }, - - 'line': { - vc: function(node, text, layoutState) { - - var start; - - if (typeof layoutState.lineCount === 'undefined') { - layoutState.lineCount = 0; - } else { - layoutState.lineCount++; - } - var lineAttrs = {}; - var rendition = node.data()["rend"] || ""; - if (rendition.indexOf("centered") >= 0) { - lineAttrs.center = true; - } - else if (rendition.indexOf("indent-center") >=0) { - start = rendition.indexOf("indent-center-"); - lineAttrs.indentCenter = parseInt(rendition.substring(start + 14, rendition.length)) / 100.0; - } - else if (rendition.indexOf("indent") >= 0) { - start = rendition.indexOf("indent-"); - lineAttrs.indent = parseInt(rendition.substring(start + 7, rendition.length)) / 100.0; - } - - var position = node.data()["f:pos"] || ""; - - if (position.indexOf("over") >= 0) { - lineAttrs.over = true; - } - - if (position.indexOf("between") >= 0) { - lineAttrs.between = true; - } - - var type = node.data()["type"] || ""; - if (type.indexOf("inter") >= 0) { - lineAttrs.interline = true; - } + }, - var vc = new FaustTranscript.Line(lineAttrs); - vc.classes.push('lineNumber' + layoutState.lineCount); + 'hand': { - // add class value to link xml ids from transcript to lines / rects in image-text-link svgs - var xmlId = node.data()["xml:id"] || ""; - vc.classes.push("xmlId-" + xmlId); - - return vc; - }, - text: function(annotation, textVC) { - var fontsize = ((annotation.data["type"] || "").indexOf("inter") >= 0 ? "interline" : "normal"); - textVC.classes.push(fontsize); - } - }, + text: function (annotation, textVC, layoutState) { + var hand = annotation.data["value"]; + var classes = classesFromHandValue(hand); + textVC.classes = textVC.classes.concat(classes); + } + }, + + 'hi': { + vc: function (node, text, layoutState) { + + var handClasses = []; + if (node.data["hand"]) { + var hand = node.data["hand"]; + handClasses = classesFromHandValue(hand); + } + + if (node.data()["rend"]) { + var rendTokens = node.data()["rend"].split(' '); + if (rendTokens.indexOf("frame") >= 0) { + return new FaustTranscript.RectInlineDecoration(handClasses); + } else if (rendTokens.indexOf("circle") >= 0) { + return new FaustTranscript.CircleInlineDecoration(handClasses); + } + } + }, + + text: function (annotation, textVC, layoutState) { + if (annotation.data["rend"]) { + var rendTokens = annotation.data["rend"].split(' '); + + var handClasses = []; + if (annotation.data["hand"]) { + var hand = annotation.data["hand"]; + handClasses = classesFromHandValue(hand); + } + + if (rendTokens.indexOf("underline") >= 0) { + var underline = new FaustTranscript.LineDecoration(textVC, handClasses, 'underline', 0.1); + textVC.decorations.push(underline); + } + if (rendTokens.indexOf("underdots") >= 0) { + var underdots = new FaustTranscript.LineDecoration(textVC, handClasses, 'underdots', 0.2); + textVC.decorations.push(underdots); + } + if (rendTokens.indexOf("overline") >= 0) { + var overline = new FaustTranscript.LineDecoration(textVC, handClasses, 'overline', -0.7); + textVC.decorations.push(overline); + } + + if (rendTokens.indexOf('sup') >= 0) { + textVC.classes.push('sup'); + } + if (rendTokens.indexOf('sub') >= 0) { + textVC.classes.push('sub'); + } + } + } + }, + + 'hspace': { + vc: function (node, text, layoutState) { + switch (node.data()["unit"]) { + case "chars": + if (node.data()['quantity']) { + var width = String(node.data()['quantity']); + return new FaustTranscript.HSpace(width); + } else { + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "f:hspace: Please specify @qunatity"); + } + break; + default: + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for hspace element! Use 'chars'!"); + } + } + }, + + 'ins': { + vc: function (node, text, layoutState) { + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + var vc = new FaustTranscript.InlineViewComponent(); + // insertion mark + if (node.data()["f:orient"] === "right") { + var insertionSign = node.data()['f:at'].substring(1) in layoutState.idMap ? "\u230a" : "\u2308"; + vc.add(Faust.TranscriptLayout.createText(insertionSign, annotationStart, annotationEnd, + text, layoutState)); + } + return vc; + }, + end: function (node, text, layoutState) { + if (node.data()["f:orient"] === "left") { + // insertion mark + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + var insertionSign = node.data()['f:at'].substring(1) in layoutState.idMap ? "\u230b" : "\u2309"; + this.add(Faust.TranscriptLayout.createText(insertionSign, annotationStart, annotationEnd, + text, layoutState)); + } + } + }, + + 'line': { + vc: function (node, text, layoutState) { + + var start; + + if (typeof layoutState.lineCount === 'undefined') { + layoutState.lineCount = 0; + } else { + layoutState.lineCount++; + } + var lineAttrs = {}; + var rendition = node.data()["rend"] || ""; + if (rendition.indexOf("centered") >= 0) { + lineAttrs.center = true; + } + else if (rendition.indexOf("indent-center") >= 0) { + start = rendition.indexOf("indent-center-"); + lineAttrs.indentCenter = parseInt(rendition.substring(start + 14, rendition.length)) / 100.0; + } + else if (rendition.indexOf("indent") >= 0) { + start = rendition.indexOf("indent-"); + lineAttrs.indent = parseInt(rendition.substring(start + 7, rendition.length)) / 100.0; + } + + var position = node.data()["f:pos"] || ""; + + if (position.indexOf("over") >= 0) { + lineAttrs.over = true; + } + + if (position.indexOf("between") >= 0) { + lineAttrs.between = true; + } + + var type = node.data()["type"] || ""; + if (type.indexOf("inter") >= 0) { + lineAttrs.interline = true; + } + + var vc = new FaustTranscript.Line(lineAttrs); + vc.classes.push('lineNumber' + layoutState.lineCount); + + // add class value to link xml ids from transcript to lines / rects in image-text-link svgs + var xmlId = node.data()["xml:id"] || ""; + vc.classes.push("xmlId-" + xmlId); + + return vc; + }, + text: function (annotation, textVC) { + var fontsize = ((annotation.data["type"] || "").indexOf("inter") >= 0 ? "interline" : "normal"); + textVC.classes.push(fontsize); + } + }, - 'over' : {text: function(annotation, textVC){ textVC.classes.push('over'); }}, + 'over': { + text: function (annotation, textVC) { + textVC.classes.push('over'); + } + }, - 'overw' : {vc: function() {return new FaustTranscript.InlineViewComponent();}}, + 'overw': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, - 'patch' : { vc: function(){return new FaustTranscript.Patch();}}, + 'patch': { + vc: function () { + return new FaustTranscript.Patch(); + } + }, // 'point' : { // vc: function (node, text, layoutState) { @@ -381,220 +413,237 @@ if(window.Faust === undefined) { // } // }, - 'rdg' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'reg' : { vc: function(){return new FaustTranscript.InlineViewComponent();}}, - - 'rewrite' : { - - text: function (annotation, textVC, layoutState) { - var rewrite = new FaustTranscript.CloneDecoration(textVC, [], 'rewrite', 0.005, -0.005); - textVC.decorations.push(rewrite); - - } - }, - - 'seg' : { - - vc: function() {return new FaustTranscript.InlineViewComponent();}, - - text : function (annotation, textVC, layoutState) { - if (annotation.data.rend) { - var rendTokens = annotation.data.rend ? annotation.data.rend.split(' ') : []; - if (rendTokens.indexOf('inbetween') >= 0 || rendTokens.indexOf('between') >= 0) { - textVC.classes.push('inbetween'); - } - } - } - }, - - 'st' : { - text : function (annotation, textVC, layoutState) { - - var rendTokens = annotation.data.rend ? annotation.data.rend.split(' ') : []; - var classes = []; - var decoration; - - - if (annotation.data.hand) { - var hand = annotation.data.hand; - classes = classes.concat(classesFromHandValue(hand)); - } else { - // TODO: this is a hack, classes should not be directly copied from the text visual component but - // instead data be taken from the annotation model - var textClasses = textVC.classes.filter(function(x) {return x.startsWith('hand-') || x.startsWith('material-');}) - classes = textClasses; - } - - if (rendTokens.indexOf('vertical') >= 0 || rendTokens.indexOf('block') >= 0 ) { - if (typeof layoutState.stVertVCs === 'undefined') {layoutState.stVertVCs = {};} - if (!(annotation.id in layoutState.stVertVCs)) { - var imgPath = './img/'; - var imgFilename = rendTokens.indexOf('vertical') >= 0 ? 'grLineStraightVertical.svg#img' - :'grLineDiagonalFalling.svg#img'; - var stVC = new FaustTranscript.CoveringImage('grLine', classes, imgPath + imgFilename, - 100, 100, layoutState.rootVC); - stVC.rotation = layoutState.currentZone.rotation; - - layoutState.stVertVCs[annotation.id] = stVC; - layoutState.currentZone.addFloat(stVC); - - decoration = new FaustTranscript.NullDecoration(textVC, classes, 'strikethrough'); - textVC.decorations.push(decoration); - } - layoutState.stVertVCs[annotation.id].coveredVCs.push(textVC); - textVC.classes.push('st-vertical'); - } else { - // count the number of strikethroughs - layoutState.textState.numSt = 'numSt' in layoutState.textState ? - layoutState.textState.numSt : 0; - - var yOffsetPerStrikethrough = 0.15; - var yOffset = yOffsetPerStrikethrough * layoutState.textState.numSt; - - - if (rendTokens.indexOf('erase') >= 0) { - textVC.classes.push('erase'); - decoration = new FaustTranscript.CloneDecoration(textVC, [], 'erase', 0, 0); - textVC.decorations.push(decoration); - - } else { - decoration = new FaustTranscript.LineDecoration(textVC, classes, 'strikethrough', -0.2 - yOffset); - textVC.decorations.push(decoration); - } - - layoutState.textState.numSt = layoutState.textState.numSt + 1; - } - - } - }, - - 'supplied' : { - vc : function (node, text, layoutState) { - - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - var vc = new FaustTranscript.InlineViewComponent(); - vc.add (Faust.TranscriptLayout.createText('[', annotationStart, annotationEnd, text, - layoutState)); - return vc; - }, - end: function(node, text, layoutState) { - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - this.add (Faust.TranscriptLayout.createText(']', annotationStart, annotationEnd, text, - layoutState)); - } - }, - - 'surface': { - vc: function(node, text, layoutState) { - return new FaustTranscript.Surface(); - } - }, - - 'treeRoot': { - vc: function(node, text, layoutState) { - return new FaustTranscript.Surface(); - } - }, - - - 'unclear' : { - vc : function (node, text, layoutState) { - - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - var vc = new FaustTranscript.InlineViewComponent(); - var startMarker = node.data()['cert'] == 'low' ? '{{' : '{'; - var certainty = node.data()['cert'] == 'low' ? 'low' : 'high'; - vc.classes.push('unclear-cert-' + certainty); - vc.add (Faust.TranscriptLayout.createText(startMarker, annotationStart, annotationEnd, text, - layoutState)); - return vc; - }, - end: function(node, text, layoutState) { - var annotationStart = node.annotation.target().range.start; - var annotationEnd = node.annotation.target().range.end; - var endMarker = node.data()['cert'] == 'low' ? '}}' : '}'; - this.add (Faust.TranscriptLayout.createText(endMarker, annotationStart, annotationEnd, text, - layoutState)); - - // hide the component if it is a less probable alternative of a choice - if (node.parent.name().localName === 'choice') { - var sibling_cert_values = node.parent.children().map(function(annotation){return annotation.data()['cert']}); - if (node.data()['cert'] == 'low' && sibling_cert_values.indexOf('high') >= 0) { - this.computeClasses = function(){ - return ['invisible']; - }; - } - } - } - }, - - - - 'under' : { - text: function(annotation, textVC, layoutState) { - textVC.classes.push('under'); - } - }, - - 'used' : { - text: function(annotation, textVC, layoutState) { - if (typeof layoutState.usedVCs === 'undefined') {layoutState.usedVCs = {};} - if (!(annotation.id in layoutState.usedVCs)) { - var imgPath = './img/'; - var usedVC = new FaustTranscript.CoveringImage('grLine',[], imgPath + 'usedMarker.svg#svgroot', - 100, 100, layoutState.rootVC); - usedVC.rotation = layoutState.currentZone.rotation; - layoutState.usedVCs[annotation.id] = usedVC; - layoutState.currentZone.addFloat(usedVC); - } - layoutState.usedVCs[annotation.id].coveredVCs.push(textVC); - textVC.classes.push('used'); - } - }, - - 'vspace': { - vc: function(node, text, layoutState) { - - //TODO real implementation, non-integer values - switch (node.data()["unit"]) { - case "lines": - if (node.data()['quantity']) { - return new FaustTranscript.VSpace(node.data()['quantity']); - } else throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "f:vspace: Please specify @qunatity"); - break; - default: - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for vspace element! Use 'lines'!"); - } - } - }, - - 'zone': { - vc: function(node, text, layoutState) { - var vc = new FaustTranscript.Zone(); - if ("rotate" in node.data()) { - vc.rotation = parseInt(node.data()["rotate"]); + 'rdg': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, + + 'reg': { + vc: function () { + return new FaustTranscript.InlineViewComponent(); + } + }, + + 'rewrite': { + + text: function (annotation, textVC, layoutState) { + var rewrite = new FaustTranscript.CloneDecoration(textVC, [], 'rewrite', 0.005, -0.005); + textVC.decorations.push(rewrite); + + } + }, + + 'seg': { + + vc: function () { + return new FaustTranscript.InlineViewComponent(); + }, + + text: function (annotation, textVC, layoutState) { + if (annotation.data.rend) { + var rendTokens = annotation.data.rend ? annotation.data.rend.split(' ') : []; + if (rendTokens.indexOf('inbetween') >= 0 || rendTokens.indexOf('between') >= 0) { + textVC.classes.push('inbetween'); + } + } + } + }, + + 'st': { + text: function (annotation, textVC, layoutState) { + + var rendTokens = annotation.data.rend ? annotation.data.rend.split(' ') : []; + var classes = []; + var decoration; + + + if (annotation.data.hand) { + var hand = annotation.data.hand; + classes = classes.concat(classesFromHandValue(hand)); + } else { + // TODO: this is a hack, classes should not be directly copied from the text visual component but + // instead data be taken from the annotation model + var textClasses = textVC.classes.filter(function (x) { + return x.startsWith('hand-') || x.startsWith('material-'); + }) + classes = textClasses; + } + + if (rendTokens.indexOf('vertical') >= 0 || rendTokens.indexOf('block') >= 0) { + if (typeof layoutState.stVertVCs === 'undefined') { + layoutState.stVertVCs = {}; + } + if (!(annotation.id in layoutState.stVertVCs)) { + var imgPath = './img/'; + var imgFilename = rendTokens.indexOf('vertical') >= 0 ? 'grLineStraightVertical.svg#img' + : 'grLineDiagonalFalling.svg#img'; + var stVC = new FaustTranscript.CoveringImage('grLine', classes, imgPath + imgFilename, + 100, 100, layoutState.rootVC); + stVC.rotation = layoutState.currentZone.rotation; + + layoutState.stVertVCs[annotation.id] = stVC; + layoutState.currentZone.addFloat(stVC); + + decoration = new FaustTranscript.NullDecoration(textVC, classes, 'strikethrough'); + textVC.decorations.push(decoration); + } + layoutState.stVertVCs[annotation.id].coveredVCs.push(textVC); + textVC.classes.push('st-vertical'); + } else { + // count the number of strikethroughs + layoutState.textState.numSt = 'numSt' in layoutState.textState ? + layoutState.textState.numSt : 0; + + var yOffsetPerStrikethrough = 0.15; + var yOffset = yOffsetPerStrikethrough * layoutState.textState.numSt; + + + if (rendTokens.indexOf('erase') >= 0) { + textVC.classes.push('erase'); + decoration = new FaustTranscript.CloneDecoration(textVC, [], 'erase', 0, 0); + textVC.decorations.push(decoration); + + } else { + decoration = new FaustTranscript.LineDecoration(textVC, classes, 'strikethrough', -0.2 - yOffset); + textVC.decorations.push(decoration); + } + + layoutState.textState.numSt = layoutState.textState.numSt + 1; + } + + } + }, + + 'supplied': { + vc: function (node, text, layoutState) { + + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + var vc = new FaustTranscript.InlineViewComponent(); + vc.add(Faust.TranscriptLayout.createText('[', annotationStart, annotationEnd, text, + layoutState)); + return vc; + }, + end: function (node, text, layoutState) { + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + this.add(Faust.TranscriptLayout.createText(']', annotationStart, annotationEnd, text, + layoutState)); + } + }, + + 'surface': { + vc: function (node, text, layoutState) { + return new FaustTranscript.Surface(); + } + }, + + 'treeRoot': { + vc: function (node, text, layoutState) { + return new FaustTranscript.Surface(); + } + }, + + + 'unclear': { + vc: function (node, text, layoutState) { + + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + var vc = new FaustTranscript.InlineViewComponent(); + var startMarker = node.data()['cert'] == 'low' ? '{{' : '{'; + var certainty = node.data()['cert'] == 'low' ? 'low' : 'high'; + vc.classes.push('unclear-cert-' + certainty); + vc.add(Faust.TranscriptLayout.createText(startMarker, annotationStart, annotationEnd, text, + layoutState)); + return vc; + }, + end: function (node, text, layoutState) { + var annotationStart = node.annotation.target().range.start; + var annotationEnd = node.annotation.target().range.end; + var endMarker = node.data()['cert'] == 'low' ? '}}' : '}'; + this.add(Faust.TranscriptLayout.createText(endMarker, annotationStart, annotationEnd, text, + layoutState)); + + // hide the component if it is a less probable alternative of a choice + if (node.parent.name().localName === 'choice') { + var sibling_cert_values = node.parent.children().map(function (annotation) { + return annotation.data()['cert'] + }); + if (node.data()['cert'] == 'low' && sibling_cert_values.indexOf('high') >= 0) { + this.computeClasses = function () { + return ['invisible']; + }; + } + } + } + }, + + + 'under': { + text: function (annotation, textVC, layoutState) { + textVC.classes.push('under'); + } + }, + + 'used': { + text: function (annotation, textVC, layoutState) { + if (typeof layoutState.usedVCs === 'undefined') { + layoutState.usedVCs = {}; + } + if (!(annotation.id in layoutState.usedVCs)) { + var imgPath = './img/'; + var usedVC = new FaustTranscript.CoveringImage('grLine', [], imgPath + 'usedMarker.svg#svgroot', + 100, 100, layoutState.rootVC); + usedVC.rotation = layoutState.currentZone.rotation; + layoutState.usedVCs[annotation.id] = usedVC; + layoutState.currentZone.addFloat(usedVC); + } + layoutState.usedVCs[annotation.id].coveredVCs.push(textVC); + textVC.classes.push('used'); + } + }, + + 'vspace': { + vc: function (node, text, layoutState) { + + //TODO real implementation, non-integer values + switch (node.data()["unit"]) { + case "lines": + if (node.data()['quantity']) { + return new FaustTranscript.VSpace(node.data()['quantity']); + } else throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "f:vspace: Please specify @qunatity"); + break; + default: + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Invalid unit for vspace element! Use 'lines'!"); + } + } + }, + + 'zone': { + vc: function (node, text, layoutState) { + var vc = new FaustTranscript.Zone(); + if ("rotate" in node.data()) { + vc.rotation = parseInt(node.data()["rotate"]); + } + if ("type" in node.data() && node.data()["type"] === "main") { + if (layoutState.mainZone) { + throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "More than one main zone specified!"); + } else { + layoutState.mainZone = vc; + // main zone is absolutely anchored + vc.setAlign('hAlign', new FaustTranscript.AbsoluteAlign(vc, 0, 0, FaustTranscript.Align.MAIN_ZONE)); + vc.setAlign('vAlign', new FaustTranscript.AbsoluteAlign(vc, 0, 0, FaustTranscript.Align.MAIN_ZONE)); + } + } + layoutState.currentZone = vc; + return vc; + } } - if ("type" in node.data() && node.data()["type"] === "main") { - if (layoutState.mainZone) { - throw (FaustTranscript.ENCODING_EXCEPTION_PREFIX + "More than one main zone specified!"); - } else { - layoutState.mainZone = vc; - // main zone is absolutely anchored - vc.setAlign('hAlign', new FaustTranscript.AbsoluteAlign(vc, 0, 0, FaustTranscript.Align.MAIN_ZONE)); - vc.setAlign('vAlign', new FaustTranscript.AbsoluteAlign(vc, 0, 0, FaustTranscript.Align.MAIN_ZONE)); - } - } - layoutState.currentZone = vc; - return vc; - } - } - } - - - }; + } + + + }; })(Faust); diff --git a/svg_rendering/page/js-gen/transcript-generation.js b/svg_rendering/page/js-gen/transcript-generation.js index 52f836c..f14cf29 100644 --- a/svg_rendering/page/js-gen/transcript-generation.js +++ b/svg_rendering/page/js-gen/transcript-generation.js @@ -1,179 +1,187 @@ -var transcriptGeneration = (function(){ - "use strict"; +var transcriptGeneration = (function () { + "use strict"; - /* remove() polyfill */ - if (!('remove' in Element.prototype)) { - Element.prototype.remove = function() { - if (this.parentNode) { - this.parentNode.removeChild(this); - } - }; - } + /* remove() polyfill */ + if (!('remove' in Element.prototype)) { + Element.prototype.remove = function () { + if (this.parentNode) { + this.parentNode.removeChild(this); + } + }; + } - var transcriptGeneration = {}; + var transcriptGeneration = {}; - var createRenderContainer = (function() { + var createRenderContainer = (function () { - var createRenderContainer = function() { - var renderContainer = document.createElement("div"); + var createRenderContainer = function () { + var renderContainer = document.createElement("div"); // renderContainer.style.height = "0px"; // renderContainer.style.width = "0px"; - renderContainer.style.overflow = "hidden"; + renderContainer.style.overflow = "auto"; + renderContainer.style.height = "100%"; + renderContainer.style.position = "fixed"; + renderContainer.style.top = "0px"; + renderContainer.style.left = "0px"; - renderContainer.style.position = "fixed"; - renderContainer.style.top = "0px"; - renderContainer.style.left = "0px"; + return renderContainer; + }; - return renderContainer; - }; + return createRenderContainer; + })(); + + + transcriptGeneration.createDiplomaticSvg = (function () { + + /** + * Iteratively generates the diplomatic transcript in-browser. + * @param {string} diplomaticTranscriptString - The transcript text and markup in standoff format + * @param {function} callback - Function to be called when the layout has finished. Is passed the SVG DOM node + */ + + + var createDiplomaticSvg = function (diplomaticTranscriptString, callback) { + + var iterations = 15; + var timeout = 5; + + var diplomaticTranscriptJson = typeof(diplomaticTranscriptString) === "object" ? diplomaticTranscriptString : JSON.parse(diplomaticTranscriptString); + if (diplomaticTranscriptString === undefined) { + throw "Argument is undefined!"; + } else if (diplomaticTranscriptJson === undefined) { + throw "JSON parsing failed!"; + } - return createRenderContainer; - })(); - - - transcriptGeneration.createDiplomaticSvg = (function() { - var iterations = 15; - var timeout = 5; - - var createDiplomaticSvg = function(diplomaticTranscriptString, callback) { - - var diplomaticTranscriptJson = typeof(diplomaticTranscriptString) === "object"? diplomaticTranscriptString : JSON.parse(diplomaticTranscriptString); - if (diplomaticTranscriptString === undefined) { - throw "Argument is undefined!"; - } else if (diplomaticTranscriptJson === undefined) { - throw "JSON parsing failed!"; - } - - var renderContainer = createRenderContainer(); - document.body.appendChild(renderContainer); - - var documentBuilder = new FaustTranscript.TranscriptAdhocTree(); - var visComponent = documentBuilder.transcriptVC(diplomaticTranscriptJson); - - var svgRoot = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - svgRoot.setAttribute("class", "diplomatic"); - renderContainer.appendChild(svgRoot); - - var innerContainer = document.createElementNS("http://www.w3.org/2000/svg", "g"); - innerContainer.setAttribute("id", "transcript_container"); - visComponent.svgCont = innerContainer; - svgRoot.appendChild(innerContainer); - - visComponent.render(); - - var computeLayout = function(currentIteration) { - visComponent.layout(); - if(currentIteration < iterations) { - // push next layout computation to end of event queue - setTimeout( function() { - computeLayout(currentIteration + 1); - }, timeout); - } else { - var rootBBox = innerContainer.getBBox(); - innerContainer.setAttribute("transform", "translate(" + (- rootBBox.x) + "," + (- rootBBox.y) + ")"); - svgRoot.setAttribute("width", rootBBox.width); - svgRoot.setAttribute("height", rootBBox.height); + var renderContainer = createRenderContainer(); + document.body.appendChild(renderContainer); + + var documentBuilder = new FaustTranscript.TranscriptAdhocTree(); + var visComponent = documentBuilder.transcriptVC(diplomaticTranscriptJson); + + var svgRoot = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svgRoot.setAttribute("class", "diplomatic"); + renderContainer.appendChild(svgRoot); + + var innerContainer = document.createElementNS("http://www.w3.org/2000/svg", "g"); + innerContainer.setAttribute("id", "transcript_container"); + visComponent.svgCont = innerContainer; + svgRoot.appendChild(innerContainer); + + visComponent.render(); + + var computeLayout = function (currentIteration) { + visComponent.layout(); + if (currentIteration < iterations) { + // push next layout computation to end of event queue + setTimeout(function () { + computeLayout(currentIteration + 1); + }, timeout); + } else { + var rootBBox = innerContainer.getBBox(); + innerContainer.setAttribute("transform", "translate(" + (-rootBBox.x) + "," + (-rootBBox.y) + ")"); + svgRoot.setAttribute("width", rootBBox.width); + svgRoot.setAttribute("height", rootBBox.height); // document.body.removeChild(renderContainer); - if (typeof callback !== 'undefined') { - callback(renderContainer.firstChild); - } + if (typeof callback !== 'undefined') { + callback(renderContainer.firstChild); + } - } - }; + } + }; - computeLayout(0); - }; + computeLayout(0); + }; + + return createDiplomaticSvg; + })(); - return createDiplomaticSvg; - })(); - - transcriptGeneration.createFacsimileOverlaySvg = (function(){ - var createFacsimileOverlaySvg = function(diplomaticSvg, textImageLinkSvgString) { - - var renderContainer = createRenderContainer(); - document.body.appendChild(renderContainer); - - // create dom nodes from text-image-link svg string - var textImageLinkSvg = new DOMParser().parseFromString(textImageLinkSvgString, "image/svg+xml").firstChild; - textImageLinkSvg.style.position = "absolute"; - textImageLinkSvg.style.top = "0px"; - textImageLinkSvg.style.left = "0px"; - renderContainer.appendChild(textImageLinkSvg); - - Array.prototype.slice.call(textImageLinkSvg.querySelectorAll(".imageannotationLine.imageannotationLinked")).forEach(function(lineNode) { - var heightFactor = 2; - var height = lineNode.getAttribute('height'); - lineNode.setAttribute('height', height * heightFactor); - var y = lineNode.getAttribute('y'); - lineNode.setAttribute('y', y - ((heightFactor * height) - height)); - - var linkedLine = lineNode.getAttributeNS("http://www.w3.org/1999/xlink", 'href'); - var classVal = "linkedto-" + linkedLine.substring(1); - lineNode.setAttribute('class', lineNode.getAttribute('class') + ' ' + classVal); - }); - - var facsimileOverlaySvg = diplomaticSvg.cloneNode(true); - facsimileOverlaySvg.style.position = "absolute"; - facsimileOverlaySvg.style.top = "0px"; - facsimileOverlaySvg.style.left = "0px"; - renderContainer.appendChild(facsimileOverlaySvg); - - facsimileOverlaySvg.setAttribute("width", textImageLinkSvg.getAttribute("width")); - facsimileOverlaySvg.setAttribute("height", textImageLinkSvg.getAttribute("height")); - - Array.prototype.slice.call(facsimileOverlaySvg.querySelectorAll(".element-line")).forEach(function(transcriptLine) { - var xmlId = SvgUtils.decodeClassValue(transcriptLine.getAttribute('class'), 'xmlId-'); - var imageLinkLine = textImageLinkSvg.querySelector(".imageannotationLine.linkedto-" + xmlId); - - if (imageLinkLine) { - SvgUtils.fitTo(transcriptLine, imageLinkLine); - } else { - transcriptLine.remove(true); - } - - }); - - facsimileOverlaySvg.setAttribute("viewBox", "0 0 " + textImageLinkSvg.getAttribute("width") + " " + textImageLinkSvg.getAttribute("height")); - facsimileOverlaySvg.setAttribute("preserveAspectRatio", "xMinYMin meet"); + transcriptGeneration.createFacsimileOverlaySvg = (function () { + var createFacsimileOverlaySvg = function (diplomaticSvg, textImageLinkSvgString) { + + var renderContainer = createRenderContainer(); + document.body.appendChild(renderContainer); + + // create dom nodes from text-image-link svg string + var textImageLinkSvg = new DOMParser().parseFromString(textImageLinkSvgString, "image/svg+xml").firstChild; + textImageLinkSvg.style.position = "absolute"; + textImageLinkSvg.style.top = "0px"; + textImageLinkSvg.style.left = "0px"; + renderContainer.appendChild(textImageLinkSvg); + + Array.prototype.slice.call(textImageLinkSvg.querySelectorAll(".imageannotationLine.imageannotationLinked")).forEach(function (lineNode) { + var heightFactor = 2; + var height = lineNode.getAttribute('height'); + lineNode.setAttribute('height', height * heightFactor); + var y = lineNode.getAttribute('y'); + lineNode.setAttribute('y', y - ((heightFactor * height) - height)); + + var linkedLine = lineNode.getAttributeNS("http://www.w3.org/1999/xlink", 'href'); + var classVal = "linkedto-" + linkedLine.substring(1); + lineNode.setAttribute('class', lineNode.getAttribute('class') + ' ' + classVal); + }); + + var facsimileOverlaySvg = diplomaticSvg.cloneNode(true); + facsimileOverlaySvg.style.position = "absolute"; + facsimileOverlaySvg.style.top = "0px"; + facsimileOverlaySvg.style.left = "0px"; + renderContainer.appendChild(facsimileOverlaySvg); + + facsimileOverlaySvg.setAttribute("width", textImageLinkSvg.getAttribute("width")); + facsimileOverlaySvg.setAttribute("height", textImageLinkSvg.getAttribute("height")); + + Array.prototype.slice.call(facsimileOverlaySvg.querySelectorAll(".element-line")).forEach(function (transcriptLine) { + var xmlId = SvgUtils.decodeClassValue(transcriptLine.getAttribute('class'), 'xmlId-'); + var imageLinkLine = textImageLinkSvg.querySelector(".imageannotationLine.linkedto-" + xmlId); + + if (imageLinkLine) { + SvgUtils.fitTo(transcriptLine, imageLinkLine); + } else { + transcriptLine.remove(true); + } + + }); + + facsimileOverlaySvg.setAttribute("viewBox", "0 0 " + textImageLinkSvg.getAttribute("width") + " " + textImageLinkSvg.getAttribute("height")); + facsimileOverlaySvg.setAttribute("preserveAspectRatio", "xMinYMin meet"); // document.body.removeChild(renderContainer); - facsimileOverlaySvg.style.position = "static"; - facsimileOverlaySvg.style.top = "auto"; - facsimileOverlaySvg.style.left = "auto"; - return facsimileOverlaySvg ; + facsimileOverlaySvg.style.position = "static"; + facsimileOverlaySvg.style.top = "auto"; + facsimileOverlaySvg.style.left = "auto"; + return facsimileOverlaySvg; + }; + + return createFacsimileOverlaySvg; + })(); + + + function serialize(node) { + var serializer = new XMLSerializer(), + serializedSvg = serializer.serializeToString(node).replace(/ /g, ' '); + return serializedSvg; }; - return createFacsimileOverlaySvg; - })(); - - - function serialize(node) { - var serializer = new XMLSerializer(), - serializedSvg = serializer.serializeToString(node).replace(/ /g, ' '); - return serializedSvg; - }; - - - transcriptGeneration.createToPhantom = function createToPhantom(transcript, links) { - transcriptGeneration.createDiplomaticSvg(transcript, function(diploSvg) { - var result = { svg: serialize(diploSvg), overlay: undefined }; - if (links) { - var overlaySvg = transcriptGeneration.createFacsimileOverlaySvg(diploSvg, links); - result.overlay = serialize(overlaySvg); - overlaySvg.parentNode.removeChild(overlaySvg); - } - try { - window.callPhantom(result); - } catch (e) { - console.log("Phantom callback failed: ", e); - } - }); - } - - return transcriptGeneration; + + transcriptGeneration.createToPhantom = function createToPhantom(transcript, links) { + transcriptGeneration.createDiplomaticSvg(transcript, function (diploSvg) { + var result = {svg: serialize(diploSvg), overlay: undefined}; + if (links) { + var overlaySvg = transcriptGeneration.createFacsimileOverlaySvg(diploSvg, links); + result.overlay = serialize(overlaySvg); + overlaySvg.parentNode.removeChild(overlaySvg); + } + try { + window.callPhantom(result); + } catch (e) { + console.log("Phantom callback failed: ", e); + } + }); + } + + return transcriptGeneration; })(); diff --git a/svg_rendering/page/js-gen/transcript-svg.js b/svg_rendering/page/js-gen/transcript-svg.js index 0305d2c..1f4ed65 100644 --- a/svg_rendering/page/js-gen/transcript-svg.js +++ b/svg_rendering/page/js-gen/transcript-svg.js @@ -17,171 +17,175 @@ * along with this program. If not, see . */ -if(window.FaustTranscript === undefined) { - window.FaustTranscript = {}; +if (window.FaustTranscript === undefined) { + window.FaustTranscript = {}; } -(function(FaustTranscript) { +(function (FaustTranscript) { - var SVG_NS = "http://www.w3.org/2000/svg"; + var SVG_NS = "http://www.w3.org/2000/svg"; // var DRAG_NS = "http://www.codedread.com/dragsvg"; - // Implementation of View Components. Keep in sync with transcript.js. - // These components are based on SVG. The model is only - // accessing a narrow interface to learn about the actual - // size, so in theory this could be exchanged with say a - // HTML / CSS Transforms implementation - - FaustTranscript.ViewComponent.prototype.getCoord = function(coordRotation) { - var matrix = this.view.viewportElement.createSVGMatrix(); - matrix = matrix.rotate(coordRotation); - return SvgUtils.boundingBox(this.view, matrix).x; - }; - - FaustTranscript.ViewComponent.prototype.getExt = function(coordRotation) { - var matrix = this.view.viewportElement.createSVGMatrix(); - matrix = matrix.rotate(coordRotation); - return SvgUtils.boundingBox(this.view, matrix).width; - }; - - FaustTranscript.ViewComponent.prototype.wrap = function(view) { - var wrapper = this.svgDocument().createElementNS(SVG_NS, "g"); - wrapper.appendChild(view); - return wrapper; - }; - - FaustTranscript.ViewComponent.prototype.setCoord = function(coord, coordRotation) { - - var myRot = this.globalRotation(); - var myRotMx = this.view.viewportElement.createSVGMatrix().rotate(myRot); - var myRotTf = this.view.viewportElement.createSVGTransformFromMatrix(myRotMx); - var myRotTfInv = this.view.viewportElement.createSVGTransformFromMatrix(myRotMx.inverse()); - - var matrix = this.view.viewportElement.createSVGMatrix(); - var currentCoord = this.getCoord(coordRotation); - var deltaCoord = coord - currentCoord; - - matrix = matrix.rotate(coordRotation); - matrix = matrix.translate(deltaCoord, 0); - matrix = matrix.rotate(-coordRotation); - var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); - this.view.transform.baseVal.consolidate(); - this.view.transform.baseVal.appendItem(myRotTfInv); - this.view.transform.baseVal.appendItem(transform); - this.view.transform.baseVal.appendItem(myRotTf); - this.view.transform.baseVal.consolidate(); - }; - - FaustTranscript.ViewComponent.prototype.rotate = function(deg) { - var matrix = this.view.viewportElement.createSVGMatrix(); - matrix = matrix.rotate(deg); - var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); - this.view.transform.baseVal.insertItemBefore(transform, 0); - }; - - FaustTranscript.ViewComponent.prototype.svgContainer = function() { - if (this.parent) { - if (this.parent.view) { - return this.parent.view; - } else { - return this.parent.svgContainer(); - } - } else { - if (this.svgCont) { - return this.svgCont; - } else { - throw ('Cannot find SVG container for view component'); - } - } - }; - - FaustTranscript.ViewComponent.prototype.svgDocument = function() { - return document; - }; - - FaustTranscript.ViewComponent.prototype.onRelayout = function() { - }; - - FaustTranscript.ViewComponent.prototype.render = function() { - this.view = this.createView(); - this.view.setAttribute('class', this.getClassesString()); - this.svgContainer().appendChild(this.view); - this.rotate(this.rotation); - this.children.forEach(function(c) { c.render(); }); - }; - - FaustTranscript.ViewComponent.prototype.measure = function() { - var bbox = SvgUtils.boundingBox(this.view); - return { width: Math.round(bbox.width), height: Math.round(bbox.height)}; - }; - - FaustTranscript.ViewComponent.prototype.getClassesString = function() { - return this.computeClasses().join(' '); - }; - - FaustTranscript.BlockViewComponent.prototype.createView = function() { - var view = this.svgDocument().createElementNS(SVG_NS, "g"); - return view; - }; - - FaustTranscript.InlineViewComponent.prototype.createView = function() { - var view = this.svgDocument().createElementNS(SVG_NS, "g"); - return view; - }; - - FaustTranscript.Patch.prototype.createView = function () { - this.patchBackground = this.svgDocument().createElementNS(SVG_NS, "rect"); - this.svgContainer().appendChild(this.patchBackground); - this.patchBackground.setAttribute("class", "patchBackground " + this.getClassesString()); - this.view = this.svgDocument().createElementNS(SVG_NS, "g"); - return this.view; - }; - - FaustTranscript.Patch.prototype.onRelayout = function () { - var bbox = SvgUtils.boundingBox(this.view); - this.patchBackground.setAttribute("x", bbox.x); - this.patchBackground.setAttribute("y", bbox.y); - this.patchBackground.setAttribute("height", bbox.height); - this.patchBackground.setAttribute("width", bbox.width); - this.patchBackground.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); - }; - - FaustTranscript.VSpace.prototype.createView = function() { - var result = this.svgDocument().createElementNS(SVG_NS, "rect"); - result.setAttribute('class', 'VSpace'); - result.setAttribute('width', '0.1em'); - result.setAttribute('style', 'visibility: hidden;'); - //TODO dynamically calculate from context line height - var height = String(Faust.TranscriptConfiguration.lineSpacingValue * this.vSpaceHeight) - + Faust.TranscriptConfiguration.lineSpacingUnit; - result.setAttribute('height', height); - return result; - }; - - FaustTranscript.HSpace.prototype.createView = function() { - var result = this.svgDocument().createElementNS(SVG_NS, "rect"); - result.setAttribute('class', 'HSpace'); - result.setAttribute('height', '0.1em'); - result.setAttribute('style', 'visibility: hidden;'); - //TODO dynamically calculate from context ? - var width = String(this.hSpaceWidth * 0.5) + 'em'; - result.setAttribute('width', width); - return result; - }; - - FaustTranscript.Surface.prototype.createView = function() { - var surface = this.svgDocument().createElementNS(SVG_NS, "g"); - surface.setAttribute('class', 'Surface'); - return surface; - }; - - FaustTranscript.Zone.prototype.render = function() { - FaustTranscript.Zone.superclass.render.call(this); - this.floats.forEach(function(float) { float.render(); }); - }; - - FaustTranscript.Zone.prototype.createView = function() { - var result = this.svgDocument().createElementNS(SVG_NS, "g"); + // Implementation of View Components. Keep in sync with transcript.js. + // These components are based on SVG. The model is only + // accessing a narrow interface to learn about the actual + // size, so in theory this could be exchanged with say a + // HTML / CSS Transforms implementation + + FaustTranscript.ViewComponent.prototype.getCoord = function (coordRotation) { + var matrix = this.view.viewportElement.createSVGMatrix(); + matrix = matrix.rotate(coordRotation); + return SvgUtils.boundingBox(this.view, matrix).x; + }; + + FaustTranscript.ViewComponent.prototype.getExt = function (coordRotation) { + var matrix = this.view.viewportElement.createSVGMatrix(); + matrix = matrix.rotate(coordRotation); + return SvgUtils.boundingBox(this.view, matrix).width; + }; + + FaustTranscript.ViewComponent.prototype.wrap = function (view) { + var wrapper = this.svgDocument().createElementNS(SVG_NS, "g"); + wrapper.appendChild(view); + return wrapper; + }; + + FaustTranscript.ViewComponent.prototype.setCoord = function (coord, coordRotation) { + + var myRot = this.globalRotation(); + var myRotMx = this.view.viewportElement.createSVGMatrix().rotate(myRot); + var myRotTf = this.view.viewportElement.createSVGTransformFromMatrix(myRotMx); + var myRotTfInv = this.view.viewportElement.createSVGTransformFromMatrix(myRotMx.inverse()); + + var matrix = this.view.viewportElement.createSVGMatrix(); + var currentCoord = this.getCoord(coordRotation); + var deltaCoord = coord - currentCoord; + + matrix = matrix.rotate(coordRotation); + matrix = matrix.translate(deltaCoord, 0); + matrix = matrix.rotate(-coordRotation); + var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); + this.view.transform.baseVal.consolidate(); + this.view.transform.baseVal.appendItem(myRotTfInv); + this.view.transform.baseVal.appendItem(transform); + this.view.transform.baseVal.appendItem(myRotTf); + this.view.transform.baseVal.consolidate(); + }; + + FaustTranscript.ViewComponent.prototype.rotate = function (deg) { + var matrix = this.view.viewportElement.createSVGMatrix(); + matrix = matrix.rotate(deg); + var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); + this.view.transform.baseVal.insertItemBefore(transform, 0); + }; + + FaustTranscript.ViewComponent.prototype.svgContainer = function () { + if (this.parent) { + if (this.parent.view) { + return this.parent.view; + } else { + return this.parent.svgContainer(); + } + } else { + if (this.svgCont) { + return this.svgCont; + } else { + throw ('Cannot find SVG container for view component'); + } + } + }; + + FaustTranscript.ViewComponent.prototype.svgDocument = function () { + return document; + }; + + FaustTranscript.ViewComponent.prototype.onRelayout = function () { + }; + + FaustTranscript.ViewComponent.prototype.render = function () { + this.view = this.createView(); + this.view.setAttribute('class', this.getClassesString()); + this.svgContainer().appendChild(this.view); + this.rotate(this.rotation); + this.children.forEach(function (c) { + c.render(); + }); + }; + + FaustTranscript.ViewComponent.prototype.measure = function () { + var bbox = SvgUtils.boundingBox(this.view); + return {width: Math.round(bbox.width), height: Math.round(bbox.height)}; + }; + + FaustTranscript.ViewComponent.prototype.getClassesString = function () { + return this.computeClasses().join(' '); + }; + + FaustTranscript.BlockViewComponent.prototype.createView = function () { + var view = this.svgDocument().createElementNS(SVG_NS, "g"); + return view; + }; + + FaustTranscript.InlineViewComponent.prototype.createView = function () { + var view = this.svgDocument().createElementNS(SVG_NS, "g"); + return view; + }; + + FaustTranscript.Patch.prototype.createView = function () { + this.patchBackground = this.svgDocument().createElementNS(SVG_NS, "rect"); + this.svgContainer().appendChild(this.patchBackground); + this.patchBackground.setAttribute("class", "patchBackground " + this.getClassesString()); + this.view = this.svgDocument().createElementNS(SVG_NS, "g"); + return this.view; + }; + + FaustTranscript.Patch.prototype.onRelayout = function () { + var bbox = SvgUtils.boundingBox(this.view); + this.patchBackground.setAttribute("x", bbox.x); + this.patchBackground.setAttribute("y", bbox.y); + this.patchBackground.setAttribute("height", bbox.height); + this.patchBackground.setAttribute("width", bbox.width); + this.patchBackground.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); + }; + + FaustTranscript.VSpace.prototype.createView = function () { + var result = this.svgDocument().createElementNS(SVG_NS, "rect"); + result.setAttribute('class', 'VSpace'); + result.setAttribute('width', '0.1em'); + result.setAttribute('style', 'visibility: hidden;'); + //TODO dynamically calculate from context line height + var height = String(Faust.TranscriptConfiguration.lineSpacingValue * this.vSpaceHeight) + + Faust.TranscriptConfiguration.lineSpacingUnit; + result.setAttribute('height', height); + return result; + }; + + FaustTranscript.HSpace.prototype.createView = function () { + var result = this.svgDocument().createElementNS(SVG_NS, "rect"); + result.setAttribute('class', 'HSpace'); + result.setAttribute('height', '0.1em'); + result.setAttribute('style', 'visibility: hidden;'); + //TODO dynamically calculate from context ? + var width = String(this.hSpaceWidth * 0.5) + 'em'; + result.setAttribute('width', width); + return result; + }; + + FaustTranscript.Surface.prototype.createView = function () { + var surface = this.svgDocument().createElementNS(SVG_NS, "g"); + surface.setAttribute('class', 'Surface'); + return surface; + }; + + FaustTranscript.Zone.prototype.render = function () { + FaustTranscript.Zone.superclass.render.call(this); + this.floats.forEach(function (float) { + float.render(); + }); + }; + + FaustTranscript.Zone.prototype.createView = function () { + var result = this.svgDocument().createElementNS(SVG_NS, "g"); // var box0 = this.svgDocument().createElementNS(SVG_NS, 'rect'); // box0.setAttribute('class', 'ZoneDot'); // box0.setAttribute('width', '0.1em'); @@ -190,279 +194,287 @@ if(window.FaustTranscript === undefined) { // box0.setAttribute('y', '0'); // box0.setAttribute('style', 'fill: transparent; stroke: black; visibility: hidden'); // result.appendChild(box0); - result.setAttribute('class', 'Zone'); + result.setAttribute('class', 'Zone'); // result.setAttributeNS(DRAG_NS, 'drag:enable', 'true'); - return result; - }; - - FaustTranscript.Line.prototype.createView = function() { - var line = this.svgDocument().createElementNS(SVG_NS, "g"); - return line; - }; - - FaustTranscript.Line.prototype.getExt = function(coordRotation) { - var matrix = this.view.viewportElement.createSVGMatrix(); - // create artificial element with real line width but fixed height - var originalLineWidth = this.constructor.superclass.getExt.call(this, 0) - var extElement = this.svgDocument().createElementNS(SVG_NS, "rect"); - this.view.insertBefore(extElement, this.view.childNodes[0]); - extElement.setAttribute("width", originalLineWidth); - extElement.setAttribute("height", String(Faust.TranscriptConfiguration.lineSpacingValue) - + Faust.TranscriptConfiguration.lineSpacingUnit); - matrix = matrix.rotate(coordRotation); - var bbox = SvgUtils.boundingBox(extElement, matrix).width; - this.view.removeChild(extElement); - return bbox; - }; - - - FaustTranscript.Text.prototype.createView = function() { - // wrapper will contain text decorations - var wrapper = this.svgDocument().createElementNS(SVG_NS, "g"); - wrapper.setAttribute('class', 'text-wrapper'); - this.textElement = this.svgDocument().createElementNS(SVG_NS, "text"); - this.textElement.setAttribute("class", "text " + this.getClassesString()); - this.textElement.appendChild(this.svgDocument().createTextNode(this.text)); - wrapper.appendChild(this.textElement); - return wrapper; - }; - - FaustTranscript.Text.prototype.onRelayout = function() { - - var bbox = SvgUtils.boundingBox(this.view); - this.bgBox.setAttribute("x", bbox.x); - this.bgBox.setAttribute("y", bbox.y); - this.bgBox.setAttribute("height", bbox.height); - this.bgBox.setAttribute("width", bbox.width); - this.decorations.forEach(function(decoration) {decoration.layout();}); - - }; - - FaustTranscript.Text.prototype.render = function() { - - this.view = this.createView(); - this.bgBox = this.svgDocument().createElementNS(SVG_NS, "rect"); - this.view.insertBefore(this.bgBox, this.view.childNodes[0]); - this.bgBox.setAttribute("class", "bgBox " + this.getClassesString()); - this.svgContainer().appendChild(this.view); - this.rotate(this.rotation); - this.decorations.forEach(function(decoration) {decoration.render();}); - this.children.forEach(function(c) { c.render(); }); - }; - - FaustTranscript.Text.prototype.getExt = function(coordRotation) { - // only measure the text extent without the decorations - var matrix = this.textElement.viewportElement.createSVGMatrix(); - matrix = matrix.rotate(coordRotation); - return SvgUtils.boundingBox(this.textElement, matrix).width; - }; - - FaustTranscript.CoveringImage.prototype.createView = function() { - this.spanningImage = this.svgDocument().createElementNS(SVG_NS, 'use'); - this.spanningImage.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); - this.spanningImage.setAttribute('class', this.type); - this.spanningImage.setAttribute('x', 0); - this.spanningImage.setAttribute('y', 0); - this.spanningImage.setAttribute('transform', 'scale(1)'); - var result = this.svgDocument().createElementNS(SVG_NS, "g"); - result.appendChild(this.spanningImage); - return result; - }; - - FaustTranscript.CoveringImage.prototype.svgContainer = function() { - return this.floatParent.view; - }; - - FaustTranscript.CoveringImage.prototype.containingRect = function () { - var that = this; - var coveredRects = this.coveredVCs.map(function (vc) { - return { - x: vc.getCoord(that.rotX()), - y: vc.getCoord(that.rotY()), - width: vc.getExt(that.rotX()), - height: vc.getExt(that.rotY()) - } - }); - var containingRect = coveredRects.reduce(SvgUtils.containingRect); - return containingRect; - }; - - FaustTranscript.CoveringImage.prototype.onRelayout = function() { - var containingRect = this.containingRect(); - // +1 works around a behaviour in firefox where the use element initially has width/height of 0, maybe due to - // deferred resource loading - var currentWidth = this.getExt(this.rotX()) + 1; - var currentHeight = this.getExt(this.rotY()) + 1; - var transform = this.spanningImage.viewportElement.createSVGTransform(); - transform.setScale(containingRect.width / currentWidth, containingRect.height / currentHeight); - //transform.setScale(1, 1); - this.spanningImage.transform.baseVal.consolidate(); - this.spanningImage.transform.baseVal.appendItem(transform); - this.spanningImage.transform.baseVal.consolidate(); - }; - - FaustTranscript.CoveringImage.prototype.position = function () { - var containingRect = this.containingRect(); - this.setCoord(containingRect.x, this.rotX()); - this.setCoord(containingRect.y, this.rotY()); - }; - - - - FaustTranscript.SpanningVC.prototype.createView = function() { - this.spanningRect = this.svgDocument().createElementNS(SVG_NS, 'use'); - this.spanningRect.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); - this.spanningRect.setAttribute('class', this.type); - this.spanningRect.setAttribute('x', 0); - this.spanningRect.setAttribute('y', 0); - this.spanningRect.setAttribute('width', this.imageWidth); - this.spanningRect.setAttribute('height', this.imageHeight); - this.spanningRect.setAttribute('transform', 'scale(0.000001)'); - - - this.svgContainer().appendChild(this.spanningRect); - var block = this.svgDocument().createElementNS(SVG_NS, 'rect'); - block.setAttribute('width', '0.1em'); - block.setAttribute('height', '0.1em'); - block.setAttribute('style', 'fill: transparent; stroke: black; visibility: hidden'); - block.setAttribute('class', 'SpanningDot'); - return block; - }; - - FaustTranscript.SpanningVC.prototype.onRelayout = function() { - var parentWidth = this.parent.getExt(this.rotX()); - var parentHeight = this.parent.getExt(this.rotY()); - var width = this.fixedWidth ? this.fixedWidth : parentWidth; - var height = this.fixedHeight ? this.fixedHeight : parentHeight; - this.spanningRect.setAttribute('x', (parentWidth - width) / 2); - this.spanningRect.setAttribute('y', (parentHeight - height) / 2); - - var transform = "scale(" + width / this.imageWidth + "," + height / this.imageHeight + ")"; - - //this.spanningRect.setAttribute('width', width); - //this.spanningRect.setAttribute('height', height); - this.spanningRect.setAttribute('transform', transform); - }; - - FaustTranscript.RectInlineDecoration.prototype.createView = function () { - this.shape = this.svgDocument().createElementNS(SVG_NS, "rect"); - this.shape.setAttribute('class', 'inline-decoration-type-rect inline-decoration'); - this.svgContainer().appendChild(this.shape); - return FaustTranscript.RectInlineDecoration.superclass.createView(); - }; - - FaustTranscript.RectInlineDecoration.prototype.onRelayout = function() { - var bbox = SvgUtils.boundingBox(this.view); - var padding = bbox.height / 10.0; - this.shape.setAttribute("x", bbox.x - padding); - this.shape.setAttribute("y", bbox.y - padding); - this.shape.setAttribute("height", bbox.height + 2 * padding); - this.shape.setAttribute("width", bbox.width + 2 * padding); - this.shape.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); - }; - - - - FaustTranscript.CircleInlineDecoration.prototype.createView = function () { - this.shape = this.svgDocument().createElementNS(SVG_NS, "ellipse"); - this.shape.setAttribute('class', 'inline-decoration-type-circle inline-decoration'); - this.svgContainer().appendChild(this.shape); - return FaustTranscript.CircleInlineDecoration.superclass.createView(); - }; - - FaustTranscript.CircleInlineDecoration.prototype.onRelayout = function() { - var bbox = SvgUtils.boundingBox(this.view); - var padding = bbox.height / 10.0; - this.shape.setAttribute("cx", bbox.x + bbox.width / 2.0); - this.shape.setAttribute("cy", bbox.y + bbox.height / 2.0); - this.shape.setAttribute("rx", bbox.width / 2.0 + padding); - this.shape.setAttribute("ry", bbox.height / 2.0 + padding); - this.shape.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); - }; - - FaustTranscript.InlineGraphic.prototype.createView = function() { - // FIXME: a g element must be used as a wrapper, because we cannot set the transform attribute on the element - // returned by createView() directly (as that is overwritten by layout). TODO: wrap the output of createView - // in a central place. - var g = this.svgDocument().createElementNS(SVG_NS, 'g'); - - this.graphic = this.svgDocument().createElementNS(SVG_NS, 'use'); - g.setAttribute('class', this.type); - this.graphic.setAttribute('width', this.imageWidth); - this.graphic.setAttribute('height', this.imageHeight); - this.graphic.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); - g.setAttribute('vector-effect', 'non-scaling-stroke'); - var transform = "scale(" + this.displayWidth / this.imageWidth + "," + this.displayHeight / this.imageHeight + ")"; - this.graphic.setAttribute('transform', transform); - g.setAttribute('transform', 'translate(0, -' + this.displayHeight + ')'); - g.appendChild(this.graphic); - return g; - }; - - FaustTranscript.GLine.prototype.createView = function() { - var line = this.svgDocument().createElementNS(SVG_NS, "line"); - line.setAttribute("x1", this.x); - line.setAttribute("y1", this.y - 10); - line.setAttribute("x2", this.x + 40); - line.setAttribute("y2", this.y - 10); - line.setAttribute("stroke-width", 1); - line.setAttribute("stroke", "black"); - return line; - }; - - FaustTranscript.GBrace.prototype.createView = function() { - var path = this.svgDocument().createElementNS(SVG_NS, "path"); - path.setAttribute("d", "M " + (this.x) + " " + (this.y) + " q 5,-10 20,-5 q 5,0 10,-10 q -5,0 10,10 q 10,-5 20,5"); - path.setAttribute("stroke-width", 1); - path.setAttribute("stroke", "black"); - path.setAttribute("fill", "transparent"); - return path; - }; - - FaustTranscript.TextDecoration.prototype.render = function() { - this.view = this.createView(); - this.view.setAttribute('class', this.classes.join(' ')); - this.text.view.appendChild(this.view); - }; - - FaustTranscript.NullDecoration.prototype.createView = function() { - var view = this.text.svgDocument().createElementNS(SVG_NS, "g"); - return view; - }; - - FaustTranscript.NullDecoration.prototype.layout = function() { - }; - - FaustTranscript.LineDecoration.prototype.createView = function() { - var view = this.text.svgDocument().createElementNS(SVG_NS, "line"); - return view; - }; - - FaustTranscript.LineDecoration.prototype.layout = function() { try { - var textBBox = this.text.textElement.getBBox(); - this.view.setAttribute("x1", textBBox.x); - this.view.setAttribute("x2", textBBox.x + textBBox.width); - var y = textBBox.height * this.yOffset; - this.view.setAttribute("y1", y); - this.view.setAttribute('y2', y); } catch (e) { console.error("Error in LineDecoration.Layout: ", e, this.text.textElement.textContent); } - }; - - FaustTranscript.CloneDecoration.prototype.createView = function() { - var view = this.text.createView(); - return view; - }; - - FaustTranscript.CloneDecoration.prototype.layout = function() { - var textBBox = this.text.textElement.getBBox(); - var matrix = this.view.viewportElement.createSVGMatrix(); - - matrix = matrix.translate(this.xOffset * textBBox.height, this.yOffset * textBBox.height); - var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); - this.view.transform.baseVal.consolidate(); - this.view.transform.baseVal.appendItem(transform); - this.view.transform.baseVal.consolidate(); - }; + return result; + }; + + FaustTranscript.Line.prototype.createView = function () { + var line = this.svgDocument().createElementNS(SVG_NS, "g"); + return line; + }; + + FaustTranscript.Line.prototype.getExt = function (coordRotation) { + var matrix = this.view.viewportElement.createSVGMatrix(); + // create artificial element with real line width but fixed height + var originalLineWidth = this.constructor.superclass.getExt.call(this, 0) + var extElement = this.svgDocument().createElementNS(SVG_NS, "rect"); + this.view.insertBefore(extElement, this.view.childNodes[0]); + extElement.setAttribute("width", originalLineWidth); + extElement.setAttribute("height", String(Faust.TranscriptConfiguration.lineSpacingValue) + + Faust.TranscriptConfiguration.lineSpacingUnit); + matrix = matrix.rotate(coordRotation); + var bbox = SvgUtils.boundingBox(extElement, matrix).width; + this.view.removeChild(extElement); + return bbox; + }; + + + FaustTranscript.Text.prototype.createView = function () { + // wrapper will contain text decorations + var wrapper = this.svgDocument().createElementNS(SVG_NS, "g"); + wrapper.setAttribute('class', 'text-wrapper'); + this.textElement = this.svgDocument().createElementNS(SVG_NS, "text"); + this.textElement.setAttribute("class", "text " + this.getClassesString()); + this.textElement.appendChild(this.svgDocument().createTextNode(this.text)); + wrapper.appendChild(this.textElement); + return wrapper; + }; + + FaustTranscript.Text.prototype.onRelayout = function () { + + var bbox = SvgUtils.boundingBox(this.view); + this.bgBox.setAttribute("x", bbox.x); + this.bgBox.setAttribute("y", bbox.y); + this.bgBox.setAttribute("height", bbox.height); + this.bgBox.setAttribute("width", bbox.width); + this.decorations.forEach(function (decoration) { + decoration.layout(); + }); + + }; + + FaustTranscript.Text.prototype.render = function () { + + this.view = this.createView(); + this.bgBox = this.svgDocument().createElementNS(SVG_NS, "rect"); + this.view.insertBefore(this.bgBox, this.view.childNodes[0]); + this.bgBox.setAttribute("class", "bgBox " + this.getClassesString()); + this.svgContainer().appendChild(this.view); + this.rotate(this.rotation); + this.decorations.forEach(function (decoration) { + decoration.render(); + }); + this.children.forEach(function (c) { + c.render(); + }); + }; + + FaustTranscript.Text.prototype.getExt = function (coordRotation) { + // only measure the text extent without the decorations + var matrix = this.textElement.viewportElement.createSVGMatrix(); + matrix = matrix.rotate(coordRotation); + return SvgUtils.boundingBox(this.textElement, matrix).width; + }; + + FaustTranscript.CoveringImage.prototype.createView = function () { + this.spanningImage = this.svgDocument().createElementNS(SVG_NS, 'use'); + this.spanningImage.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); + this.spanningImage.setAttribute('class', this.type); + this.spanningImage.setAttribute('x', 0); + this.spanningImage.setAttribute('y', 0); + this.spanningImage.setAttribute('transform', 'scale(1)'); + var result = this.svgDocument().createElementNS(SVG_NS, "g"); + result.appendChild(this.spanningImage); + return result; + }; + + FaustTranscript.CoveringImage.prototype.svgContainer = function () { + return this.floatParent.view; + }; + + FaustTranscript.CoveringImage.prototype.containingRect = function () { + var that = this; + var coveredRects = this.coveredVCs.map(function (vc) { + return { + x: vc.getCoord(that.rotX()), + y: vc.getCoord(that.rotY()), + width: vc.getExt(that.rotX()), + height: vc.getExt(that.rotY()) + } + }); + var containingRect = coveredRects.reduce(SvgUtils.containingRect); + return containingRect; + }; + + FaustTranscript.CoveringImage.prototype.onRelayout = function () { + var containingRect = this.containingRect(); + // +1 works around a behaviour in firefox where the use element initially has width/height of 0, maybe due to + // deferred resource loading + var currentWidth = this.getExt(this.rotX()) + 1; + var currentHeight = this.getExt(this.rotY()) + 1; + var transform = this.spanningImage.viewportElement.createSVGTransform(); + transform.setScale(containingRect.width / currentWidth, containingRect.height / currentHeight); + //transform.setScale(1, 1); + this.spanningImage.transform.baseVal.consolidate(); + this.spanningImage.transform.baseVal.appendItem(transform); + this.spanningImage.transform.baseVal.consolidate(); + }; + + FaustTranscript.CoveringImage.prototype.position = function () { + var containingRect = this.containingRect(); + this.setCoord(containingRect.x, this.rotX()); + this.setCoord(containingRect.y, this.rotY()); + }; + + + FaustTranscript.SpanningVC.prototype.createView = function () { + this.spanningRect = this.svgDocument().createElementNS(SVG_NS, 'use'); + this.spanningRect.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); + this.spanningRect.setAttribute('class', this.type); + this.spanningRect.setAttribute('x', 0); + this.spanningRect.setAttribute('y', 0); + this.spanningRect.setAttribute('width', this.imageWidth); + this.spanningRect.setAttribute('height', this.imageHeight); + this.spanningRect.setAttribute('transform', 'scale(0.000001)'); + + + this.svgContainer().appendChild(this.spanningRect); + var block = this.svgDocument().createElementNS(SVG_NS, 'rect'); + block.setAttribute('width', '0.1em'); + block.setAttribute('height', '0.1em'); + block.setAttribute('style', 'fill: transparent; stroke: black; visibility: hidden'); + block.setAttribute('class', 'SpanningDot'); + return block; + }; + + FaustTranscript.SpanningVC.prototype.onRelayout = function () { + var parentWidth = this.parent.getExt(this.rotX()); + var parentHeight = this.parent.getExt(this.rotY()); + var width = this.fixedWidth ? this.fixedWidth : parentWidth; + var height = this.fixedHeight ? this.fixedHeight : parentHeight; + this.spanningRect.setAttribute('x', (parentWidth - width) / 2); + this.spanningRect.setAttribute('y', (parentHeight - height) / 2); + + var transform = "scale(" + width / this.imageWidth + "," + height / this.imageHeight + ")"; + + //this.spanningRect.setAttribute('width', width); + //this.spanningRect.setAttribute('height', height); + this.spanningRect.setAttribute('transform', transform); + }; + + FaustTranscript.RectInlineDecoration.prototype.createView = function () { + this.shape = this.svgDocument().createElementNS(SVG_NS, "rect"); + this.shape.setAttribute('class', 'inline-decoration-type-rect inline-decoration'); + this.svgContainer().appendChild(this.shape); + return FaustTranscript.RectInlineDecoration.superclass.createView(); + }; + + FaustTranscript.RectInlineDecoration.prototype.onRelayout = function () { + var bbox = SvgUtils.boundingBox(this.view); + var padding = bbox.height / 10.0; + this.shape.setAttribute("x", bbox.x - padding); + this.shape.setAttribute("y", bbox.y - padding); + this.shape.setAttribute("height", bbox.height + 2 * padding); + this.shape.setAttribute("width", bbox.width + 2 * padding); + this.shape.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); + }; + + + FaustTranscript.CircleInlineDecoration.prototype.createView = function () { + this.shape = this.svgDocument().createElementNS(SVG_NS, "ellipse"); + this.shape.setAttribute('class', 'inline-decoration-type-circle inline-decoration'); + this.svgContainer().appendChild(this.shape); + return FaustTranscript.CircleInlineDecoration.superclass.createView(); + }; + + FaustTranscript.CircleInlineDecoration.prototype.onRelayout = function () { + var bbox = SvgUtils.boundingBox(this.view); + var padding = bbox.height / 10.0; + this.shape.setAttribute("cx", bbox.x + bbox.width / 2.0); + this.shape.setAttribute("cy", bbox.y + bbox.height / 2.0); + this.shape.setAttribute("rx", bbox.width / 2.0 + padding); + this.shape.setAttribute("ry", bbox.height / 2.0 + padding); + this.shape.transform.baseVal.initialize(this.view.transform.baseVal.consolidate()); + }; + + FaustTranscript.InlineGraphic.prototype.createView = function () { + // FIXME: a g element must be used as a wrapper, because we cannot set the transform attribute on the element + // returned by createView() directly (as that is overwritten by layout). TODO: wrap the output of createView + // in a central place. + var g = this.svgDocument().createElementNS(SVG_NS, 'g'); + + this.graphic = this.svgDocument().createElementNS(SVG_NS, 'use'); + g.setAttribute('class', this.type); + this.graphic.setAttribute('width', this.imageWidth); + this.graphic.setAttribute('height', this.imageHeight); + this.graphic.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.imageUrl); + g.setAttribute('vector-effect', 'non-scaling-stroke'); + var transform = "scale(" + this.displayWidth / this.imageWidth + "," + this.displayHeight / this.imageHeight + ")"; + this.graphic.setAttribute('transform', transform); + g.setAttribute('transform', 'translate(0, -' + this.displayHeight + ')'); + g.appendChild(this.graphic); + return g; + }; + + FaustTranscript.GLine.prototype.createView = function () { + var line = this.svgDocument().createElementNS(SVG_NS, "line"); + line.setAttribute("x1", this.x); + line.setAttribute("y1", this.y - 10); + line.setAttribute("x2", this.x + 40); + line.setAttribute("y2", this.y - 10); + line.setAttribute("stroke-width", 1); + line.setAttribute("stroke", "black"); + return line; + }; + + FaustTranscript.GBrace.prototype.createView = function () { + var path = this.svgDocument().createElementNS(SVG_NS, "path"); + path.setAttribute("d", "M " + (this.x) + " " + (this.y) + " q 5,-10 20,-5 q 5,0 10,-10 q -5,0 10,10 q 10,-5 20,5"); + path.setAttribute("stroke-width", 1); + path.setAttribute("stroke", "black"); + path.setAttribute("fill", "transparent"); + return path; + }; + + FaustTranscript.TextDecoration.prototype.render = function () { + this.view = this.createView(); + this.view.setAttribute('class', this.classes.join(' ')); + this.text.view.appendChild(this.view); + }; + + FaustTranscript.NullDecoration.prototype.createView = function () { + var view = this.text.svgDocument().createElementNS(SVG_NS, "g"); + return view; + }; + + FaustTranscript.NullDecoration.prototype.layout = function () { + }; + + FaustTranscript.LineDecoration.prototype.createView = function () { + var view = this.text.svgDocument().createElementNS(SVG_NS, "line"); + return view; + }; + + FaustTranscript.LineDecoration.prototype.layout = function () { + try { + var textBBox = this.text.textElement.getBBox(); + this.view.setAttribute("x1", textBBox.x); + this.view.setAttribute("x2", textBBox.x + textBBox.width); + var y = textBBox.height * this.yOffset; + this.view.setAttribute("y1", y); + this.view.setAttribute('y2', y); + } catch (e) { + console.error("Error in LineDecoration.Layout: ", e, this.text.textElement.textContent); + } + }; + + FaustTranscript.CloneDecoration.prototype.createView = function () { + var view = this.text.createView(); + return view; + }; + + FaustTranscript.CloneDecoration.prototype.layout = function () { + var textBBox = this.text.textElement.getBBox(); + var matrix = this.view.viewportElement.createSVGMatrix(); + + matrix = matrix.translate(this.xOffset * textBBox.height, this.yOffset * textBBox.height); + var transform = this.view.viewportElement.createSVGTransformFromMatrix(matrix); + this.view.transform.baseVal.consolidate(); + this.view.transform.baseVal.appendItem(transform); + this.view.transform.baseVal.consolidate(); + }; })(FaustTranscript); diff --git a/svg_rendering/page/js-gen/transcript.js b/svg_rendering/page/js-gen/transcript.js index 8e8acc5..816e4d5 100644 --- a/svg_rendering/page/js-gen/transcript.js +++ b/svg_rendering/page/js-gen/transcript.js @@ -17,523 +17,529 @@ * along with this program. If not, see . */ -if(window.FaustTranscript === undefined) { - window.FaustTranscript = {}; +if (window.FaustTranscript === undefined) { + window.FaustTranscript = {}; } -(function(FaustTranscript) { - - FaustTranscript.ENCODING_EXCEPTION_PREFIX = "ENCODING ERROR: "; - - FaustTranscript.ViewComponent = function() { - this.classes = []; - this.initViewComponent(); - }; - FaustTranscript.ViewComponent.prototype = { - rotation: 0, - elementName: '', - globalRotation: function () { - var e = this; - var result = 0; - while (e.parent) { - result += e.rotation; - e = e.parent; - } - result += e.rotation; - return result; - }, - initViewComponent: function() { - //this.parent = null; - this.pos = -1; - this.children = []; - - this.x = 0; - this.y = 0; - this.width = 0; - this.height = 0; - //this.hAlign = null; - //this.vAlign = null; - }, - add: function(vc) { - vc.parent = this; - vc.pos = this.children.length; - this.children.push(vc); - vc.defaultAligns(); - return vc; - }, - previous: function() { - return (this.parent == null || this.pos <= 0) ? null : this.parent.children[this.pos - 1]; - }, - next: function() { - return (this.parent == null || (this.pos + 1) >= this.parent.children.length) ? null : this.parent.children[this.pos + 1]; - }, - layout: function() { - this.computeDimension(); - this.computePosition(); - var dimensions = new FaustTranscript.Dimensions(); - if (this.children.length <= 0) { - dimensions.update(this.x, this.y, this.x + this.width, this.y + this.height); - } else { - - this.children.forEach(function(c) { - //if (!c.layoutSatisfied) { - c.layout(); - dimensions.update (c.x, c.y, c.x + c.width, c.y + c.height); - //} - }); - } - - this.onRelayout(); - - return dimensions; - }, - checkLayoutDiff: function(old, nu) { - var epsilon = 0.01; - this.layoutSatisfied = this.layoutSatisfied && abs(old - nu) < epsilon; - }, - computeDimension: function() { - var oldWidth = this.width; - var oldHeight = this.height; - //Y.each(this.children, function(c) { c.computeDimension(); }); - this.dimension(); - this.checkLayoutDiff(oldWidth, this.width); - this.checkLayoutDiff(oldHeight, this.height); - }, - dimension: function() { - this.width = 0; - this.height = 0; - this.children.forEach(function(c) { - if (c.width > this.width) { - this.width = c.width; +(function (FaustTranscript) { + + FaustTranscript.ENCODING_EXCEPTION_PREFIX = "ENCODING ERROR: "; + + FaustTranscript.ViewComponent = function () { + this.classes = []; + this.initViewComponent(); + }; + FaustTranscript.ViewComponent.prototype = { + rotation: 0, + elementName: '', + globalRotation: function () { + var e = this; + var result = 0; + while (e.parent) { + result += e.rotation; + e = e.parent; + } + result += e.rotation; + return result; + }, + initViewComponent: function () { + //this.parent = null; + this.pos = -1; + this.children = []; + + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + //this.hAlign = null; + //this.vAlign = null; + }, + add: function (vc) { + vc.parent = this; + vc.pos = this.children.length; + this.children.push(vc); + vc.defaultAligns(); + return vc; + }, + previous: function () { + return (this.parent == null || this.pos <= 0) ? null : this.parent.children[this.pos - 1]; + }, + next: function () { + return (this.parent == null || (this.pos + 1) >= this.parent.children.length) ? null : this.parent.children[this.pos + 1]; + }, + layout: function () { + this.computeDimension(); + this.computePosition(); + var dimensions = new FaustTranscript.Dimensions(); + if (this.children.length <= 0) { + dimensions.update(this.x, this.y, this.x + this.width, this.y + this.height); + } else { + + this.children.forEach(function (c) { + //if (!c.layoutSatisfied) { + c.layout(); + dimensions.update(c.x, c.y, c.x + c.width, c.y + c.height); + //} + }); + } + + this.onRelayout(); + + return dimensions; + }, + checkLayoutDiff: function (old, nu) { + var epsilon = 0.01; + this.layoutSatisfied = this.layoutSatisfied && abs(old - nu) < epsilon; + }, + computeDimension: function () { + var oldWidth = this.width; + var oldHeight = this.height; + //Y.each(this.children, function(c) { c.computeDimension(); }); + this.dimension(); + this.checkLayoutDiff(oldWidth, this.width); + this.checkLayoutDiff(oldHeight, this.height); + }, + dimension: function () { + this.width = 0; + this.height = 0; + this.children.forEach(function (c) { + if (c.width > this.width) { + this.width = c.width; + } + this.height += c.height; + + }, this); + }, + computePosition: function () { + var oldX = this.x; + var oldY = this.y; + this.position(); + //Y.each(this.children, function(c) { c.computePosition(); }); + this.checkLayoutDiff(oldX, this.x); + this.checkLayoutDiff(oldY, this.y); + }, + position: function () { + this.hAlign.align(); + this.vAlign.align(); + }, + computeClasses: function () { + return (this.elementName ? ['element-' + this.elementName] : []).concat(this.classes); + }, + rotX: function () { + return 0 + this.globalRotation(); + }, + rotY: function () { + return 90 + this.globalRotation(); + }, + + defaultAligns: function () { + + this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + + if (this.previous()) { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.previous(), this.rotX(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } else { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } + + }, + setAlign: function (name, align) { + if (this[name]) { + + if (align.priority === this[name].priority) { + var xmlId = this.xmlId ? this.xmlId : ''; + throw(FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Conflicting alignment instructions for element " + + this.elementName + " #" + xmlId + " (" + name + ", " + + FaustTranscript.Align[align.priority] + " )"); + } else if (align.priority > this[name].priority) { + this[name] = align; + } + } else { + this[name] = align; + } } - this.height += c.height; - - }, this); - }, - computePosition: function() { - var oldX = this.x; - var oldY = this.y; - this.position(); - //Y.each(this.children, function(c) { c.computePosition(); }); - this.checkLayoutDiff(oldX, this.x); - this.checkLayoutDiff(oldY, this.y); - }, - position: function() { - this.hAlign.align(); - this.vAlign.align(); - }, - computeClasses: function() { - return (this.elementName ? ['element-' + this.elementName] : []).concat(this.classes); - }, - rotX: function() {return 0 + this.globalRotation();}, - rotY: function() {return 90 + this.globalRotation();}, - - defaultAligns: function () { - - this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - - if (this.previous()) { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.previous(), this.rotX(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } else { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } - - }, - setAlign: function (name, align) { - if (this[name]) { - - if (align.priority === this[name].priority){ - var xmlId = this.xmlId ? this.xmlId : ''; - throw(FaustTranscript.ENCODING_EXCEPTION_PREFIX + "Conflicting alignment instructions for element " - + this.elementName + " #" + xmlId + " (" + name + ", " - + FaustTranscript.Align[align.priority] + " )"); - } else if (align.priority > this[name].priority) { - this[name] = align; + }; + + FaustTranscript.BlockViewComponent = function () { + FaustTranscript.BlockViewComponent.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.BlockViewComponent, FaustTranscript.ViewComponent); + + FaustTranscript.BlockViewComponent.prototype.defaultAligns = function () { + + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + + if (this.previous()) { + this.setAlign("vAlign", new FaustTranscript.Align(this, this.previous(), this.rotY(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } else { + this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } + }; + + FaustTranscript.InlineViewComponent = function () { + FaustTranscript.InlineViewComponent.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.InlineViewComponent, FaustTranscript.ViewComponent); + + FaustTranscript.InlineViewComponent.prototype.defaultAligns = function () { + + this.setAlign("vAlign", new FaustTranscript.NullAlign()); + + if (this.previous()) { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.previous(), this.rotX(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } else { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } + }; + + FaustTranscript.VSpace = function (height) { + FaustTranscript.VSpace.superclass.constructor.call(this); + this.vSpaceHeight = height; + }; + + Y.extend(FaustTranscript.VSpace, FaustTranscript.BlockViewComponent); + + + FaustTranscript.Patch = function () { + FaustTranscript.Patch.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.Patch, FaustTranscript.BlockViewComponent); + + + FaustTranscript.HSpace = function (width) { + FaustTranscript.HSpace.superclass.constructor.call(this); + this.hSpaceWidth = width; + }; + + Y.extend(FaustTranscript.HSpace, FaustTranscript.InlineViewComponent); + + FaustTranscript.Surface = function () { + FaustTranscript.Surface.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.Surface, FaustTranscript.BlockViewComponent); + + FaustTranscript.Surface.prototype.position = function () { + this.x = 0; + this.y = 0; + // TODO: surface-specific layout + }; + + + FaustTranscript.Zone = function () { + FaustTranscript.Zone.superclass.constructor.call(this); + this.floats = []; + }; + + Y.extend(FaustTranscript.Zone, FaustTranscript.BlockViewComponent); + + FaustTranscript.Zone.prototype.addFloat = function (vc) { + vc.parent = this; + vc.pos = this.children.length; + this.floats.push(vc); + vc.defaultAligns(); + return vc; + }; + + FaustTranscript.Zone.prototype.layout = function () { + FaustTranscript.Zone.superclass.layout.call(this); + this.floats.forEach(function (float) { + float.layout(); + }); + }; + + FaustTranscript.Line = function (lineAttrs) { + FaustTranscript.Line.superclass.constructor.call(this); + this.lineAttrs = lineAttrs; + }; + + Y.extend(FaustTranscript.Line, FaustTranscript.ViewComponent); + + FaustTranscript.Line.prototype.dimension = function () { + }; + + FaustTranscript.Line.prototype.numberOfPrecedingIntermediateLines = function () { + if (this.parent == null || this.pos <= 0) + return 0; + pre = this.parent.children[this.pos - 1]; + if (typeof pre.lineAttrs !== 'undefined' && pre.lineAttrs['interline'] === true) + return pre.numberOfPrecedingIntermediateLines() + 1; + else + return 0; + }; + + + FaustTranscript.Line.prototype.previousNonIntermediateLine = function () { + if (this.pos == 1) + return this.parent.children[0]; + if (this.parent == null || this.pos <= 0) + return null; + pre = this.parent.children[this.pos - 1]; + + if (typeof pre.lineAttrs !== 'undefined' && pre.lineAttrs['interline'] === true) + return pre.previousNonIntermediateLine(); + else + return pre; + }; + + FaustTranscript.Line.prototype.defaultAligns = function () { + + if ("indent" in this.lineAttrs) { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, this.lineAttrs["indent"], FaustTranscript.Align.INDENT_ATTR)); + } else if ("indentCenter" in this.lineAttrs) { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0.5, this.lineAttrs["indentCenter"], FaustTranscript.Align.INDENT_CENTER_ATTR)); + } else { + this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } + + INTERLINE_DISTANCE = 0.5; + REGULAR_LINE_DISTANCE = 1; + + if (this.previous()) { + var yourJoint = this.lineAttrs['interline'] ? (this.numberOfPrecedingIntermediateLines() + 1) * INTERLINE_DISTANCE : + (Math.max(0, this.numberOfPrecedingIntermediateLines() - 1) * INTERLINE_DISTANCE) + REGULAR_LINE_DISTANCE; + if (Faust.TranscriptConfiguration.overlay === "overlay") { + //yourJoint = ("between" in this.lineAttrs)? 1 : 1; + yourJoint = ("over" in this.lineAttrs) ? 0.1 : yourJoint; + } else { + yourJoint = ("between" in this.lineAttrs) ? 0.7 : yourJoint; + yourJoint = ("over" in this.lineAttrs) ? 0.5 : yourJoint; + } + + this.setAlign("vAlign", new FaustTranscript.Align(this, this.previousNonIntermediateLine(), this.rotY(), 0, yourJoint, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + + } else { + this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); + } + }; + + FaustTranscript.Text = function (text) { + FaustTranscript.Text.superclass.constructor.call(this); + this.decorations = []; + this.text = text.replace(/\s+/g, "\u00a0"); + this.textElement = null; + }; + + Y.extend(FaustTranscript.Text, FaustTranscript.InlineViewComponent); + + FaustTranscript.Text.prototype.dimension = function () { + var measured = this.measure(); + this.width = measured.width; + this.height = measured.height; + }; + + FaustTranscript.FloatVC = function (classes, floatParent) { + FaustTranscript.FloatVC.superclass.constructor.call(this); + this.classes = this.classes.concat(classes); + this.floatParent = floatParent; + }; + + Y.extend(FaustTranscript.FloatVC, FaustTranscript.ViewComponent); + + FaustTranscript.FloatVC.prototype.globalRotation = function () { + // Floats are always global + return this.rotation; + }; + + FaustTranscript.CoveringImage = function (type, classes, imageUrl, fixedWidth, fixedHeight, floatParent) { + FaustTranscript.CoveringImage.superclass.constructor.call(this, classes, floatParent); + this.type = type; + this.imageUrl = imageUrl; + this.fixedWidth = fixedWidth; + this.fixedHeight = fixedHeight; + this.coveredVCs = []; + this.classes.push('use-image'); + }; + + Y.extend(FaustTranscript.CoveringImage, FaustTranscript.FloatVC); + + FaustTranscript.StretchingImage = function (type, classes, imageUrl, fixedWidth, fixedHeight, floatParent) { + FaustTranscript.StretchingImage.superclass.constructor.call(this, classes, floatParent); + this.type = type; + this.imageUrl = imageUrl; + this.fixedWidth = fixedWidth; + this.fixedHeight = fixedHeight; + this.coveredVCs = []; + this.classes.push('use-image'); + }; + + Y.extend(FaustTranscript.StretchingImage, FaustTranscript.FloatVC); + + + FaustTranscript.SpanningVC = function (type, imageUrl, imageWidth, imageHeight, fixedWidth, fixedHeight) { + FaustTranscript.SpanningVC.superclass.constructor.call(this); + this.type = type; + this.imageUrl = imageUrl; + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; + this.fixedWidth = fixedWidth; + this.fixedHeight = fixedHeight; + this.classes.push('use-image'); + }; + + Y.extend(FaustTranscript.SpanningVC, FaustTranscript.ViewComponent); + + FaustTranscript.InlineDecoration = function (classes) { + FaustTranscript.InlineDecoration.superclass.constructor.call(this); + this.classes = this.classes.concat(classes); + this.classes.push('inline-decoration'); + }; + + Y.extend(FaustTranscript.InlineDecoration, FaustTranscript.InlineViewComponent); + + FaustTranscript.RectInlineDecoration = function (classes) { + FaustTranscript.RectInlineDecoration.superclass.constructor.call(this); + this.classes.push('inline-decoration-type-rect'); + }; + + Y.extend(FaustTranscript.RectInlineDecoration, FaustTranscript.InlineDecoration); + + FaustTranscript.CircleInlineDecoration = function (classes) { + FaustTranscript.CircleInlineDecoration.superclass.constructor.call(this); + this.classes.push('inline-decoration-type-circle'); + }; + + Y.extend(FaustTranscript.CircleInlineDecoration, FaustTranscript.InlineDecoration); + + + FaustTranscript.InlineGraphic = function (type, imageUrl, imageWidth, imageHeight, displayWidth, displayHeight) { + FaustTranscript.InlineGraphic.superclass.constructor.call(this); + this.type = type; + this.imageUrl = imageUrl; + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; + this.displayWidth = displayWidth; + this.displayHeight = displayHeight; + this.classes.push('use-image'); + }; + + Y.extend(FaustTranscript.InlineGraphic, FaustTranscript.InlineViewComponent); + + FaustTranscript.GLine = function () { + FaustTranscript.GLine.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.GLine, FaustTranscript.ViewComponent); + + FaustTranscript.GLine.prototype.dimension = function () { + this.width = 40; + this.height = 20; + }; + + + FaustTranscript.GBrace = function () { + FaustTranscript.GBrace.superclass.constructor.call(this); + }; + + Y.extend(FaustTranscript.GBrace, FaustTranscript.ViewComponent); + + FaustTranscript.GBrace.prototype.dimension = function () { + this.width = 40; + this.height = 20; + }; + + FaustTranscript.TextDecoration = function (text, classes) { + this.text = text; + this.classes = classes; + this.classes.push('text-decoration'); + }; + + FaustTranscript.TextDecoration.prototype.layout = function () { + }; + + FaustTranscript.NullDecoration = function (text, classes, name) { + FaustTranscript.NullDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); + }; + Y.extend(FaustTranscript.NullDecoration, FaustTranscript.TextDecoration); + + FaustTranscript.LineDecoration = function (text, classes, name, yOffset) { + FaustTranscript.LineDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); + this.yOffset = yOffset; + }; + Y.extend(FaustTranscript.LineDecoration, FaustTranscript.TextDecoration); + + FaustTranscript.CloneDecoration = function (text, classes, name, xOffset, yOffset) { + FaustTranscript.CloneDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); + this.xOffset = xOffset; + this.yOffset = yOffset; + }; + Y.extend(FaustTranscript.CloneDecoration, FaustTranscript.TextDecoration); + + FaustTranscript.Align = function (me, you, coordRotation, myJoint, yourJoint, priority) { + this.me = me; + this.you = you; + this.coordRotation = coordRotation; + this.myJoint = myJoint; + this.yourJoint = yourJoint; + this.priority = priority; + }; + + FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER = 0; + FaustTranscript.Align['0'] = 'IMPLICIT_BY_DOC_ORDER'; + FaustTranscript.Align.REND_ATTR = 5; + FaustTranscript.Align['5'] = 'REND_ATTR'; + FaustTranscript.Align.INDENT_ATTR = 7; + FaustTranscript.Align['7'] = 'INDENT_ATTR'; + FaustTranscript.Align.INDENT_ATTR = 7; + FaustTranscript.Align['8'] = 'INDENT_CENTER_ATTR'; + FaustTranscript.Align.EXPLICIT = 10; + FaustTranscript.Align['10'] = 'EXPLICIT'; + FaustTranscript.Align.MAIN_ZONE = 15; + FaustTranscript.Align['15'] = 'MAIN_ZONE'; + + + FaustTranscript.Align.prototype.align = function () { + var value = this.you.getCoord(this.coordRotation); + value -= this.myJoint * this.me.getExt(this.coordRotation); + value += this.yourJoint * this.you.getExt(this.coordRotation); + this.me.setCoord(value, this.coordRotation); + }; + + FaustTranscript.AbsoluteAlign = function (me, coordRotation, coordinate, priority) { + this.me = me; + this.coordRotation = coordRotation; + this.coordinate = coordinate; + this.priority = priority; + }; + + FaustTranscript.AbsoluteAlign.prototype.align = function () { + this.me.setCoord(this.coordinate, this.coordRotation); + }; + + FaustTranscript.NullAlign = function (priority) { + this.priority = priority; + }; + + FaustTranscript.NullAlign.prototype.align = function () { + }; + + FaustTranscript.Dimensions = function () { + }; + + FaustTranscript.Dimensions.prototype = function () { + }; + + FaustTranscript.Dimensions.prototype.update = function (xMin, yMin, xMax, yMax) { + + if (!this.xMin || this.xMin > xMin) { + this.xMin = xMin; + } + + if (!this.yMin || this.yMin > yMin) { + this.yMin = yMin; + } + + if (!this.xMax || this.xMax < xMax) { + this.xMax = xMax; + } + + if (!this.yMax || this.yMax < yMax) { + this.yMax = yMax; } - } else { - this[name] = align; - } - } - }; - - FaustTranscript.BlockViewComponent = function() { - FaustTranscript.BlockViewComponent.superclass.constructor.call(this); - }; - - Y.extend (FaustTranscript.BlockViewComponent, FaustTranscript.ViewComponent); - - FaustTranscript.BlockViewComponent.prototype.defaultAligns = function () { - - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - - if (this.previous()) { - this.setAlign("vAlign", new FaustTranscript.Align(this, this.previous(), this.rotY(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } else { - this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } - }; - - FaustTranscript.InlineViewComponent = function() { - FaustTranscript.InlineViewComponent.superclass.constructor.call(this); - }; - - Y.extend (FaustTranscript.InlineViewComponent, FaustTranscript.ViewComponent); - - FaustTranscript.InlineViewComponent.prototype.defaultAligns = function () { - - this.setAlign("vAlign", new FaustTranscript.NullAlign()); - - if (this.previous()) { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.previous(), this.rotX(), 0, 1, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } else { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } - }; - - FaustTranscript.VSpace = function(height) { - FaustTranscript.VSpace.superclass.constructor.call(this); - this.vSpaceHeight = height; - }; - - Y.extend (FaustTranscript.VSpace, FaustTranscript.BlockViewComponent); - - - FaustTranscript.Patch = function() { - FaustTranscript.Patch.superclass.constructor.call(this); - }; - - Y.extend (FaustTranscript.Patch, FaustTranscript.BlockViewComponent); - - - FaustTranscript.HSpace = function(width) { - FaustTranscript.HSpace.superclass.constructor.call(this); - this.hSpaceWidth = width; - }; - - Y.extend (FaustTranscript.HSpace, FaustTranscript.InlineViewComponent); - - FaustTranscript.Surface = function() { - FaustTranscript.Surface.superclass.constructor.call(this); - }; - - Y.extend(FaustTranscript.Surface, FaustTranscript.BlockViewComponent); - - FaustTranscript.Surface.prototype.position = function() { - this.x = 0; - this.y = 0; - // TODO: surface-specific layout - }; - - - - FaustTranscript.Zone = function() { - FaustTranscript.Zone.superclass.constructor.call(this); - this.floats = []; - }; - - Y.extend(FaustTranscript.Zone, FaustTranscript.BlockViewComponent); - - FaustTranscript.Zone.prototype.addFloat = function (vc) { - vc.parent = this; - vc.pos = this.children.length; - this.floats.push(vc); - vc.defaultAligns(); - return vc; - }; - - FaustTranscript.Zone.prototype.layout = function () { - FaustTranscript.Zone.superclass.layout.call(this); - this.floats.forEach(function (float) { - float.layout(); - }); - }; - - FaustTranscript.Line = function(lineAttrs) { - FaustTranscript.Line.superclass.constructor.call(this); - this.lineAttrs = lineAttrs; - }; - - Y.extend(FaustTranscript.Line, FaustTranscript.ViewComponent); - - FaustTranscript.Line.prototype.dimension = function() { - }; - - FaustTranscript.Line.prototype.numberOfPrecedingIntermediateLines = function() { - if (this.parent == null || this.pos <= 0) - return 0; - pre = this.parent.children[this.pos - 1]; - if (typeof pre.lineAttrs !== 'undefined' && pre.lineAttrs['interline'] === true) - return pre.numberOfPrecedingIntermediateLines() + 1; - else - return 0; - }; - - - FaustTranscript.Line.prototype.previousNonIntermediateLine = function() { - if (this.pos == 1) - return this.parent.children[0]; - if (this.parent == null || this.pos <= 0) - return null; - pre = this.parent.children[this.pos - 1]; - - if (typeof pre.lineAttrs !== 'undefined' && pre.lineAttrs['interline'] === true) - return pre.previousNonIntermediateLine(); - else - return pre; - }; - - FaustTranscript.Line.prototype.defaultAligns = function () { - - if ("indent" in this.lineAttrs) { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, this.lineAttrs["indent"], FaustTranscript.Align.INDENT_ATTR)); - } else if ("indentCenter" in this.lineAttrs) { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0.5, this.lineAttrs["indentCenter"], FaustTranscript.Align.INDENT_CENTER_ATTR)); - } else { - this.setAlign("hAlign", new FaustTranscript.Align(this, this.parent, this.rotX(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } - - INTERLINE_DISTANCE = 0.5; - REGULAR_LINE_DISTANCE = 1; - - if (this.previous()) { - var yourJoint = this.lineAttrs['interline'] ? (this.numberOfPrecedingIntermediateLines() + 1) * INTERLINE_DISTANCE : - (Math.max(0, this.numberOfPrecedingIntermediateLines() - 1) * INTERLINE_DISTANCE) + REGULAR_LINE_DISTANCE; - if (Faust.TranscriptConfiguration.overlay === "overlay") { - //yourJoint = ("between" in this.lineAttrs)? 1 : 1; - yourJoint = ("over" in this.lineAttrs)? 0.1 : yourJoint; - } else { - yourJoint = ("between" in this.lineAttrs)? 0.7 : yourJoint; - yourJoint = ("over" in this.lineAttrs)? 0.5 : yourJoint; - } - - this.setAlign("vAlign", new FaustTranscript.Align(this, this.previousNonIntermediateLine(), this.rotY(), 0, yourJoint, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - - } else { - this.setAlign("vAlign", new FaustTranscript.Align(this, this.parent, this.rotY(), 0, 0, FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER)); - } - }; - - FaustTranscript.Text = function(text) { - FaustTranscript.Text.superclass.constructor.call(this); - this.decorations = []; - this.text = text.replace(/\s+/g, "\u00a0"); - this.textElement = null; - }; - - Y.extend(FaustTranscript.Text, FaustTranscript.InlineViewComponent); - - FaustTranscript.Text.prototype.dimension = function() { - var measured = this.measure(); - this.width = measured.width; - this.height = measured.height; - }; - - FaustTranscript.FloatVC = function(classes, floatParent) { - FaustTranscript.FloatVC.superclass.constructor.call(this); - this.classes = this.classes.concat(classes); - this.floatParent = floatParent; - }; - - Y.extend (FaustTranscript.FloatVC, FaustTranscript.ViewComponent); - - FaustTranscript.FloatVC.prototype.globalRotation = function() { - // Floats are always global - return this.rotation; - }; - - FaustTranscript.CoveringImage = function(type, classes, imageUrl, fixedWidth, fixedHeight, floatParent) { - FaustTranscript.CoveringImage.superclass.constructor.call(this, classes, floatParent); - this.type = type; - this.imageUrl = imageUrl; - this.fixedWidth = fixedWidth; - this.fixedHeight = fixedHeight; - this.coveredVCs = []; - this.classes.push('use-image'); - }; - - Y.extend (FaustTranscript.CoveringImage, FaustTranscript.FloatVC); - - FaustTranscript.StretchingImage = function(type, classes, imageUrl, fixedWidth, fixedHeight, floatParent) { - FaustTranscript.StretchingImage.superclass.constructor.call(this, classes, floatParent); - this.type = type; - this.imageUrl = imageUrl; - this.fixedWidth = fixedWidth; - this.fixedHeight = fixedHeight; - this.coveredVCs = []; - this.classes.push('use-image'); - }; - - Y.extend(FaustTranscript.StretchingImage, FaustTranscript.FloatVC); - - - FaustTranscript.SpanningVC = function(type, imageUrl, imageWidth, imageHeight, fixedWidth, fixedHeight) { - FaustTranscript.SpanningVC.superclass.constructor.call(this); - this.type = type; - this.imageUrl = imageUrl; - this.imageWidth = imageWidth; - this.imageHeight = imageHeight; - this.fixedWidth = fixedWidth; - this.fixedHeight = fixedHeight; - this.classes.push('use-image'); - }; - - Y.extend (FaustTranscript.SpanningVC, FaustTranscript.ViewComponent); - - FaustTranscript.InlineDecoration = function(classes) { - FaustTranscript.InlineDecoration.superclass.constructor.call(this); - this.classes = this.classes.concat(classes); - this.classes.push('inline-decoration'); - }; - - Y.extend (FaustTranscript.InlineDecoration, FaustTranscript.InlineViewComponent); - - FaustTranscript.RectInlineDecoration = function(classes) { - FaustTranscript.RectInlineDecoration.superclass.constructor.call(this); - this.classes.push('inline-decoration-type-rect'); - }; - - Y.extend (FaustTranscript.RectInlineDecoration, FaustTranscript.InlineDecoration); - - FaustTranscript.CircleInlineDecoration = function(classes) { - FaustTranscript.CircleInlineDecoration.superclass.constructor.call(this); - this.classes.push('inline-decoration-type-circle'); - }; - - Y.extend (FaustTranscript.CircleInlineDecoration, FaustTranscript.InlineDecoration); - - - FaustTranscript.InlineGraphic = function(type, imageUrl, imageWidth, imageHeight, displayWidth, displayHeight) { - FaustTranscript.InlineGraphic.superclass.constructor.call(this); - this.type = type; - this.imageUrl = imageUrl; - this.imageWidth = imageWidth; - this.imageHeight = imageHeight; - this.displayWidth = displayWidth; - this.displayHeight = displayHeight; - this.classes.push('use-image'); - }; - - Y.extend (FaustTranscript.InlineGraphic, FaustTranscript.InlineViewComponent); - - FaustTranscript.GLine = function() { - FaustTranscript.GLine.superclass.constructor.call(this); - }; - - Y.extend(FaustTranscript.GLine, FaustTranscript.ViewComponent); - - FaustTranscript.GLine.prototype.dimension = function() { - this.width = 40; - this.height = 20; - }; - - - FaustTranscript.GBrace = function() { - FaustTranscript.GBrace.superclass.constructor.call(this); - }; - - Y.extend(FaustTranscript.GBrace, FaustTranscript.ViewComponent); - - FaustTranscript.GBrace.prototype.dimension = function() { - this.width = 40; - this.height = 20; - }; - - FaustTranscript.TextDecoration = function(text, classes) { - this.text = text; - this.classes = classes; - this.classes.push('text-decoration'); - }; - - FaustTranscript.TextDecoration.prototype.layout = function() {}; - - FaustTranscript.NullDecoration = function (text, classes, name) { - FaustTranscript.NullDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); - }; - Y.extend(FaustTranscript.NullDecoration, FaustTranscript.TextDecoration); - - FaustTranscript.LineDecoration = function (text, classes, name, yOffset) { - FaustTranscript.LineDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); - this.yOffset = yOffset; - }; - Y.extend(FaustTranscript.LineDecoration, FaustTranscript.TextDecoration); - - FaustTranscript.CloneDecoration = function (text, classes, name, xOffset, yOffset) { - FaustTranscript.CloneDecoration.superclass.constructor.call(this, text, classes.concat(['text-decoration-type-' + name])); - this.xOffset = xOffset; - this.yOffset = yOffset; - }; - Y.extend(FaustTranscript.CloneDecoration, FaustTranscript.TextDecoration); - - FaustTranscript.Align = function(me, you, coordRotation, myJoint, yourJoint, priority) { - this.me = me; - this.you = you; - this.coordRotation = coordRotation; - this.myJoint = myJoint; - this.yourJoint = yourJoint; - this.priority = priority; - }; - - FaustTranscript.Align.IMPLICIT_BY_DOC_ORDER = 0; - FaustTranscript.Align['0'] = 'IMPLICIT_BY_DOC_ORDER'; - FaustTranscript.Align.REND_ATTR = 5; - FaustTranscript.Align['5'] = 'REND_ATTR'; - FaustTranscript.Align.INDENT_ATTR = 7; - FaustTranscript.Align['7'] = 'INDENT_ATTR'; - FaustTranscript.Align.INDENT_ATTR = 7; - FaustTranscript.Align['8'] = 'INDENT_CENTER_ATTR'; - FaustTranscript.Align.EXPLICIT = 10; - FaustTranscript.Align['10'] = 'EXPLICIT'; - FaustTranscript.Align.MAIN_ZONE = 15; - FaustTranscript.Align['15'] = 'MAIN_ZONE'; - - - FaustTranscript.Align.prototype.align = function() { - var value = this.you.getCoord(this.coordRotation); - value -= this.myJoint * this.me.getExt(this.coordRotation); - value += this.yourJoint * this.you.getExt(this.coordRotation); - this.me.setCoord(value, this.coordRotation); - }; - - FaustTranscript.AbsoluteAlign = function (me, coordRotation, coordinate, priority) { - this.me = me; - this.coordRotation = coordRotation; - this.coordinate = coordinate; - this.priority = priority; - }; - - FaustTranscript.AbsoluteAlign.prototype.align = function() { - this.me.setCoord(this.coordinate, this.coordRotation); - }; - - FaustTranscript.NullAlign = function (priority) { - this.priority = priority; - }; - - FaustTranscript.NullAlign.prototype.align = function() { - }; - - FaustTranscript.Dimensions = function() {}; - - FaustTranscript.Dimensions.prototype = function() {}; - - FaustTranscript.Dimensions.prototype.update = function(xMin, yMin, xMax, yMax) { - - if (!this.xMin || this.xMin > xMin ) { - this.xMin = xMin; - } - - if (!this.yMin || this.yMin > yMin ) { - this.yMin = yMin; - } - - if (!this.xMax || this.xMax < xMax ) { - this.xMax = xMax; - } - - if (!this.yMax || this.yMax < yMax ) { - this.yMax = yMax; - } - }; + }; })(FaustTranscript);