|
|
@ -21,16 +21,14 @@ |
|
|
|
MurmurHash3_64, Name, Parser, Pattern, PDFImage, PDFJS, serifFonts, |
|
|
|
MurmurHash3_64, Name, Parser, Pattern, PDFImage, PDFJS, serifFonts, |
|
|
|
stdFontMap, symbolsFonts, getTilingPatternIR, warn, Util, Promise, |
|
|
|
stdFontMap, symbolsFonts, getTilingPatternIR, warn, Util, Promise, |
|
|
|
LegacyPromise, RefSetCache, isRef, TextRenderingMode, CMapFactory, |
|
|
|
LegacyPromise, RefSetCache, isRef, TextRenderingMode, CMapFactory, |
|
|
|
OPS, UNSUPPORTED_FEATURES, UnsupportedManager */ |
|
|
|
OPS, UNSUPPORTED_FEATURES, UnsupportedManager, NormalizedUnicodes, |
|
|
|
|
|
|
|
IDENTITY_MATRIX, reverseIfRtl */ |
|
|
|
|
|
|
|
|
|
|
|
'use strict'; |
|
|
|
'use strict'; |
|
|
|
|
|
|
|
|
|
|
|
var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
function PartialEvaluator(pdfManager, xref, handler, pageIndex, |
|
|
|
function PartialEvaluator(pdfManager, xref, handler, pageIndex, |
|
|
|
uniquePrefix, idCounters, fontCache) { |
|
|
|
uniquePrefix, idCounters, fontCache) { |
|
|
|
this.state = new EvalState(); |
|
|
|
|
|
|
|
this.stateStack = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.pdfManager = pdfManager; |
|
|
|
this.pdfManager = pdfManager; |
|
|
|
this.xref = xref; |
|
|
|
this.xref = xref; |
|
|
|
this.handler = handler; |
|
|
|
this.handler = handler; |
|
|
@ -96,7 +94,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
buildFormXObject: function PartialEvaluator_buildFormXObject(resources, |
|
|
|
buildFormXObject: function PartialEvaluator_buildFormXObject(resources, |
|
|
|
xobj, smask, |
|
|
|
xobj, smask, |
|
|
|
operatorList, |
|
|
|
operatorList, |
|
|
|
state) { |
|
|
|
initialState) { |
|
|
|
var matrix = xobj.dict.get('Matrix'); |
|
|
|
var matrix = xobj.dict.get('Matrix'); |
|
|
|
var bbox = xobj.dict.get('BBox'); |
|
|
|
var bbox = xobj.dict.get('BBox'); |
|
|
|
var group = xobj.dict.get('Group'); |
|
|
|
var group = xobj.dict.get('Group'); |
|
|
@ -123,7 +121,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]); |
|
|
|
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]); |
|
|
|
|
|
|
|
|
|
|
|
this.getOperatorList(xobj, (xobj.dict.get('Resources') || resources), |
|
|
|
this.getOperatorList(xobj, (xobj.dict.get('Resources') || resources), |
|
|
|
operatorList, state); |
|
|
|
operatorList, initialState); |
|
|
|
operatorList.addOp(OPS.paintFormXObjectEnd, []); |
|
|
|
operatorList.addOp(OPS.paintFormXObjectEnd, []); |
|
|
|
|
|
|
|
|
|
|
|
if (group) { |
|
|
|
if (group) { |
|
|
@ -221,15 +219,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
handleSMask: function PartialEvaluator_handleSmask(smask, resources, |
|
|
|
handleSMask: function PartialEvaluator_handleSmask(smask, resources, |
|
|
|
operatorList) { |
|
|
|
operatorList, |
|
|
|
|
|
|
|
stateManager) { |
|
|
|
var smaskContent = smask.get('G'); |
|
|
|
var smaskContent = smask.get('G'); |
|
|
|
var smaskOptions = { |
|
|
|
var smaskOptions = { |
|
|
|
subtype: smask.get('S').name, |
|
|
|
subtype: smask.get('S').name, |
|
|
|
backdrop: smask.get('BC') |
|
|
|
backdrop: smask.get('BC') |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
this.buildFormXObject(resources, smaskContent, smaskOptions, |
|
|
|
this.buildFormXObject(resources, smaskContent, smaskOptions, |
|
|
|
operatorList); |
|
|
|
operatorList, stateManager.state.clone()); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
handleTilingType: |
|
|
|
handleTilingType: |
|
|
@ -250,7 +248,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
|
|
|
|
|
|
|
|
handleSetFont: |
|
|
|
handleSetFont: |
|
|
|
function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, |
|
|
|
function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, |
|
|
|
operatorList) { |
|
|
|
operatorList, state) { |
|
|
|
// TODO(mack): Not needed?
|
|
|
|
// TODO(mack): Not needed?
|
|
|
|
var fontName; |
|
|
|
var fontName; |
|
|
|
if (fontArgs) { |
|
|
|
if (fontArgs) { |
|
|
@ -260,7 +258,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var font = this.loadFont(fontName, fontRef, this.xref, resources, |
|
|
|
var font = this.loadFont(fontName, fontRef, this.xref, resources, |
|
|
|
operatorList); |
|
|
|
operatorList); |
|
|
|
this.state.font = font; |
|
|
|
state.font = font; |
|
|
|
var loadedName = font.loadedName; |
|
|
|
var loadedName = font.loadedName; |
|
|
|
if (!font.sent) { |
|
|
|
if (!font.sent) { |
|
|
|
var fontData = font.translated.exportData(); |
|
|
|
var fontData = font.translated.exportData(); |
|
|
@ -276,10 +274,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
return loadedName; |
|
|
|
return loadedName; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
handleText: function PartialEvaluator_handleText(chars) { |
|
|
|
handleText: function PartialEvaluator_handleText(chars, state) { |
|
|
|
var font = this.state.font.translated; |
|
|
|
var font = state.font.translated; |
|
|
|
var glyphs = font.charsToGlyphs(chars); |
|
|
|
var glyphs = font.charsToGlyphs(chars); |
|
|
|
var isAddToPathSet = !!(this.state.textRenderingMode & |
|
|
|
var isAddToPathSet = !!(state.textRenderingMode & |
|
|
|
TextRenderingMode.ADD_TO_PATH_FLAG); |
|
|
|
TextRenderingMode.ADD_TO_PATH_FLAG); |
|
|
|
if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) { |
|
|
|
if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) { |
|
|
|
for (var i = 0; i < glyphs.length; i++) { |
|
|
|
for (var i = 0; i < glyphs.length; i++) { |
|
|
@ -302,7 +300,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
setGState: function PartialEvaluator_setGState(resources, gState, |
|
|
|
setGState: function PartialEvaluator_setGState(resources, gState, |
|
|
|
operatorList, xref) { |
|
|
|
operatorList, xref, |
|
|
|
|
|
|
|
stateManager) { |
|
|
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
// TODO(mack): This should be rewritten so that this function returns
|
|
|
|
// TODO(mack): This should be rewritten so that this function returns
|
|
|
@ -324,7 +323,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
break; |
|
|
|
break; |
|
|
|
case 'Font': |
|
|
|
case 'Font': |
|
|
|
var loadedName = self.handleSetFont(resources, null, value[0], |
|
|
|
var loadedName = self.handleSetFont(resources, null, value[0], |
|
|
|
operatorList); |
|
|
|
operatorList, |
|
|
|
|
|
|
|
stateManager.state); |
|
|
|
operatorList.addDependency(loadedName); |
|
|
|
operatorList.addDependency(loadedName); |
|
|
|
gStateObj.push([key, [loadedName, value[1]]]); |
|
|
|
gStateObj.push([key, [loadedName, value[1]]]); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -338,7 +338,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
var dict = xref.fetchIfRef(value); |
|
|
|
var dict = xref.fetchIfRef(value); |
|
|
|
if (isDict(dict)) { |
|
|
|
if (isDict(dict)) { |
|
|
|
self.handleSMask(dict, resources, operatorList); |
|
|
|
self.handleSMask(dict, resources, operatorList, stateManager); |
|
|
|
gStateObj.push([key, true]); |
|
|
|
gStateObj.push([key, true]); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
warn('Unsupported SMask type'); |
|
|
|
warn('Unsupported SMask type'); |
|
|
@ -495,7 +495,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
getOperatorList: function PartialEvaluator_getOperatorList(stream, |
|
|
|
getOperatorList: function PartialEvaluator_getOperatorList(stream, |
|
|
|
resources, |
|
|
|
resources, |
|
|
|
operatorList, |
|
|
|
operatorList, |
|
|
|
evaluatorState) { |
|
|
|
initialState) { |
|
|
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var xref = this.xref; |
|
|
|
var xref = this.xref; |
|
|
@ -507,10 +507,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
resources = (resources || Dict.empty); |
|
|
|
resources = (resources || Dict.empty); |
|
|
|
var xobjs = (resources.get('XObject') || Dict.empty); |
|
|
|
var xobjs = (resources.get('XObject') || Dict.empty); |
|
|
|
var patterns = (resources.get('Pattern') || Dict.empty); |
|
|
|
var patterns = (resources.get('Pattern') || Dict.empty); |
|
|
|
var preprocessor = new EvaluatorPreprocessor(stream, xref); |
|
|
|
var stateManager = new StateManager(initialState || new EvalState()); |
|
|
|
if (evaluatorState) { |
|
|
|
var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); |
|
|
|
preprocessor.setState(evaluatorState); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var promise = new LegacyPromise(); |
|
|
|
var promise = new LegacyPromise(); |
|
|
|
var operation; |
|
|
|
var operation; |
|
|
@ -570,9 +568,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
'XObject should have a Name subtype'); |
|
|
|
'XObject should have a Name subtype'); |
|
|
|
|
|
|
|
|
|
|
|
if ('Form' == type.name) { |
|
|
|
if ('Form' == type.name) { |
|
|
|
|
|
|
|
stateManager.save(); |
|
|
|
self.buildFormXObject(resources, xobj, null, operatorList, |
|
|
|
self.buildFormXObject(resources, xobj, null, operatorList, |
|
|
|
preprocessor.getState()); |
|
|
|
stateManager.state.clone()); |
|
|
|
args = []; |
|
|
|
args = []; |
|
|
|
|
|
|
|
stateManager.restore(); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} else if ('Image' == type.name) { |
|
|
|
} else if ('Image' == type.name) { |
|
|
|
self.buildPaintImageXObject(resources, xobj, false, |
|
|
|
self.buildPaintImageXObject(resources, xobj, false, |
|
|
@ -587,7 +587,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
case OPS.setFont: |
|
|
|
case OPS.setFont: |
|
|
|
// eagerly collect all fonts
|
|
|
|
// eagerly collect all fonts
|
|
|
|
var loadedName = self.handleSetFont(resources, args, null, |
|
|
|
var loadedName = self.handleSetFont(resources, args, null, |
|
|
|
operatorList); |
|
|
|
operatorList, |
|
|
|
|
|
|
|
stateManager.state); |
|
|
|
operatorList.addDependency(loadedName); |
|
|
|
operatorList.addDependency(loadedName); |
|
|
|
args[0] = loadedName; |
|
|
|
args[0] = loadedName; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -602,37 +603,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
operatorList, cacheKey, imageCache); |
|
|
|
operatorList, cacheKey, imageCache); |
|
|
|
args = []; |
|
|
|
args = []; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
case OPS.save: |
|
|
|
|
|
|
|
var old = this.state; |
|
|
|
|
|
|
|
this.stateStack.push(this.state); |
|
|
|
|
|
|
|
this.state = old.clone(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case OPS.restore: |
|
|
|
|
|
|
|
var prev = this.stateStack.pop(); |
|
|
|
|
|
|
|
if (prev) { |
|
|
|
|
|
|
|
this.state = prev; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case OPS.showText: |
|
|
|
case OPS.showText: |
|
|
|
args[0] = this.handleText(args[0]); |
|
|
|
args[0] = this.handleText(args[0], stateManager.state); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.showSpacedText: |
|
|
|
case OPS.showSpacedText: |
|
|
|
var arr = args[0]; |
|
|
|
var arr = args[0]; |
|
|
|
var arrLength = arr.length; |
|
|
|
var arrLength = arr.length; |
|
|
|
for (var i = 0; i < arrLength; ++i) { |
|
|
|
for (var i = 0; i < arrLength; ++i) { |
|
|
|
if (isString(arr[i])) { |
|
|
|
if (isString(arr[i])) { |
|
|
|
arr[i] = this.handleText(arr[i]); |
|
|
|
arr[i] = this.handleText(arr[i], stateManager.state); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.nextLineShowText: |
|
|
|
case OPS.nextLineShowText: |
|
|
|
args[0] = this.handleText(args[0]); |
|
|
|
args[0] = this.handleText(args[0], stateManager.state); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.nextLineSetSpacingShowText: |
|
|
|
case OPS.nextLineSetSpacingShowText: |
|
|
|
args[2] = this.handleText(args[2]); |
|
|
|
args[2] = this.handleText(args[2], stateManager.state); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setTextRenderingMode: |
|
|
|
case OPS.setTextRenderingMode: |
|
|
|
this.state.textRenderingMode = args[0]; |
|
|
|
stateManager.state.textRenderingMode = args[0]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
// Parse the ColorSpace data to a raw format.
|
|
|
|
// Parse the ColorSpace data to a raw format.
|
|
|
|
case OPS.setFillColorSpace: |
|
|
|
case OPS.setFillColorSpace: |
|
|
@ -665,7 +655,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var gState = extGState.get(dictName.name); |
|
|
|
var gState = extGState.get(dictName.name); |
|
|
|
self.setGState(resources, gState, operatorList, xref); |
|
|
|
self.setGState(resources, gState, operatorList, xref, |
|
|
|
|
|
|
|
stateManager); |
|
|
|
args = []; |
|
|
|
args = []; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
@ -682,40 +673,165 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
getTextContent: function PartialEvaluator_getTextContent(stream, resources, |
|
|
|
getTextContent: function PartialEvaluator_getTextContent(stream, resources, |
|
|
|
textState) { |
|
|
|
stateManager) { |
|
|
|
|
|
|
|
|
|
|
|
textState = (textState || new TextState()); |
|
|
|
stateManager = (stateManager || new StateManager(new TextState())); |
|
|
|
|
|
|
|
|
|
|
|
var bidiTexts = []; |
|
|
|
var textContent = { |
|
|
|
|
|
|
|
items: [], |
|
|
|
|
|
|
|
styles: Object.create(null) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
var bidiTexts = textContent.items; |
|
|
|
var SPACE_FACTOR = 0.35; |
|
|
|
var SPACE_FACTOR = 0.35; |
|
|
|
var MULTI_SPACE_FACTOR = 1.5; |
|
|
|
var MULTI_SPACE_FACTOR = 1.5; |
|
|
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var xref = this.xref; |
|
|
|
var xref = this.xref; |
|
|
|
|
|
|
|
|
|
|
|
function handleSetFont(fontName, fontRef) { |
|
|
|
|
|
|
|
return self.loadFont(fontName, fontRef, xref, resources, null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources = (xref.fetchIfRef(resources) || Dict.empty); |
|
|
|
resources = (xref.fetchIfRef(resources) || Dict.empty); |
|
|
|
|
|
|
|
|
|
|
|
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
|
|
|
|
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
|
|
|
|
var xobjs = null; |
|
|
|
var xobjs = null; |
|
|
|
var xobjsCache = {}; |
|
|
|
var xobjsCache = {}; |
|
|
|
|
|
|
|
|
|
|
|
var preprocessor = new EvaluatorPreprocessor(stream, xref); |
|
|
|
var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); |
|
|
|
var res = resources; |
|
|
|
var res = resources; |
|
|
|
|
|
|
|
|
|
|
|
var chunkBuf = []; |
|
|
|
|
|
|
|
var font = null; |
|
|
|
|
|
|
|
var charSpace = 0, wordSpace = 0; |
|
|
|
|
|
|
|
var operation; |
|
|
|
var operation; |
|
|
|
|
|
|
|
var textState; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function newTextChunk() { |
|
|
|
|
|
|
|
var font = textState.font; |
|
|
|
|
|
|
|
if (!(font.loadedName in textContent.styles)) { |
|
|
|
|
|
|
|
textContent.styles[font.loadedName] = { |
|
|
|
|
|
|
|
fontFamily: font.fallbackName, |
|
|
|
|
|
|
|
ascent: font.ascent, |
|
|
|
|
|
|
|
descent: font.descent, |
|
|
|
|
|
|
|
vertical: font.vertical |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
str: '', |
|
|
|
|
|
|
|
dir: null, |
|
|
|
|
|
|
|
width: 0, |
|
|
|
|
|
|
|
height: 0, |
|
|
|
|
|
|
|
transform: null, |
|
|
|
|
|
|
|
fontName: font.loadedName |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function runBidi(textChunk) { |
|
|
|
|
|
|
|
var bidiResult = PDFJS.bidi(textChunk.str, -1, textState.font.vertical); |
|
|
|
|
|
|
|
textChunk.str = bidiResult.str; |
|
|
|
|
|
|
|
textChunk.dir = bidiResult.dir; |
|
|
|
|
|
|
|
return textChunk; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function handleSetFont(fontName, fontRef) { |
|
|
|
|
|
|
|
var font = textState.font = self.loadFont(fontName, fontRef, xref, |
|
|
|
|
|
|
|
resources, null).translated; |
|
|
|
|
|
|
|
textState.fontMatrix = font.fontMatrix ? font.fontMatrix : |
|
|
|
|
|
|
|
FONT_IDENTITY_MATRIX; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function buildTextGeometry(chars, textChunk) { |
|
|
|
|
|
|
|
var font = textState.font; |
|
|
|
|
|
|
|
textChunk = textChunk || newTextChunk(); |
|
|
|
|
|
|
|
if (!textChunk.transform) { |
|
|
|
|
|
|
|
// 9.4.4 Text Space Details
|
|
|
|
|
|
|
|
var tsm = [textState.fontSize * textState.textHScale, 0, |
|
|
|
|
|
|
|
0, textState.fontSize, |
|
|
|
|
|
|
|
0, textState.textRise]; |
|
|
|
|
|
|
|
var trm = textChunk.transform = Util.transform(textState.ctm, |
|
|
|
|
|
|
|
Util.transform(textState.textMatrix, tsm)); |
|
|
|
|
|
|
|
if (!font.vertical) { |
|
|
|
|
|
|
|
textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var width = 0; |
|
|
|
|
|
|
|
var height = 0; |
|
|
|
|
|
|
|
var glyphs = font.charsToGlyphs(chars); |
|
|
|
|
|
|
|
var defaultVMetrics = font.defaultVMetrics; |
|
|
|
|
|
|
|
for (var i = 0; i < glyphs.length; i++) { |
|
|
|
|
|
|
|
var glyph = glyphs[i]; |
|
|
|
|
|
|
|
if (!glyph) { // Previous glyph was a space.
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var vMetricX = null; |
|
|
|
|
|
|
|
var vMetricY = null; |
|
|
|
|
|
|
|
var glyphWidth = null; |
|
|
|
|
|
|
|
if (font.vertical) { |
|
|
|
|
|
|
|
if (glyph.vmetric) { |
|
|
|
|
|
|
|
glyphWidth = glyph.vmetric[0]; |
|
|
|
|
|
|
|
vMetricX = glyph.vmetric[1]; |
|
|
|
|
|
|
|
vMetricY = glyph.vmetric[2]; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
glyphWidth = glyph.width; |
|
|
|
|
|
|
|
vMetricX = glyph.width * 0.5; |
|
|
|
|
|
|
|
vMetricY = defaultVMetrics[2]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
glyphWidth = glyph.width; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var glyphUnicode = glyph.unicode; |
|
|
|
|
|
|
|
if (glyphUnicode in NormalizedUnicodes) { |
|
|
|
|
|
|
|
glyphUnicode = NormalizedUnicodes[glyphUnicode]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glyphUnicode = reverseIfRtl(glyphUnicode); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The following will calculate the x and y of the individual glyphs.
|
|
|
|
|
|
|
|
// if (font.vertical) {
|
|
|
|
|
|
|
|
// tsm[4] -= vMetricX * Math.abs(textState.fontSize) *
|
|
|
|
|
|
|
|
// textState.fontMatrix[0];
|
|
|
|
|
|
|
|
// tsm[5] -= vMetricY * textState.fontSize *
|
|
|
|
|
|
|
|
// textState.fontMatrix[0];
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// var trm = Util.transform(textState.textMatrix, tsm);
|
|
|
|
|
|
|
|
// var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm);
|
|
|
|
|
|
|
|
// var x = pt[0];
|
|
|
|
|
|
|
|
// var y = pt[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var tx = 0; |
|
|
|
|
|
|
|
var ty = 0; |
|
|
|
|
|
|
|
if (!font.vertical) { |
|
|
|
|
|
|
|
var w0 = glyphWidth * textState.fontMatrix[0]; |
|
|
|
|
|
|
|
tx = (w0 * textState.fontSize + textState.charSpacing) * |
|
|
|
|
|
|
|
textState.textHScale; |
|
|
|
|
|
|
|
width += tx; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
var w1 = glyphWidth * textState.fontMatrix[0]; |
|
|
|
|
|
|
|
ty = w1 * textState.fontSize + textState.charSpacing; |
|
|
|
|
|
|
|
height += ty; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
textState.translateTextMatrix(tx, ty); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
textChunk.str += glyphUnicode; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var a = textState.textLineMatrix[0]; |
|
|
|
|
|
|
|
var b = textState.textLineMatrix[1]; |
|
|
|
|
|
|
|
var scaleLineX = Math.sqrt(a * a + b * b); |
|
|
|
|
|
|
|
a = textState.ctm[0]; |
|
|
|
|
|
|
|
b = textState.ctm[1]; |
|
|
|
|
|
|
|
var scaleCtmX = Math.sqrt(a * a + b * b); |
|
|
|
|
|
|
|
if (!font.vertical) { |
|
|
|
|
|
|
|
textChunk.width += width * scaleCtmX * scaleLineX; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
textChunk.height += Math.abs(height * scaleCtmX * scaleLineX); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return textChunk; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while ((operation = preprocessor.read())) { |
|
|
|
while ((operation = preprocessor.read())) { |
|
|
|
|
|
|
|
textState = stateManager.state; |
|
|
|
var fn = operation.fn; |
|
|
|
var fn = operation.fn; |
|
|
|
var args = operation.args; |
|
|
|
var args = operation.args; |
|
|
|
switch (fn) { |
|
|
|
switch (fn) { |
|
|
|
// TODO: Add support for SAVE/RESTORE and XFORM here.
|
|
|
|
|
|
|
|
case OPS.setFont: |
|
|
|
case OPS.setFont: |
|
|
|
font = handleSetFont(args[0].name).translated; |
|
|
|
handleSetFont(args[0].name); |
|
|
|
textState.fontSize = args[1]; |
|
|
|
textState.fontSize = args[1]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setTextRise: |
|
|
|
case OPS.setTextRise: |
|
|
@ -728,64 +844,79 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
textState.leading = args[0]; |
|
|
|
textState.leading = args[0]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.moveText: |
|
|
|
case OPS.moveText: |
|
|
|
textState.translateTextMatrix(args[0], args[1]); |
|
|
|
textState.translateTextLineMatrix(args[0], args[1]); |
|
|
|
|
|
|
|
textState.textMatrix = textState.textLineMatrix.slice(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setLeadingMoveText: |
|
|
|
case OPS.setLeadingMoveText: |
|
|
|
textState.leading = -args[1]; |
|
|
|
textState.leading = -args[1]; |
|
|
|
textState.translateTextMatrix(args[0], args[1]); |
|
|
|
textState.translateTextLineMatrix(args[0], args[1]); |
|
|
|
|
|
|
|
textState.textMatrix = textState.textLineMatrix.slice(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.nextLine: |
|
|
|
case OPS.nextLine: |
|
|
|
textState.translateTextMatrix(0, -textState.leading); |
|
|
|
textState.carriageReturn(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setTextMatrix: |
|
|
|
case OPS.setTextMatrix: |
|
|
|
textState.setTextMatrix(args[0], args[1], |
|
|
|
textState.setTextMatrix(args[0], args[1], args[2], args[3], |
|
|
|
args[2], args[3], args[4], args[5]); |
|
|
|
args[4], args[5]); |
|
|
|
|
|
|
|
textState.setTextLineMatrix(args[0], args[1], args[2], args[3], |
|
|
|
|
|
|
|
args[4], args[5]); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setCharSpacing: |
|
|
|
case OPS.setCharSpacing: |
|
|
|
charSpace = args[0]; |
|
|
|
textState.charSpace = args[0]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setWordSpacing: |
|
|
|
case OPS.setWordSpacing: |
|
|
|
wordSpace = args[0]; |
|
|
|
textState.wordSpace = args[0]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.beginText: |
|
|
|
case OPS.beginText: |
|
|
|
textState.initialiseTextObj(); |
|
|
|
textState.textMatrix = IDENTITY_MATRIX.slice(); |
|
|
|
|
|
|
|
textState.textLineMatrix = IDENTITY_MATRIX.slice(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.showSpacedText: |
|
|
|
case OPS.showSpacedText: |
|
|
|
var items = args[0]; |
|
|
|
var items = args[0]; |
|
|
|
|
|
|
|
var textChunk = newTextChunk(); |
|
|
|
for (var j = 0, jj = items.length; j < jj; j++) { |
|
|
|
for (var j = 0, jj = items.length; j < jj; j++) { |
|
|
|
if (typeof items[j] === 'string') { |
|
|
|
if (typeof items[j] === 'string') { |
|
|
|
chunkBuf.push(fontCharsToUnicode(items[j], font)); |
|
|
|
buildTextGeometry(items[j], textChunk); |
|
|
|
} else if (items[j] < 0 && font.spaceWidth > 0) { |
|
|
|
} else { |
|
|
|
var fakeSpaces = -items[j] / font.spaceWidth; |
|
|
|
var val = items[j] / 1000; |
|
|
|
if (fakeSpaces > MULTI_SPACE_FACTOR) { |
|
|
|
if (!textState.font.vertical) { |
|
|
|
fakeSpaces = Math.round(fakeSpaces); |
|
|
|
var offset = -val * textState.fontSize * textState.textHScale; |
|
|
|
while (fakeSpaces--) { |
|
|
|
textState.translateTextMatrix(offset, 0); |
|
|
|
chunkBuf.push(' '); |
|
|
|
textChunk.width += offset; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
var offset = -val * textState.fontSize; |
|
|
|
|
|
|
|
textState.translateTextMatrix(0, offset); |
|
|
|
|
|
|
|
textChunk.height += offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (items[j] < 0 && textState.font.spaceWidth > 0) { |
|
|
|
|
|
|
|
var fakeSpaces = -items[j] / textState.font.spaceWidth; |
|
|
|
|
|
|
|
if (fakeSpaces > MULTI_SPACE_FACTOR) { |
|
|
|
|
|
|
|
fakeSpaces = Math.round(fakeSpaces); |
|
|
|
|
|
|
|
while (fakeSpaces--) { |
|
|
|
|
|
|
|
textChunk.str += ' '; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (fakeSpaces > SPACE_FACTOR) { |
|
|
|
|
|
|
|
textChunk.str += ' '; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (fakeSpaces > SPACE_FACTOR) { |
|
|
|
|
|
|
|
chunkBuf.push(' '); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bidiTexts.push(runBidi(textChunk)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.showText: |
|
|
|
case OPS.showText: |
|
|
|
chunkBuf.push(fontCharsToUnicode(args[0], font)); |
|
|
|
bidiTexts.push(runBidi(buildTextGeometry(args[0]))); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.nextLineShowText: |
|
|
|
case OPS.nextLineShowText: |
|
|
|
// For search, adding a extra white space for line breaks would be
|
|
|
|
textState.carriageReturn(); |
|
|
|
// better here, but that causes too much spaces in the
|
|
|
|
bidiTexts.push(runBidi(buildTextGeometry(args[0]))); |
|
|
|
// text-selection divs.
|
|
|
|
|
|
|
|
chunkBuf.push(fontCharsToUnicode(args[0], font)); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.nextLineSetSpacingShowText: |
|
|
|
case OPS.nextLineSetSpacingShowText: |
|
|
|
// Note comment in "'"
|
|
|
|
textState.wordSpacing = args[0]; |
|
|
|
chunkBuf.push(fontCharsToUnicode(args[2], font)); |
|
|
|
textState.charSpacing = args[1]; |
|
|
|
|
|
|
|
textState.carriageReturn(); |
|
|
|
|
|
|
|
bidiTexts.push(runBidi(buildTextGeometry(args[2]))); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.paintXObject: |
|
|
|
case OPS.paintXObject: |
|
|
|
// Set the chunk such that the following if won't add something
|
|
|
|
|
|
|
|
// to the state.
|
|
|
|
|
|
|
|
chunkBuf.length = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (args[0].code) { |
|
|
|
if (args[0].code) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -797,7 +928,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
var name = args[0].name; |
|
|
|
var name = args[0].name; |
|
|
|
if (xobjsCache.key === name) { |
|
|
|
if (xobjsCache.key === name) { |
|
|
|
if (xobjsCache.texts) { |
|
|
|
if (xobjsCache.texts) { |
|
|
|
Util.concatenateToArray(bidiTexts, xobjsCache.texts); |
|
|
|
Util.concatenateToArray(bidiTexts, xobjsCache.texts.items); |
|
|
|
|
|
|
|
Util.extendObj(textContent.styles, xobjsCache.texts.styles); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -818,11 +950,23 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var formTexts = this.getTextContent(xobj, |
|
|
|
stateManager.save(); |
|
|
|
(xobj.dict.get('Resources') || resources), textState); |
|
|
|
var matrix = xobj.dict.get('Matrix'); |
|
|
|
|
|
|
|
if (isArray(matrix) && matrix.length === 6) { |
|
|
|
|
|
|
|
stateManager.transform(matrix); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var formTextContent = this.getTextContent( |
|
|
|
|
|
|
|
xobj, |
|
|
|
|
|
|
|
xobj.dict.get('Resources') || resources, |
|
|
|
|
|
|
|
stateManager |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
Util.concatenateToArray(bidiTexts, formTextContent.items); |
|
|
|
|
|
|
|
Util.extendObj(textContent.styles, formTextContent.styles); |
|
|
|
|
|
|
|
stateManager.restore(); |
|
|
|
|
|
|
|
|
|
|
|
xobjsCache.key = name; |
|
|
|
xobjsCache.key = name; |
|
|
|
xobjsCache.texts = formTexts; |
|
|
|
xobjsCache.texts = formTextContent; |
|
|
|
Util.concatenateToArray(bidiTexts, formTexts); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.setGState: |
|
|
|
case OPS.setGState: |
|
|
|
var dictName = args[0]; |
|
|
|
var dictName = args[0]; |
|
|
@ -836,36 +980,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { |
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < gsState.length; i++) { |
|
|
|
for (var i = 0; i < gsState.length; i++) { |
|
|
|
if (gsState[i] === 'Font') { |
|
|
|
if (gsState[i] === 'Font') { |
|
|
|
font = handleSetFont(args[0].name).translated; |
|
|
|
handleSetFont(args[0].name); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} // switch
|
|
|
|
|
|
|
|
} // while
|
|
|
|
if (chunkBuf.length > 0) { |
|
|
|
|
|
|
|
var chunk = chunkBuf.join(''); |
|
|
|
|
|
|
|
var bidiText = PDFJS.bidi(chunk, -1, font.vertical); |
|
|
|
|
|
|
|
var renderParams = textState.calcRenderParams(preprocessor.ctm); |
|
|
|
|
|
|
|
var fontHeight = textState.fontSize * renderParams.vScale; |
|
|
|
|
|
|
|
var fontAscent = (font.ascent ? (font.ascent * fontHeight) : |
|
|
|
|
|
|
|
(font.descent ? ((1 + font.descent) * fontHeight) : fontHeight)); |
|
|
|
|
|
|
|
bidiText.x = renderParams.renderMatrix[4] - (fontAscent * |
|
|
|
|
|
|
|
Math.sin(renderParams.angle)); |
|
|
|
|
|
|
|
bidiText.y = renderParams.renderMatrix[5] + (fontAscent * |
|
|
|
|
|
|
|
Math.cos(renderParams.angle)); |
|
|
|
|
|
|
|
if (bidiText.dir == 'ttb') { |
|
|
|
|
|
|
|
bidiText.x += renderParams.vScale / 2; |
|
|
|
|
|
|
|
bidiText.y -= renderParams.vScale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
bidiText.angle = renderParams.angle; |
|
|
|
|
|
|
|
bidiText.size = fontHeight; |
|
|
|
|
|
|
|
bidiTexts.push(bidiText); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chunkBuf.length = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return bidiTexts; |
|
|
|
return textContent; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
extractDataStructures: function |
|
|
|
extractDataStructures: function |
|
|
@ -1467,64 +1589,89 @@ var OperatorList = (function OperatorListClosure() { |
|
|
|
return OperatorList; |
|
|
|
return OperatorList; |
|
|
|
})(); |
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var StateManager = (function StateManagerClosure() { |
|
|
|
|
|
|
|
function StateManager(initialState) { |
|
|
|
|
|
|
|
this.state = initialState; |
|
|
|
|
|
|
|
this.stateStack = []; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
StateManager.prototype = { |
|
|
|
|
|
|
|
save: function () { |
|
|
|
|
|
|
|
var old = this.state; |
|
|
|
|
|
|
|
this.stateStack.push(this.state); |
|
|
|
|
|
|
|
this.state = old.clone(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
restore: function () { |
|
|
|
|
|
|
|
var prev = this.stateStack.pop(); |
|
|
|
|
|
|
|
if (prev) { |
|
|
|
|
|
|
|
this.state = prev; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
transform: function (args) { |
|
|
|
|
|
|
|
this.state.ctm = Util.transform(this.state.ctm, args); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
return StateManager; |
|
|
|
|
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
var TextState = (function TextStateClosure() { |
|
|
|
var TextState = (function TextStateClosure() { |
|
|
|
function TextState() { |
|
|
|
function TextState() { |
|
|
|
|
|
|
|
this.ctm = new Float32Array(IDENTITY_MATRIX); |
|
|
|
this.fontSize = 0; |
|
|
|
this.fontSize = 0; |
|
|
|
this.textMatrix = [1, 0, 0, 1, 0, 0]; |
|
|
|
this.font = null; |
|
|
|
this.stateStack = []; |
|
|
|
this.fontMatrix = FONT_IDENTITY_MATRIX; |
|
|
|
//textState variables
|
|
|
|
this.textMatrix = IDENTITY_MATRIX.slice(); |
|
|
|
|
|
|
|
this.textLineMatrix = IDENTITY_MATRIX.slice(); |
|
|
|
|
|
|
|
this.charSpacing = 0; |
|
|
|
|
|
|
|
this.wordSpacing = 0; |
|
|
|
this.leading = 0; |
|
|
|
this.leading = 0; |
|
|
|
this.textHScale = 1; |
|
|
|
this.textHScale = 1; |
|
|
|
this.textRise = 0; |
|
|
|
this.textRise = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TextState.prototype = { |
|
|
|
TextState.prototype = { |
|
|
|
initialiseTextObj: function TextState_initialiseTextObj() { |
|
|
|
|
|
|
|
var m = this.textMatrix; |
|
|
|
|
|
|
|
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { |
|
|
|
setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { |
|
|
|
var m = this.textMatrix; |
|
|
|
var m = this.textMatrix; |
|
|
|
m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; |
|
|
|
m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { |
|
|
|
|
|
|
|
var m = this.textLineMatrix; |
|
|
|
|
|
|
|
m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; |
|
|
|
|
|
|
|
}, |
|
|
|
translateTextMatrix: function TextState_translateTextMatrix(x, y) { |
|
|
|
translateTextMatrix: function TextState_translateTextMatrix(x, y) { |
|
|
|
var m = this.textMatrix; |
|
|
|
var m = this.textMatrix; |
|
|
|
m[4] = m[0] * x + m[2] * y + m[4]; |
|
|
|
m[4] = m[0] * x + m[2] * y + m[4]; |
|
|
|
m[5] = m[1] * x + m[3] * y + m[5]; |
|
|
|
m[5] = m[1] * x + m[3] * y + m[5]; |
|
|
|
}, |
|
|
|
}, |
|
|
|
calcRenderParams: function TextState_calcRenderingParams(cm) { |
|
|
|
translateTextLineMatrix: function TextState_translateTextMatrix(x, y) { |
|
|
|
var tm = this.textMatrix; |
|
|
|
var m = this.textLineMatrix; |
|
|
|
var a = this.fontSize; |
|
|
|
m[4] = m[0] * x + m[2] * y + m[4]; |
|
|
|
var b = a * this.textHScale; |
|
|
|
m[5] = m[1] * x + m[3] * y + m[5]; |
|
|
|
var c = this.textRise; |
|
|
|
|
|
|
|
var vScale = Math.sqrt((tm[2] * tm[2]) + (tm[3] * tm[3])); |
|
|
|
|
|
|
|
var angle = Math.atan2(tm[1], tm[0]); |
|
|
|
|
|
|
|
var m0 = tm[0] * cm[0] + tm[1] * cm[2]; |
|
|
|
|
|
|
|
var m1 = tm[0] * cm[1] + tm[1] * cm[3]; |
|
|
|
|
|
|
|
var m2 = tm[2] * cm[0] + tm[3] * cm[2]; |
|
|
|
|
|
|
|
var m3 = tm[2] * cm[1] + tm[3] * cm[3]; |
|
|
|
|
|
|
|
var m4 = tm[4] * cm[0] + tm[5] * cm[2] + cm[4]; |
|
|
|
|
|
|
|
var m5 = tm[4] * cm[1] + tm[5] * cm[3] + cm[5]; |
|
|
|
|
|
|
|
var renderMatrix = [ |
|
|
|
|
|
|
|
b * m0, |
|
|
|
|
|
|
|
b * m1, |
|
|
|
|
|
|
|
a * m2, |
|
|
|
|
|
|
|
a * m3, |
|
|
|
|
|
|
|
c * m2 + m4, |
|
|
|
|
|
|
|
c * m3 + m5 |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
renderMatrix: renderMatrix, |
|
|
|
|
|
|
|
vScale: vScale, |
|
|
|
|
|
|
|
angle: angle |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { |
|
|
|
|
|
|
|
// 9.4.4 Text Space Details
|
|
|
|
|
|
|
|
var tsm = [this.fontSize * this.textHScale, 0, |
|
|
|
|
|
|
|
0, this.fontSize, |
|
|
|
|
|
|
|
0, this.textRise]; |
|
|
|
|
|
|
|
return Util.transform(ctm, Util.transform(this.textMatrix, tsm)); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
carriageReturn: function TextState_carriageReturn() { |
|
|
|
|
|
|
|
this.translateTextLineMatrix(0, -this.leading); |
|
|
|
|
|
|
|
this.textMatrix = this.textLineMatrix.slice(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
clone: function TextState_clone() { |
|
|
|
|
|
|
|
var clone = Object.create(this); |
|
|
|
|
|
|
|
clone.textMatrix = this.textMatrix.slice(); |
|
|
|
|
|
|
|
clone.textLineMatrix = this.textLineMatrix.slice(); |
|
|
|
|
|
|
|
clone.fontMatrix = this.fontMatrix.slice(); |
|
|
|
|
|
|
|
return clone; |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
return TextState; |
|
|
|
return TextState; |
|
|
|
})(); |
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
var EvalState = (function EvalStateClosure() { |
|
|
|
var EvalState = (function EvalStateClosure() { |
|
|
|
function EvalState() { |
|
|
|
function EvalState() { |
|
|
|
|
|
|
|
this.ctm = new Float32Array(IDENTITY_MATRIX); |
|
|
|
this.font = null; |
|
|
|
this.font = null; |
|
|
|
this.textRenderingMode = TextRenderingMode.FILL; |
|
|
|
this.textRenderingMode = TextRenderingMode.FILL; |
|
|
|
} |
|
|
|
} |
|
|
@ -1650,17 +1797,16 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() { |
|
|
|
'null': null |
|
|
|
'null': null |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function EvaluatorPreprocessor(stream, xref) { |
|
|
|
function EvaluatorPreprocessor(stream, xref, stateManager) { |
|
|
|
// TODO(mduan): pass array of knownCommands rather than OP_MAP
|
|
|
|
// TODO(mduan): pass array of knownCommands rather than OP_MAP
|
|
|
|
// dictionary
|
|
|
|
// dictionary
|
|
|
|
this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref); |
|
|
|
this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref); |
|
|
|
this.ctm = new Float32Array([1, 0, 0, 1, 0, 0]); |
|
|
|
this.stateManager = stateManager; |
|
|
|
this.savedStates = []; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
EvaluatorPreprocessor.prototype = { |
|
|
|
EvaluatorPreprocessor.prototype = { |
|
|
|
get savedStatesDepth() { |
|
|
|
get savedStatesDepth() { |
|
|
|
return this.savedStates.length; |
|
|
|
return this.stateManager.stateStack.length; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
read: function EvaluatorPreprocessor_read() { |
|
|
|
read: function EvaluatorPreprocessor_read() { |
|
|
@ -1717,38 +1863,17 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() { |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
getState: function EvaluatorPreprocessor_getState() { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
ctm: this.ctm |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setState: function EvaluatorPreprocessor_setState(state) { |
|
|
|
|
|
|
|
this.ctm = state.ctm; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
preprocessCommand: |
|
|
|
preprocessCommand: |
|
|
|
function EvaluatorPreprocessor_preprocessCommand(fn, args) { |
|
|
|
function EvaluatorPreprocessor_preprocessCommand(fn, args) { |
|
|
|
switch (fn | 0) { |
|
|
|
switch (fn | 0) { |
|
|
|
case OPS.save: |
|
|
|
case OPS.save: |
|
|
|
this.savedStates.push(this.getState()); |
|
|
|
this.stateManager.save(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.restore: |
|
|
|
case OPS.restore: |
|
|
|
var previousState = this.savedStates.pop(); |
|
|
|
this.stateManager.restore(); |
|
|
|
if (previousState) { |
|
|
|
|
|
|
|
this.setState(previousState); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
case OPS.transform: |
|
|
|
case OPS.transform: |
|
|
|
var ctm = this.ctm; |
|
|
|
this.stateManager.transform(args); |
|
|
|
var m = new Float32Array(6); |
|
|
|
|
|
|
|
m[0] = ctm[0] * args[0] + ctm[2] * args[1]; |
|
|
|
|
|
|
|
m[1] = ctm[1] * args[0] + ctm[3] * args[1]; |
|
|
|
|
|
|
|
m[2] = ctm[0] * args[2] + ctm[2] * args[3]; |
|
|
|
|
|
|
|
m[3] = ctm[1] * args[2] + ctm[3] * args[3]; |
|
|
|
|
|
|
|
m[4] = ctm[0] * args[4] + ctm[2] * args[5] + ctm[4]; |
|
|
|
|
|
|
|
m[5] = ctm[1] * args[4] + ctm[3] * args[5] + ctm[5]; |
|
|
|
|
|
|
|
this.ctm = m; |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|