diff --git a/fonts.js b/fonts.js
index 878d3c9ef..d283fc3d8 100755
--- a/fonts.js
+++ b/fonts.js
@@ -114,60 +114,6 @@ var serifFonts = {
   'Wide Latin': true, 'Windsor': true, 'XITS': true
 };
 
-var FontMeasure = (function FontMeasure() {
-  var kScalePrecision = 30;
-  var ctx = document.createElement('canvas').getContext('2d');
-  ctx.scale(1 / kScalePrecision, 1);
-
-  var current;
-  var measureCache;
-
-  return {
-    setActive: function fonts_setActive(font, size) {
-      if (current == font) {
-        var sizes = current.sizes;
-        if (!(measureCache = sizes[size]))
-          measureCache = sizes[size] = Object.create(null);
-      } else {
-        measureCache = null;
-      }
-
-      var name = font.loadedName;
-      var bold = font.bold ? 'bold' : 'normal';
-      var italic = font.italic ? 'italic' : 'normal';
-      size *= kScalePrecision;
-      var rule = italic + ' ' + bold + ' ' + size + 'px "' + name + '"';
-      ctx.font = rule;
-      current = font;
-    },
-    measureText: function fonts_measureText(text, font, size) {
-      var width;
-      if (measureCache && (width = measureCache[text]))
-        return width;
-
-      try {
-        width = 0.0;
-        var composite = font.composite;
-        for (var i = 0; i < text.length; i++) {
-          var charcode = composite ? 
-            ((text.charCodeAt(i++) << 8) + text.charCodeAt(i)) :
-            text.charCodeAt(i);
-          var charWidth = parseFloat(font.encoding[charcode].width);
-          width += charWidth;
-        }
-        // XXX should use the unit-per-em value from the embedded font
-        var unitsPerEm = 1000;
-        width = width * size / unitsPerEm;
-      } catch(e) {
-        width = ctx.measureText(text).width / kScalePrecision;
-      }
-      if (measureCache)
-        measureCache[text] = width;
-      return width;
-    }
-  };
-})();
-
 var FontLoader = {
   listeningForFontLoad: false,
 
@@ -1142,9 +1088,10 @@ var Font = (function Font() {
           // so create an identity encoding
           var widths = properties.widths;
           for (i = 0; i < numGlyphs; i++) {
+            var width = widths[i];
             encoding[i] = {
               unicode: i + kCmapGlyphOffset,
-              width: widths[i] || properties.defaultWidth
+              width: IsNum(width) ? width : properties.defaultWidth
             };
           }
         } else {
@@ -2360,13 +2307,13 @@ var Type2CFF = (function() {
         if (code == -1)
           index = code = mapping.unicode || index;
 
-        var width = mapping.width || defaultWidth;
         if (code <= 0x1f || (code >= 127 && code <= 255))
           code += kCmapGlyphOffset;
 
+        var width = mapping.width;
         properties.glyphs[glyph] = properties.encoding[index] = {
           unicode: code,
-          width: width
+          width: IsNum(width) ? width : defaultWidth
         };
 
         charstrings.push({
diff --git a/pdf.js b/pdf.js
index 18f93dcf8..272a9f28e 100644
--- a/pdf.js
+++ b/pdf.js
@@ -4242,9 +4242,10 @@ var PartialEvaluator = (function() {
               continue;
 
             var code = j >> 1;
+            var width = glyphsWidths[code];
             encoding[code] = {
               unicode: glyphID,
-              width: glyphsWidths[code] || defaultWidth
+              width: IsNum(width) ? width : defaultWidth
             };
           }
         } else if (type == 'CIDFontType0') {
@@ -4316,7 +4317,7 @@ var PartialEvaluator = (function() {
         var width = properties.widths[i] || properties.widths[glyph];
         map[i] = {
           unicode: index,
-          width: width || properties.defaultWidth
+          width: IsNum(width) ? width : properties.defaultWidth
         };
 
         if (glyph)
@@ -4615,9 +4616,6 @@ function ScratchCanvas(width, height) {
 }
 
 var CanvasGraphics = (function() {
-  var kScalePrecision = 50.0;
-  var kRasterizerMin = 14;
-
   function constructor(canvasCtx, imageCanvas) {
     this.ctx = canvasCtx;
     this.current = new CanvasExtraState();
@@ -4878,22 +4876,13 @@ var CanvasGraphics = (function() {
         return;
 
       var fontObj = font.fontObj;
-      var name = fontObj.loadedName;
-      if (!name) {
-        // TODO: fontDescriptor is not available, fallback to default font
-        name = 'sans-serif';
-      }
-
       this.current.font = fontObj;
       this.current.fontSize = size;
 
+      var name = fontObj.loadedName || 'sans-serif';
       if (this.ctx.$setFont) {
         this.ctx.$setFont(name, size);
       } else {
-        FontMeasure.setActive(fontObj, size);
-
-        size = (size <= kRasterizerMin) ? size * kScalePrecision : size;
-
         var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
                                    (fontObj.bold ? 'bold' : 'normal');
 
@@ -4944,42 +4933,40 @@ var CanvasGraphics = (function() {
 
       ctx.translate(current.x, -1 * current.y);
 
-      var scaleFactorX = 1, scaleFactorY = 1;
       var font = current.font;
       if (font) {
-        if (current.fontSize <= kRasterizerMin) {
-          scaleFactorX = scaleFactorY = kScalePrecision;
-          ctx.scale(1 / scaleFactorX, 1 / scaleFactorY);
-        }
         ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX);
         text = font.charsToUnicode(text);
       }
 
-      var size = current.fontSize;
+      var composite = font.composite;
+      var encoding = font.encoding;
+      var fontSize = current.fontSize;
       var charSpacing = current.charSpacing;
       var wordSpacing = current.wordSpacing;
       var textHScale = current.textHScale;
+      ctx.scale(1 / textHScale, 1);
 
-      if (charSpacing != 0 || wordSpacing != 0 || textHScale != 1) {
-        scaleFactorX *= textHScale;
-        ctx.scale(1 / textHScale, 1);
-        var width = 0;
-
-        for (var i = 0, ii = text.length; i < ii; ++i) {
-          ctx.fillText(text.charAt(i), 0, 0);
-          var c = originalText.charAt(i);
-          var charWidth = FontMeasure.measureText(c, font, size);
-          charWidth += charSpacing;
-          if (c.charCodeAt(0) == 32)
-            charWidth += wordSpacing;
-          ctx.translate(charWidth * scaleFactorX, 0);
-          width += charWidth;
+      var width = 0;
+      for (var i = 0; i < text.length; i++) {
+        if (composite) {
+          var position = i * 2 + 1;
+          var charcode = (originalText.charCodeAt(position - 1) << 8) +
+                          originalText.charCodeAt(position);
+        } else {
+          var charcode = originalText.charCodeAt(i);
         }
-        current.x += width;
-      } else {
-        ctx.fillText(text, 0, 0);
-        current.x += FontMeasure.measureText(originalText, font, size);
+
+        var charWidth = font.encoding[charcode].width * fontSize * 0.001;
+        charWidth += charSpacing;
+        if (charcode == 32)
+          charWidth += wordSpacing;
+
+        ctx.fillText(text.charAt(i), 0, 0);
+        ctx.translate(charWidth, 0);
+        width += charWidth;
       }
+      current.x += width;
 
       this.ctx.restore();
     },