commit 48da9bd71ddae0c51f8aff4c0d6806a8e32c4e23
parent db27122d3942ebec4471c260403d87cdd6541add
Author: Fazlul Shahriar <fshahriar@gmail.com>
Date: Fri, 22 Jun 2018 16:43:17 -0400
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
Diffstat:
M | src/cmd/fontsrv/x11.c | | | 81 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
1 file changed, 43 insertions(+), 38 deletions(-)
diff --git a/src/cmd/fontsrv/x11.c b/src/cmd/fontsrv/x11.c
@@ -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