/*
ArcText - Rick Companje (c) 10-1-2008
Rendering dynamic text on a circle / arc
Built with processing but can easily be rewirtten to Flash, Flex, C++ etc.
Credits to teknoel.com
*/

Handle hFontsize, hTracking, hRotation, hRadius;
String [] labels = {"FONT SIZE", "TRACKING", "ROTATION", "ARC RADIUS"};
Handle[] handles;
PFont bmpfont, font;
String txt = "dynamic text rendering on an arc";

int r=200;
int w=400;
int h=400;

void setup() {
  size(w,h);
  smooth();

  bmpfont = loadFont("Standard0755-8.vlw");
  font = loadFont("Arial-BoldMT-48.vlw");

  handles = new Handle[4];
  handles[0] = hFontsize = new Handle(0,26,48);
  handles[1] = hTracking = new Handle(-1,0,1); //  EM units
  handles[2] = hRotation = new Handle(0,0,TWO_PI); //path rotation offset
  handles[3] = hRadius = new Handle(-300,100,300); //negative radius renders the text on the inside of the path

}

void draw() {
  background(0);
  
  pushMatrix();
    translate(w/2,h/2+35);
    rotate(hRotation.value);
    r = int(hRadius.value);
    noFill();
    stroke(50);
    ellipse(0,0,2*r,2*r);
    int cross=20;
    line(0,-cross,0,cross);
    line(-cross,0,cross,0);
    textFont(font,int(hFontsize.value));
    float angle = 0;
    textAlign(CENTER);

    for (int i=0; i<txt.length(); i++) {
  
      char letter = txt.charAt(i);
    
      //first half letter width
      float adjacent=r;
      float opposite=textWidth(letter)/2;
      angle += atan(opposite/adjacent);
    
      //tracking between letters in EM measurements
      adjacent=r;
      opposite=textWidth("M")*hTracking.value; //EM is relative to the width of the letter M
      angle += atan(opposite/adjacent);
  
      pushMatrix();
        rotate(-angle);
        stroke(50);
        line(0,r-50,0,r+20);
        fill(255);
        noStroke();
        text(letter,0,r);
      popMatrix();
    
      //second half letter width
      adjacent=r;
      opposite=textWidth(letter)/2;
      angle += atan(opposite/adjacent);
  }    
  popMatrix();
  drawHandles();
}

void drawHandles() {
  textFont(bmpfont,8);
  textAlign(LEFT);
  text("ArcText - Rick Companje (c) 10-1-2008 - Credits to teknoel.com",5,height-5);
  
  for (int i=0; i<handles.length; i++) {
    textAlign(RIGHT);
    fill(255);
    text(labels[i],60,20+i*15);
    handles[i].draw(70,10+i*15);
    textAlign(LEFT);
    fill(255);
    text(handles[i].value,197,20+i*15);
  }
}




public class Handle {
  
  float fMin=0, fMax=1, value=.5;
  int x = 0;
  int y = 0;
  int w = 115; //width
  int h = 12; //height
  
  Handle() {
  }
  
  Handle(float fMin, float fDefault, float fMax) {
    this.fMin = fMin;
    this.fMax = fMax;
    this.value = fDefault;
  }
  
  void draw(int x, int y) {
    this.x = x;
    this.y = y;
    
    if (mousePressed && mouseY>=y && mouseY<=y+h && mouseX>=x && mouseX<=x+w) {
      value = fMin + float(mouseX-x)/w * (fMax-fMin);
    }
    
    noFill();
    stroke(255);
    rect(x,y,w,h);    
    noStroke();
    float normValue = (value-fMin)/(fMax-fMin);   
    fill(180);
    rect(x+2,y+2,normValue*(w-3),h-3);
  }
}