#include "test.h" enum { Guard = 8, Testw = 3 * Fontsz, Testh = 3 * Fontsz, Testn = Testw * Testh, Missingn = Fontsz * Fontsz, }; static u32int guardcolor = 0x5a5a5a5a; static char *testfonts[] = { "/usr/share/fonts/TTF/DejaVuSans.ttf", "/usr/share/fonts/TTF/Jigmo.ttf", "/usr/share/fonts/TTF/Jigmo2.ttf", }; static char *missingfonts[] = { "/strans-test-no-such-font", }; static void fillpixels(u32int *p, int n, u32int color) { int i; for(i = 0; i < n; i++) p[i] = color; } static int hasink(u32int *p, int n) { int i; for(i = 0; i < n; i++) if(p[i] != Colbg) return 1; return 0; } static int renders(Rune r) { u32int buf[Fontsz * Fontsz]; fillpixels(buf, nelem(buf), Colbg); putfont(buf, Fontsz, Fontsz, 0, 0, r); return hasink(buf, nelem(buf)); } static int inkbounds(u32int *p, int *minx, int *miny, int *maxx, int *maxy) { int x, y; *minx = Testw; *miny = Testh; *maxx = -1; *maxy = -1; for(y = 0; y < Testh; y++){ for(x = 0; x < Testw; x++){ if(p[y * Testw + x] == Colbg) continue; *minx = min(*minx, x); *miny = min(*miny, y); *maxx = max(*maxx, x); *maxy = max(*maxy, y); } } return *maxx >= 0; } static void checkclip(struct ct *t, u32int *ref, int dx, int dy) { u32int *buf, *mem, *want; int i, sx, sy, x, y; mem = emalloc((Testn + 2 * Guard) * sizeof mem[0]); want = emalloc(Testn * sizeof want[0]); fillpixels(mem, Testn + 2 * Guard, guardcolor); buf = mem + Guard; fillpixels(buf, Testn, Colbg); fillpixels(want, Testn, Colbg); for(y = 0; y < Testh; y++){ for(x = 0; x < Testw; x++){ sx = x - dx; sy = y - dy; if(sx >= 0 && sx < Testw && sy >= 0 && sy < Testh) want[y * Testw + x] = ref[sy * Testw + sx]; } } putfont(buf, Testw, Testh, Fontsz + dx, Fontsz + dy, 'A'); CT_CHECK(t, hasink(buf, Testn)); CT_EQ_MEM(t, want, buf, Testn * sizeof buf[0]); for(i = 0; i < Guard; i++){ CT_EQ_UINT(t, guardcolor, mem[i]); CT_EQ_UINT(t, guardcolor, mem[Guard + Testn + i]); } free(want); free(mem); } void font_render(struct ct *t) { u32int *buf, *missing, *ref; int i, minx, miny, maxx, maxy; missing = emalloc((Missingn + 2 * Guard) * sizeof missing[0]); fillpixels(missing, Missingn + 2 * Guard, guardcolor); buf = missing + Guard; fillpixels(buf, Missingn, Colbg); CT_CHECK(t, !fontinit(missingfonts, nelem(missingfonts))); putfont(buf, Fontsz, Fontsz, 0, 0, 'A'); for(i = 0; i < Missingn; i++) CT_EQ_UINT(t, Colbg, buf[i]); for(i = 0; i < Guard; i++){ CT_EQ_UINT(t, guardcolor, missing[i]); CT_EQ_UINT(t, guardcolor, missing[Guard + Missingn + i]); } if(!CT_CHECK(t, fontinit(testfonts, nelem(testfonts)))){ free(missing); return; } CT_CHECK(t, renders('A')); CT_CHECK(t, renders(0xac00)); CT_CHECK(t, renders(0x4e00)); CT_CHECK(t, renders(0x1f600)); CT_CHECK(t, renders(0x2000b)); fillpixels(missing, Missingn + 2 * Guard, guardcolor); buf = missing + Guard; fillpixels(buf, Missingn, Colbg); putfont(buf, Fontsz, Fontsz, 0, 0, 0x10ffff); for(i = 0; i < Missingn; i++) CT_EQ_UINT(t, Colbg, buf[i]); for(i = 0; i < Guard; i++){ CT_EQ_UINT(t, guardcolor, missing[i]); CT_EQ_UINT(t, guardcolor, missing[Guard + Missingn + i]); } free(missing); ref = emalloc(Testn * sizeof ref[0]); fillpixels(ref, Testn, Colbg); putfont(ref, Testw, Testh, Fontsz, Fontsz, 'A'); if(!CT_CHECK(t, inkbounds(ref, &minx, &miny, &maxx, &maxy))){ free(ref); return; } checkclip(t, ref, -minx - 1, 0); checkclip(t, ref, Testw - maxx, 0); checkclip(t, ref, 0, -miny - 1); checkclip(t, ref, 0, Testh - maxy); free(ref); }