Merge pull request #2493 from brendandahl/wip-encode

Add support for hmoveto and vmoveto during flex.
This commit is contained in:
Yury Delendik 2012-12-21 08:35:45 -08:00
commit fee89cc77c
4 changed files with 83 additions and 18 deletions

View File

@ -4507,11 +4507,21 @@ var Type1Parser = function type1Parser() {
return args; return args;
} }
// Remove the same number of args from the stack that are in the args
// parameter. Args should be built from breakUpArgs().
function popArgs(stack, args) {
for (var i = 0, ii = args.length; i < ii; i++) {
for (var j = 0, jj = args[i].arg.length; j < jj; j++) {
stack.pop();
}
}
}
function decodeCharString(array) { function decodeCharString(array) {
var charstring = []; var charstring = [];
var lsb = 0; var lsb = 0;
var width = 0; var width = 0;
var flexState = 0; var flexing = false;
var value = ''; var value = '';
var count = array.length; var count = array.length;
@ -4595,27 +4605,60 @@ var Type1Parser = function type1Parser() {
continue; continue;
} else if (value == 10) { // callsubr } else if (value == 10) { // callsubr
if (charstring[charstring.length - 1] < 3) { // subr #0..2 if (charstring[charstring.length - 1] < 3) { // subr #0..2
// XXX: According to the spec if flex or hinting is not used then
// subroutines 0-3 can actually be anything defined by the font,
// so we really shouldn't be doing flex here but when
// callothersubr 0-2 is used. There hasn't been a real world
// example of this yet so we'll keep doing it here.
var subrNumber = charstring.pop(); var subrNumber = charstring.pop();
switch (subrNumber) { switch (subrNumber) {
case 1: case 1:
flexState = 1; // prepare for flex coordinates flexing = true; // prepare for flex coordinates
break;
case 2:
flexState = 2; // flex in progress
break; break;
case 0: case 0:
// type2 flex command does not need final coords var flexArgs = breakUpArgs(charstring, 17);
charstring.push('exch', 'drop', 'exch', 'drop'); popArgs(charstring, flexArgs);
charstring.push('flex');
flexState = 0; charstring.push(
flexArgs[2].value + flexArgs[0].value, // bcp1x + rpx
flexArgs[3].value + flexArgs[1].value, // bcp1y + rpy
flexArgs[4].value, // bcp2x
flexArgs[5].value, // bcp2y
flexArgs[6].value, // p2x
flexArgs[7].value, // p2y
flexArgs[8].value, // bcp3x
flexArgs[9].value, // bcp3y
flexArgs[10].value, // bcp4x
flexArgs[11].value, // bcp4y
flexArgs[12].value, // p3x
flexArgs[13].value, // p3y
flexArgs[14].value, // flexDepth
// 15 = finalx unused by flex
// 16 = finaly unused by flex
'flex'
);
flexing = false;
break; break;
} }
continue; continue;
} }
} else if (value == 21 && flexState > 0) { } else if (value == 21 && flexing) { // rmoveto
if (flexState > 1)
continue; // ignoring rmoveto continue; // ignoring rmoveto
value = 5; // first segment replacing with rlineto } else if (value == 22 && flexing) { // hmoveto
// Add the dy for flex.
charstring.push(0);
continue; // ignoring hmoveto
} else if (value == 4 && flexing) { // vmoveto
// Add the dx for flex and but also swap the values so they are the
// right order.
var vArgs = breakUpArgs(charstring, 1);
popArgs(charstring, vArgs);
charstring.push(0);
for (var t = 0, tt = vArgs[0].arg.length; t < tt; t++) {
charstring.push(vArgs[0].arg[t]);
}
continue; // ignoring vmoveto
} else if (!HINTING_ENABLED && (value == 1 || value == 3)) { } else if (!HINTING_ENABLED && (value == 1 || value == 3)) {
charstring.push('drop', 'drop'); charstring.push('drop', 'drop');
continue; continue;
@ -5191,6 +5234,17 @@ Type1Font.prototype = {
}, },
wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
var comp = new CFFCompiler();
// TODO: remove this function after refactoring wrap to use the CFFCompiler.
function encodeNumber(num) {
var val = comp.encodeNumber(num);
var ret = '';
for (var i = 0; i < val.length; i++) {
ret += String.fromCharCode(val[i]);
}
return ret;
}
var fields = { var fields = {
// major version, minor version, header size, offset size // major version, minor version, header size, offset size
'header': '\x01\x00\x04\x04', 'header': '\x01\x00\x04\x04',
@ -5210,7 +5264,7 @@ Type1Font.prototype = {
var boundingBox = properties.bbox; var boundingBox = properties.bbox;
for (var i = 0, ii = boundingBox.length; i < ii; i++) for (var i = 0, ii = boundingBox.length; i < ii; i++)
dict += self.encodeNumber(boundingBox[i]); dict += encodeNumber(boundingBox[i]);
dict += '\x05'; // FontBBox; dict += '\x05'; // FontBBox;
var offset = fields.header.length + var offset = fields.header.length +
@ -5298,11 +5352,10 @@ Type1Font.prototype = {
var value = properties.privateData[field]; var value = properties.privateData[field];
if (isArray(value)) { if (isArray(value)) {
data += self.encodeNumber(value[0]); for (var i = 0, ii = value.length; i < ii; i++)
for (var i = 1, ii = value.length; i < ii; i++) data += encodeNumber(value[i]);
data += self.encodeNumber(value[i] - value[i - 1]);
} else { } else {
data += self.encodeNumber(value); data += encodeNumber(value);
} }
data += fieldMap[field]; data += fieldMap[field];
} }

BIN
test/pdfs/issue1453.pdf Normal file

Binary file not shown.

BIN
test/pdfs/issue2462.pdf Normal file

Binary file not shown.

View File

@ -741,6 +741,18 @@
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue1453",
"file": "pdfs/issue1453.pdf",
"md5": "cee0ee8ea3a0643cbd716d57fd44f628",
"rounds": 1,
"type": "eq"
},
{ "id": "issue2462",
"file": "pdfs/issue2462.pdf",
"md5": "d4e3dddfdd35464c71cf0310bff29b42",
"rounds": 1,
"type": "eq"
},
{ "id": "issue1998", { "id": "issue1998",
"file": "pdfs/issue1998.pdf", "file": "pdfs/issue1998.pdf",
"md5": "586e0213be2f461360ec26770b5a4e48", "md5": "586e0213be2f461360ec26770b5a4e48",