diff options
Diffstat (limited to 'src/libdraw/getsubfont.c')
-rw-r--r-- | src/libdraw/getsubfont.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c index 0d8be9ff..3f3b6954 100644 --- a/src/libdraw/getsubfont.c +++ b/src/libdraw/getsubfont.c @@ -8,8 +8,10 @@ int _fontpipe(char*); +static void scalesubfont(Subfont*, int); + Subfont* -_getsubfont(Display *d, char *name) +_getsubfont(Display *d, Font *ff, char *name) { int fd; Subfont *f; @@ -36,5 +38,61 @@ _getsubfont(Display *d, char *name) if(f == 0) fprint(2, "getsubfont: can't read %s: %r\n", name); close(fd); + if(ff->scale != 1 && ff->scale != 0) + scalesubfont(f, ff->scale); return f; } + +static void +scalesubfont(Subfont *f, int scale) +{ + Image *i; + Rectangle r, r2; + int y, x, x2, j; + uchar *src, *dst; + int srcn, dstn, n, mask, v, pack; + + r = f->bits->r; + r2 = r; + r2.min.x *= scale; + r2.min.y *= scale; + r2.max.x *= scale; + r2.max.y *= scale; + + srcn = bytesperline(r, f->bits->depth); + src = malloc(srcn); + dstn = bytesperline(r2, f->bits->depth); + dst = malloc(dstn+1); + i = allocimage(f->bits->display, r2, f->bits->chan, 0, DBlack); + for(y=r.min.y; y < r.max.y; y++) { + n = unloadimage(f->bits, Rect(r.min.x, y, r.max.x, y+1), src, srcn); + if(n != srcn) + sysfatal("scalesubfont: bad unload: %d < %d: %r", n, srcn); + memset(dst, 0, dstn+1); + pack = 8 / f->bits->depth; + mask = (1<<f->bits->depth) - 1; + for(x=0; x<Dx(r); x++) { + v = ((src[x/pack] << ((x%pack)*f->bits->depth)) >> (8 - f->bits->depth)) & mask; + for(j=0; j<scale; j++) { + x2 = x*scale+j; + dst[x2/pack] |= v << (8 - f->bits->depth) >> ((x2%pack)*f->bits->depth); + } + } + if(dst[dstn] != 0) + sysfatal("overflow dst"); + for(j=0; j<scale; j++) + loadimage(i, Rect(r2.min.x, y*scale+j, r2.max.x, y*scale+j+1), dst, dstn); + } + freeimage(f->bits); + f->bits = i; + f->height *= scale; + f->ascent *= scale; + + for(j=0; j<f->n; j++) { + f->info[j].x *= scale; + f->info[j].top *= scale; + f->info[j].bottom *= scale; + f->info[j].left *= scale; + f->info[j].width *= scale; + } +} |