From: Artur Adib Date: Thu, 1 Dec 2011 15:42:07 +0000 (-0500) Subject: Merge branch 'master' of git://github.com/mozilla/pdf.js into text-select X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=5e1d78ef20a169a3475f33b330fca503bd8df66f;p=pdf.js.git Merge branch 'master' of git://github.com/mozilla/pdf.js into text-select Conflicts: src/canvas.js --- 5e1d78ef20a169a3475f33b330fca503bd8df66f diff --cc src/canvas.js index 16a8708,f16313d..1e8febe --- a/src/canvas.js +++ b/src/canvas.js @@@ -564,60 -528,7 +564,60 @@@ var CanvasGraphics = (function canvasGr nextLine: function canvasGraphicsNextLine() { this.moveText(0, this.current.leading); }, - showText: function canvasGraphicsShowText(text) { + applyTextTransforms: function canvasApplyTransforms() { + var ctx = this.ctx; + var current = this.current; + var textHScale = current.textHScale; - var font = current.font; ++ var fontMatrix = current.font.fontMatrix || IDENTITY_MATRIX; + + ctx.transform.apply(ctx, current.textMatrix); + ctx.scale(1, -1); + ctx.translate(current.x, -1 * current.y); - ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX); ++ ctx.transform.apply(ctx, fontMatrix); + ctx.scale(1 / textHScale, 1); + }, + getTextGeometry: function canvasGetTextGeometry() { + var geom = {}; + var ctx = this.ctx; + var font = this.current.font; + var ctxMatrix = ctx.mozCurrentTransform; + if (ctxMatrix) { + var bl = Util.applyTransform([0, 0], ctxMatrix); + var tr = Util.applyTransform([1, 1], ctxMatrix); + geom.x = bl[0]; + geom.y = bl[1]; + geom.hScale = tr[0] - bl[0]; + geom.vScale = tr[1] - bl[1]; + } + var spaceGlyph = font.charsToGlyphs(' '); + // Hack (sometimes space is not encoded) + if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0) + spaceGlyph = font.charsToGlyphs('i'); + // Fallback + if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0) + spaceGlyph = [{width: 0}]; + geom.spaceWidth = spaceGlyph[0].width; + return geom; + }, + pushTextDivs: function canvasGraphicsPushTextDivs(text) { + var div = document.createElement('div'); + var fontSize = this.current.fontSize; + + // vScale and hScale already contain the scaling to pixel units + // as mozCurrentTransform reflects ctx.scale() changes + // (see beginDrawing()) + var fontHeight = fontSize * text.geom.vScale; + div.dataset.canvasWidth = text.canvasWidth * text.geom.hScale; + + div.style.fontSize = fontHeight + 'px'; + div.style.fontFamily = this.current.font.loadedName || 'sans-serif'; + div.style.left = text.geom.x + 'px'; + div.style.top = (text.geom.y - fontHeight) + 'px'; + div.innerHTML = text.str; + div.dataset.textLength = text.length; + this.textDivs.push(div); + }, + showText: function canvasGraphicsShowText(str, skipTextSelection) { var ctx = this.ctx; var current = this.current; var font = current.font; @@@ -626,19 -537,9 +626,21 @@@ var charSpacing = current.charSpacing; var wordSpacing = current.wordSpacing; var textHScale = current.textHScale; + var fontMatrix = font.fontMatrix || IDENTITY_MATRIX; + var textHScale2 = textHScale * fontMatrix[0]; var glyphsLength = glyphs.length; + var textLayer = this.textLayer; + var text = {str: '', length: 0, canvasWidth: 0, geom: {}}; + var textSelection = textLayer && !skipTextSelection ? true : false; + + if (textSelection) { + ctx.save(); + this.applyTextTransforms(); + text.geom = this.getTextGeometry(); + ctx.restore(); + } + + // Type3 fonts - each glyph is a "mini-PDF" if (font.coded) { ctx.save(); ctx.transform.apply(ctx, current.textMatrix); @@@ -662,13 -562,11 +663,14 @@@ this.restore(); var transformed = Util.applyTransform([glyph.width, 0], fontMatrix); - var charWidth = transformed[0] * fontSize + charSpacing; - ctx.translate(charWidth, 0); - current.x += charWidth; + var width = transformed[0] * fontSize + charSpacing; + + ctx.translate(width, 0); + current.x += width * textHScale2; - text.str += glyph.fontChar; ++ text.str += glyph.unicode; + text.length++; - text.canvasWidth += charWidth; ++ text.canvasWidth += width; } ctx.restore(); } else { @@@ -685,70 -588,30 +687,70 @@@ } var char = glyph.fontChar; + var charWidth = glyph.width * fontSize * 0.001 + charSpacing; ctx.fillText(char, width, 0); - width += glyph.width * fontSize * 0.001 + charSpacing; + width += charWidth; - text.str += char === ' ' ? ' ' : char; - // TODO actual characters can be extracted from the glyph.unicode ++ text.str += glyph.unicode === ' ' ? ' ' : glyph.unicode; + text.length++; + text.canvasWidth += charWidth; } - - current.x += width; + current.x += width * textHScale2; - ctx.restore(); } - }, + if (textSelection) + this.pushTextDivs(text); + + return text; + }, showSpacedText: function canvasGraphicsShowSpacedText(arr) { var ctx = this.ctx; var current = this.current; var fontSize = current.fontSize; - var textHScale = current.textHScale; + var textHScale2 = current.textHScale * + (current.font.fontMatrix || IDENTITY_MATRIX)[0]; var arrLength = arr.length; + var textLayer = this.textLayer; + var font = current.font; + var text = {str: '', length: 0, canvasWidth: 0, geom: {}}; + var textSelection = textLayer ? true : false; + + if (textSelection) { + ctx.save(); + this.applyTextTransforms(); + text.geom = this.getTextGeometry(); + ctx.restore(); + } + for (var i = 0; i < arrLength; ++i) { var e = arr[i]; if (isNum(e)) { - var spacingLength = -e * 0.001 * fontSize * textHScale; - current.x -= e * 0.001 * fontSize * textHScale2; ++ var spacingLength = -e * 0.001 * fontSize * textHScale2; + current.x += spacingLength; + + if (textSelection) { + // Emulate precise spacing via HTML spaces + text.canvasWidth += spacingLength; + if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero + var numFakeSpaces = Math.round(-e / text.geom.spaceWidth); + for (var j = 0; j < numFakeSpaces; ++j) + text.str += ' '; + text.length += numFakeSpaces > 0 ? 1 : 0; + } + } } else if (isString(e)) { - this.showText(e); + var shownText = this.showText(e, true); + + if (textSelection) { + if (shownText.str === ' ') { + text.str += ' '; + } else { + text.str += shownText.str; + } + text.canvasWidth += shownText.canvasWidth; + text.length += e.length; + } } else { malformed('TJ array element ' + e + ' is not string or num'); }