/* * $ gcc dump.c -o dump -mwindows */ #include #include #include #include #include #define POINT_FMT "%3d: %9f, %9f\n" int dump_ttpolygon(unsigned char *buf, int npoints) { LPTTPOLYGONHEADER header = (void*)buf; int buf_size = header->cb; int first_point = npoints; printf(POINT_FMT, npoints++, header->pfxStart.x.value + header->pfxStart.x.fract / 65536., header->pfxStart.y.value + header->pfxStart.y.fract / 65536.); buf += sizeof(*header); buf_size -= sizeof(*header); while (buf_size > 0) { LPTTPOLYCURVE curve = (void*)buf; int curve_size; int i; curve_size = 2 * sizeof(WORD) + curve->cpfx * sizeof(POINTFX); if (curve_size > buf_size) { printf("curve too large\n"); return; } printf("(%s)\n", (curve->wType == TT_PRIM_LINE) ? "polyline" : "spline"); buf_size -= curve_size; buf += curve_size; for (i = 0; i < curve->cpfx; i++) { LPPOINTFX pt = curve->apfx + i; if ( i == curve->cpfx - 1 && !buf_size && curve->wType != TT_PRIM_LINE && memcmp(&header->pfxStart, pt, sizeof(POINTFX)) == 0) printf(POINT_FMT, first_point, pt->x.value + pt->x.fract / 65536., pt->y.value + pt->y.fract / 65536.); else printf(POINT_FMT, npoints++, pt->x.value + pt->x.fract / 65536., pt->y.value + pt->y.fract / 65536.); } } return npoints; } int print_glyph_metrics(char ch, const char *face, long size, int unhinted) { LOGFONT lf; HFONT font; HDC dc; unsigned char *buf; DWORD buf_size; TEXTMETRIC tm; GLYPHMETRICS gm; MAT2 mat; UINT format = GGO_NATIVE; if (unhinted) format |= GGO_UNHINTED; memset(&lf, 0, sizeof(lf)); lf.lfHeight = -size; strcpy(lf.lfFaceName, face); font = CreateFontIndirect(&lf); if (!font) return 0; dc = GetDC(NULL); SelectObject(dc, font); memset(&gm, 0, sizeof(gm)); memset(&mat, 0, sizeof(mat)); mat.eM11.value = 1; mat.eM22.value = 1; buf_size = GetGlyphOutline(dc, ch, format, &gm, 0, NULL, &mat); buf = malloc(buf_size); GetTextFace(dc, buf_size, buf); GetTextMetrics(dc, &tm); printf("dumping `%c' of address@hidden", ch, buf, tm.tmHeight - tm.tmInternalLeading); if (GetGlyphOutline(dc, ch, format, &gm, buf_size, buf, &mat) != GDI_ERROR) { int i = 0; int npoints = 0; while (buf_size > 0 ) { LPTTPOLYGONHEADER ttpoly = (LPTTPOLYGONHEADER)buf; if (ttpoly->cb > buf_size) { printf("ttpoly too large\n"); return 0; } printf("Contour %d\n", i++); npoints = dump_ttpolygon((void*)ttpoly, npoints); printf("\n"); buf += ttpoly->cb; buf_size -= ttpoly->cb; } } ReleaseDC(NULL, dc); DeleteObject(font); return 1; } int main(int argc, char **argv) { char *face = "Tahoma"; long size = 12; int unhinted = 0; char ch; while ((ch = getopt(argc, argv, "s:f:u")) != -1) { switch (ch) { case 's': size = atoi(optarg); break; case 'f': face = optarg; break; case 'u': unhinted = 1; break; default: break; } } if (optind >= argc) { printf("Usage: %s [-f face] [-s size] [-u] \n", argv[0]); return 1; } ch = argv[optind][0]; print_glyph_metrics(ch, face, size, unhinted); return 0; }