title: How to calculate bounding box of text object on dynamic canvas
body: <p>I am attempting to calculate the pixel height and width of a text object on a html canvas. I've already attempted some code seen below but I've been getting wrong results. Is there a cleaner way to calculate this? The dynamic canvas needs to adjust according to match how long and large the text could be.</p>
  
  <ol>
  <li>px height and width needs to properly calculate. Top-left most pixel to bottom-right most pixel.</li>
  <li>The canvas needs to adjust size to minimize calculation time and account for text amount including "\n"s. I tried </li>
  </ol>
  
  <p>canvas.setWidth(400+text.getBoundingRectWidth());
  canvas.setHeight(400+text.getBoundingRectHeight());</p>
  
  <p>but I am not sure it works.</p>
  
  <p>How can I rewrite this code to have canvas size be dynamic and adjusts to text that can change (e.g. person writing an essay in a textarea)?</p>
  
  <p>How can I correctly calculate the size of the text?</p>
  
  <p><strong>If someone rewrites this code to meet my specifications above properly, I can provide a reward (money, giftcard, free pizza, etc...). I've been spending many hours trying to figure this out.</strong></p>
  
  <p>Researching:
  <a href="https://stackoverflow.com/questions/9852159/calculate-bounding-box-of-arbitrary-pixel-based-drawing">Calculate bounding box of arbitrary pixel-based drawing</a>
  Looks promising.</p>
  
  <p>HERE IS THE JSBIN (Based off <a href="https://stackoverflow.com/questions/32916928/fabric-js-get-text-bounding-box-width-and-height">Fabric.js: Get text bounding box width and height</a>)
  <a href="http://jsbin.com/zoqolik/3/edit?html,css,js,console,output" rel="nofollow noreferrer">http://jsbin.com/zoqolik/3/edit?html,css,js,console,output</a></p>
  
  <pre><code>fabric.Object.prototype.objectCaching = false;
  var txt = '\n'+'Adklfmask'+'\n'+'asdfsd'+'\n'+'asdfsd'+'\n'+'asdfsd'+"\n";
  
  
  var canvas = new fabric.Canvas('canvas');
  var text = new fabric.IText(txt, { 
      left: 200, 
      top: 200, 
      fontFamily: 'Princess Sofia',
      padding: 5,
      fontSize: 35,
      lineHeight: 2.5,
      textAlign: 'center'
  });
  
  canvas.add(text);
  canvas.renderAll();
  
  var ctx = canvas.getContext();
  
  var hei = Math.ceil(300+text.getBoundingRectHeight());
  var wid = Math.ceil(300+text.getBoundingRectWidth());
  
  function setWidth(width) {
    var canvas = document.getElementById("canvas");  
    canvas.width = width;
  }
  function setHeight(height) {
    var canvas = document.getElementById("canvas");  
    canvas.height = height;
  }
  canvas.setWidth(400+text.getBoundingRectWidth());
  canvas.setHeight(400+text.getBoundingRectHeight());
  
  // get/draw bounding box
  var bbox = getBoundingBox(ctx, 0, 0, wid, hei);
  console.log(bbox.width + ' x ' + bbox.height);
  drawBoundingBox(ctx, bbox);
  
  
  function getBoundingBox(ctx, left, top, width, height) {
      var ret = {};
  
      // Get the pixel data from the canvas
      var data = ctx.getImageData(left, top, width, height).data;
      console.log(data);
      var first = false; 
      var last = false;
      var right = false;
      var left = false;
      var r = height;
      var w = 0;
      var c = 0;
      var d = 0;
  
      // 1. get bottom
      while(!last &amp;&amp; r) {
          r--;
          for(c = 0; c &lt; width; c++) {
              if(data[r * width * 4 + c * 4 + 3]) {
                  console.log('last', r);
                  last = r+1;
                  ret.bottom = r+1;
                  break;
              }
          }
      }
  
      // 2. get top
      r = 0;
      var checks = [];
      while(!first &amp;&amp; r &lt; last) {
  
          for(c = 0; c &lt; width; c++) {
              if(data[r * width * 4 + c * 4 + 3]) {
                  console.log('first', r);
                  first = r-1;
                  ret.top = r-1;
                  ret.height = last - first - 1;
                  break;
              }
          }
          r++;
      }
  
      // 3. get right
      c = width;
      while(!right &amp;&amp; c) {
          c--;
          for(r = 0; r &lt; height; r++) {
              if(data[r * width * 4 + c * 4 + 3]) {
                  console.log('right', c);
                  right = c+1;
                  ret.right = c+1;
                  break;
              }
          }
      }
  
      // 4. get left
      c = 0;
      while(!left &amp;&amp; c &lt; right) {
  
          for(r = 0; r &lt; height; r++) {
              if(data[r * width * 4 + c * 4 + 3]) {
                  console.log('left', c-1);
                  left = c;
                  ret.left = c;
                  ret.width = right - left - 1;
                  break;
              }
          }
          c++;
  
          // If we've got it then return the height
          if(left) {
              return ret;    
          }
      }
  
      // We screwed something up...  What do you expect from free code?
      return false;
  }
  </code></pre>