From fc5b7dbb1fc788b9c5bcaf6231b81e6101377f77 Mon Sep 17 00:00:00 2001 From: Mack Duan Date: Mon, 25 Mar 2013 15:32:47 -0700 Subject: [PATCH 1/3] Add support for form text annotations --- src/annotation.js | 128 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/src/annotation.js b/src/annotation.js index 467cbf9f8..c6240438f 100644 --- a/src/annotation.js +++ b/src/annotation.js @@ -189,7 +189,11 @@ var Annotation = (function AnnotationClosure() { return; } - return WidgetAnnotation; + if (fieldType === 'Tx') { + return TextWidgetAnnotation; + } else { + return WidgetAnnotation; + } } else { return Annotation; } @@ -313,6 +317,128 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { return WidgetAnnotation; })(); +var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { + function TextWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + + if (params.data) { + return; + } + + this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q'); + } + + // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont() + function setTextStyles(element, item, fontObj) { + + var style = element.style; + style.fontSize = item.fontSize + 'px'; + style.direction = item.fontDirection < 0 ? 'rtl': 'ltr'; + + if (!fontObj) { + return; + } + + style.fontWeight = fontObj.black ? + (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + style.fontStyle = fontObj.italic ? 'italic' : 'normal'; + + var fontName = fontObj.loadedName; + var fontFamily = fontName ? '"' + fontName + '", ' : ''; + // Use a reasonable default font if the font doesn't specify a fallback + var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif'; + style.fontFamily = fontFamily + fallbackName; + } + + + var parent = WidgetAnnotation.prototype; + Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { + hasHtml: function TextWidgetAnnotation_hasHtml() { + return !!this.data.fieldValue; + }, + + getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) { + assert(!isWorker, 'getHtmlElement() shall be called from main thread'); + + var item = this.data; + + var element = this.getEmptyContainer('div'); + element.style.display = 'table'; + + var content = document.createElement('div'); + content.textContent = item.fieldValue; + var textAlignment = item.textAlignment; + content.style.textAlign = ['left', 'center', 'right'][textAlignment]; + content.style.verticalAlign = 'middle'; + content.style.display = 'table-cell'; + + var fontObj = item.fontRefName ? + commonObjs.getData(item.fontRefName) : null; + var cssRules = setTextStyles(content, item, fontObj); + + element.appendChild(content); + + return element; + }, + + appendToOperatorList: function TextWidgetAnnotation_appendToOperatorList( + operatorList, dependencies, evaluator) { + + // Even if there is an appearance stream, ignore it. This is the + // behaviour used by Adobe Reader. + + var defaultAppearance = this.data.defaultAppearance; + if (!defaultAppearance) { + return; + } + + // Include any font resources found in the default appearance + + var stream = new Stream(stringToBytes(defaultAppearance)); + var list = evaluator.getOperatorList(stream, this.fieldResources, + dependencies); + + var fnArray = operatorList.fnArray; + var argsArray = operatorList.argsArray; + var appearanceFnArray = list.fnArray; + var appearanceArgsArray = list.argsArray; + + // TODO(mack): Add support for stroke color + this.data.rgb = [0, 0, 0]; + for (var i = 0, n = fnArray.length; i < n; ++i) { + var fnName = appearanceFnArray[i]; + var args = appearanceArgsArray[i]; + if (fnName === 'dependency') { + var dependency = args[i]; + if (dependency.indexOf('g_font_') === 0) { + this.data.fontRefName = dependency; + } + fnArray.push(fnName); + argsArray.push(args); + } else if (fnName === 'setFont') { + this.data.fontRefName = args[0]; + var size = args[1]; + if (size < 0) { + this.data.fontDirection = -1; + this.data.fontSize = -size; + } else { + this.data.fontDirection = 1; + this.data.fontSize = size; + } + } else if (fnName === 'setFillRGBColor') { + this.data.rgb = args; + } else if (fnName === 'setFillGray') { + var rgbValue = args[0] * 255; + this.data.rgb = [rgbValue, rgbValue, rgbValue]; + } + } + } + }); + + return TextWidgetAnnotation; +})(); + var TextAnnotation = (function TextAnnotationClosure() { function TextAnnotation(params) { Annotation.call(this, params); From 234812a807318eeda7ee98e22828e9de14ad1746 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 28 May 2013 20:16:21 -0500 Subject: [PATCH 2/3] Fixing appendToOperatorList --- src/annotation.js | 98 ++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/src/annotation.js b/src/annotation.js index c6240438f..1e18199ca 100644 --- a/src/annotation.js +++ b/src/annotation.js @@ -129,7 +129,7 @@ var Annotation = (function AnnotationClosure() { ); }, - getOperatorList: function Annotation_appendToOperatorList(evaluator) { + getOperatorList: function Annotation_getToOperatorList(evaluator) { var promise = new Promise(); @@ -382,57 +382,77 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { return element; }, - appendToOperatorList: function TextWidgetAnnotation_appendToOperatorList( - operatorList, dependencies, evaluator) { + getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) { + + + var promise = new Promise(); + var data = this.data; // Even if there is an appearance stream, ignore it. This is the // behaviour used by Adobe Reader. - var defaultAppearance = this.data.defaultAppearance; + var defaultAppearance = data.defaultAppearance; if (!defaultAppearance) { - return; + promise.resolve({ + queue: { + fnArray: [], + argsArray: [] + }, + dependency: {} + }); + return promise; } // Include any font resources found in the default appearance var stream = new Stream(stringToBytes(defaultAppearance)); - var list = evaluator.getOperatorList(stream, this.fieldResources, - dependencies); + var listPromise = evaluator.getOperatorList(stream, this.fieldResources); + listPromise.then(function(appearanceStreamData) { + var appearanceFnArray = appearanceStreamData.queue.fnArray; + var appearanceArgsArray = appearanceStreamData.queue.argsArray; + var fnArray = []; + var argsArray = []; - var fnArray = operatorList.fnArray; - var argsArray = operatorList.argsArray; - var appearanceFnArray = list.fnArray; - var appearanceArgsArray = list.argsArray; - - // TODO(mack): Add support for stroke color - this.data.rgb = [0, 0, 0]; - for (var i = 0, n = fnArray.length; i < n; ++i) { - var fnName = appearanceFnArray[i]; - var args = appearanceArgsArray[i]; - if (fnName === 'dependency') { - var dependency = args[i]; - if (dependency.indexOf('g_font_') === 0) { - this.data.fontRefName = dependency; + // TODO(mack): Add support for stroke color + data.rgb = [0, 0, 0]; + for (var i = 0, n = fnArray.length; i < n; ++i) { + var fnName = appearanceFnArray[i]; + var args = appearanceArgsArray[i]; + if (fnName === 'dependency') { + var dependency = args[i]; + if (dependency.indexOf('g_font_') === 0) { + data.fontRefName = dependency; + } + fnArray.push(fnName); + argsArray.push(args); + } else if (fnName === 'setFont') { + data.fontRefName = args[0]; + var size = args[1]; + if (size < 0) { + data.fontDirection = -1; + data.fontSize = -size; + } else { + data.fontDirection = 1; + data.fontSize = size; + } + } else if (fnName === 'setFillRGBColor') { + data.rgb = args; + } else if (fnName === 'setFillGray') { + var rgbValue = args[0] * 255; + data.rgb = [rgbValue, rgbValue, rgbValue]; } - fnArray.push(fnName); - argsArray.push(args); - } else if (fnName === 'setFont') { - this.data.fontRefName = args[0]; - var size = args[1]; - if (size < 0) { - this.data.fontDirection = -1; - this.data.fontSize = -size; - } else { - this.data.fontDirection = 1; - this.data.fontSize = size; - } - } else if (fnName === 'setFillRGBColor') { - this.data.rgb = args; - } else if (fnName === 'setFillGray') { - var rgbValue = args[0] * 255; - this.data.rgb = [rgbValue, rgbValue, rgbValue]; } - } + promise.resolve({ + queue: { + fnArray: fnArray, + argsArray: argsArray + }, + dependency: {} + }); + + }); + + return promise; } }); From 1c6189df258104fd7c0c981bbce97a78ba83ad37 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 31 May 2013 14:13:23 -0700 Subject: [PATCH 3/3] Add tx annotation test file. --- test/pdfs/annotation-tx.pdf | Bin 0 -> 11672 bytes test/test_manifest.json | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 test/pdfs/annotation-tx.pdf diff --git a/test/pdfs/annotation-tx.pdf b/test/pdfs/annotation-tx.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d62db2e55be9fed759376f8e00e6bdcc267cea0f GIT binary patch literal 11672 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 literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index 7d6eb1cb5..3222c54da 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -970,6 +970,13 @@ "link": true, "type": "eq" }, + { "id": "annotation-tx", + "file": "pdfs/annotation-tx.pdf", + "md5": "56321ea830be9c4f8437ca17ac535b2d", + "rounds": 1, + "type": "eq", + "about": "Text widget annotation witout appearance streams." + }, { "id": "gesamt", "file": "pdfs/gesamt.pdf", "md5": "f9148b71aad9a7856f70f303d7e78703",