src/module.js
/**
     * renderRegion uses the provided bounds and top/bottom paths for a region to render an SVG path in between
     * @returns {Object} the rendered SVGPathElement
     */
renderRegion uses the provided bounds and top/bottom paths for a region to render an SVG path in between
@returns {Object} the rendered SVGPathElement
renderRegion uses the provided bounds and top / bottom paths for a region to render an SVG path in between @returns { Object } the rendered SVGPathElement
function renderRegion() {
      let straightTextRegion = region.fitTextInBounds();
      let topPathLength = region.topPath.getTotalLength();
      let bottomPathLength = region.bottomPath.getTotalLength();
      let step = wordmark.lutResolution;
      let topPathLUT = [];
      let bottomPathLUT = [];
      let topPathBounds = getPathElemBounds(region.topPath);
      let bottomPathBounds = getPathElemBounds(region.bottomPath);
      if (wordmark.debug) {
        region.debugPoints = [];
      }
      for (let i = 0; i < step + 1; i++) {
        topPathLUT.push(region.topPath.getPointAtLength(topPathLength * i / step));
        bottomPathLUT.push(region.bottomPath.getPointAtLength(bottomPathLength * i / step));
        if (wordmark.debug) {
          region.debugPoints.push(topPathLUT[topPathLUT.length - 1]);
          region.debugPoints.push(bottomPathLUT[bottomPathLUT.length - 1]);
        }
      }
      if (Math.abs(topPathBounds.width - bottomPathBounds.width) < epsilon && Math.abs(topPathBounds.x - bottomPathBounds.x) < epsilon) {
        straightTextRegion.commands.forEach((cmd) => {
          if ('ML'.indexOf(cmd.type) > -1) {
            for (let j = 0; j < step - 1; j++) {
              let sampleTopA = topPathLUT[j];
              let sampleTopB = topPathLUT[j + 1];
              if ((cmd.x <= sampleTopB.x && cmd.x >= sampleTopA.x) || (j >= step - 2 && cmd.x >= sampleTopB.x)) {
                let topLerpY = lerp(sampleTopA.y, sampleTopB.y, (cmd.x - sampleTopA.x) / (sampleTopB.x - sampleTopA.x));
                for (let k = 0; k < step - 1; k++) {
                  let sampleBottomA = bottomPathLUT[k];
                  let sampleBottomB = bottomPathLUT[k + 1];
                  if ((cmd.x <= sampleBottomB.x && cmd.x >= sampleBottomA.x) || (k >= step - 2 && cmd.x >= sampleBottomB.x)) {
                    let bottomLerpY = lerp(sampleBottomA.y, sampleBottomB.y, (cmd.x - sampleBottomA.x) / (sampleBottomB.x - sampleBottomA.x));
                    let yProportional = (cmd.y - region.bounds.y) / region.bounds.height; 
                    cmd.y = lerp(topLerpY, bottomLerpY, yProportional);
                    j = k = step;
                  }
                }
              }
            }
          }
        });
      }
      else {
        straightTextRegion.commands.forEach((cmd) => {
          if ('ML'.indexOf(cmd.type) > -1) {
            let xProgress = (cmd.x - region.bounds.x) / region.bounds.width;
            let yProgress = (cmd.y - region.bounds.y) / region.bounds.height;
            let stepProgressX = (step) * xProgress;
            let floorStepProgressX = Math.max(0,Math.floor(stepProgressX));
            let ceilStepProgressX = Math.min(step, Math.ceil(stepProgressX));
            let topMinPt = topPathLUT[floorStepProgressX];
            let topMaxPt = topPathLUT[ceilStepProgressX];
            let bottomMinPt = bottomPathLUT[floorStepProgressX];
            let bottomMaxPt = bottomPathLUT[ceilStepProgressX];
            let progressRatio = (stepProgressX - floorStepProgressX) / (ceilStepProgressX - floorStepProgressX + epsilon);
            let topPt = {
              x: lerp(topMinPt.x, topMaxPt.x, progressRatio),
              y: lerp(topMinPt.y, topMaxPt.y, progressRatio)
            };
            let bottomPt = {
              x: lerp(bottomMinPt.x, bottomMaxPt.x, progressRatio),
              y: lerp(bottomMinPt.y, bottomMaxPt.y, progressRatio)
            };
            let lerpX = lerp(topPt.x,bottomPt.x, yProgress);
            let lerpY = lerp(topPt.y,bottomPt.y, yProgress);
            cmd.x = lerpX;
            cmd.y = lerpY;
          }
        });
      }
      let newPathToAppend = createSVGElement('path');
      newPathToAppend.setAttribute('d', straightTextRegion.toPathData(wordmark.precision));
      if (region.fill >= 0 && region.fill !== null) {
        newPathToAppend.setAttribute('fill', wordmark.colors[region.fill]);
      }
      else {
        newPathToAppend.setAttribute('fill', 'none');
      }
      if (region.stroke >= 0 && region.stroke !== null) {
        newPathToAppend.setAttribute('stroke', wordmark.colors[region.stroke]);
      }
      else {
        newPathToAppend.setAttribute('stroke', 'none');
      }
      newPathToAppend.setAttribute('stroke-width', region.bounds.height / 40);
      newPathToAppend.setAttribute('stroke-linejoin', 'round');
      newPathToAppend.setAttribute('stroke-linecap', 'round');
      return newPathToAppend;
    }
function renderRegion ( ) { let straightTextRegion = region . fitTextInBounds ( ) ; let topPathLength = region . topPath . getTotalLength ( ) ; let bottomPathLength = region . bottomPath . getTotalLength ( ) ; let step = wordmark . lutResolution ; let topPathLUT = [ ] ; let bottomPathLUT = [ ] ; let topPathBounds = getPathElemBounds ( region . topPath ) ; let bottomPathBounds = getPathElemBounds ( region . bottomPath ) ; if ( wordmark . debug ) { region . debugPoints = [ ] ; } for ( let i = 0 ; i < step + 1 ; i ++ ) { topPathLUT . push ( region . topPath . getPointAtLength ( topPathLength * i / step ) ) ; bottomPathLUT . push ( region . bottomPath . getPointAtLength ( bottomPathLength * i / step ) ) ; if ( wordmark . debug ) { region . debugPoints . push ( topPathLUT [ topPathLUT . length - 1 ] ) ; region . debugPoints . push ( bottomPathLUT [ bottomPathLUT . length - 1 ] ) ; } } if ( Math . abs ( topPathBounds . width - bottomPathBounds . width ) < epsilon && Math . abs ( topPathBounds . x - bottomPathBounds . x ) < epsilon ) { straightTextRegion . commands . forEach ( ( cmd ) => { if ( 'ML' . indexOf ( cmd . type ) > - 1 ) { for ( let j = 0 ; j < step - 1 ; j ++ ) { let sampleTopA = topPathLUT [ j ] ; let sampleTopB = topPathLUT [ j + 1 ] ; if ( ( cmd . x <= sampleTopB . x && cmd . x >= sampleTopA . x ) || ( j >= step - 2 && cmd . x >= sampleTopB . x ) ) { let topLerpY = lerp ( sampleTopA . y , sampleTopB . y , ( cmd . x - sampleTopA . x ) / ( sampleTopB . x - sampleTopA . x ) ) ; for ( let k = 0 ; k < step - 1 ; k ++ ) { let sampleBottomA = bottomPathLUT [ k ] ; let sampleBottomB = bottomPathLUT [ k + 1 ] ; if ( ( cmd . x <= sampleBottomB . x && cmd . x >= sampleBottomA . x ) || ( k >= step - 2 && cmd . x >= sampleBottomB . x ) ) { let bottomLerpY = lerp ( sampleBottomA . y , sampleBottomB . y , ( cmd . x - sampleBottomA . x ) / ( sampleBottomB . x - sampleBottomA . x ) ) ; let yProportional = ( cmd . y - region . bounds . y ) / region . bounds . height ; cmd . y = lerp ( topLerpY , bottomLerpY , yProportional ) ; j = k = step ; } } } } } } ) ; } else { straightTextRegion . commands . forEach ( ( cmd ) => { if ( 'ML' . indexOf ( cmd . type ) > - 1 ) { let xProgress = ( cmd . x - region . bounds . x ) / region . bounds . width ; let yProgress = ( cmd . y - region . bounds . y ) / region . bounds . height ; let stepProgressX = ( step ) * xProgress ; let floorStepProgressX = Math . max ( 0 , Math . floor ( stepProgressX ) ) ; let ceilStepProgressX = Math . min ( step , Math . ceil ( stepProgressX ) ) ; let topMinPt = topPathLUT [ floorStepProgressX ] ; let topMaxPt = topPathLUT [ ceilStepProgressX ] ; let bottomMinPt = bottomPathLUT [ floorStepProgressX ] ; let bottomMaxPt = bottomPathLUT [ ceilStepProgressX ] ; let progressRatio = ( stepProgressX - floorStepProgressX ) / ( ceilStepProgressX - floorStepProgressX + epsilon ) ; let topPt = { x : lerp ( topMinPt . x , topMaxPt . x , progressRatio ) , y : lerp ( topMinPt . y , topMaxPt . y , progressRatio ) } ; let bottomPt = { x : lerp ( bottomMinPt . x , bottomMaxPt . x , progressRatio ) , y : lerp ( bottomMinPt . y , bottomMaxPt . y , progressRatio ) } ; let lerpX = lerp ( topPt . x , bottomPt . x , yProgress ) ; let lerpY = lerp ( topPt . y , bottomPt . y , yProgress ) ; cmd . x = lerpX ; cmd . y = lerpY ; } } ) ; } let newPathToAppend = createSVGElement ( 'path' ) ; newPathToAppend . setAttribute ( 'd' , straightTextRegion . toPathData ( wordmark . precision ) ) ; if ( region . fill >= 0 && region . fill !== null ) { newPathToAppend . setAttribute ( 'fill' , wordmark . colors [ region . fill ] ) ; } else { newPathToAppend . setAttribute ( 'fill' , 'none' ) ; } if ( region . stroke >= 0 && region . stroke !== null ) { newPathToAppend . setAttribute ( 'stroke' , wordmark . colors [ region . stroke ] ) ; } else { newPathToAppend . setAttribute ( 'stroke' , 'none' ) ; } newPathToAppend . setAttribute ( 'stroke-width' , region . bounds . height / 40 ) ; newPathToAppend . setAttribute ( 'stroke-linejoin' , 'round' ) ; newPathToAppend . setAttribute ( 'stroke-linecap' , 'round' ) ; return newPathToAppend ; }
renderRegion uses the provided bounds and top/bottom paths for a region to render an SVG path in between
 @returns {Object} the rendered SVGPathElement
renderRegion uses the provided bounds and top / bottom paths for a region to render an SVG path in between @returns { Object } the rendered SVGPathElement
//calls renderTextToBounds and then renders text between paths. returns opentype path //assuming similar widths and left positions ~= no horizontal distortion //found closest top, now let's find closest bottom //don't forget cmd is scaled already