fontsrv: copy some fixes from OS X to X11

* Avoid allocating empty images by adding 1 to width/height. This was
  crashing fontsrv. The total width of the subfont image can be zero
  even if the characters are present in the font. For example, all the
  characters in x0300.bit (part of "Combining Diacritical Marks" Unicode
  block) have zero width.
* Make sure U+0000 is always present in the font, otherwise libdraw
  complains with: "stringwidth: bad character set for rune 0x0000 in ..."
* Use the same fallback glyph (pjw face) as OS X. This also fixes a bug
  where advance was set to the total width of subfont instead of the
  character.

Update #125 (most likely fixes the crash if in X11)

Change-Id: Icdc2b641b8b0c08644569006e91cf613b4d5477f
This commit is contained in:
Fazlul Shahriar 2018-06-22 16:43:17 -04:00 committed by David du Colombier
parent db27122d39
commit 48da9bd71d

View file

@ -66,19 +66,16 @@ load(XFont *f)
return;
e = FT_New_Face(lib, f->fontfile, f->index, &face);
if(e){
fprint(2, "load failed for %s (%s) index:%d\n", f->name, f->fontfile, f->index);
return;
}
if(!FT_IS_SCALABLE(face)) {
fprint(2, "%s is a non scalable font, skipping\n", f->name);
FT_Done_Face(face);
f->loaded = 1;
f->loaded = 1;
return;
}
f->unit = face->units_per_EM;
f->height = (int)((face->ascender - face->descender) * 1.2);
f->originy = face->descender; // bbox.yMin (or descender) is negative, becase the baseline is y-coord 0
@ -96,7 +93,11 @@ load(XFont *f)
f->nrange++;
}
}
// libdraw expects U+0000 to be present
if(!f->range[0]) {
f->range[0] = 1;
f->nrange++;
}
FT_Done_Face(face);
f->loaded = 1;
}
@ -108,14 +109,13 @@ mksubfont(XFont *xf, char *name, int lo, int hi, int size, int antialias)
FT_Error e;
Memimage *m, *mc, *m1;
double pixel_size;
int x, y, y0;
int w, x, y, y0;
int i;
Fontchar *fc, *fc0;
Memsubfont *sf;
//Point rect_points[4];
e = FT_New_Face(lib, xf->fontfile, xf->index, &face);
if(e){
fprint(2, "load failed for %s (%s) index:%d\n", xf->name, xf->fontfile, xf->index);
return nil;
@ -129,16 +129,16 @@ mksubfont(XFont *xf, char *name, int lo, int hi, int size, int antialias)
}
pixel_size = (dpi*size)/72.0;
x = (int)((face->max_advance_width) * pixel_size/xf->unit + 0.99999999);
w = x = (int)((face->max_advance_width) * pixel_size/xf->unit + 0.99999999);
y = (int)((face->ascender - face->descender) * pixel_size/xf->unit + 0.99999999);
y0 = (int)(-face->descender * pixel_size/xf->unit + 0.99999999);
m = allocmemimage(Rect(0, 0, x*(hi+1-lo), y), antialias ? GREY8 : GREY1);
m = allocmemimage(Rect(0, 0, x*(hi+1-lo)+1, y+1), antialias ? GREY8 : GREY1);
if(m == nil) {
FT_Done_Face(face);
return nil;
}
mc = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1);
mc = allocmemimage(Rect(0, 0, x+1, y+1), antialias ? GREY8 : GREY1);
if(mc == nil) {
freememimage(m);
FT_Done_Face(face);
@ -165,41 +165,42 @@ mksubfont(XFont *xf, char *name, int lo, int hi, int size, int antialias)
x = 0;
for(i=lo; i<=hi; i++, fc++) {
int r;
int k, r;
int advance;
memfillcolor(mc, DBlack);
e = FT_Load_Char(face, i, FT_LOAD_RENDER|FT_LOAD_NO_HINTING|(antialias ? 0:FT_LOAD_TARGET_MONO));
if(e){
fprint(2, "FT_Load_Char failed for %d\n", i);
//mempoly(mc, rect_points, 4, Endsquare, Endsquare, 0, memopaque, ZP, S);
memimageline(mc, m->r.min, Pt(m->r.max.x, m->r.min.y), Endsquare, Endsquare, 0, memopaque, ZP, S);
memimageline(mc, m->r.min, Pt(m->r.min.x, m->r.max.y), Endsquare, Endsquare, 0, memopaque, ZP, S);
memimageline(mc, Pt(m->r.max.x, m->r.min.y), m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
memimageline(mc, Pt(m->r.min.x, m->r.max.y), m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
memimageline(mc, m->r.min, m->r.max, Endsquare, Endsquare, 0, memopaque, ZP, S);
advance = Dx(m->r);
memimagedraw(m, Rect(x, 0, x + advance, y), mc, ZP, memopaque, ZP, S);
} else {
FT_Bitmap *bitmap = &face->glyph->bitmap;
uchar *base = byteaddr(mc, mc->r.min);
advance = (face->glyph->advance.x+32) >> 6;
for(r=0; r < bitmap->rows; r++)
memmove(base + r*mc->width*sizeof(u32int), bitmap->buffer + r*bitmap->pitch, bitmap->pitch);
memimagedraw(m, Rect(x, 0, x + advance, y), mc,
Pt(-face->glyph->bitmap_left, -(y - y0 - face->glyph->bitmap_top)),
memopaque, ZP, S);
}
fc->x = x;
fc->top = 0;
fc->bottom = y;
fc->left = 0;
fc->bottom = Dy(m->r);
e = 1;
k = FT_Get_Char_Index(face, i);
if(k != 0) {
e = FT_Load_Glyph(face, k, FT_LOAD_RENDER|FT_LOAD_NO_HINTING|(antialias ? 0:FT_LOAD_TARGET_MONO));
}
if(e || face->glyph->advance.x <= 0) {
fc->width = 0;
fc->left = 0;
if(i == 0) {
drawpjw(m, fc, x, w, y, y - y0);
x += fc->width;
}
continue;
}
FT_Bitmap *bitmap = &face->glyph->bitmap;
uchar *base = byteaddr(mc, mc->r.min);
advance = (face->glyph->advance.x+32) >> 6;
for(r=0; r < bitmap->rows; r++)
memmove(base + r*mc->width*sizeof(u32int), bitmap->buffer + r*bitmap->pitch, bitmap->pitch);
memimagedraw(m, Rect(x, 0, x + advance, y), mc,
Pt(-face->glyph->bitmap_left, -(y - y0 - face->glyph->bitmap_top)),
memopaque, ZP, S);
fc->width = advance;
fc->left = 0;
x += advance;
#ifdef DEBUG_FT_BITMAP
@ -229,6 +230,10 @@ mksubfont(XFont *xf, char *name, int lo, int hi, int size, int antialias)
// round up to 32-bit boundary
// so that in-memory data is same
// layout as in-file data.
if(x == 0)
x = 1;
if(y == 0)
y = 1;
if(antialias)
x += -x & 3;
else