aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-06-03 15:51:10 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-06-03 15:51:10 -0700
commitc5d4b505e27520a8373894a3382d529a00b6791f (patch)
tree9183309de3ce32516d72858b7af3ecb826021184 /sys
parentd1f071bf9aa394525745f0b4f582f97112ece26e (diff)
changed from short to int in vertex
Diffstat (limited to 'sys')
-rw-r--r--sys/libfont/font.c556
1 files changed, 232 insertions, 324 deletions
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 <u.h>
-#include <libn.h>
-#include <libfont.h>
-
-#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