static void validateGlyphClasses(GDEFCtx h, GNode** classList, long numClasses) { int i,j; int hadConflictingClassDef = 0; hotCtx g = h->g; /* Check and warn if the same glyph has ended up in more than one class */ for (i = 0; i < numClasses; i++) { GNode *p1; GNode *headNode1 = classList[i]; char *className1; if (headNode1 == NULL) continue; className1 = headNode1->markClassName; if (className1 == NULL) className1 = "mark attachment class 1"; for (j = i+1; j < numClasses; j++) { GNode *p2; GNode *headNode2 = classList[j]; char *className2; if (headNode2 == NULL) continue; className2 = headNode2->markClassName; if (className2 == NULL) className2 = "mark attachment class 2"; for (p1 = headNode1; p1 != NULL;) { GNode *prev = NULL; for (p2 = headNode2; p2 != NULL;) { if (p1->gid == p2->gid) { hadConflictingClassDef = 1; featGlyphDump(g, p1->gid, 0, 0); hotMsg(g, hotWARNING, "GDEF MarkAttachment. Glyph '%s' gid '%d'. previous glyph class '%s' conflicts with new class '%s'.", g->note.array, p1->gid, className1, className2); } prev = p2; p2 = p2->nextCl; } p1 = p1->nextCl; } } } if (hadConflictingClassDef) { hotMsg(g, hotWARNING, "GDEF MarkAttachment Classes. There are conflicting MarkAttachment assignments."); } }
int MMFXFill(hotCtx g) { MMFXCtx h = g->ctx.MMFX; int i; Offset offset; if (!IS_MM(g)) { return 0; } /* Fill header */ h->tbl.version = VERSION(1, 0); h->tbl.nMetrics = (unsigned short)h->metrics.cnt; h->tbl.offSize = (HEADER_SIZE + uint16 * h->metrics.cnt + h->metrics.array[h->metrics.cnt - 1].index > 65535) ? 4 : 2; /* Sort metrics by id */ qsort(h->metrics.array, h->metrics.cnt, sizeof(Metric), cmpIds); /* Check if all named metrics present */ for (i = 0; i < h->metrics.cnt; i++) { if (h->metrics.array[i].id >= MMFXNamedMetricCnt) { break; } } if (i < MMFXNamedMetricCnt) { hotMsg(g, hotFATAL, "Missing named metrics"); } else if (i > MMFXNamedMetricCnt) { hotMsg(g, hotFATAL, "Duplicate named metrics"); } /* Allocate and fill offset array */ offset = (unsigned short)(HEADER_SIZE + h->tbl.offSize * h->metrics.cnt); h->tbl.offset = MEM_NEW(g, sizeof(long) * h->metrics.cnt); for (i = 0; i < h->metrics.cnt; i++) { h->tbl.offset[i] = offset + h->metrics.array[i].index; } return 1; }
/* Execute metric at default instance. Assumes only one returned result */ cffFixed MMFXExecMetric(hotCtx g, unsigned id) { MMFXCtx h = g->ctx.MMFX; unsigned length; unsigned cstrInx; cffFixed result[T2_MAX_OP_STACK]; if (getMetric(h, id, &cstrInx, &length)) { hotMsg(g, hotFATAL, "Metric id <%u> not found", id); } cffExecLocalMetric(g->ctx.cff, &h->cstrs.array[cstrInx], h->cstrs.cnt - cstrInx, result); return result[0]; }
void setGlyphClassGDef(hotCtx g, GNode *simple, GNode *ligature, GNode *mark, GNode *component) { GDEFCtx h = g->ctx.GDEF; GNode **simpleClass = dnaNEXT(h->glyphClasess); GNode **ligClass = dnaNEXT(h->glyphClasess); GNode **markClass = dnaNEXT(h->glyphClasess); GNode **compClass = dnaNEXT(h->glyphClasess); int hadConflictingClassDef = 0; char* glyphClassNames[] = {"Base", "Ligature", "Mark","Component"}; long i,j; if (simple == NULL) *simpleClass = NULL; else *simpleClass = simple; if (ligature == NULL) *ligClass = NULL; else *ligClass = ligature; if (mark == NULL) *markClass = NULL; else *markClass = mark; if (component == NULL) *compClass = NULL; else *compClass = component; /* Check and warn if the same glyph has ended up in more than one class */ for (i = 0; i < h->glyphClasess.cnt; i++) { GNode *p1; GNode *prev1 = NULL; GNode *headNode1 = h->glyphClasess.array[i]; if (headNode1 == NULL) continue; for (j = i+1; j < h->glyphClasess.cnt; j++) { GNode *p2; GNode *headNode2 = h->glyphClasess.array[j]; if (headNode2 == NULL) continue; for (p1 = headNode1; p1 != NULL;) { GNode *prev2 = NULL; unsigned int removedP1 = 0; for (p2 = headNode2; p2 != NULL;) { if (p1->gid == p2->gid) { if (j != 2) { // remove glyph from current class. if (i != 2) /* If the gid in class j is being overridden by the mark class definition, then we do not complain */ { hadConflictingClassDef = 1; featGlyphDump(g, p1->gid, 0, 0); hotMsg(g, hotWARNING, "GDEF GlyphClass. Glyph '%s' gid '%d'. previous glyph class '%s' overrides new class '%s'.", g->note.array, p1->gid, glyphClassNames[i], glyphClassNames[j]); } removeNodeFromClass(h, &(h->glyphClasess.array[j]), &headNode2, &prev2, &p2); } else { // class j is the mark class; we need to remove p1 from the glyph class i. We do this silently, as the mark class always supersedes other classes. removeNodeFromClass(h, &(h->glyphClasess.array[i]), &headNode1, &prev1, &p1); removedP1 = 1; } } else { prev2 = p2; p2 = p2->nextCl; } if (p1 == NULL) break; /* This can happen because all teh p1's get removed by mark class overrides above */ } if (!removedP1) { prev1 = p1; if (p1 != NULL) p1 = p1->nextCl; } } } } if (hadConflictingClassDef) { hotMsg(g, hotWARNING, "GDEF Glyph Class. Since there were conflicting GlyphClass assignments, you should examine this auto-built GDEF table, and make sure that the glyph class assignments are as needed. If not, you should specify the GDEF table explicitly, in the features file.\n"); } }