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

Fix cmaps #298

Merged
merged 3 commits into from
Dec 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 15 additions & 41 deletions src/core/embedders/CMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,25 @@ import {
lowSurrogate,
} from 'src/utils/unicode';

/** [[start, end], mappings] */
type BfRange = [[string, string], string[]];
/** [fontId, codePoint] */
type BfChar = [string, string];

/** `glyphs` should be an array of unique glyphs sorted by their ID */
/** `glyphs` should be an array of unique glyphs */
export const createCmap = (glyphs: Glyph[], glyphId: (g?: Glyph) => number) => {
const bfRanges: BfRange[] = [];

let first: number = glyphId(glyphs[0]);
let mappings: string[] = [];

const bfChars: BfChar[] = new Array(glyphs.length);
for (let idx = 0, len = glyphs.length; idx < len; idx++) {
const currGlyph = glyphs[idx];
const nextGlyph = glyphs[idx + 1];

const currGlyphId = glyphId(currGlyph);
const nextGlyphId = glyphId(nextGlyph);

const { codePoints } = currGlyph;
mappings.push(cmapHexFormat(...codePoints.map(cmapCodePointFormat)));

if (idx !== 0 && nextGlyphId - currGlyphId !== 1) {
const last = currGlyphId;
const delimiters: [string, string] = [
cmapHexFormat(cmapHexString(first)),
cmapHexFormat(cmapHexString(last)),
];
bfRanges.push([delimiters, mappings]);

first = nextGlyphId;
mappings = [];
}
const glyph = glyphs[idx];
const id = cmapHexFormat(cmapHexString(glyphId(glyph)));
const unicode = cmapHexFormat(...glyph.codePoints.map(cmapCodePointFormat));
bfChars[idx] = [id, unicode];
}

return fillCmapTemplate(bfRanges);
return fillCmapTemplate(bfChars);
};

/* =============================== Templates ================================ */

// prettier-ignore
const fillBfrangeTemplate = ([[start, end], mappings]: BfRange) => `
${mappings.length} beginbfrange
${start} ${end} [${mappings.join(' ')}]
endbfrange
`.trim();

// prettier-ignore
const fillCmapTemplate = (bfRanges: BfRange[]) => `
const fillCmapTemplate = (bfChars: BfChar[]) => `\
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
Expand All @@ -68,12 +40,14 @@ begincmap
1 begincodespacerange
<0000><ffff>
endcodespacerange
${bfRanges.map(fillBfrangeTemplate).join('\n')}
${bfChars.length} beginbfchar
${bfChars.map(([glyphId, codePoint]) => `${glyphId} ${codePoint}`).join('\n')}
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
`.trim();
end\
`;

/* =============================== Utilities ================================ */

Expand Down
4 changes: 2 additions & 2 deletions tests/core/embedders/CMap.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const allGlyphsInFontSortedById = (font: Font) => {
};

describe(`createCmap`, () => {
it(`created CMaps for embedded Ubuntu-R font files`, () => {
it(`creates CMaps for embedded Ubuntu-R font files`, () => {
const font = fontkit.create(ubuntuFont);

const glyphs = allGlyphsInFontSortedById(font);
Expand All @@ -35,7 +35,7 @@ describe(`createCmap`, () => {
expect(cmap).toEqual(String(ubuntuFontCmap));
});

it(`created CMaps for embedded SourceHanSerifJP-Regular font files`, () => {
it(`creates CMaps for embedded SourceHanSerifJP-Regular font files`, () => {
const font = fontkit.create(sourceHansJpFont);

const glyphs = allGlyphsInFontSortedById(font);
Expand Down
Loading