From 376f8bde1495c7975c169f14d0a76d706606fe01 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 3 Nov 2015 10:12:41 -0600 Subject: [PATCH 1/3] Combines standalone divs into text groups. --- src/core/evaluator.js | 191 ++++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 63 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index ec7e9dcfa..cf77ad510 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -920,7 +920,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { items: [], styles: Object.create(null) }; - var bidiTexts = textContent.items; + var textContentItem = { + initialized: false, + str: [], + width: 0, + height: 0, + vertical: false, + lastAdvanceWidth: 0, + lastAdvanceHeight: 0, + textAdvanceScale: 0, + transform: null, + fontName: null + }; var SPACE_FACTOR = 0.3; var MULTI_SPACE_FACTOR = 1.5; @@ -937,7 +948,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var textState; - function newTextChunk() { + function ensureTextContentItem() { + if (textContentItem.initialized) { + return textContentItem; + } var font = textState.font; if (!(font.loadedName in textContent.styles)) { textContent.styles[font.loadedName] = { @@ -947,24 +961,61 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { vertical: font.vertical }; } - return { - // |str| is initially an array which we push individual chars to, and - // then runBidi() overwrites it with the final string. - str: [], - dir: null, - width: 0, - height: 0, - transform: null, - fontName: font.loadedName - }; + textContentItem.fontName = font.loadedName; + + // 9.4.4 Text Space Details + var tsm = [textState.fontSize * textState.textHScale, 0, + 0, textState.fontSize, + 0, textState.textRise]; + + if (font.isType3Font && + textState.fontMatrix !== FONT_IDENTITY_MATRIX && + textState.fontSize === 1) { + var glyphHeight = font.bbox[3] - font.bbox[1]; + if (glyphHeight > 0) { + glyphHeight = glyphHeight * textState.fontMatrix[3]; + tsm[3] *= glyphHeight; + } + } + + var trm = Util.transform(textState.ctm, + Util.transform(textState.textMatrix, tsm)); + textContentItem.transform = trm; + if (!font.vertical) { + textContentItem.width = 0; + textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); + textContentItem.vertical = false; + } else { + textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); + textContentItem.height = 0; + textContentItem.vertical = true; + } + + var a = textState.textLineMatrix[0]; + var b = textState.textLineMatrix[1]; + var scaleLineX = Math.sqrt(a * a + b * b); + a = textState.ctm[0]; + b = textState.ctm[1]; + var scaleCtmX = Math.sqrt(a * a + b * b); + textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; + textContentItem.lastAdvanceWidth = 0; + textContentItem.lastAdvanceHeight = 0; + + textContentItem.initialized = true; + return textContentItem; } - function runBidi(textChunk) { + function runBidiTransform(textChunk) { var str = textChunk.str.join(''); - var bidiResult = PDFJS.bidi(str, -1, textState.font.vertical); - textChunk.str = bidiResult.str; - textChunk.dir = bidiResult.dir; - return textChunk; + var bidiResult = PDFJS.bidi(str, -1, textChunk.vertical); + return { + str: bidiResult.str, + dir: bidiResult.dir, + width: textChunk.width, + height: textChunk.height, + transform: textChunk.transform, + fontName: textChunk.fontName + }; } function handleSetFont(fontName, fontRef) { @@ -976,33 +1027,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }); } - function buildTextGeometry(chars, textChunk) { + function buildTextContentItem(chars) { var font = textState.font; - textChunk = textChunk || newTextChunk(); - if (!textChunk.transform) { - // 9.4.4 Text Space Details - var tsm = [textState.fontSize * textState.textHScale, 0, - 0, textState.fontSize, - 0, textState.textRise]; - - if (font.isType3Font && - textState.fontMatrix !== FONT_IDENTITY_MATRIX && - textState.fontSize === 1) { - var glyphHeight = font.bbox[3] - font.bbox[1]; - if (glyphHeight > 0) { - glyphHeight = glyphHeight * textState.fontMatrix[3]; - tsm[3] *= glyphHeight; - } - } - - var trm = textChunk.transform = Util.transform(textState.ctm, - Util.transform(textState.textMatrix, tsm)); - if (!font.vertical) { - textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); - } else { - textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); - } - } + var textChunk = ensureTextContentItem(); var width = 0; var height = 0; var glyphs = font.charsToGlyphs(chars); @@ -1071,16 +1098,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textChunk.str.push(glyphUnicode); } - var a = textState.textLineMatrix[0]; - var b = textState.textLineMatrix[1]; - var scaleLineX = Math.sqrt(a * a + b * b); - a = textState.ctm[0]; - b = textState.ctm[1]; - var scaleCtmX = Math.sqrt(a * a + b * b); if (!font.vertical) { - textChunk.width += width * scaleCtmX * scaleLineX; + textChunk.lastAdvanceWidth = width; + textChunk.width += width * textChunk.textAdvanceScale; } else { - textChunk.height += Math.abs(height * scaleCtmX * scaleLineX); + textChunk.lastAdvanceHeight = height; + textChunk.height += Math.abs(height * textChunk.textAdvanceScale); } return textChunk; } @@ -1101,6 +1124,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { } } + function flushTextContentItem() { + if (!textContentItem.initialized) { + return; + } + textContent.items.push(runBidiTransform(textContentItem)); + + textContentItem.initialized = false; + textContentItem.str.length = 0; + } + var timeSlotManager = new TimeSlotManager(); return new Promise(function next(resolve, reject) { @@ -1119,35 +1152,60 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textState = stateManager.state; var fn = operation.fn; args = operation.args; + var advance; switch (fn | 0) { case OPS.setFont: + flushTextContentItem(); textState.fontSize = args[1]; return handleSetFont(args[0].name).then(function() { next(resolve, reject); }, reject); case OPS.setTextRise: + flushTextContentItem(); textState.textRise = args[0]; break; case OPS.setHScale: + flushTextContentItem(); textState.textHScale = args[0] / 100; break; case OPS.setLeading: + flushTextContentItem(); textState.leading = args[0]; break; case OPS.moveText: + // Optimization to treat same line movement as advance + var isSameTextLine = !textState.font ? false : + ((textState.font.vertical ? args[0] : args[1]) === 0); + if (isSameTextLine && textContentItem.initialized) { + textState.translateTextLineMatrix(args[0], args[1]); + textContentItem.width += + (args[0] - textContentItem.lastAdvanceWidth); + textContentItem.height += + (args[1] - textContentItem.lastAdvanceHeight); + advance = (args[0] - args[1]) * 1000 / textState.fontSize; + if (advance > 0) { + addFakeSpaces(advance, textContentItem.str); + } + break; + } + + flushTextContentItem(); textState.translateTextLineMatrix(args[0], args[1]); textState.textMatrix = textState.textLineMatrix.slice(); break; case OPS.setLeadingMoveText: + flushTextContentItem(); textState.leading = -args[1]; textState.translateTextLineMatrix(args[0], args[1]); textState.textMatrix = textState.textLineMatrix.slice(); break; case OPS.nextLine: + flushTextContentItem(); textState.carriageReturn(); break; case OPS.setTextMatrix: + flushTextContentItem(); textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); textState.setTextLineMatrix(args[0], args[1], args[2], args[3], @@ -1160,17 +1218,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textState.wordSpacing = args[0]; break; case OPS.beginText: + flushTextContentItem(); textState.textMatrix = IDENTITY_MATRIX.slice(); textState.textLineMatrix = IDENTITY_MATRIX.slice(); break; case OPS.showSpacedText: var items = args[0]; - var textChunk = newTextChunk(); var offset; for (var j = 0, jj = items.length; j < jj; j++) { if (typeof items[j] === 'string') { - buildTextGeometry(items[j], textChunk); + buildTextContentItem(items[j]); } else { + if (j === 0) { + ensureTextContentItem(); + } // PDF Specification 5.3.2 states: // The number is expressed in thousandths of a unit of text // space. @@ -1179,7 +1240,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // In the default coordinate system, a positive adjustment // has the effect of moving the next glyph painted either to // the left or down by the given amount. - var advance = items[j]; + advance = items[j]; var val = advance * textState.fontSize / 1000; if (textState.font.vertical) { offset = val * @@ -1187,37 +1248,39 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textState.textMatrix[3]); textState.translateTextMatrix(0, val); // Value needs to be added to height to paint down. - textChunk.height += offset; + textContentItem.height += offset; } else { offset = val * ( textState.textHScale * textState.textMatrix[0] + textState.textMatrix[1]); textState.translateTextMatrix(-val, 0); // Value needs to be subtracted from width to paint left. - textChunk.width -= offset; + textContentItem.width -= offset; advance = -advance; } if (advance > 0) { - addFakeSpaces(advance, textChunk.str); + addFakeSpaces(advance, textContentItem.str); } } } - bidiTexts.push(runBidi(textChunk)); break; case OPS.showText: - bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + buildTextContentItem(args[0]); break; case OPS.nextLineShowText: + flushTextContentItem(); textState.carriageReturn(); - bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + buildTextContentItem(args[0]); break; case OPS.nextLineSetSpacingShowText: + flushTextContentItem(); textState.wordSpacing = args[0]; textState.charSpacing = args[1]; textState.carriageReturn(); - bidiTexts.push(runBidi(buildTextGeometry(args[2]))); + buildTextContentItem(args[2]); break; case OPS.paintXObject: + flushTextContentItem(); if (args[0].code) { break; } @@ -1229,7 +1292,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var name = args[0].name; if (xobjsCache.key === name) { if (xobjsCache.texts) { - Util.appendToArray(bidiTexts, xobjsCache.texts.items); + Util.appendToArray(textContent.items, xobjsCache.texts.items); Util.extendObj(textContent.styles, xobjsCache.texts.styles); } break; @@ -1260,7 +1323,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { return self.getTextContent(xobj, task, xobj.dict.get('Resources') || resources, stateManager). then(function (formTextContent) { - Util.appendToArray(bidiTexts, formTextContent.items); + Util.appendToArray(textContent.items, formTextContent.items); Util.extendObj(textContent.styles, formTextContent.styles); stateManager.restore(); @@ -1270,6 +1333,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { next(resolve, reject); }, reject); case OPS.setGState: + flushTextContentItem(); var dictName = args[0]; var extGState = resources.get('ExtGState'); @@ -1300,6 +1364,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }, reject); return; } + flushTextContentItem(); resolve(textContent); }); }, From fa423cfab0b6f2d1b42c7de24fca39e3be834dc2 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 6 Nov 2015 08:40:44 -0600 Subject: [PATCH 2/3] Refactors fake space heuristics for speed. --- src/core/evaluator.js | 95 +++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index cf77ad510..6c4d33fe9 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -929,11 +929,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { lastAdvanceWidth: 0, lastAdvanceHeight: 0, textAdvanceScale: 0, + spaceWidth: 0, + fakeSpaceMin: Infinity, + fakeMultiSpaceMin: Infinity, + fakeMultiSpaceMax: -0, + textRunBreakAllowed: false, transform: null, fontName: null }; var SPACE_FACTOR = 0.3; var MULTI_SPACE_FACTOR = 1.5; + var MULTI_SPACE_FACTOR_MAX = 4; var self = this; var xref = this.xref; @@ -1001,6 +1007,24 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textContentItem.lastAdvanceWidth = 0; textContentItem.lastAdvanceHeight = 0; + var spaceWidth = font.spaceWidth / 1000 * textState.fontSize; + if (spaceWidth) { + textContentItem.spaceWidth = spaceWidth; + textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR; + textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR; + textContentItem.fakeMultiSpaceMax = + spaceWidth * MULTI_SPACE_FACTOR_MAX; + // It's okay for monospace fonts to fake as much space as needed. + textContentItem.textRunBreakAllowed = !font.isMonospace; + } else { + textContentItem.spaceWidth = 0; + textContentItem.fakeSpaceMin = Infinity; + textContentItem.fakeMultiSpaceMin = Infinity; + textContentItem.fakeMultiSpaceMax = 0; + textContentItem.textRunBreakAllowed = false; + } + + textContentItem.initialized = true; return textContentItem; } @@ -1076,8 +1100,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var wordSpacing = textState.wordSpacing; charSpacing += wordSpacing; if (wordSpacing > 0) { - addFakeSpaces(wordSpacing * 1000 / textState.fontSize, - textChunk.str); + addFakeSpaces(wordSpacing, textChunk.str); } } @@ -1105,21 +1128,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textChunk.lastAdvanceHeight = height; textChunk.height += Math.abs(height * textChunk.textAdvanceScale); } + return textChunk; } function addFakeSpaces(width, strBuf) { - var spaceWidth = textState.font.spaceWidth; - if (spaceWidth <= 0) { + if (width < textContentItem.fakeSpaceMin) { return; } - var fakeSpaces = width / spaceWidth; - if (fakeSpaces > MULTI_SPACE_FACTOR) { - fakeSpaces = Math.round(fakeSpaces); - while (fakeSpaces--) { - strBuf.push(' '); - } - } else if (fakeSpaces > SPACE_FACTOR) { + if (width < textContentItem.fakeMultiSpaceMin) { + strBuf.push(' '); + return; + } + var fakeSpaces = Math.round(width / textContentItem.spaceWidth); + while (fakeSpaces-- > 0) { strBuf.push(' '); } } @@ -1177,16 +1199,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // Optimization to treat same line movement as advance var isSameTextLine = !textState.font ? false : ((textState.font.vertical ? args[0] : args[1]) === 0); - if (isSameTextLine && textContentItem.initialized) { + advance = args[0] - args[1]; + if (isSameTextLine && textContentItem.initialized && + advance > 0 && + advance <= textContentItem.fakeMultiSpaceMax) { textState.translateTextLineMatrix(args[0], args[1]); textContentItem.width += (args[0] - textContentItem.lastAdvanceWidth); textContentItem.height += (args[1] - textContentItem.lastAdvanceHeight); - advance = (args[0] - args[1]) * 1000 / textState.fontSize; - if (advance > 0) { - addFakeSpaces(advance, textContentItem.str); - } + var diff = (args[0] - textContentItem.lastAdvanceWidth) - + (args[1] - textContentItem.lastAdvanceHeight); + addFakeSpaces(diff, textContentItem.str); break; } @@ -1229,9 +1253,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { if (typeof items[j] === 'string') { buildTextContentItem(items[j]); } else { - if (j === 0) { - ensureTextContentItem(); - } + ensureTextContentItem(); + // PDF Specification 5.3.2 states: // The number is expressed in thousandths of a unit of text // space. @@ -1240,25 +1263,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // In the default coordinate system, a positive adjustment // has the effect of moving the next glyph painted either to // the left or down by the given amount. - advance = items[j]; - var val = advance * textState.fontSize / 1000; + advance = items[j] * textState.fontSize / 1000; + var breakTextRun = false; if (textState.font.vertical) { - offset = val * + offset = advance * (textState.textHScale * textState.textMatrix[2] + textState.textMatrix[3]); - textState.translateTextMatrix(0, val); - // Value needs to be added to height to paint down. - textContentItem.height += offset; + textState.translateTextMatrix(0, advance); + breakTextRun = textContentItem.textRunBreakAllowed && + advance > textContentItem.fakeMultiSpaceMax; + if (!breakTextRun) { + // Value needs to be added to height to paint down. + textContentItem.height += offset; + } } else { - offset = val * ( + advance = -advance; + offset = advance * ( textState.textHScale * textState.textMatrix[0] + textState.textMatrix[1]); - textState.translateTextMatrix(-val, 0); - // Value needs to be subtracted from width to paint left. - textContentItem.width -= offset; - advance = -advance; + textState.translateTextMatrix(advance, 0); + breakTextRun = textContentItem.textRunBreakAllowed && + advance > textContentItem.fakeMultiSpaceMax; + if (!breakTextRun) { + // Value needs to be subtracted from width to paint left. + textContentItem.width += offset; + } } - if (advance > 0) { + if (breakTextRun) { + flushTextContentItem(); + } else if (advance > 0) { addFakeSpaces(advance, textContentItem.str); } } From 4ee0bade8266893c3ab3fb04f372c0f4af3a77b3 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 6 Nov 2015 08:54:50 -0600 Subject: [PATCH 3/3] Test for text layer issue 1045. --- test/pdfs/.gitignore | 1 + test/pdfs/issue1045.pdf | Bin 0 -> 22741 bytes test/test_manifest.json | 7 +++++++ 3 files changed, 8 insertions(+) create mode 100644 test/pdfs/issue1045.pdf diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index f0155bea8..ee5c9c3a2 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -137,6 +137,7 @@ !vertical.pdf !ZapfDingbats.pdf !bug878026.pdf +!issue1045.pdf !issue5010.pdf !issue4934.pdf !issue4650.pdf diff --git a/test/pdfs/issue1045.pdf b/test/pdfs/issue1045.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ca7f5b7ae1a9443bdbc4d0e29236682cb337e99c GIT binary patch literal 22741 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