Posted by: algorithmist | October 20, 2008

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;
}

Responses

  1. [...] Bezier, path deform, spline, text effect, tutorial trackback Regarding the code listed in my previous post, let’s take one step back and look at the problem from a very high level. Often, it’s [...]

  2. [...] it’s just a bit over my head with all the Math that seems to be involved like in this example : http://algorithmist.wordpress.com/20…ne-code-part-i which I can’t seem to make sense of in order to test it out in my own project and simplify it. If [...]

  3. Any chance to have a look at the full source for this ? thanks.

  4. 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


Categories