From c98b905e0d6eefa54ced8625c22698e881615e7f Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 11 Jul 2012 16:29:07 -0700 Subject: [PATCH 1/9] Add support for type 1 seac charstring command. --- src/fonts.js | 6 +++++- test/pdfs/issue818.pdf.link | 1 + test/test_manifest.json | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/issue818.pdf.link diff --git a/src/fonts.js b/src/fonts.js index c955c4d1a..ba94f4305 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3391,8 +3391,8 @@ var Type1Parser = function type1Parser() { '1': 'vstem', '2': 'hstem', + '6': 'endchar', // seac // Type1 only command with command not (yet) built-in ,throw an error - '6': -1, // seac '7': -1, // sbw '11': 'sub', @@ -3464,6 +3464,10 @@ var Type1Parser = function type1Parser() { // pop or setcurrentpoint commands can be ignored // since we are not doing callothersubr continue; + } else if (escape == 6) { + // seac is like type 2's special endchar but it doesn't use the + // first argument asb, so remove it. + charstring.splice(charstring.length - 5, 1); } else if (!kHintingEnabled && (escape == 1 || escape == 2)) { charstring.push('drop', 'drop', 'drop', 'drop', 'drop', 'drop'); continue; diff --git a/test/pdfs/issue818.pdf.link b/test/pdfs/issue818.pdf.link new file mode 100644 index 000000000..c7ed0236a --- /dev/null +++ b/test/pdfs/issue818.pdf.link @@ -0,0 +1 @@ +http://www.effi.org/system/files?file=effi-siv-251110.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 4a0595348..e515bbe69 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -624,5 +624,13 @@ "pageLimit": 2, "link": true, "type": "eq" + }, + { "id": "issue818", + "file": "pdfs/issue818.pdf", + "md5": "dd2f8a5bd65164ad74da2b45a6ca90cc", + "rounds": 1, + "pageLimit": 1, + "link": true, + "type": "eq" } ] From 813b5e78b0624e42bb2649694cd694f5c793d563 Mon Sep 17 00:00:00 2001 From: benbro Date: Wed, 18 Jul 2012 21:41:36 +0300 Subject: [PATCH 2/9] Prevent the error callback from being called twice --- src/core.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core.js b/src/core.js index 409ae060d..27d5551d1 100644 --- a/src/core.js +++ b/src/core.js @@ -52,8 +52,12 @@ function getPdf(arg, callback) { if ('progress' in params) xhr.onprogress = params.progress || undefined; - if ('error' in params) + var calledErrorBack = false; + + if ('error' in params && !calledErrorBack) { + calledErrorBack = true; xhr.onerror = params.error || undefined; + } xhr.onreadystatechange = function getPdfOnreadystatechange(e) { if (xhr.readyState === 4) { @@ -61,7 +65,8 @@ function getPdf(arg, callback) { var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || xhr.responseArrayBuffer || xhr.response); callback(data); - } else if (params.error) { + } else if (params.error && !calledErrorBack) { + calledErrorBack = true; params.error(e); } } From f60d7c564f6c067d8bf0b5e5ab4ef4700a207073 Mon Sep 17 00:00:00 2001 From: benbro Date: Wed, 18 Jul 2012 22:05:55 +0300 Subject: [PATCH 3/9] Moved the check for calledErrorBack inside the xhr.onerror function --- src/core.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core.js b/src/core.js index 27d5551d1..1b3d91dbd 100644 --- a/src/core.js +++ b/src/core.js @@ -54,9 +54,12 @@ function getPdf(arg, callback) { var calledErrorBack = false; - if ('error' in params && !calledErrorBack) { - calledErrorBack = true; - xhr.onerror = params.error || undefined; + if ('error' in params) { + xhr.onerror = function errorBack() { + if (!calledErrorBack) { + calledErrorBack = true; + params.error(); + } } xhr.onreadystatechange = function getPdfOnreadystatechange(e) { From ac005ed359e0e191cfbfa203ce4d5a894b3646c6 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 18 Jul 2012 16:23:51 -0700 Subject: [PATCH 4/9] 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 Date: Thu, 19 Jul 2012 18:06:37 -0700 Subject: [PATCH 5/9] 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 24a3e0c8cc30759950972ebf4339c93fbf89e0ef Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 20 Jul 2012 09:09:48 -0700 Subject: [PATCH 6/9] Don't trigger TODO on marked content. --- src/canvas.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index cc6d50ded..32c171216 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1196,20 +1196,20 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // Marked content markPoint: function CanvasGraphics_markPoint(tag) { - TODO('Marked content'); + // TODO Marked content. }, markPointProps: function CanvasGraphics_markPointProps(tag, properties) { - TODO('Marked content'); + // TODO Marked content. }, beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) { - TODO('Marked content'); + // TODO Marked content. }, beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps( tag, properties) { - TODO('Marked content'); + // TODO Marked content. }, endMarkedContent: function CanvasGraphics_endMarkedContent() { - TODO('Marked content'); + // TODO Marked content. }, // Compatibility From 34eb537160feb14d23285696e7a0d2eb76b31a8d Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 20 Jul 2012 13:48:48 -0700 Subject: [PATCH 7/9] 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 From 97e72d58649e80196c1eef79d4e73ded3ed65893 Mon Sep 17 00:00:00 2001 From: benbro Date: Sat, 21 Jul 2012 00:51:36 +0300 Subject: [PATCH 8/9] Add missing bracket --- src/core.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core.js b/src/core.js index 1b3d91dbd..2b9481041 100644 --- a/src/core.js +++ b/src/core.js @@ -60,6 +60,7 @@ function getPdf(arg, callback) { calledErrorBack = true; params.error(); } + } } xhr.onreadystatechange = function getPdfOnreadystatechange(e) { From 792ef1b14dc7f48b3828d61cbcae0539ad95ece2 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 20 Jul 2012 15:53:39 -0700 Subject: [PATCH 9/9] Support div number format for seac operator. --- src/fonts.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/fonts.js b/src/fonts.js index 6589901bd..7b2dfbd4a 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3429,7 +3429,8 @@ var Type1Parser = function type1Parser() { for (var i = 0; i < numArgs; i++) { if (index < 0) { args.unshift({ arg: [0], - value: 0 }); + value: 0, + offset: 0 }); warn('Malformed charstring stack: not enough values on stack.'); continue; } @@ -3443,11 +3444,13 @@ var Type1Parser = function type1Parser() { b = 1; } args.unshift({ arg: [a, b, 'div'], - value: a / b }); + value: a / b, + offset: index - 2 }); index -= 3; } else if (isInt(token)) { args.unshift({ arg: stack.slice(index, index + 1), - value: token }); + value: token, + offset: index }); index--; } else { warn('Malformed charsting stack: found bad token ' + token + '.'); @@ -3501,7 +3504,9 @@ var Type1Parser = function type1Parser() { } else if (escape == 6) { // seac is like type 2's special endchar but it doesn't use the // first argument asb, so remove it. - charstring.splice(charstring.length - 5, 1); + var args = breakUpArgs(charstring, 5); + var arg0 = args[0]; + charstring.splice(arg0.offset, arg0.arg.length); } else if (!kHintingEnabled && (escape == 1 || escape == 2)) { charstring.push('drop', 'drop', 'drop', 'drop', 'drop', 'drop'); continue;