Refactors showText: split type3, remove showSpacedText
This commit is contained in:
parent
d2da73b8c4
commit
d53dc2e7d6
@ -676,18 +676,31 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
break;
|
||||
case OPS.showSpacedText:
|
||||
var arr = args[0];
|
||||
var combinedGlyphs = [];
|
||||
var arrLength = arr.length;
|
||||
for (i = 0; i < arrLength; ++i) {
|
||||
if (isString(arr[i])) {
|
||||
arr[i] = self.handleText(arr[i], stateManager.state);
|
||||
var arrItem = arr[i];
|
||||
if (isString(arrItem)) {
|
||||
Array.prototype.push.apply(combinedGlyphs,
|
||||
self.handleText(arrItem, stateManager.state));
|
||||
} else if (isNum(arrItem)) {
|
||||
combinedGlyphs.push(arrItem);
|
||||
}
|
||||
}
|
||||
args[0] = combinedGlyphs;
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.nextLineShowText:
|
||||
operatorList.addOp(OPS.nextLine);
|
||||
args[0] = self.handleText(args[0], stateManager.state);
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.nextLineSetSpacingShowText:
|
||||
args[2] = self.handleText(args[2], stateManager.state);
|
||||
operatorList.addOp(OPS.nextLine);
|
||||
operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
|
||||
operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
|
||||
args[0] = self.handleText(args[0], stateManager.state);
|
||||
fn = OPS.showText;
|
||||
break;
|
||||
case OPS.setTextRenderingMode:
|
||||
stateManager.state.textRenderingMode = args[0];
|
||||
|
@ -352,6 +352,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
||||
this.fontSize = 0;
|
||||
this.fontSizeScale = 1;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.textMatrixScale = 1;
|
||||
this.fontMatrix = FONT_IDENTITY_MATRIX;
|
||||
this.leading = 0;
|
||||
// Current point (in user coordinates)
|
||||
@ -1129,6 +1130,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// Text
|
||||
beginText: function CanvasGraphics_beginText() {
|
||||
this.current.textMatrix = IDENTITY_MATRIX;
|
||||
this.current.textMatrixScale = 1;
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
},
|
||||
@ -1233,6 +1235,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
},
|
||||
setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
|
||||
this.current.textMatrix = [a, b, c, d, e, f];
|
||||
this.current.textMatrixScale = Math.sqrt(a * a + b * b);
|
||||
|
||||
this.current.x = this.current.lineX = 0;
|
||||
this.current.y = this.current.lineY = 0;
|
||||
@ -1240,24 +1243,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
nextLine: function CanvasGraphics_nextLine() {
|
||||
this.moveText(0, this.current.leading);
|
||||
},
|
||||
applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y + current.textRise);
|
||||
if (current.fontDirection > 0) {
|
||||
ctx.scale(current.textHScale, -1);
|
||||
} else {
|
||||
ctx.scale(-current.textHScale, 1);
|
||||
}
|
||||
},
|
||||
|
||||
paintChar: function CanvasGraphics_paintChar(character, x, y) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize / current.fontSizeScale;
|
||||
var textRenderingMode = current.textRenderingMode;
|
||||
var fontSize = current.fontSize / current.fontSizeScale;
|
||||
var fillStrokeMode = textRenderingMode &
|
||||
TextRenderingMode.FILL_STROKE_MASK;
|
||||
var isAddToPathSet = !!(textRenderingMode &
|
||||
@ -1323,181 +1315,182 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
},
|
||||
|
||||
showText: function CanvasGraphics_showText(glyphs) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
var fontSizeScale = current.fontSizeScale;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale * current.fontDirection;
|
||||
var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
|
||||
var glyphsLength = glyphs.length;
|
||||
var vertical = font.vertical;
|
||||
var defaultVMetrics = font.defaultVMetrics;
|
||||
var i, glyph, width;
|
||||
if (font.isType3Font) {
|
||||
return this.showType3Text(glyphs);
|
||||
}
|
||||
|
||||
var fontSize = current.fontSize;
|
||||
if (fontSize === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Type3 fonts - each glyph is a "mini-PDF"
|
||||
if (font.isType3Font) {
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y);
|
||||
var ctx = this.ctx;
|
||||
var fontSizeScale = current.fontSizeScale;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var fontDirection = current.fontDirection;
|
||||
var textHScale = current.textHScale * fontDirection;
|
||||
var glyphsLength = glyphs.length;
|
||||
var vertical = font.vertical;
|
||||
var defaultVMetrics = font.defaultVMetrics;
|
||||
var widthAdvanceScale = fontSize * current.fontMatrix[0];
|
||||
|
||||
ctx.scale(textHScale, 1);
|
||||
var simpleFillText =
|
||||
current.textRenderingMode === TextRenderingMode.FILL &&
|
||||
!font.disableFontFace;
|
||||
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
current.x += wordSpacing * textHScale;
|
||||
continue;
|
||||
}
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y + current.textRise);
|
||||
|
||||
this.processingType3 = glyph;
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
var operatorList = font.charProcOperatorList[glyph.operatorListId];
|
||||
this.executeOperatorList(operatorList);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
width = ((transformed[0] * fontSize + charSpacing) *
|
||||
current.fontDirection);
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
this.processingType3 = null;
|
||||
if (fontDirection > 0) {
|
||||
ctx.scale(textHScale, -1);
|
||||
} else {
|
||||
ctx.save();
|
||||
this.applyTextTransforms();
|
||||
ctx.scale(textHScale, 1);
|
||||
}
|
||||
|
||||
var lineWidth = current.lineWidth;
|
||||
var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
|
||||
var scale = Math.sqrt(a1 * a1 + b1 * b1);
|
||||
if (scale === 0 || lineWidth === 0) {
|
||||
lineWidth = this.getSinglePixelWidth();
|
||||
var lineWidth = current.lineWidth;
|
||||
var scale = current.textMatrixScale;
|
||||
if (scale === 0 || lineWidth === 0) {
|
||||
lineWidth = this.getSinglePixelWidth();
|
||||
} else {
|
||||
lineWidth /= scale;
|
||||
}
|
||||
|
||||
if (fontSizeScale != 1.0) {
|
||||
ctx.scale(fontSizeScale, fontSizeScale);
|
||||
lineWidth /= fontSizeScale;
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineWidth;
|
||||
|
||||
var x = 0, i;
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
x += fontDirection * wordSpacing;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
x += -glyph * fontSize * 0.001;
|
||||
continue;
|
||||
}
|
||||
|
||||
var restoreNeeded = false;
|
||||
var character = glyph.fontChar;
|
||||
var accent = glyph.accent;
|
||||
var scaledX, scaledY, scaledAccentX, scaledAccentY;
|
||||
var width = glyph.width;
|
||||
if (vertical) {
|
||||
var vmetric, vx, vy;
|
||||
vmetric = glyph.vmetric || defaultVMetrics;
|
||||
vx = glyph.vmetric ? vmetric[1] : width * 0.5;
|
||||
vx = -vx * widthAdvanceScale;
|
||||
vy = vmetric[2] * widthAdvanceScale;
|
||||
|
||||
width = vmetric ? -vmetric[0] : width;
|
||||
scaledX = vx / fontSizeScale;
|
||||
scaledY = (x + vy) / fontSizeScale;
|
||||
} else {
|
||||
lineWidth /= scale;
|
||||
scaledX = x / fontSizeScale;
|
||||
scaledY = 0;
|
||||
}
|
||||
|
||||
if (fontSizeScale != 1.0) {
|
||||
ctx.scale(fontSizeScale, fontSizeScale);
|
||||
lineWidth /= fontSizeScale;
|
||||
if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
|
||||
// some standard fonts may not have the exact width, trying to
|
||||
// rescale per character
|
||||
var measuredWidth = ctx.measureText(character).width * 1000 /
|
||||
fontSize * fontSizeScale;
|
||||
var characterScaleX = width / measuredWidth;
|
||||
restoreNeeded = true;
|
||||
ctx.save();
|
||||
ctx.scale(characterScaleX, 1);
|
||||
scaledX /= characterScaleX;
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineWidth;
|
||||
|
||||
var x = 0;
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
x += current.fontDirection * wordSpacing;
|
||||
continue;
|
||||
}
|
||||
|
||||
var restoreNeeded = false;
|
||||
var character = glyph.fontChar;
|
||||
var vmetric = glyph.vmetric || defaultVMetrics;
|
||||
if (vertical) {
|
||||
var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
|
||||
vx = -vx * fontSize * current.fontMatrix[0];
|
||||
var vy = vmetric[2] * fontSize * current.fontMatrix[0];
|
||||
}
|
||||
width = vmetric ? -vmetric[0] : glyph.width;
|
||||
var charWidth = width * fontSize * current.fontMatrix[0] +
|
||||
charSpacing * current.fontDirection;
|
||||
var accent = glyph.accent;
|
||||
|
||||
var scaledX, scaledY, scaledAccentX, scaledAccentY;
|
||||
|
||||
if (vertical) {
|
||||
scaledX = vx / fontSizeScale;
|
||||
scaledY = (x + vy) / fontSizeScale;
|
||||
} else {
|
||||
scaledX = x / fontSizeScale;
|
||||
scaledY = 0;
|
||||
}
|
||||
|
||||
if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) {
|
||||
// some standard fonts may not have the exact width, trying to
|
||||
// rescale per character
|
||||
var measuredWidth = ctx.measureText(character).width * 1000 /
|
||||
current.fontSize * current.fontSizeScale;
|
||||
var characterScaleX = width / measuredWidth;
|
||||
restoreNeeded = true;
|
||||
ctx.save();
|
||||
ctx.scale(characterScaleX, 1);
|
||||
scaledX /= characterScaleX;
|
||||
if (accent) {
|
||||
scaledAccentX /= characterScaleX;
|
||||
}
|
||||
}
|
||||
|
||||
if (simpleFillText && !accent) {
|
||||
// common case
|
||||
ctx.fillText(character, scaledX, scaledY);
|
||||
} else {
|
||||
this.paintChar(character, scaledX, scaledY);
|
||||
if (accent) {
|
||||
scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
|
||||
scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
|
||||
this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
|
||||
}
|
||||
|
||||
x += charWidth;
|
||||
|
||||
if (restoreNeeded) {
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
if (vertical) {
|
||||
current.y -= x * textHScale;
|
||||
} else {
|
||||
current.x += x * textHScale;
|
||||
|
||||
var charWidth = width * widthAdvanceScale + charSpacing * fontDirection;
|
||||
x += charWidth;
|
||||
|
||||
if (restoreNeeded) {
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
if (vertical) {
|
||||
current.y -= x * textHScale;
|
||||
} else {
|
||||
current.x += x * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
},
|
||||
showSpacedText: function CanvasGraphics_showSpacedText(arr) {
|
||||
|
||||
showType3Text: function CanvasGraphics_showType3Text(glyphs) {
|
||||
// Type3 fonts - each glyph is a "mini-PDF"
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
// TJ array's number is independent from fontMatrix
|
||||
var textHScale = current.textHScale * 0.001 * current.fontDirection;
|
||||
var arrLength = arr.length;
|
||||
var vertical = font.vertical;
|
||||
var fontDirection = current.fontDirection;
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale * fontDirection;
|
||||
var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
|
||||
var glyphsLength = glyphs.length;
|
||||
var i, glyph, width;
|
||||
|
||||
for (var i = 0; i < arrLength; ++i) {
|
||||
var e = arr[i];
|
||||
if (isNum(e)) {
|
||||
var spacingLength = -e * fontSize * textHScale;
|
||||
if (vertical) {
|
||||
current.y += spacingLength;
|
||||
} else {
|
||||
current.x += spacingLength;
|
||||
}
|
||||
|
||||
} else {
|
||||
this.showText(e);
|
||||
}
|
||||
if (fontSize === 0) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
|
||||
this.nextLine();
|
||||
this.showText(text);
|
||||
},
|
||||
nextLineSetSpacingShowText:
|
||||
function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
|
||||
charSpacing,
|
||||
text) {
|
||||
this.setWordSpacing(wordSpacing);
|
||||
this.setCharSpacing(charSpacing);
|
||||
this.nextLineShowText(text);
|
||||
|
||||
ctx.save();
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.translate(current.x, current.y);
|
||||
|
||||
ctx.scale(textHScale, 1);
|
||||
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
current.x += wordSpacing * textHScale;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
var spacingLength = -glyph * 0.001 * fontSize;
|
||||
this.ctx.translate(spacingLength, 0);
|
||||
current.x += spacingLength * textHScale;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.processingType3 = glyph;
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
var operatorList = font.charProcOperatorList[glyph.operatorListId];
|
||||
this.executeOperatorList(operatorList);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
width = ((transformed[0] * fontSize + charSpacing) * fontDirection);
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
}
|
||||
ctx.restore();
|
||||
this.processingType3 = null;
|
||||
},
|
||||
|
||||
// Type3 fonts
|
||||
|
@ -246,27 +246,8 @@ var Stepper = (function StepperClosure() {
|
||||
return d;
|
||||
}
|
||||
|
||||
function glyphsToString(glyphs) {
|
||||
var out = '';
|
||||
for (var i = 0; i < glyphs.length; i++) {
|
||||
if (glyphs[i] === null) {
|
||||
out += ' ';
|
||||
} else {
|
||||
out += glyphs[i].fontChar;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
var opMap = null;
|
||||
|
||||
var glyphCommands = {
|
||||
'showText': 0,
|
||||
'showSpacedText': 0,
|
||||
'nextLineShowText': 0,
|
||||
'nextLineSetSpacingShowText': 2
|
||||
};
|
||||
|
||||
function simplifyArgs(args) {
|
||||
if (typeof args === 'string') {
|
||||
var MAX_STRING_LENGTH = 75;
|
||||
@ -367,24 +348,26 @@ var Stepper = (function StepperClosure() {
|
||||
line.appendChild(c('td', i.toString()));
|
||||
var fn = opMap[operatorList.fnArray[i]];
|
||||
var decArgs = args;
|
||||
if (fn in glyphCommands) {
|
||||
var glyphIndex = glyphCommands[fn];
|
||||
var glyphs = args[glyphIndex];
|
||||
decArgs = args.slice();
|
||||
var newArg;
|
||||
if (fn === 'showSpacedText') {
|
||||
newArg = [];
|
||||
for (var j = 0; j < glyphs.length; j++) {
|
||||
if (typeof glyphs[j] === 'number') {
|
||||
newArg.push(glyphs[j]);
|
||||
} else {
|
||||
newArg.push(glyphsToString(glyphs[j]));
|
||||
if (fn === 'showText') {
|
||||
var glyphs = args[0];
|
||||
var newArgs = [];
|
||||
var str = [];
|
||||
for (var j = 0; j < glyphs.length; j++) {
|
||||
var glyph = glyphs[j];
|
||||
if (typeof glyph === 'object' && glyph !== null) {
|
||||
str.push(glyph.fontChar);
|
||||
} else {
|
||||
if (str.length > 0) {
|
||||
newArgs.push(str.join(''));
|
||||
str = [];
|
||||
}
|
||||
newArgs.push(glyph); // null or number
|
||||
}
|
||||
} else {
|
||||
newArg = glyphsToString(glyphs);
|
||||
}
|
||||
decArgs[glyphIndex] = newArg;
|
||||
if (str.length > 0) {
|
||||
newArgs.push(str.join(''));
|
||||
}
|
||||
decArgs = [newArgs];
|
||||
}
|
||||
line.appendChild(c('td', fn));
|
||||
line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
|
||||
|
Loading…
x
Reference in New Issue
Block a user