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; }
int MMSDFill(hotCtx g) { int i; Offset offset; MMSDCtx h = g->ctx.MMSD; if (!IS_MM(g)) { return 0; } h->tbl.version = VERSION(1, 0); h->tbl.flags = 0; if (g->font.flags & HOT_USE_FOR_SUBST) { h->tbl.flags |= MMSD_USE_FOR_SUBST; } if (g->font.flags & HOT_CANT_INSTANCE) { h->tbl.flags |= MMSD_CANT_INSTANCE; } /* Fill axis table */ h->tbl.axis_.nAxes = (unsigned short)g->font.mm.axis.cnt; h->tbl.axis_.axisSize = AXIS_SIZE; h->tbl.axis_.axis_ = MEM_NEW(g, sizeof(AxisRec) * h->tbl.axis_.nAxes); for (i = 0; i < h->tbl.axis_.nAxes; i++) { AxisRec *dst = &h->tbl.axis_.axis_[i]; MMAxis *src = &g->font.mm.axis.array[i]; dst->longLabel_ = src->longLabel; dst->shortLabel_ = src->shortLabel; } if (g->font.mm.instance.cnt != 0) { /* Fill instance table */ h->tbl.instance_.nInstances = (unsigned short)g->font.mm.instance.cnt; h->tbl.instance_.instanceSize = INSTANCE_SIZE; h->tbl.instance_.instance_ = MEM_NEW(g, sizeof(InstanceRec) * h->tbl.instance_.nInstances); for (i = 0; i < h->tbl.instance_.nInstances; i++) { h->tbl.instance_.instance_[i].nameSuffix_ = g->font.mm.instance.array[i].suffix; } } else { h->tbl.instance_.nInstances = 0; } if (g->font.mm.style.cnt != 0) { /* Fill style table */ h->tbl.style_.nStyles = (unsigned short)g->font.mm.style.cnt; h->tbl.style_.styleSize = STYLE_SIZE; h->tbl.style_.style_ = MEM_NEW(g, sizeof(StyleRec) * h->tbl.style_.nStyles); for (i = 0; i < h->tbl.style_.nStyles; i++) { StyleRec *dst = &h->tbl.style_.style_[i]; MMStyle *src = &g->font.mm.style.array[i]; dst->axis = (unsigned char)src->axis; dst->flags = (unsigned char)src->flags; dst->action[0].point = src->action[0].point; dst->action[0].delta = src->action[0].delta; dst->action[1].point = src->action[1].point; dst->action[1].delta = src->action[1].delta; } } else { h->tbl.style_.nStyles = 0; } /* Fill offsets */ h->tbl.axis = offset = HEADER_SIZE; offset += AXIS_TBL_SIZE(h); if (h->tbl.instance_.nInstances != 0) { h->tbl.instance = offset; offset += INSTANCE_TBL_SIZE(h); } else { h->tbl.instance = 0; } if (h->tbl.style_.nStyles != 0) { h->tbl.style = offset; offset += STYLE_TBL_SIZE(h); } else { h->tbl.style = 0; } /* Calculate string offsets */ for (i = 0; i < h->tbl.axis_.nAxes; i++) { AxisRec *axis = &h->tbl.axis_.axis_[i]; axis->longLabel = offset; offset += strlen(axis->longLabel_) + 1; axis->shortLabel = offset; offset += strlen(axis->shortLabel_) + 1; } if (h->tbl.instance != 0) { for (i = 0; i < h->tbl.instance_.nInstances; i++) { InstanceRec *instance = &h->tbl.instance_.instance_[i]; instance->nameSuffix = offset; offset += strlen(instance->nameSuffix_) + 1; } } return 1; }
/* Print proofs at the current UDV */ static void printCaretOffset(hotCtx g, short caretoff, int iMaster) { #define IN2PIX(a) ((a)*72) #define MARGIN IN2PIX(.25) #define PTSIZE (60) #define YTOP IN2PIX(11.4) #define LINEGAP IN2PIX(1.3) #define SCALE ((double)PTSIZE/1000) #define GAP (.15) hheaCtx h = g->ctx.hhea; int xLine; char msg[1024]; static int caretPrint = 0; static double xCurr = MARGIN; static double yCurr = YTOP; if (caretPrint == 0) { printf("%%!\n" "/_MT{moveto}bind def\n" "/_NP{newpath}bind def\n" "/_LT{lineto}bind def\n" "/_CT{curveto}bind def\n" "/_CP{closepath}bind def\n"); printf("/Times-Roman findfont 9 scalefont setfont\n\n"); caretPrint = 1; } printf("/caret {_NP " "%hd %f mul %hd _MT " "%hd %f mul %hd _LT\n" " .1 setlinewidth stroke 0 0 _MT}bind def\n\n", g->font.TypoAscender, h->caretoff.tangent, g->font.TypoAscender, g->font.TypoDescender, h->caretoff.tangent, g->font.TypoDescender); /* Set up for a line */ printf("gsave\n"); yCurr -= LINEGAP; if (yCurr < MARGIN + IN2PIX(.3)) { printf("showpage\n"); yCurr = YTOP - LINEGAP; } printf("%f %f translate\n", xCurr, yCurr); /* Draw baselines */ printf("0 0 _MT %d 0 _LT ", IN2PIX(5)); printf("%f 0 _MT %f 0 _LT\n", IN2PIX(5 + GAP), (double)IN2PIX(8)); printf(".1 setlinewidth stroke\n"); /* Prepare message */ sprintf(msg, "%d %s", caretoff, g->font.FontName.array); if (IS_MM(g)) { if (iMaster == -1) sprintf(&msg[strlen(msg)], "[dflt]"); else sprintf(&msg[strlen(msg)], "[%d/%d]", iMaster, g->font.mm.nMasters); } printf("0 -20 _MT (%s) show\n", msg); fprintf(stderr, "%s\n", msg); printf("%.3f %.3f scale\n", SCALE, SCALE); /* Print glyphs with offset */ xLine = 0; printGlyphRun(g, &xLine, (int)(IN2PIX(5)/SCALE), caretoff, 1); /* Print some glyphs without the offset, for contrast */ printf("%f 0 translate\n", IN2PIX(5 + GAP)/SCALE - xLine); xLine = (int)(IN2PIX(5 + GAP)/SCALE); printGlyphRun(g, &xLine, (int)(IN2PIX(8)/SCALE), caretoff, 0); printf("grestore\n"); }
/* Calculate caret offset for an italic font. Shear heuristic glyph upright, calculate its left (a) and right (b) sidebearings. Return a-(a+b)/2 */ static short calcCaretOffset(hotCtx g) { hheaCtx h = g->ctx.hhea; unsigned int i; double a; double b; FWord hAdv; short caretoff; GID gid = GID_UNDEF; static cffPathCallbacks pathcb = { NULL, caretoffMoveto, caretoffLineto, caretoffCurveto, NULL, NULL, NULL, NULL, }; UV uv[] = { UV_CARET_OFFSET_1, UV_CARET_OFFSET_2, UV_CARET_OFFSET_3, }; /* Determine heuristic glyph */ for (i = 0; i < ARRAY_LEN(uv); i++) if ((gid = mapUV2GID(g, uv[i])) != GID_UNDEF) break; if (gid == GID_UNDEF) return 0; h->caretoff.tangent = tan(FIX2DBL(-g->font.ItalicAngle) / RAD_DEG); h->caretoff.bboxLeft = DBL_MAX; h->caretoff.bboxRight = 0; if (IS_MM(g)) cffSetUDV(g->ctx.cff, g->font.mm.axis.cnt, g->font.mm.UDV); hAdv = cffGetGlyphInfo(g->ctx.cff, gid, &pathcb)->hAdv; if (h->caretoff.bboxLeft == DBL_MAX) return 0; a = h->caretoff.bboxLeft; b = hAdv - h->caretoff.bboxRight; caretoff = (short)RND(a - (a + b) / 2); #if HOT_DEBUG #if 0 printCaretOffset(g, caretoff, -1); if (IS_MM(g)) { Fixed WV[TX_MAX_MASTERS]; int i; for (i = 0; i < g->font.mm.nMasters; i++) WV[i] = 0; for (i = 0; i < g->font.mm.nMasters; i++) { WV[i] = INT2FIX(1); cffSetWV(g->ctx.cff, g->font.mm.nMasters, WV); printCaretOffset(g, caretoff, i); WV[i] = 0; } } #endif #endif return caretoff; }