Text Along Spline Code Part I

Although this work is not finished, I don’t have time to write a full TechNote on the subject, so I’m going to post the ‘basic’ code for this algorithm and deconstruct it over several posts.  This will provide an introduction to the method before it gets too complicated with production details.  The Flex driver is not yet ready for general posting and download, so here is the code from the handler that renders the text along the spline.  It is currently a two-pass algorithm,

__spline.draw(1.0);

__myText = __input__.text;

// first pass - get total width of displayed text (using
// uniform spacing - punctuation taken into account later)
var totalWidth:Number = 0;
for( var i:uint=0; i<__myText.length; ++i )
{
  var tf:TextField = __createLetter(__myText.charAt(i));
  totalWidth      += tf.textWidth + __tracking;
  __letters[i]     = tf;
}

var arcLength:Number = __spline.arcLength();
var aInverse:Number  = 1/arcLength;
var maxS:Number      = totalWidth*aInverse;

// second pass - place text along spline
var s:Number              = 0;
var m:Number              = -1;
var endX:Number           = __spline.getX(1);
var endY:Number           = __spline.getY(1);
var cacheRotation:Boolean = true;
var rotation:Number       = 0;

for( i=0; i<__myText.length; ++i )
{
  tf = __letters[i];

  if( s <= 1 )
  {
    var myX:Number = __spline.getX(s);
    var myY:Number = __spline.getY(s);
    if( s < 0.95 )
    {
      var dX:Number  = __spline.getX(s+0.05) - myX;
      var dY:Number  = __spline.getY(s+0.05) - myY;
    }
    else
    {
      dX = endX - __spline.getX(0.94);
      dY = endY - __spline.getY(0.94);
    }

    // normalize
    var d:Number  = Math.sqrt(dX*dX + dY*dY);
    var uX:Number = dX/d;
    var uY:Number = dY/d;

    tf.rotation         = Math.atan2(dY, dX)*Consts.RAD_TO_DEG;
    var myWidth:Number  = tf.textWidth;
    var myHeight:Number = tf.textHeight;

    tf.x = myX + myHeight*uY;
    tf.y = myY - myHeight*uX;
  }
  else
  {
    // text extends beyond end of spline - slope estimate towards
    // end of spline to continue along in a straight line
    if( cacheRotation )
    {
      dX            = endX - __spline.getX(0.92);
      dY            = endY - __spline.getY(0.92);
      d             = Math.sqrt(dX*dX + dY*dY);
      uX            = dX/d;
      uY            = dY/d;
      rotation      = Math.atan2(dY, dX)*Consts.RAD_TO_DEG;
      cacheRotation = false;
    }

    tf.rotation  = rotation;
    myWidth      = tf.textWidth;
    myHeight     = tf.textHeight;

    // distance along line from end of of spline to current
    // text starting position
    d    = (s-1)*arcLength;
    myX  = endX + d*uX;
    myY  = endY + d*uY;
    tf.x = myX + uY*myHeight;
    tf.y = myY - uX*myHeight;
  }

  _textContainer.addChild(tf);
  s += (myWidth + __tracking)*aInverse;
}

4 thoughts on “Text Along Spline Code Part I

  1. When arc length along a general path is implemented in Degrafa, a full demo will be provided. 95% of the code is available right in this post (__spline is a reference to a Singularity Bezier Spline with arc-length parameterization, __input__ is the id of a Label). The point of the deconstruction is that if you download the Singularity package, there is more than enough basic information to construct your own example.

    regards,

    – jim armstrong

Comments are closed.