Writing Text without line/word breaks ... but in Javascript

Hello

I found a very uselful program to justify text as I wanted here : https://forum.processing.org/one/topic/writing-text-without-line-word-breaks.html. The code is in Java (processing) thanks to @calsign.

It is in perfect java, I need to translate into javascript with p5.js. I use this resource that helps me a lot.

I cannot figure out the good way to write it in Javascript, especially with the array (the var tokens for instance) I put modification I am not sure in bold (or with ** and **).

I think I am close but I miss something. Thank you in advance.

_Here is my attempt: _

            // justify one line of text
            function linejustify(s, x, y, w) {

              // how long is the text?
              var tw = textWidth(s);

              // is it longer than expected width? if so, return
              if (tw > w) {
                print("Text is too long.");
                return;
              }

              // does it match perfectly? if so, print it
              if (tw == w) {
                text(s, x, y);
                return;
              }

              // if not, how much pixels shall we add to reach expected length?
              var gap = w - tw;

              // split the text into words
            **  var tokens = split(s, " "); **

              // is there only one word - or no word at all? if so, print it
              if (tokens.length <= 1) {
                text(s, x, y);
                return;
              }
              // otherwise,
              // we will distribute the missing pixels after each word, in the spaces
              var spaces = tokens.length - 1;

            **  var pixelsToAddAfterToken = new [tokens.length];
              //int[] pixelsToAddAfterToken = new int[tokens.length];   ** 

            for (var i = 0; i < spaces; i++) {
                pixelsToAddAfterToken[i] = floor(gap/spaces);
                if (i <= gap%spaces) pixelsToAddAfterToken[i]++;
              }

              for (var i = 0; i < tokens.length; i++) {
                text(tokens[i], x, y);
                x += textWidth(tokens[i]) + textWidth(" ") + pixelsToAddAfterToken[i];
              }
            }

            //All should be self-explanatory except leading...
            //leading is how much room should be in-between each line of text.

            function textJustify(input, x, y, w, leading) {
              push();

              ** var seperatedStrings = [0]; **
              var lastSeperation = 0;

              for(var i = 0; i < input.length(); i ++) {
                if(textWidth(input.substring(0, i - lastSeperation)) > w * .99) {
                  seperatedStrings = append(seperatedStrings, input.substring(lastSeperation, i));
                  lastSeperation = i;
                }

              }

              if(lastSeperation < input.length()) seperatedStrings = append(seperatedStrings, input.substring(lastSeperation, input.length()));


              for(var i = 0; i < seperatedStrings.length; i ++) {
                linejustify(seperatedStrings[i], x, y + leading * i, w);
              }


              pop();
            }


            function setup() {
              size(250, 150);
              background(255);
              fill(0);
              textFont(createFont("", 12), 12);
              textJustify("This text should be perfectly justified. Even with two lines! You can add more text... And it still works, as far as I can tell.", 0, 40, width, 14);

            }

Answers

  • edited March 2018 Answer ✓

    I had to add a small modification as it wasn't splitting right at spaces but sometimes in the middle of a word. Tested version here: http://p5js.sketchpad.cc/sp/pad/view/VpPhDt6aVF/latest

    Kf

    //Processing Forum on Jan 6/2018
    //Porting textAling code from java to JS
    //REFERENCE: https:// forum.processing.org/two/discussion/25852/writing-text-without-line-word-breaks-but-in-javascript#latest
    //REFERENCE: https:// forum.processing.org/one/topic/writing-text-without-line-word-breaks.html
    //By KF
    
    var txt;
    
    function setup() {
      createCanvas(250, 150);
      background(88);
      fill(0);
      //textFont(createFont("", 12), 12);  
      textFont('Helvetica');
      textSize(12);
      txt="This text should be perfectly justified.  Even with two lines! You can add more text... And it still works, as far  as I can tell.";
      textJustify(txt, 0, 40, width, 14);
    }
    
    // *********************************************************************************
    //All should be self-explanatory except leading...
    //leading is how much room should be in-between each line of text.
    
    function textJustify(input, x, y, w, leading) {
      push();
    
      var seperatedStrings=[]; 
      var lastSeperation = 0;
      var spcPos=0;
    
      //Split lines so it fits in defined output width 
      for (var i = 0; i < input.length; i++) {
        if (input[i]==" ")
          spcPos=i;
    
        if (textWidth(input.substring(lastSeperation, i )) > w * .95) {
          i=spcPos;
          seperatedStrings.push( input.substring(lastSeperation, i));
          print("Split line at i:"+i+" "+input.substring(lastSeperation, i));
          lastSeperation = i;
        }
      }
    
      //Add last bit of string if not done by prev function
      if (lastSeperation < input.length ) {
        seperatedStrings.push( input.substring(lastSeperation, input.length));
      }
    
      for (var i = 0; i < seperatedStrings.length; i++) {
        linejustify(seperatedStrings[i], x, y + leading * i, w);
      } 
      pop();
    }
    
    // *********************************************************************************
    // justify one line of text
    function linejustify(s, x, y, w) {
    
      print("s "+s+" "+w);
    
      // how long is the text?
      var tw = textWidth(s);  //https://p5js.org/reference/#/p5/textWidth
    
      // is it longer than expected width? if so, return
      if (tw > w) {
        print("Text is too long.");
        return;
      }
    
      // does it match perfectly? if so, print it
      if (tw == w) {
        text(s, x, y);
        return;
      }
    
      // if not, how much pixels shall we add to reach expected length?
      var gap = w - tw;
    
      // split the text into words
      var tokens = splitTokens(s, ' ');   //https://p5js.org/reference/#/p5/splitTokens
    
      // is there only one word - or no word at all? if so, print it
      if (tokens.length <= 1) {
        text(s, x, y);
        return;
      }
      // otherwise,
      // we will distribute the missing pixels after each word, in the spaces
      var spaces = tokens.length - 1;
    
      var pixelsToAddAfterToken = [];
    
      print("tokens.length "+tokens.length);
    
      for (var i = 0; i < spaces; i++) {
        pixelsToAddAfterToken[i] = floor(gap/spaces);
        if (i <= gap%spaces) pixelsToAddAfterToken[i]++;
      }
    
      for (var i = 0; i < tokens.length; i++) {
        print(i+" "+tokens[i]);
        text(tokens[i], x, y);
        x += textWidth(tokens[i]) + textWidth(" ") + pixelsToAddAfterToken[i];
      }
    }
    

    Keyword: textAlign kf_keyword

  • Thank you very much. I have now to work a little bit to manage very long string.

Sign In or Register to comment.