Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font compression does not work for Emoji fonts #177

Open
DuaneOBrien opened this Issue Mar 14, 2019 · 3 comments

Comments

Projects
None yet
2 participants
@DuaneOBrien
Copy link

DuaneOBrien commented Mar 14, 2019

After updating from 2.9.1 to 2.9.2, the PDF output by decktape has significantly increased in size.

Compare PDF from #176 : https://github.com/DuaneOBrien/decktape-emoji-bug/blob/master/decktape-emoji-bug-output.pdf : (132k in size)

To PDF generated from the same content post-update: https://github.com/DuaneOBrien/decktape-emoji-bug/blob/master/decktape-emoji-bug-output-post-update.pdf (14.8mb in size)

I have not yet tried trying --screenshots settings to see if this affects the output.

Chrome Version: 72.0.3626.121

@astefanutti

This comment has been minimized.

Copy link
Owner

astefanutti commented Mar 14, 2019

I've tried with other presentations and the increase do not happen. So I highly suspect it's caused by the font compression algorithm failing to support Emoji that use zero width joiner sequences.

@astefanutti astefanutti added the bug label Mar 14, 2019

@astefanutti astefanutti changed the title Update to 2.9.2 significantly increased PDF file sizes (~100x) Font compression does not work for Emoji fonts Mar 14, 2019

@DuaneOBrien

This comment has been minimized.

Copy link
Author

DuaneOBrien commented Mar 17, 2019

Bummer!

Is this another bug that's further upstream? Anything I can do to help refine test cases, investigate, etc?

@astefanutti

This comment has been minimized.

Copy link
Owner

astefanutti commented Mar 17, 2019

That one is likely on Decktape side. It's likely the way it aggregates font glyphes over slides that doesn't handle emoji correctly:

decktape/decktape.js

Lines 407 to 452 in 46b23e5

function parseFont(fontObject) {
const pdfStreamInput = cpyCxtParser.parseNewObject(fontObject.getObjectID());
const fontDictionary = pdfStreamInput.toJSObject();
// See "Introduction to Font Data Structures" from PDF specification
if (fontDictionary.Subtype.value === 'Type0') {
// TODO: properly support composite fonts with multiple descendants
const descendant = cpyCxtParser
.parseNewObject(fontDictionary.DescendantFonts.toJSArray()[0].getObjectID())
.toJSObject();
if (descendant.Subtype.value == 'CIDFontType2') {
const descriptor = cpyCxtParser
.parseNewObject(descendant.FontDescriptor.getObjectID())
.toJSObject();
const id = descriptor.FontFile2.getObjectID();
const buffer = readStream(cpyCxtParser.parseNewObject(id));
const font = Font.create(buffer, { type: 'ttf', hinting: true });
// PDF font name does not contain sub family on Windows 10 so a more robust key
// is computed from the font metadata
const name = descriptor.FontName.value + ' - ' + fontMetadataKey(font.data.name);
if (context.pdfFonts[name]) {
const f = context.pdfFonts[name].font;
font.data.glyf.forEach((g, i) => {
if (g.contours && g.contours.length > 0) {
if (!f.data.glyf[i].contours || f.data.glyf[i].contours.length === 0) {
f.data.glyf[i] = g;
}
} else if (g.compound) {
if (typeof f.data.glyf[i].compound === 'undefined'
&& f.data.glyf[i].contours.length === 0) {
f.data.glyf[i] = g;
}
}
});
const replacement = {};
replacement[id] = context.pdfFonts[name].id;
cpyCxt.replaceSourceObjects(replacement);
} else {
const xObjectId = printer.getObjectsContext().allocateNewObjectID();
context.pdfFonts[name] = { id: xObjectId, font: font };
const replacement = {};
replacement[id] = xObjectId;
cpyCxt.replaceSourceObjects(replacement);
}
}
}
}

Your presentation is enough to reproduce and test the future fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.