Skip to content

Commit

Permalink
Add generic .notdef when writing CFF if missing
Browse files Browse the repository at this point in the history
  • Loading branch information
skef committed Feb 27, 2025
1 parent 6457ed3 commit 38a1f91
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 20 deletions.
30 changes: 12 additions & 18 deletions c/shared/cffwrite/cffwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1471,24 +1471,17 @@ int cfwBegFont(cfwCtx g, cfwMapCallback *map, uint32_t maxNumSubrs,
}

/* Order glyphs in CID-keyed font. */
static void orderCIDKeyedGlyphs(controlCtx h) {
static void orderCIDKeyedGlyphs(controlCtx h, bool has_notdef) {
cfwCtx g = h->g;
long i;
long nGlyphs = h->_new->glyphs.cnt;
bool has_notdef = true;
Glyph *glyphs = h->_new->glyphs.array;
dnaDCL(uint16_t, fdmap);

dnaINIT(g->ctx.dnaSafe, fdmap, 1, 1);
dnaSET_CNT(fdmap, h->_new->FDArray.cnt);
memset(fdmap.array, 0, sizeof(uint16_t) * h->_new->FDArray.cnt);

if (glyphs[0].info == NULL) {
if (!(g->flags & CFW_NO_NOTDEF_OK))
cfwFatal(h->g, cfwErrNoCID0, NULL);
has_notdef = false;
}

if (!(g->flags & CFW_PRESERVE_GLYPH_ORDER)) {
/* Insertion sort glyphs by CID order */
for (i = 2; i < nGlyphs; i++) {
Expand Down Expand Up @@ -1611,24 +1604,17 @@ static bool glyphLT(cfwCtx g, abfGlyphInfo *a, abfGlyphInfo *b) {
}

/* Order glyphs in name-keyed font. */
static void orderNameKeyedGlyphs(controlCtx h) {
static void orderNameKeyedGlyphs(controlCtx h, bool has_notdef) {
cfwCtx g = h->g;
int predef;
int id;
long i;
long j;
long k;
bool has_notdef = true;
Glyph tmp;
long nGlyphs = h->_new->glyphs.cnt;
Glyph *glyphs = h->_new->glyphs.array;

if (glyphs[0].info == NULL) {
if (!(g->flags & CFW_NO_NOTDEF_OK))
cfwFatal(h->g, cfwErrNoNotdef, NULL);
has_notdef = false;
}

if (!(g->flags & CFW_PRESERVE_GLYPH_ORDER)) {
/* Sort glyphs by encoding order using insertion sort */
for (i = 2; i < nGlyphs; i++) {
Expand Down Expand Up @@ -1938,6 +1924,14 @@ int cfwEndFont(cfwCtx g, abfTopDict *top) {
}
}

bool has_notdef = true;
if (h->_new->glyphs.array[0].info == NULL) {
if (!(g->flags & CFW_NO_NOTDEF_OK)) {
cfwAddNotdef(g, h->_new->flags & FONT_CID, true);
} else
has_notdef = false;
}

/* if we only had empty glyphs, set bbox to zeros */
zeroOutEmptyFontBBox(g);

Expand Down Expand Up @@ -1975,9 +1969,9 @@ int cfwEndFont(cfwCtx g, abfTopDict *top) {
*/

if (h->_new->flags & FONT_CID) {
orderCIDKeyedGlyphs(h);
orderCIDKeyedGlyphs(h, has_notdef);
} else {
orderNameKeyedGlyphs(h);
orderNameKeyedGlyphs(h, has_notdef);
}

// No .notdef but we didn't error out above so move the whole array back 1
Expand Down
1 change: 1 addition & 0 deletions c/shared/cffwrite/cffwrite_share.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ long cfwSeenGlyph(cfwCtx g, abfGlyphInfo *info, int *result,
long startNew, long endNew);
void cfwAddGlyph(cfwCtx g, abfGlyphInfo *info, float hAdv, long length,
long offset, long seen_index);
void cfwAddNotdef(cfwCtx g, int isCID, int warn);

SRI cfwIsStdString(cfwCtx g, const char *str);

Expand Down
46 changes: 46 additions & 0 deletions c/shared/cffwrite/cffwrite_t2cstr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2552,6 +2552,52 @@ static void glyphEnd(abfGlyphCallbacks *cb) {
updateFontBoundingBox(g);
}

void cfwAddNotdef(cfwCtx g, int isCID, int warn) {
if (warn)
g->logger->log(sWARNING, "No .notdef in input: adding glyph with generic outline");

abfGlyphCallbacks gcb = cfwGlyphCallbacks;
gcb.direct_ctx = g;

abfGlyphInfo info;
info.flags = isCID ? ABF_GLYPH_CID : 0;
info.tag = 0;
info.gname.ptr = ".notdef";
info.gname.impl = 0;
info.encoding.next = NULL;
info.encoding.code = ABF_GLYPH_UNENC;
info.cid = 0;
info.iFD = 0;
info.sup.begin = 0;
info.sup.end = 0;
info.blendInfo.vsindex = info.blendInfo.maxstack = info.blendInfo.numRegions = 0;
info.blendInfo.blendDeltaArgs = NULL;

glyphBeg(&gcb, &info);
glyphWidth(&gcb, 500);
glyphStem(&gcb, 0, 0, 50);
glyphStem(&gcb, 0, 650, 700);
glyphStem(&gcb, ABF_VERT_STEM, 0, 50);
glyphStem(&gcb, ABF_VERT_STEM, 450, 500);
glyphMove(&gcb, 0, 0);
glyphLine(&gcb, 500, 0);
glyphLine(&gcb, 500, 700);
glyphLine(&gcb, 0, 700);
glyphMove(&gcb, 250, 395);
glyphLine(&gcb, 80, 650);
glyphLine(&gcb, 420, 650);
glyphMove(&gcb, 280, 350);
glyphLine(&gcb, 450, 605);
glyphLine(&gcb, 450, 95);
glyphMove(&gcb, 80, 50);
glyphLine(&gcb, 250, 305);
glyphLine(&gcb, 420, 50);
glyphMove(&gcb, 50, 605);
glyphLine(&gcb, 220, 350);
glyphLine(&gcb, 50, 95);
glyphEnd(&gcb);
}

/* Public callback set */
const abfGlyphCallbacks cfwGlyphCallbacks = {
NULL,
Expand Down
2 changes: 1 addition & 1 deletion c/shared/include/tx_help/cff.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"-no_opt disable charstring optimizations (e.g.: x 0 rmoveto => x hmoveto)\n"
"-go order according to GOADB file (rather than default optimizations)\n"
"-maxs N set the maximum number of subroutines (0 means 32765)\n"
"-amnd write output even when .notdef is missing\n"
"-amnd don't add .notdef to output if missing\n"
"\n"
"CFF mode writes a CFF conversion of an abstract font. The precise form of the\n"
"CFF font that is written can be controlled to a limited extent by the options\n",
Expand Down
2 changes: 1 addition & 1 deletion c/shared/include/tx_help/cff2.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"-no_opt disable charstring optimizations (e.g.: x 0 rmoveto => x hmoveto)\n"
"-go order according to GOADB file (rather than default optimizations)\n"
"-maxs N set the maximum number of subroutines (0 means 32765)\n"
"-amnd write output even when .notdef is missing\n"
"-amnd don't add .notdef to output if missing\n"
"\n"
"CFF2 mode writes a CFF2 conversion of an abstract font.\n"
"\n"
Expand Down

0 comments on commit 38a1f91

Please sign in to comment.