From c5d4b505e27520a8373894a3382d529a00b6791f Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 3 Jun 2020 15:51:10 -0700 Subject: changed from short to int in vertex --- sys/libfont/font.c | 556 ++++++++++++++++++++++------------------------------- 1 file changed, 232 insertions(+), 324 deletions(-) (limited to 'sys') diff --git a/sys/libfont/font.c b/sys/libfont/font.c index 7de5d19..53988f6 100644 --- a/sys/libfont/font.c +++ b/sys/libfont/font.c @@ -1,96 +1,4 @@ -#include -#include -#include - -#define SAMPLE 8 /* should not be > 255 */ - -#define getshort(b) getbytes((b), 2) -#define getint(b) getbytes((b), 4) - -// ----------------------------------------------------------------------- -// internal types - -typedef struct Buffer Buffer; -typedef struct Edge Edge; -typedef struct ActiveEdge ActiveEdge; -typedef struct Point Point; - -struct Buffer -{ - uchar *data; - int cursor; - int size; -}; - -struct Edge { - float x0, y0, x1, y1; - int invert; -}; - -struct ActiveEdge -{ - struct ActiveEdge *next; - float fx,fdx,fdy; - float direction; - float sy; - float ey; -}; - -struct Point -{ - float x,y; -}; - -// ----------------------------------------------------------------------- -// opaque external types - -struct font·Info -{ - struct { - void *heap; - union { - mem·Allocator; - mem·Allocator mal; - }; - }; - - uchar *data; // pointer to .ttf file - int fontstart; // offset of start of font - - int numglyphs; // number of glyphs, needed for range checking - /* table locations as offset from start of ttf file */ - struct { - int loca; - int head; - int glyf; - int hhea; - int hmtx; - int kern; - int gpos; - int fpgm; - int svg; - int cvt; - }; - int index_map; // a cmap mapping for our chosen character encoding - int index_fmt; // format needed to map from glyph index to glyph - - Buffer cff; // cff font data - Buffer charstrings; // the charstring index - Buffer gsubrs; // global charstring subroutines index - Buffer subrs; // private charstring subroutines index - Buffer fontdicts; // array of font dicts - Buffer fdselect; // map from glyph to fontdict -}; - -struct font·Bitmap -{ - int w; - int h; - int stride; - uchar *pixels; -}; - -typedef int test_oversample_pow2[(SAMPLE & (SAMPLE-1)) == 0 ? 1 : -1]; +#include "font.h" // ----------------------------------------------------------------------- // buffer helpers to parse data from file @@ -417,7 +325,7 @@ init(font·Info *info, uchar *data, int offset) info->kern = find_table(data, offset, "kern"); // not required info->gpos = find_table(data, offset, "GPOS"); // not required info->fpgm = find_table(data, offset, "fpgm"); // not required (execute once per load) - info->cvt = find_table(data, offset, "cvt"); // not required (execute once per size) + info->cvt = find_table(data, offset, "cvt"); // not required (execute once per resize) printf("cvt found at %d\n", info->cvt); printf("fpgm found at %d\n", info->cvt); @@ -688,10 +596,10 @@ void setvertex(font·Vertex *v, uchar type, int32 x, int32 y, int32 cx, int32 cy) { v->type = type; - v->x = (short) x; - v->y = (short) y; - v->cx = (short) cx; - v->cy = (short) cy; + v->x = (slong)x; + v->y = (slong)y; + v->cx = (slong)cx; + v->cy = (slong)cy; } static @@ -783,232 +691,232 @@ static int glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pverts) { - short numc; - uchar *contourend; - uchar *data = info->data; - font·Vertex *verts = nil; - int numv = 0; - int g = glyph_offset(info, glyph_index); - - *pverts = nil; - - /* glyph not found */ - if (g < 0) - return 0; - - numc = ttshort(data + g); - - if (numc > 0) { - uchar flags=0, flagcount; - int32 nins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - int32 x,y,cx,cy,sx,sy,scx,scy; - - uchar *points; - contourend = data + g + 10; - nins = ttushort(data + g + 10 + numc * 2); - points = data + g + 10 + 2*numc + 2 + nins; - printf("number of instructions %d\n", nins); - - n = 1+ttushort(contourend + numc*2-2); - - m = n + 2*numc; // a loose bound on how many verts we might need - verts = info->alloc(info->heap, m, sizeof(verts[0])); - if (verts == 0) - return 0; - - next_move = 0; - flagcount = 0; - - // in first pass, we load uninterpreted data into the allocated array - // above, shifted to the end of the array so we won't overwrite it when - // we create our final data starting from the front - - off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated - - // first load flags - - for (i = 0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else - --flagcount; - verts[off+i].type = flags; - } - - // now load x coordinates - x=0; - for (i = 0; i < n; ++i) { - flags = verts[off+i].type; - if (flags & 2) { - short dx = *points++; - x += (flags & 16) ? dx : -dx; // ??? - } else { - if (!(flags & 16)) { - x = x + (short)(points[0]*256 + points[1]); - points += 2; - } - } - verts[off+i].x = (short)x; - } - - // now load y coordinates - y = 0; - for (i = 0; i < n; ++i) { - flags = verts[off+i].type; - if (flags & 4) { - short dy = *points++; - y += (flags & 32) ? dy : -dy; // ??? - } else { - if (!(flags & 32)) { - y = y + (short) (points[0]*256 + points[1]); - points += 2; - } - } - verts[off+i].y = (short)y; - } - - // now convert them to our format - numv = 0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) { - flags = verts[off+i].type; - x = (short)verts[off+i].x; - y = (short)verts[off+i].y; - - if (next_move == i) { - if (i != 0) - numv = close_shape(verts, numv, was_off, start_off, sx,sy,scx,scy,cx,cy); - - // now start the new one - start_off = !(flags & 1); - if (start_off) { - // if we start off with an off-curve point, then when we need to find a point on the curve - // where we can start, and we need to save some state for when we wraparound. - scx = x; - scy = y; - if (!(verts[off+i+1].type & 1)) { - // next point is also a curve point, so interpolate an on-point curve - sx = (x + (int32) verts[off+i+1].x) >> 1; - sy = (y + (int32) verts[off+i+1].y) >> 1; - } else { - // otherwise just use the next point as our start point - sx = (int32) verts[off+i+1].x; - sy = (int32) verts[off+i+1].y; - ++i; // we're using point i+1 as the starting point, so skip it - } - } else { - sx = x; - sy = y; - } - setvertex(&verts[numv++], font·Vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + ttushort(contourend+j*2); - ++j; - } else { - if (!(flags & 1)) { // if it's a curve - if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - setvertex(&verts[numv++], font·Vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - setvertex(&verts[numv++], font·Vcurve, x,y, cx, cy); - else - setvertex(&verts[numv++], font·Vline, x,y,0,0); - was_off = 0; - } - } - } - numv = close_shape(verts, numv, was_off, start_off, sx, sy, scx, scy, cx, cy); - } else if (numc < 0) { - // Compound shapes. - int more = 1; - uchar *comp = data + g + 10; - numv = 0; - verts = 0; - while (more) { - ushort flags, gidx; - int comp_num_verts = 0, i; - font·Vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = ttshort(comp); comp+=2; - gidx = ttshort(comp); comp+=2; - - if (flags & 2) { // XY values - if (flags & 1) { // shorts - mtx[4] = ttshort(comp); comp+=2; - mtx[5] = ttshort(comp); comp+=2; - } else { - mtx[4] = ttchar(comp); comp+=1; - mtx[5] = ttchar(comp); comp+=1; - } - } - else { - // @TODO handle matching point - assert(0); - } - if (flags & (1<<3)) { // WE_HAVE_A_SCALE - mtx[0] = mtx[3] = ttshort(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE - mtx[0] = ttshort(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = ttshort(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO - mtx[0] = ttshort(comp)/16384.0f; comp+=2; - mtx[1] = ttshort(comp)/16384.0f; comp+=2; - mtx[2] = ttshort(comp)/16384.0f; comp+=2; - mtx[3] = ttshort(comp)/16384.0f; comp+=2; - } - - // Find transformation scales. - m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - // Get indexed glyph. - comp_num_verts = font·glyph_shape(info, gidx, &comp_verts); - if (comp_num_verts > 0) { - // Transform verts. - for (i = 0; i < comp_num_verts; ++i) { - font·Vertex* v = &comp_verts[i]; - short x,y; - x=v->x; y=v->y; - v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - } - // Append verts. - tmp = info->alloc(info->heap, numv+comp_num_verts, sizeof(font·Vertex)); - if (!tmp) { - if (verts) info->free(info->heap, verts); - if (comp_verts) info->free(info->heap, comp_verts); - return 0; - } - if (numv > 0) - memcpy(tmp, verts, numv*sizeof(font·Vertex)); - - memcpy(tmp+numv, comp_verts, comp_num_verts*sizeof(font·Vertex)); - - if (verts) - info->free(info->heap, verts); - - verts = tmp; - info->free(info->heap, comp_verts); - numv += comp_num_verts; - } - // More components ? - more = flags & (1<<5); - } - } - - *pverts = verts; - return numv; + short numc; + uchar *contourend; + uchar *data = info->data; + font·Vertex *verts = nil; + int numv = 0; + int g = glyph_offset(info, glyph_index); + + *pverts = nil; + + /* glyph not found */ + if (g < 0) + return 0; + + numc = ttshort(data + g); + + if (numc > 0) { + uchar flags=0, flagcount; + int32 nins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + int32 x,y,cx,cy,sx,sy,scx,scy; + + uchar *points; + contourend = data + g + 10; + nins = ttushort(data + g + 10 + numc * 2); + points = data + g + 10 + 2*numc + 2 + nins; + printf("number of instructions %d\n", nins); + + n = 1+ttushort(contourend + numc*2-2); + + m = n + 2*numc; // a loose bound on how many verts we might need + verts = info->alloc(info->heap, m, sizeof(verts[0])); + if (verts == 0) + return 0; + + next_move = 0; + flagcount = 0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i = 0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + verts[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i = 0; i < n; ++i) { + flags = verts[off+i].type; + if (flags & 2) { + slong dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (short)(points[0]*256 + points[1]); // this cast is critical + points += 2; + } + } + verts[off+i].x = (slong)x; + } + + // now load y coordinates + y = 0; + for (i = 0; i < n; ++i) { + flags = verts[off+i].type; + if (flags & 4) { + slong dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (short)(points[0]*256 + points[1]); // this cast is critical + points += 2; + } + } + verts[off+i].y = (slong)y; + } + + // now convert them to our format + numv = 0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = verts[off+i].type; + x = (slong)verts[off+i].x; + y = (slong)verts[off+i].y; + + if (next_move == i) { + if (i != 0) + numv = close_shape(verts, numv, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(verts[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (int32) verts[off+i+1].x) >> 1; + sy = (y + (int32) verts[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (int32) verts[off+i+1].x; + sy = (int32) verts[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + setvertex(&verts[numv++], font·Vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttushort(contourend+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + setvertex(&verts[numv++], font·Vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + setvertex(&verts[numv++], font·Vcurve, x,y, cx, cy); + else + setvertex(&verts[numv++], font·Vline, x,y,0,0); + was_off = 0; + } + } + } + numv = close_shape(verts, numv, was_off, start_off, sx, sy, scx, scy, cx, cy); + } else if (numc < 0) { + // Compound shapes. + int more = 1; + uchar *comp = data + g + 10; + numv = 0; + verts = 0; + while (more) { + ushort flags, gidx; + int comp_num_verts = 0, i; + font·Vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttshort(comp); comp+=2; + gidx = ttshort(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttshort(comp); comp+=2; + mtx[5] = ttshort(comp); comp+=2; + } else { + mtx[4] = ttchar(comp); comp+=1; + mtx[5] = ttchar(comp); comp+=1; + } + } + else { + // @TODO handle matching point + assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttshort(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttshort(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttshort(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttshort(comp)/16384.0f; comp+=2; + mtx[1] = ttshort(comp)/16384.0f; comp+=2; + mtx[2] = ttshort(comp)/16384.0f; comp+=2; + mtx[3] = ttshort(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = font·glyph_shape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform verts. + for (i = 0; i < comp_num_verts; ++i) { + font·Vertex* v = &comp_verts[i]; + short x,y; + x=v->x; y=v->y; + v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append verts. + tmp = info->alloc(info->heap, numv+comp_num_verts, sizeof(font·Vertex)); + if (!tmp) { + if (verts) info->free(info->heap, verts); + if (comp_verts) info->free(info->heap, comp_verts); + return 0; + } + if (numv > 0) + memcpy(tmp, verts, numv*sizeof(font·Vertex)); + + memcpy(tmp+numv, comp_verts, comp_num_verts*sizeof(font·Vertex)); + + if (verts) + info->free(info->heap, verts); + + verts = tmp; + info->free(info->heap, comp_verts); + numv += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } + + *pverts = verts; + return numv; } typedef struct -- cgit v1.2.1