From ac005ed359e0e191cfbfa203ce4d5a894b3646c6 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Wed, 18 Jul 2012 16:23:51 -0700
Subject: [PATCH 1/3] Support more type 1 font hsbw formats.

---
 src/fonts.js | 44 +++++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/src/fonts.js b/src/fonts.js
index c955c4d1a..00937ea08 100644
--- a/src/fonts.js
+++ b/src/fonts.js
@@ -3422,6 +3422,27 @@ var Type1Parser = function type1Parser() {
 
   var kEscapeCommand = 12;
 
+  // The initial stack can have numbers expressed with the div command which
+  // need to be calculated before conversion. Looking at the spec it doesn't
+  // appear div should even be allowed as a first command but there have been
+  // a number of fonts that have this.
+  function evaluateStack(stack) {
+    var newStack = [];
+    for (var i = 0, ii = stack.length; i < ii; i++) {
+      var token = stack[i];
+      if (token === 'div') {
+        var b = newStack.pop();
+        var a = newStack.pop();
+        newStack.push(a / b);
+      } else if (isInt(token)) {
+        newStack.push(token);
+      } else {
+        warn('Unsupported initial stack ' + stack);
+      }
+    }
+    return newStack;
+  }
+
   function decodeCharString(array) {
     var charstring = [];
     var lsb = 0;
@@ -3471,24 +3492,13 @@ var Type1Parser = function type1Parser() {
 
           command = charStringDictionary['12'][escape];
         } else {
-          // TODO Clean this code
           if (value == 13) { // hsbw
-            if (charstring.length == 2) {
-              lsb = charstring[0];
-              width = charstring[1];
-              charstring.splice(0, 1);
-            } else if (charstring.length == 4 && charstring[3] == 'div') {
-              lsb = charstring[0];
-              width = charstring[1] / charstring[2];
-              charstring.splice(0, 1);
-            } else if (charstring.length == 4 && charstring[2] == 'div') {
-              lsb = charstring[0] / charstring[1];
-              width = charstring[3];
-              charstring.splice(0, 3);
-            } else {
-              error('Unsupported hsbw format: ' + charstring);
-            }
-
+            charstring = evaluateStack(charstring);
+            if (charstring.length !== 2)
+              warn('Unsupported hsbw format.');
+            lsb = charstring[0];
+            width = charstring[1];
+            charstring.splice(0, 1);
             charstring.push(lsb, 'hmoveto');
             continue;
           } else if (value == 10) { // callsubr

From 8fccd199484c7bd1935da23c08c7df39293d8ecd Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 19 Jul 2012 18:06:37 -0700
Subject: [PATCH 2/3] Leave div commands on stack and change evaluation.

---
 src/fonts.js | 57 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/src/fonts.js b/src/fonts.js
index 00937ea08..7f005e418 100644
--- a/src/fonts.js
+++ b/src/fonts.js
@@ -3422,25 +3422,35 @@ var Type1Parser = function type1Parser() {
 
   var kEscapeCommand = 12;
 
-  // The initial stack can have numbers expressed with the div command which
-  // need to be calculated before conversion. Looking at the spec it doesn't
-  // appear div should even be allowed as a first command but there have been
-  // a number of fonts that have this.
-  function evaluateStack(stack) {
-    var newStack = [];
-    for (var i = 0, ii = stack.length; i < ii; i++) {
-      var token = stack[i];
-      if (token === 'div') {
-        var b = newStack.pop();
-        var a = newStack.pop();
-        newStack.push(a / b);
-      } else if (isInt(token)) {
-        newStack.push(token);
+  // Breaks up the stack by arguments and also calculates the value.
+  function breakUpArgs(stack, numArgs) {
+    var args = [];
+    var index = stack.length - 1;
+    for (var i = 0; i < numArgs; i++) {
+      if (index < 0) {
+        args.unshift({ arg: [0],
+                       value: 0 });
+        warn('Malformed charstring stack: not enough values on stack.');
+        continue;
+      }
+      if (stack[index] === 'div') {
+        var a = stack[index - 2];
+        var b = stack[index - 1];
+        if (!isInt(a) || !isInt(b)) {
+          warn('Malformed charsting stack: expected ints on stack for div.');
+          a = 0;
+          b = 1;
+        }
+        args.unshift({ arg: [a, b, 'div'],
+                       value: a / b });
+        index -= 3;
       } else {
-        warn('Unsupported initial stack ' + stack);
+        args.unshift({ arg: stack.slice(index, index + 1),
+                       value: stack[index] });
+        index--;
       }
     }
-    return newStack;
+    return args;
   }
 
   function decodeCharString(array) {
@@ -3493,13 +3503,14 @@ var Type1Parser = function type1Parser() {
           command = charStringDictionary['12'][escape];
         } else {
           if (value == 13) { // hsbw
-            charstring = evaluateStack(charstring);
-            if (charstring.length !== 2)
-              warn('Unsupported hsbw format.');
-            lsb = charstring[0];
-            width = charstring[1];
-            charstring.splice(0, 1);
-            charstring.push(lsb, 'hmoveto');
+            var args = breakUpArgs(charstring, 2);
+            lsb = args[0]['value'];
+            width = args[1]['value'];
+            // To convert to type2 we have to move the width value to the first
+            // part of the charstring and then use hmoveto with lsb.
+            charstring = args[1]['arg'];
+            charstring = charstring.concat(args[0]['arg']);
+            charstring.push('hmoveto');
             continue;
           } else if (value == 10) { // callsubr
             if (charstring[charstring.length - 1] < 3) { // subr #0..2

From 34eb537160feb14d23285696e7a0d2eb76b31a8d Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Fri, 20 Jul 2012 13:48:48 -0700
Subject: [PATCH 3/3] Add another warning for malformed stack.  Fix/add
 variable names.

---
 src/fonts.js | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/fonts.js b/src/fonts.js
index 7f005e418..a99103f63 100644
--- a/src/fonts.js
+++ b/src/fonts.js
@@ -3433,7 +3433,8 @@ var Type1Parser = function type1Parser() {
         warn('Malformed charstring stack: not enough values on stack.');
         continue;
       }
-      if (stack[index] === 'div') {
+      var token = stack[index];
+      if (token === 'div') {
         var a = stack[index - 2];
         var b = stack[index - 1];
         if (!isInt(a) || !isInt(b)) {
@@ -3444,10 +3445,12 @@ var Type1Parser = function type1Parser() {
         args.unshift({ arg: [a, b, 'div'],
                        value: a / b });
         index -= 3;
-      } else {
+      } else if (isInt(token)) {
         args.unshift({ arg: stack.slice(index, index + 1),
-                       value: stack[index] });
+                       value: token });
         index--;
+      } else {
+        warn('Malformed charsting stack: found bad token ' + token + '.');
       }
     }
     return args;
@@ -3504,12 +3507,14 @@ var Type1Parser = function type1Parser() {
         } else {
           if (value == 13) { // hsbw
             var args = breakUpArgs(charstring, 2);
-            lsb = args[0]['value'];
-            width = args[1]['value'];
+            var arg0 = args[0];
+            var arg1 = args[1];
+            lsb = arg0.value;
+            width = arg1.value;
             // To convert to type2 we have to move the width value to the first
             // part of the charstring and then use hmoveto with lsb.
-            charstring = args[1]['arg'];
-            charstring = charstring.concat(args[0]['arg']);
+            charstring = arg1.arg;
+            charstring = charstring.concat(arg0.arg);
             charstring.push('hmoveto');
             continue;
           } else if (value == 10) { // callsubr