@@ -893,6 +893,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
893
893
styles : Object .create (null )
894
894
};
895
895
var bidiTexts = textContent .items ;
896
+ // At the end of each textChunk, auto insert spaces based on:
897
+ var SPACE_FACTOR_CHUNKS = 0.6 ;
898
+ // If performing a spacedText operation, auto insert spaces based on:
896
899
var SPACE_FACTOR = 0.35 ;
897
900
var MULTI_SPACE_FACTOR = 1.5 ;
898
901
@@ -1037,8 +1040,73 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
1037
1040
} else {
1038
1041
textChunk .height += Math .abs (height * scaleCtmX * scaleLineX );
1039
1042
}
1043
+ addSpaceIfNecessary (textChunk , font );
1040
1044
return textChunk ;
1041
1045
}
1046
+ function getChunkPosition (chunk , font ) {
1047
+ var tx = chunk .transform ;
1048
+ var angle = Math .atan2 (tx [1 ], tx [0 ]);
1049
+ if (font .vertical ) {
1050
+ angle += Math .PI / 2 ;
1051
+ }
1052
+ // Start by calculating the height
1053
+ var fontAscent = Math .sqrt ((tx [2 ] * tx [2 ]) + (tx [3 ] * tx [3 ]));
1054
+ // Then modify to add the ascent
1055
+ if (font .ascent ) {
1056
+ fontAscent = font .ascent * fontAscent ;
1057
+ } else if (font .descent ) {
1058
+ fontAscent = (1 + font .descent ) * fontAscent ;
1059
+ }
1060
+ return {
1061
+ x : (angle === 0 ? tx [4 ] : tx [4 ] + (fontAscent * Math .sin (angle ))),
1062
+ y : tx [5 ]
1063
+ };
1064
+ }
1065
+ function addSpaceIfNecessary (newChunk , font ) {
1066
+ // If the new chunk starts with a space, it does not need one.
1067
+ if (newChunk .str [0 ] === ' ' || newChunk .str [0 ] === '-' ) {
1068
+ return ;
1069
+ }
1070
+ if (bidiTexts .length === 0 ) {
1071
+ return ;
1072
+ }
1073
+ // If the last chunk ends with a space it does not need one.
1074
+ var lastChunk = bidiTexts [bidiTexts .length - 1 ];
1075
+ if (lastChunk .str .length === 0 ) {
1076
+ return ;
1077
+ }
1078
+ var lastChar = lastChunk .str [lastChunk .str .length - 1 ];
1079
+ if (lastChar === ' ' || lastChar === '-' ) {
1080
+ return ;
1081
+ }
1082
+ var lastPosition = getChunkPosition (lastChunk , font );
1083
+ var newPosition = getChunkPosition (newChunk , font );
1084
+ var yDiff = Math .abs (lastPosition .y - newPosition .y );
1085
+ if (yDiff >= lastChunk .height || yDiff >= newChunk .height ) {
1086
+ // On different lines, add a space.
1087
+ lastChunk .str += ' ' ;
1088
+ } else {
1089
+ var wordSpacing = textState .wordSpacing ; // Try default wordSpacing.
1090
+ if (wordSpacing === 0 ) {
1091
+ // Heuristic for wordSpacing
1092
+ wordSpacing = newChunk .width / newChunk .str .length *
1093
+ SPACE_FACTOR_CHUNKS ;
1094
+ }
1095
+ var addSpace ;
1096
+ if (newPosition .x >= lastPosition .x ) {
1097
+ // Left to right. Add a space if next is past wordSpacing.
1098
+ addSpace = newPosition .x >= lastPosition .x + lastChunk .width +
1099
+ wordSpacing ;
1100
+ } else {
1101
+ // Right to left. Add space if next is before sart.
1102
+ addSpace = lastPosition .x >= newPosition .x + newChunk .width +
1103
+ wordSpacing ;
1104
+ }
1105
+ if (addSpace ) {
1106
+ lastChunk .str += ' ' ;
1107
+ }
1108
+ }
1109
+ }
1042
1110
1043
1111
var timeSlotManager = new TimeSlotManager ();
1044
1112
@@ -1121,6 +1189,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
1121
1189
textState .translateTextMatrix (0 , offset );
1122
1190
textChunk .height += offset ;
1123
1191
}
1192
+ // Automatically insert spaces if the shift is big enough.
1124
1193
if (items [j ] < 0 && textState .font .spaceWidth > 0 ) {
1125
1194
var fakeSpaces = -items [j ] / textState .font .spaceWidth ;
1126
1195
if (fakeSpaces > MULTI_SPACE_FACTOR ) {
0 commit comments