Skip to content

Commit fee89cc

Browse files
committed
Merge pull request mozilla#2493 from brendandahl/wip-encode
Add support for hmoveto and vmoveto during flex.
2 parents 1d0c005 + acf64b3 commit fee89cc

File tree

4 files changed

+83
-18
lines changed

4 files changed

+83
-18
lines changed

src/fonts.js

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,11 +4507,21 @@ var Type1Parser = function type1Parser() {
45074507
return args;
45084508
}
45094509

4510+
// Remove the same number of args from the stack that are in the args
4511+
// parameter. Args should be built from breakUpArgs().
4512+
function popArgs(stack, args) {
4513+
for (var i = 0, ii = args.length; i < ii; i++) {
4514+
for (var j = 0, jj = args[i].arg.length; j < jj; j++) {
4515+
stack.pop();
4516+
}
4517+
}
4518+
}
4519+
45104520
function decodeCharString(array) {
45114521
var charstring = [];
45124522
var lsb = 0;
45134523
var width = 0;
4514-
var flexState = 0;
4524+
var flexing = false;
45154525

45164526
var value = '';
45174527
var count = array.length;
@@ -4595,27 +4605,60 @@ var Type1Parser = function type1Parser() {
45954605
continue;
45964606
} else if (value == 10) { // callsubr
45974607
if (charstring[charstring.length - 1] < 3) { // subr #0..2
4608+
// XXX: According to the spec if flex or hinting is not used then
4609+
// subroutines 0-3 can actually be anything defined by the font,
4610+
// so we really shouldn't be doing flex here but when
4611+
// callothersubr 0-2 is used. There hasn't been a real world
4612+
// example of this yet so we'll keep doing it here.
45984613
var subrNumber = charstring.pop();
45994614
switch (subrNumber) {
46004615
case 1:
4601-
flexState = 1; // prepare for flex coordinates
4602-
break;
4603-
case 2:
4604-
flexState = 2; // flex in progress
4616+
flexing = true; // prepare for flex coordinates
46054617
break;
46064618
case 0:
4607-
// type2 flex command does not need final coords
4608-
charstring.push('exch', 'drop', 'exch', 'drop');
4609-
charstring.push('flex');
4610-
flexState = 0;
4619+
var flexArgs = breakUpArgs(charstring, 17);
4620+
popArgs(charstring, flexArgs);
4621+
4622+
charstring.push(
4623+
flexArgs[2].value + flexArgs[0].value, // bcp1x + rpx
4624+
flexArgs[3].value + flexArgs[1].value, // bcp1y + rpy
4625+
flexArgs[4].value, // bcp2x
4626+
flexArgs[5].value, // bcp2y
4627+
flexArgs[6].value, // p2x
4628+
flexArgs[7].value, // p2y
4629+
flexArgs[8].value, // bcp3x
4630+
flexArgs[9].value, // bcp3y
4631+
flexArgs[10].value, // bcp4x
4632+
flexArgs[11].value, // bcp4y
4633+
flexArgs[12].value, // p3x
4634+
flexArgs[13].value, // p3y
4635+
flexArgs[14].value, // flexDepth
4636+
// 15 = finalx unused by flex
4637+
// 16 = finaly unused by flex
4638+
'flex'
4639+
);
4640+
4641+
flexing = false;
46114642
break;
46124643
}
46134644
continue;
46144645
}
4615-
} else if (value == 21 && flexState > 0) {
4616-
if (flexState > 1)
4617-
continue; // ignoring rmoveto
4618-
value = 5; // first segment replacing with rlineto
4646+
} else if (value == 21 && flexing) { // rmoveto
4647+
continue; // ignoring rmoveto
4648+
} else if (value == 22 && flexing) { // hmoveto
4649+
// Add the dy for flex.
4650+
charstring.push(0);
4651+
continue; // ignoring hmoveto
4652+
} else if (value == 4 && flexing) { // vmoveto
4653+
// Add the dx for flex and but also swap the values so they are the
4654+
// right order.
4655+
var vArgs = breakUpArgs(charstring, 1);
4656+
popArgs(charstring, vArgs);
4657+
charstring.push(0);
4658+
for (var t = 0, tt = vArgs[0].arg.length; t < tt; t++) {
4659+
charstring.push(vArgs[0].arg[t]);
4660+
}
4661+
continue; // ignoring vmoveto
46194662
} else if (!HINTING_ENABLED && (value == 1 || value == 3)) {
46204663
charstring.push('drop', 'drop');
46214664
continue;
@@ -5191,6 +5234,17 @@ Type1Font.prototype = {
51915234
},
51925235

51935236
wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
5237+
var comp = new CFFCompiler();
5238+
// TODO: remove this function after refactoring wrap to use the CFFCompiler.
5239+
function encodeNumber(num) {
5240+
var val = comp.encodeNumber(num);
5241+
var ret = '';
5242+
for (var i = 0; i < val.length; i++) {
5243+
ret += String.fromCharCode(val[i]);
5244+
}
5245+
return ret;
5246+
}
5247+
51945248
var fields = {
51955249
// major version, minor version, header size, offset size
51965250
'header': '\x01\x00\x04\x04',
@@ -5210,7 +5264,7 @@ Type1Font.prototype = {
52105264

52115265
var boundingBox = properties.bbox;
52125266
for (var i = 0, ii = boundingBox.length; i < ii; i++)
5213-
dict += self.encodeNumber(boundingBox[i]);
5267+
dict += encodeNumber(boundingBox[i]);
52145268
dict += '\x05'; // FontBBox;
52155269

52165270
var offset = fields.header.length +
@@ -5298,11 +5352,10 @@ Type1Font.prototype = {
52985352
var value = properties.privateData[field];
52995353

53005354
if (isArray(value)) {
5301-
data += self.encodeNumber(value[0]);
5302-
for (var i = 1, ii = value.length; i < ii; i++)
5303-
data += self.encodeNumber(value[i] - value[i - 1]);
5355+
for (var i = 0, ii = value.length; i < ii; i++)
5356+
data += encodeNumber(value[i]);
53045357
} else {
5305-
data += self.encodeNumber(value);
5358+
data += encodeNumber(value);
53065359
}
53075360
data += fieldMap[field];
53085361
}

test/pdfs/issue1453.pdf

17.2 KB
Binary file not shown.

test/pdfs/issue2462.pdf

137 KB
Binary file not shown.

test/test_manifest.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,18 @@
741741
"rounds": 1,
742742
"type": "eq"
743743
},
744+
{ "id": "issue1453",
745+
"file": "pdfs/issue1453.pdf",
746+
"md5": "cee0ee8ea3a0643cbd716d57fd44f628",
747+
"rounds": 1,
748+
"type": "eq"
749+
},
750+
{ "id": "issue2462",
751+
"file": "pdfs/issue2462.pdf",
752+
"md5": "d4e3dddfdd35464c71cf0310bff29b42",
753+
"rounds": 1,
754+
"type": "eq"
755+
},
744756
{ "id": "issue1998",
745757
"file": "pdfs/issue1998.pdf",
746758
"md5": "586e0213be2f461360ec26770b5a4e48",

0 commit comments

Comments
 (0)