diff options
author | Fazlul Shahriar <fshahriar@gmail.com> | 2018-06-22 16:43:17 -0400 |
---|---|---|
committer | David du Colombier <0intro@gmail.com> | 2018-10-05 23:38:31 +0200 |
commit | 48da9bd71ddae0c51f8aff4c0d6806a8e32c4e23 (patch) | |
tree | 47af35532b23f284a3f84588f08eb442b8701889 /src/cmd/fontsrv | |
parent | db27122d3942ebec4471c260403d87cdd6541add (diff) | |
download | plan9port-48da9bd71ddae0c51f8aff4c0d6806a8e32c4e23.tar.gz plan9port-48da9bd71ddae0c51f8aff4c0d6806a8e32c4e23.tar.bz2 plan9port-48da9bd71ddae0c51f8aff4c0d6806a8e32c4e23.zip |
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 (limited to 'src/cmd/fontsrv')
-rw-r--r-- | src/cmd/fontsrv/x11.c | 81 |
1 files changed, 43 insertions, 38 deletions
diff --git a/src/cmd/fontsrv/x11.c b/src/cmd/fontsrv/x11.c index a097ca4d..455e8126 100644 --- 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 |