Skip to content

Commit 32f9cab

Browse files
committed
Support the vertical writing mode with SVG backend.
1 parent c218e94 commit 32f9cab

File tree

1 file changed

+57
-16
lines changed

1 file changed

+57
-16
lines changed

src/display/svg.js

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
744744
current.y = current.lineY = 0;
745745

746746
current.xcoords = [];
747+
current.ycoords = [];
747748
current.tspan = this.svgFactory.createElement("svg:tspan");
748749
current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
749750
current.tspan.setAttributeNS(
@@ -768,6 +769,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
768769
current.txtElement = this.svgFactory.createElement("svg:text");
769770
current.txtgrp = this.svgFactory.createElement("svg:g");
770771
current.xcoords = [];
772+
current.ycoords = [];
771773
}
772774

773775
moveText(x, y) {
@@ -776,6 +778,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
776778
current.y = current.lineY += y;
777779

778780
current.xcoords = [];
781+
current.ycoords = [];
779782
current.tspan = this.svgFactory.createElement("svg:tspan");
780783
current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
781784
current.tspan.setAttributeNS(
@@ -794,11 +797,14 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
794797
return;
795798
}
796799

800+
const fontSizeScale = current.fontSizeScale;
797801
const charSpacing = current.charSpacing;
798802
const wordSpacing = current.wordSpacing;
799803
const fontDirection = current.fontDirection;
800804
const textHScale = current.textHScale * fontDirection;
801805
const vertical = font.vertical;
806+
const spacingDir = vertical ? 1 : -1;
807+
const defaultVMetrics = font.defaultVMetrics;
802808
const widthAdvanceScale = fontSize * current.fontMatrix[0];
803809

804810
let x = 0;
@@ -808,39 +814,72 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
808814
x += fontDirection * wordSpacing;
809815
continue;
810816
} else if (isNum(glyph)) {
811-
x += -glyph * fontSize * 0.001;
817+
x += (spacingDir * glyph * fontSize) / 1000;
812818
continue;
813819
}
814820

815-
const width = glyph.width;
816-
const character = glyph.fontChar;
817821
const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
818-
const charWidth = width * widthAdvanceScale + spacing * fontDirection;
822+
const character = glyph.fontChar;
823+
let scaledX, scaledY;
824+
let width = glyph.width;
825+
if (vertical) {
826+
let vx;
827+
const vmetric = glyph.vmetric || defaultVMetrics;
828+
vx = glyph.vmetric ? vmetric[1] : width * 0.5;
829+
vx = -vx * widthAdvanceScale;
830+
const vy = vmetric[2] * widthAdvanceScale;
831+
832+
width = vmetric ? -vmetric[0] : width;
833+
scaledX = vx / fontSizeScale;
834+
scaledY = (x + vy) / fontSizeScale;
835+
} else {
836+
scaledX = x / fontSizeScale;
837+
scaledY = 0;
838+
}
819839

820-
if (!glyph.isInFont && !font.missingFile) {
821-
x += charWidth;
840+
if (glyph.isInFont || font.missingFile) {
841+
current.xcoords.push(current.x + scaledX);
842+
if (vertical) {
843+
current.ycoords.push(-current.y + scaledY);
844+
}
845+
current.tspan.textContent += character;
846+
} else {
822847
// TODO: To assist with text selection, we should replace the missing
823848
// character with a space character if charWidth is not zero.
824849
// But we cannot just do "character = ' '", because the ' ' character
825850
// might actually map to a different glyph.
826-
continue;
827851
}
828-
current.xcoords.push(current.x + x);
829-
current.tspan.textContent += character;
852+
853+
let charWidth;
854+
if (vertical) {
855+
charWidth = width * widthAdvanceScale - spacing * fontDirection;
856+
} else {
857+
charWidth = width * widthAdvanceScale + spacing * fontDirection;
858+
}
859+
830860
x += charWidth;
831861
}
832-
if (vertical) {
833-
current.y -= x * textHScale;
834-
} else {
835-
current.x += x * textHScale;
836-
}
837-
838862
current.tspan.setAttributeNS(
839863
null,
840864
"x",
841865
current.xcoords.map(pf).join(" ")
842866
);
843-
current.tspan.setAttributeNS(null, "y", pf(-current.y));
867+
if (vertical) {
868+
current.tspan.setAttributeNS(
869+
null,
870+
"y",
871+
current.ycoords.map(pf).join(" ")
872+
);
873+
} else {
874+
current.tspan.setAttributeNS(null, "y", pf(-current.y));
875+
}
876+
877+
if (vertical) {
878+
current.y -= x;
879+
} else {
880+
current.x += x * textHScale;
881+
}
882+
844883
current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
845884
current.tspan.setAttributeNS(
846885
null,
@@ -966,6 +1005,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
9661005
current.tspan = this.svgFactory.createElement("svg:tspan");
9671006
current.tspan.setAttributeNS(null, "y", pf(-current.y));
9681007
current.xcoords = [];
1008+
current.ycoords = [];
9691009
}
9701010

9711011
endText() {
@@ -1017,6 +1057,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
10171057
this.current.fillColor = Util.makeCssRgb(r, g, b);
10181058
this.current.tspan = this.svgFactory.createElement("svg:tspan");
10191059
this.current.xcoords = [];
1060+
this.current.ycoords = [];
10201061
}
10211062

10221063
setStrokeColorN(args) {

0 commit comments

Comments
 (0)