Browse Source

Fix text spacing with vertical fonts (#6387)

According to the PDF spec 5.3.2, a positive value means in horizontal,
that the next glyph is further to the left (so narrower), and in
vertical that it is further down (so wider).
This change fixes the way PDF.js has interpreted the value.
Fabian Lange 10 years ago
parent
commit
2564827503
  1. 30
      src/core/evaluator.js
  2. 8
      src/display/canvas.js
  3. 1
      test/pdfs/.gitignore
  4. BIN
      test/pdfs/issue6387.pdf
  5. 13
      test/test_manifest.json

30
src/core/evaluator.js

@ -731,11 +731,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var arr = args[0]; var arr = args[0];
var combinedGlyphs = []; var combinedGlyphs = [];
var arrLength = arr.length; var arrLength = arr.length;
var state = stateManager.state;
for (i = 0; i < arrLength; ++i) { for (i = 0; i < arrLength; ++i) {
var arrItem = arr[i]; var arrItem = arr[i];
if (isString(arrItem)) { if (isString(arrItem)) {
Array.prototype.push.apply(combinedGlyphs, Array.prototype.push.apply(combinedGlyphs,
self.handleText(arrItem, stateManager.state)); self.handleText(arrItem, state));
} else if (isNum(arrItem)) { } else if (isNum(arrItem)) {
combinedGlyphs.push(arrItem); combinedGlyphs.push(arrItem);
} }
@ -1131,17 +1132,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (typeof items[j] === 'string') { if (typeof items[j] === 'string') {
buildTextGeometry(items[j], textChunk); buildTextGeometry(items[j], textChunk);
} else { } else {
var val = items[j] / 1000; // PDF Specification 5.3.2 states:
if (!textState.font.vertical) { // The number is expressed in thousandths of a unit of text
offset = -val * textState.fontSize * textState.textHScale * // space.
textState.textMatrix[0]; // This amount is subtracted from the current horizontal or
textState.translateTextMatrix(offset, 0); // vertical coordinate, depending on the writing mode.
textChunk.width += offset; // In the default coordinate system, a positive adjustment
} else { // has the effect of moving the next glyph painted either to
offset = -val * textState.fontSize * // the left or down by the given amount.
textState.textMatrix[3]; var val = items[j] * textState.fontSize / 1000;
if (textState.font.vertical) {
offset = val * textState.textMatrix[3];
textState.translateTextMatrix(0, offset); textState.translateTextMatrix(0, offset);
// Value needs to be added to height to paint down.
textChunk.height += offset; textChunk.height += offset;
} else {
offset = val * textState.textHScale *
textState.textMatrix[0];
textState.translateTextMatrix(offset, 0);
// Value needs to be subtracted from width to paint left.
textChunk.width -= offset;
} }
if (items[j] < 0 && textState.font.spaceWidth > 0) { if (items[j] < 0 && textState.font.spaceWidth > 0) {
var fakeSpaces = -items[j] / textState.font.spaceWidth; var fakeSpaces = -items[j] / textState.font.spaceWidth;

8
src/display/canvas.js

@ -1360,6 +1360,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var textHScale = current.textHScale * fontDirection; var textHScale = current.textHScale * fontDirection;
var glyphsLength = glyphs.length; var glyphsLength = glyphs.length;
var vertical = font.vertical; var vertical = font.vertical;
var spacingDir = vertical ? 1 : -1;
var defaultVMetrics = font.defaultVMetrics; var defaultVMetrics = font.defaultVMetrics;
var widthAdvanceScale = fontSize * current.fontMatrix[0]; var widthAdvanceScale = fontSize * current.fontMatrix[0];
@ -1406,7 +1407,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
x += fontDirection * wordSpacing; x += fontDirection * wordSpacing;
continue; continue;
} else if (isNum(glyph)) { } else if (isNum(glyph)) {
x += -glyph * fontSize * 0.001; x += spacingDir * glyph * fontSize / 1000;
continue; continue;
} }
@ -1476,6 +1477,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var font = current.font; var font = current.font;
var fontSize = current.fontSize; var fontSize = current.fontSize;
var fontDirection = current.fontDirection; var fontDirection = current.fontDirection;
var spacingDir = font.vertical ? 1 : -1;
var charSpacing = current.charSpacing; var charSpacing = current.charSpacing;
var wordSpacing = current.wordSpacing; var wordSpacing = current.wordSpacing;
var textHScale = current.textHScale * fontDirection; var textHScale = current.textHScale * fontDirection;
@ -1483,7 +1485,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var glyphsLength = glyphs.length; var glyphsLength = glyphs.length;
var isTextInvisible = var isTextInvisible =
current.textRenderingMode === TextRenderingMode.INVISIBLE; current.textRenderingMode === TextRenderingMode.INVISIBLE;
var i, glyph, width; var i, glyph, width, spacingLength;
if (isTextInvisible || fontSize === 0) { if (isTextInvisible || fontSize === 0) {
return; return;
@ -1504,7 +1506,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
current.x += wordSpacing * textHScale; current.x += wordSpacing * textHScale;
continue; continue;
} else if (isNum(glyph)) { } else if (isNum(glyph)) {
var spacingLength = -glyph * 0.001 * fontSize; spacingLength = spacingDir * glyph * fontSize / 1000;
this.ctx.translate(spacingLength, 0); this.ctx.translate(spacingLength, 0);
current.x += spacingLength * textHScale; current.x += spacingLength * textHScale;
continue; continue;

1
test/pdfs/.gitignore vendored

@ -100,6 +100,7 @@
!issue5747.pdf !issue5747.pdf
!issue6099.pdf !issue6099.pdf
!issue6336.pdf !issue6336.pdf
!issue6387.pdf
!issue6410.pdf !issue6410.pdf
!gradientfill.pdf !gradientfill.pdf
!bug903856.pdf !bug903856.pdf

BIN
test/pdfs/issue6387.pdf

Binary file not shown.

13
test/test_manifest.json

@ -1574,6 +1574,19 @@
"lastPage": 1, "lastPage": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue6387-canvas",
"file": "pdfs/issue6387.pdf",
"md5": "08c39ac6d0aab1596e6e59793eaf3ee4",
"rounds": 1,
"type": "eq"
},
{ "id": "issue6387-text",
"file": "pdfs/issue6387.pdf",
"md5": "08c39ac6d0aab1596e6e59793eaf3ee4",
"rounds": 1,
"type": "text",
"about": "Note that the text layer seems to be off to the right."
},
{ "id": "issue4890", { "id": "issue4890",
"file": "pdfs/issue4890.pdf", "file": "pdfs/issue4890.pdf",
"md5": "1666feb4cd26318c2bdbea6a175dce87", "md5": "1666feb4cd26318c2bdbea6a175dce87",

Loading…
Cancel
Save