|
@@ -27519,9 +27519,10 @@ var ShapeUtils = {
|
|
|
//
|
|
|
|
|
|
var holeIndex = contour.length;
|
|
|
+
|
|
|
holes.forEach( removeDupEndPts );
|
|
|
|
|
|
- for ( i = 0; i < holes.length; i ++ ) {
|
|
|
+ for ( var i = 0; i < holes.length; i ++ ) {
|
|
|
|
|
|
holeIndices.push( holeIndex );
|
|
|
holeIndex += holes[ i ].length;
|
|
@@ -37991,155 +37992,151 @@ Object.assign( Font.prototype, {
|
|
|
|
|
|
generateShapes: function ( text, size, divisions ) {
|
|
|
|
|
|
- function createPaths( text ) {
|
|
|
-
|
|
|
- var chars = String( text ).split( '' );
|
|
|
- var scale = size / data.resolution;
|
|
|
- var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
|
|
|
-
|
|
|
- var offsetX = 0, offsetY = 0;
|
|
|
-
|
|
|
- var paths = [];
|
|
|
+ if ( size === undefined ) size = 100;
|
|
|
+ if ( divisions === undefined ) divisions = 4;
|
|
|
|
|
|
- for ( var i = 0; i < chars.length; i ++ ) {
|
|
|
+ var shapes = [];
|
|
|
+ var paths = createPaths( text, size, divisions, this.data );
|
|
|
|
|
|
- var char = chars[ i ];
|
|
|
+ for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
|
|
|
|
|
|
- if ( char === '\n' ) {
|
|
|
+ Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
|
|
|
|
|
|
- offsetX = 0;
|
|
|
- offsetY -= line_height;
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ return shapes;
|
|
|
|
|
|
- var ret = createPath( char, scale, offsetX, offsetY );
|
|
|
- offsetX += ret.offsetX;
|
|
|
- paths.push( ret.path );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+} );
|
|
|
|
|
|
- }
|
|
|
+function createPaths( text, size, divisions, data ) {
|
|
|
|
|
|
- return paths;
|
|
|
+ var chars = String( text ).split( '' );
|
|
|
+ var scale = size / data.resolution;
|
|
|
+ var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
|
|
|
|
|
|
- }
|
|
|
+ var paths = [];
|
|
|
|
|
|
- function createPath( c, scale, offsetX, offsetY ) {
|
|
|
+ var offsetX = 0, offsetY = 0;
|
|
|
|
|
|
- var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
|
|
|
+ for ( var i = 0; i < chars.length; i ++ ) {
|
|
|
|
|
|
- if ( ! glyph ) return;
|
|
|
+ var char = chars[ i ];
|
|
|
|
|
|
- var path = new ShapePath();
|
|
|
+ if ( char === '\n' ) {
|
|
|
|
|
|
- var pts = [];
|
|
|
- var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
|
|
|
+ offsetX = 0;
|
|
|
+ offsetY -= line_height;
|
|
|
|
|
|
- if ( glyph.o ) {
|
|
|
+ } else {
|
|
|
|
|
|
- var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
|
|
|
+ var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
|
|
|
+ offsetX += ret.offsetX;
|
|
|
+ paths.push( ret.path );
|
|
|
|
|
|
- for ( var i = 0, l = outline.length; i < l; ) {
|
|
|
+ }
|
|
|
|
|
|
- var action = outline[ i ++ ];
|
|
|
+ }
|
|
|
|
|
|
- switch ( action ) {
|
|
|
+ return paths;
|
|
|
|
|
|
- case 'm': // moveTo
|
|
|
+}
|
|
|
|
|
|
- x = outline[ i ++ ] * scale + offsetX;
|
|
|
- y = outline[ i ++ ] * scale + offsetY;
|
|
|
+function createPath( char, divisions, scale, offsetX, offsetY, data ) {
|
|
|
|
|
|
- path.moveTo( x, y );
|
|
|
+ var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
|
|
|
|
|
|
- break;
|
|
|
+ if ( ! glyph ) return;
|
|
|
|
|
|
- case 'l': // lineTo
|
|
|
+ var path = new ShapePath();
|
|
|
|
|
|
- x = outline[ i ++ ] * scale + offsetX;
|
|
|
- y = outline[ i ++ ] * scale + offsetY;
|
|
|
+ var pts = [];
|
|
|
+ var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
|
|
|
|
|
|
- path.lineTo( x, y );
|
|
|
+ if ( glyph.o ) {
|
|
|
|
|
|
- break;
|
|
|
+ var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
|
|
|
|
|
|
- case 'q': // quadraticCurveTo
|
|
|
+ for ( var i = 0, l = outline.length; i < l; ) {
|
|
|
|
|
|
- cpx = outline[ i ++ ] * scale + offsetX;
|
|
|
- cpy = outline[ i ++ ] * scale + offsetY;
|
|
|
- cpx1 = outline[ i ++ ] * scale + offsetX;
|
|
|
- cpy1 = outline[ i ++ ] * scale + offsetY;
|
|
|
+ var action = outline[ i ++ ];
|
|
|
|
|
|
- path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
|
|
|
+ switch ( action ) {
|
|
|
|
|
|
- laste = pts[ pts.length - 1 ];
|
|
|
+ case 'm': // moveTo
|
|
|
|
|
|
- if ( laste ) {
|
|
|
+ x = outline[ i ++ ] * scale + offsetX;
|
|
|
+ y = outline[ i ++ ] * scale + offsetY;
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
- cpy0 = laste.y;
|
|
|
+ path.moveTo( x, y );
|
|
|
|
|
|
-
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ case 'l': // lineTo
|
|
|
|
|
|
- break;
|
|
|
+ x = outline[ i ++ ] * scale + offsetX;
|
|
|
+ y = outline[ i ++ ] * scale + offsetY;
|
|
|
|
|
|
- case 'b': // bezierCurveTo
|
|
|
+ path.lineTo( x, y );
|
|
|
|
|
|
- cpx = outline[ i ++ ] * scale + offsetX;
|
|
|
- cpy = outline[ i ++ ] * scale + offsetY;
|
|
|
- cpx1 = outline[ i ++ ] * scale + offsetX;
|
|
|
- cpy1 = outline[ i ++ ] * scale + offsetY;
|
|
|
- cpx2 = outline[ i ++ ] * scale + offsetX;
|
|
|
- cpy2 = outline[ i ++ ] * scale + offsetY;
|
|
|
+ break;
|
|
|
|
|
|
- path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
|
|
|
+ case 'q': // quadraticCurveTo
|
|
|
|
|
|
- laste = pts[ pts.length - 1 ];
|
|
|
+ cpx = outline[ i ++ ] * scale + offsetX;
|
|
|
+ cpy = outline[ i ++ ] * scale + offsetY;
|
|
|
+ cpx1 = outline[ i ++ ] * scale + offsetX;
|
|
|
+ cpy1 = outline[ i ++ ] * scale + offsetY;
|
|
|
|
|
|
- if ( laste ) {
|
|
|
+ path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
- cpy0 = laste.y;
|
|
|
+ laste = pts[ pts.length - 1 ];
|
|
|
|
|
|
-
|
|
|
+ if ( laste ) {
|
|
|
|
|
|
- }
|
|
|
+ cpx0 = laste.x;
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- break;
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ case 'b': // bezierCurveTo
|
|
|
|
|
|
- return { offsetX: glyph.ha * scale, path: path };
|
|
|
+ cpx = outline[ i ++ ] * scale + offsetX;
|
|
|
+ cpy = outline[ i ++ ] * scale + offsetY;
|
|
|
+ cpx1 = outline[ i ++ ] * scale + offsetX;
|
|
|
+ cpy1 = outline[ i ++ ] * scale + offsetY;
|
|
|
+ cpx2 = outline[ i ++ ] * scale + offsetX;
|
|
|
+ cpy2 = outline[ i ++ ] * scale + offsetY;
|
|
|
|
|
|
- }
|
|
|
+ path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
|
|
|
|
|
|
- //
|
|
|
+ laste = pts[ pts.length - 1 ];
|
|
|
|
|
|
- if ( size === undefined ) size = 100;
|
|
|
- if ( divisions === undefined ) divisions = 4;
|
|
|
+ if ( laste ) {
|
|
|
|
|
|
- var data = this.data;
|
|
|
+ cpx0 = laste.x;
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- var paths = createPaths( text );
|
|
|
- var shapes = [];
|
|
|
+
|
|
|
|
|
|
- for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
|
|
|
+ }
|
|
|
|
|
|
- Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- return shapes;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
-} );
|
|
|
+ return { offsetX: glyph.ha * scale, path: path };
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
@@ -39226,6 +39223,9 @@ Object.assign( PropertyMixer.prototype, {
|
|
|
* @author tschw
|
|
|
*/
|
|
|
|
|
|
+// Characters [].:/ are reserved for track binding syntax.
|
|
|
+var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
|
|
|
+
|
|
|
function Composite( targetGroup, path, optionalParsedPath ) {
|
|
|
|
|
|
var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
|
|
@@ -39327,35 +39327,47 @@ Object.assign( PropertyBinding, {
|
|
|
* @param {string} name Node name to be sanitized.
|
|
|
* @return {string}
|
|
|
*/
|
|
|
- sanitizeNodeName: function ( name ) {
|
|
|
+ sanitizeNodeName: ( function () {
|
|
|
|
|
|
- return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' );
|
|
|
+ var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
|
|
|
|
|
|
- },
|
|
|
+ return function sanitizeNodeName ( name ) {
|
|
|
+
|
|
|
+ return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ }() ),
|
|
|
|
|
|
parseTrackName: function () {
|
|
|
|
|
|
+ // Attempts to allow node names from any language. ES5's `\w` regexp matches
|
|
|
+ // only latin characters, and the unicode \p{L} is not yet supported. So
|
|
|
+ // instead, we exclude reserved characters and match everything else.
|
|
|
+ var wordChar = '[^' + RESERVED_CHARS_RE + ']';
|
|
|
+ var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
|
|
|
+
|
|
|
// Parent directories, delimited by '/' or ':'. Currently unused, but must
|
|
|
// be matched to parse the rest of the track name.
|
|
|
- var directoryRe = /((?:[\w-]+[\/:])*)/;
|
|
|
+ var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
|
|
|
|
|
|
// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
|
|
|
- var nodeRe = /([\w-\.]+)?/;
|
|
|
+ var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
|
|
|
|
|
|
- // Object on target node, and accessor. Name may contain only word
|
|
|
+ // Object on target node, and accessor. May not contain reserved
|
|
|
// characters. Accessor may contain any character except closing bracket.
|
|
|
- var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
|
|
|
+ var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
|
|
|
|
|
|
- // Property and accessor. May contain only word characters. Accessor may
|
|
|
+ // Property and accessor. May not contain reserved characters. Accessor may
|
|
|
// contain any non-bracket characters.
|
|
|
- var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
|
|
|
+ var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
|
|
|
|
|
|
var trackRe = new RegExp( ''
|
|
|
+ '^'
|
|
|
- + directoryRe.source
|
|
|
- + nodeRe.source
|
|
|
- + objectRe.source
|
|
|
- + propertyRe.source
|
|
|
+ + directoryRe
|
|
|
+ + nodeRe
|
|
|
+ + objectRe
|
|
|
+ + propertyRe
|
|
|
+ '$'
|
|
|
);
|
|
|
|