📄 otf2bdf.c
字号:
if (nocmap) {
if (code >= face->num_glyphs)
/*
* At this point, all the glyphs are done.
*/
break;
idx = code;
} else
idx = FT_Get_Char_Index(face, code);
/*
* If the glyph could not be loaded for some reason, or a subset is
* being generated and the index is not in the subset bitmap, just
* continue.
*/
if (idx <= 0 || FT_Load_Glyph(face, idx, load_flags))
continue;
if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))
continue;
/*
* Determine the DWIDTH (device width, or advance width in TT terms)
* and the SWIDTH (scalable width) values.
*/
dwidth = face->glyph->metrics.horiAdvance >> 6;
dw = (double) dwidth;
swidth = (FT_Short) ((dw * 72000.0) / swscale);
/*
* Determine the actual bounding box of the glyph bitmap. Do not
* forget that the glyph is rendered upside down!
*/
sx = sy = 0xffff;
ex = ey = 0;
bp = face->glyph->bitmap.buffer;
for (y = 0; y < face->glyph->bitmap.rows; y++) {
for (x = 0; x < face->glyph->bitmap.width; x++) {
if (bp[x >> 3] & (0x80 >> (x & 7))) {
if (x < sx) sx = x;
if (x > ex) ex = x;
if (y < sy) sy = y;
if (y > ey) ey = y;
}
}
bp += face->glyph->bitmap.pitch;
}
/*
* If the glyph is actually an empty bitmap, set the size to 0 all
* around.
*/
if (sx == 0xffff && sy == 0xffff && ex == 0 && ey == 0)
sx = ex = sy = ey = 0;
else {
/*
* Adjust the end points.
*/
ex++;
ey++;
}
/*
* Increment the number of glyphs generated.
*/
ng++;
/*
* Test to see if the font is going to be monowidth or not by
* comparing the current glyph width against the last one.
*/
if (wd != 0xffff && ismono && (ex - sx) + 1 != wd)
ismono = 0;
/*
* Adjust the font bounding box.
*/
wd = ex - sx;
ht = ey - sy;
x_off = sx + face->glyph->bitmap_left;
y_off = sy + face->glyph->bitmap_top - face->glyph->bitmap.rows;
bbx.maxas = MAX(bbx.maxas, ht + y_off);
bbx.maxds = MAX(bbx.maxds, -y_off);
bbx.rbearing = wd + x_off;
bbx.maxrb = MAX(bbx.maxrb, bbx.rbearing);
bbx.minlb = MIN(bbx.minlb, x_off);
bbx.maxlb = MAX(bbx.maxlb, x_off);
/*
* Add to the average width accumulator.
*/
aw += wd;
/*
* Print the bitmap header.
*/
fprintf(tmp, "STARTCHAR %04lX\nENCODING %ld\n", code,
(long) remapped_code);
fprintf(tmp, "SWIDTH %hd 0\n", swidth);
fprintf(tmp, "DWIDTH %hd 0\n", dwidth);
fprintf(tmp, "BBX %hd %hd %hd %hd\n", wd, ht, x_off, y_off);
/*
* Check for an error return here in case the temporary file system
* fills up or the file is deleted while it is being used.
*/
eof = fprintf(tmp, "BITMAP\n");
bp = face->glyph->bitmap.buffer + (sy * face->glyph->bitmap.pitch);
for (y = 0; eof != EOF && y < ey - sy; y++) {
for (idx = 0, x = 0; eof != EOF && x < ex - sx; x++) {
if (x > sx && (x & 7) == 0) {
/*
* Print the next byte.
*/
eof = fprintf(tmp, "%02lX", idx & 0xff);
idx = 0;
}
if (bp[(x+sx) >> 3] & (0x80 >> ((x+sx) & 7)))
idx |= (0x80 >> (x & 7));
}
bp += face->glyph->bitmap.pitch;
if (eof != EOF)
/*
* Because of the structure of the loop, the last byte should
* always be printed.
*/
fprintf(tmp, "%02lX\n", idx & 0xff);
}
if (eof != EOF)
fprintf(tmp, "ENDCHAR\n");
}
fclose(tmp);
/*
* If a write error occured, delete the temporary file and issue an error
* message.
*/
if (eof == EOF) {
(void) unlink(tmpfile);
fprintf(stderr, "%s: problem writing to temporary file '%s'.\n",
prog, tmpfile);
return -1;
}
/*
* If no characters were generated, just unlink the temp file and issue a
* warning.
*/
if (ng == 0) {
(void) unlink(tmpfile);
fprintf(stderr, "%s: no glyphs generated from '%s'.\n", prog, iname);
return -1;
}
/*
* Reopen the temporary file so it can be copied to the actual output
* file.
*/
if ((tmp = fopen(tmpfile, "r")) == 0) {
/*
* Unable to open the file for read, so attempt to delete it and issue
* an error message.
*/
(void) unlink(tmpfile);
fprintf(stderr, "%s: unable to open temporary file '%s' for read.\n",
prog, tmpfile);
return -1;
}
/*
* Calculate the average width.
*/
aw = (FT_Long) ((((double) aw / (double) ng) + 0.5) * 10.0);
/*
* Generate the XLFD font name.
*/
make_xlfd_name(xlfd, sizeof(xlfd), aw, ismono);
/*
* Start writing the font out.
*/
fprintf(out, "STARTFONT 2.1\n");
/*
* Add the vanity comments.
*/
fprintf(out, "COMMENT\n");
fprintf(out, "COMMENT Converted from OpenType font \"%s\" by \"%s %s\".\n",
iname, prog, OTF2BDF_VERSION);
fprintf(out, "COMMENT\n");
fprintf(out, "FONT %s\n", xlfd);
fprintf(out, "SIZE %d %d %d\n", point_size, hres, vres);
/*
* Generate the font bounding box.
*/
fprintf(out, "FONTBOUNDINGBOX %hd %hd %hd %hd\n",
bbx.maxrb - bbx.minlb, bbx.maxas + bbx.maxds,
bbx.minlb, -bbx.maxds);
/*
* Print the properties.
*/
fprintf(out, "STARTPROPERTIES %hd\n", 19);
/*
* Print the font properties from the XLFD name.
*/
for (i = 0, xp = xlfd; i < 14; i++) {
/*
* Print the XLFD property name.
*/
fprintf(out, "%s ", xlfd_props[i]);
/*
* Make sure the ATOM properties are wrapped in double quotes.
*/
if (i < 6 || i == 10 || i > 11)
putc('"', out);
/*
* Skip the leading '-' in the XLFD name.
*/
xp++;
/*
* Skip until the next '-' or NULL.
*/
for (; *xp && *xp != '-'; xp++)
putc(*xp, out);
/*
* Make sure the ATOM properties are wrapped in double quotes.
*/
if (i < 6 || i == 10 || i > 11)
putc('"', out);
putc('\n', out);
}
/*
* Make sure to add the FONT_ASCENT and FONT_DESCENT properties
* because X11 can not live without them.
*/
fprintf(out, "FONT_ASCENT %hd\nFONT_DESCENT %hd\n",
(horizontal->Ascender * imetrics.y_ppem) / upm,
-((horizontal->Descender * imetrics.y_ppem) / upm));
/*
* Get the copyright string from the font.
*/
(void) otf_get_english_string(face, BDFOTF_COPYRIGHT_STRING, 0, xlfd,
sizeof(xlfd));
fprintf(out, "COPYRIGHT \"%s\"\n", xlfd);
/*
* Last, print the two user-defined properties _OTF_FONTFILE and
* _OTF_PSNAME. _OTF_FONTFILE provides a reference to the original OT
* font file which some systems can take advantage of, and _OTF_PSNAME
* provides the Postscript name of the font if it exists.
*/
(void) otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd,
sizeof(xlfd));
fprintf(out, "_OTF_FONTFILE \"%s\"\n_OTF_PSNAME \"%s\"\n", iname, xlfd);
fprintf(out, "ENDPROPERTIES\n");
/*
* Print the actual number of glyphs to the output file.
*/
eof = fprintf(out, "CHARS %ld\n", ng);
/*
* Copy the temporary file to the output file.
*/
while (eof != EOF && (ng = fread(iobuf, 1, OTF2BDF_IOBUFSIZ, tmp))) {
if (fwrite(iobuf, 1, ng, out) == 0)
eof = EOF;
}
/*
* Close the temporary file and delete it.
*/
fclose(tmp);
(void) unlink(tmpfile);
/*
* If an error occured when writing to the output file, issue a warning
* and return.
*/
if (eof == EOF) {
fprintf(stderr, "%s: problem writing to output file '%s'.\n",
prog, oname);
return -1;
}
/*
* End the font and do memory cleanup on the glyph and raster structures.
*/
eof = fprintf(out, "ENDFONT\n");
return eof;
}
static int
generate_bdf(FILE *out, char *iname, char *oname)
{
FT_Long i;
/*
* Get the requested cmap.
*/
for (i = 0; i < face->num_charmaps; i++) {
if (face->charmaps[i]->platform_id == pid &&
face->charmaps[i]->encoding_id == eid)
break;
}
if (i == face->num_charmaps && pid == 3 && eid == 1) {
/*
* Make a special case when this fails with pid == 3 and eid == 1.
* Change to eid == 0 and try again. This captures the two possible
* cases for MS fonts. Some other method should be used to cycle
* through all the alternatives later.
*/
for (i = 0; i < face->num_charmaps; i++) {
if (face->charmaps[i]->platform_id == pid &&
face->charmaps[i]->encoding_id == 0)
break;
}
if (i < face->num_charmaps) {
pid = 3;
eid = 1;
FT_Set_Charmap(face, face->charmaps[i]);
} else {
/*
* No CMAP was found.
*/
nocmap = 1;
pid = eid = -1;
}
} else {
FT_Set_Charmap(face, face->charmaps[i]);
nocmap = 0;
}
if (nocmap && verbose) {
fprintf(stderr,
"%s: no character map for platform %d encoding %d. ",
prog, pid, eid);
fprintf(stderr, "Generating all glyphs.\n");
}
/*
* Now go through and generate the glyph bitmaps themselves.
*/
return generate_font(out, iname, oname);
}
#define isdig(cc) ((cc) >= '0' && (cc) <= '9')
/*
* Routine to parse a subset specification supplied on the command line.
* The syntax for this specification is the same as the syntax used for
* the XLFD font names (XLFD documentation, page 9).
*
* Example:
*
* "60 70 80_90" means the glyphs at codes 60, 70, and between 80 and
* 90 inclusive.
*/
static void
parse_subset(char *s)
{
long l, r;
/*
* Make sure to clear the flag and bitmap in case more than one subset is
* specified on the command line.
*/
maxcode = 0;
do_subset = 0;
(void) memset((char *) subset, 0, sizeof(unsigned long) * 2048);
while (*s) {
/*
* Collect the next code value.
*/
for (l = r = 0; *s && isdig(*s); s++)
l = (l * 10) + (*s - '0');
/*
* If the next character is an '_', advance and collect the end of the
* specified range.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -