diff options
author | Keith Packard <keithp@keithp.com> | 2004-10-04 07:49:49 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2004-10-04 07:49:49 +0000 |
commit | e27025eda79dbf6428c20d2d0dd635ddffaa3fba (patch) | |
tree | c63fc6037dc2e9c5e92086be642766669a56c11e | |
parent | 1b7271c78065d6a1ab3396df916529fc7958b0e2 (diff) |
Fix a clipping bug
Change glyph representation to allow splines and include metrics.
Add some new helper functions.
Expose _twin_path_scurve for glyphs
Increase sin table precision.
Fix off-by-one error in y position. Lock screen while adding expose damage
Change clock appearance. Use corrected glyph metrics
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | twin.h | 26 | ||||
-rw-r--r-- | twin_draw.c | 4 | ||||
-rw-r--r-- | twin_font.c | 578 | ||||
-rw-r--r-- | twin_glyphs.c | 1564 | ||||
-rw-r--r-- | twin_matrix.c | 15 | ||||
-rw-r--r-- | twin_path.c | 22 | ||||
-rw-r--r-- | twin_spline.c | 2 | ||||
-rw-r--r-- | twin_trig.c | 172 | ||||
-rw-r--r-- | twin_x11.c | 6 | ||||
-rw-r--r-- | twinint.h | 23 | ||||
-rw-r--r-- | xtwin.c | 158 |
12 files changed, 2287 insertions, 315 deletions
@@ -1,3 +1,35 @@ +2004-10-04 Keith Packard <keithp@keithp.com> + + * twin.h: + * twin_draw.c: (twin_composite): + Fix a clipping bug + + * twinint.h: + * twin_font.c: (_snap), (_twin_g_base), (_twin_pen_size), + (twin_text_metrics_ucs4), (twin_add_snap), (twin_n_in_spline), + (twin_spline_fit), (_ucs4_string), (px), (py), (twin_dump_glyphs), + (twin_path_ucs4), (twin_text_metrics_utf8): + * twin_glyphs.c: + Change glyph representation to allow splines and include metrics. + + * twin_matrix.c: (_twin_matrix_expand): + * twin_path.c: (twin_path_rmove), (twin_path_rdraw): + Add some new helper functions. + + * twin_spline.c: + Expose _twin_path_scurve for glyphs + + * twin_trig.c: + Increase sin table precision. + + * twin_x11.c: (_twin_x11_put_span), (twin_x11_screen_damaged), + (twin_x11_damage): + Fix off-by-one error in y position. + Lock screen while adding expose damage + + * xtwin.c: (twin_clock_face), (twin_clock), (main): + Change clock appearance. Use corrected glyph metrics + 2004-10-01 Keith Packard <keithp@keithp.com> * twin.h: @@ -49,16 +49,16 @@ typedef enum { TWIN_A8, TWIN_RGB16, TWIN_ARGB32 } twin_format_t; /* * Angles */ -typedef int16_t twin_angle_t; /* -512 .. 512 for -180 .. 180 */ +typedef int16_t twin_angle_t; /* -2048 .. 2048 for -180 .. 180 */ -#define TWIN_ANGLE_360 1024 -#define TWIN_ANGLE_180 512 -#define TWIN_ANGLE_90 256 -#define TWIN_ANGLE_45 128 -#define TWIN_ANGLE_22_5 64 -#define TWIN_ANGLE_11_25 32 +#define TWIN_ANGLE_360 4096 +#define TWIN_ANGLE_180 (TWIN_ANGLE_360 >> 1) +#define TWIN_ANGLE_90 (TWIN_ANGLE_360 >> 2) +#define TWIN_ANGLE_45 (TWIN_ANGLE_360 >> 3) +#define TWIN_ANGLE_22_5 (TWIN_ANGLE_360 >> 4) +#define TWIN_ANGLE_11_25 (TWIN_ANGLE_360 >> 5) -#define twin_degrees_to_angle(d) ((d) * 512 / 180) +#define twin_degrees_to_angle(d) ((twin_angle_t) ((((int32_t) (d)) * TWIN_ANGLE_360 / 360))) /* * A rectangle @@ -182,6 +182,10 @@ typedef int32_t twin_fixed_t; /* 16.16 format */ #define twin_int_to_fixed(i) ((twin_fixed_t) (i) << 16) +typedef struct _twin_point { + twin_fixed_t x, y; +} twin_point_t; + /* * Place matrices in structures so they can be easily copied */ @@ -333,10 +337,16 @@ twin_matrix_rotate (twin_matrix_t *m, twin_angle_t a); void twin_path_move (twin_path_t *path, twin_fixed_t x, twin_fixed_t y); +void +twin_path_rmove (twin_path_t *path, twin_fixed_t x, twin_fixed_t y); + void twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y); void +twin_path_rdraw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y); + +void twin_path_circle(twin_path_t *path, twin_fixed_t radius); void diff --git a/twin_draw.c b/twin_draw.c index ee634da..c18c4b9 100644 --- a/twin_draw.c +++ b/twin_draw.c @@ -298,8 +298,8 @@ twin_composite (twin_pixmap_t *dst, right = dst->width; if (top < 0) top = 0; - if (top > dst->height) - top = dst->height; + if (bottom > dst->height) + bottom = dst->height; op = comp3[operator][operand_index(src)][operand_index(msk)][dst->format]; if (op) diff --git a/twin_font.c b/twin_font.c index 9beaca5..ba052b3 100644 --- a/twin_font.c +++ b/twin_font.c @@ -34,9 +34,7 @@ #define DBGMSG(x) #endif -#define Scale(f) (((twin_fixed_t) (f) * path->state.font_size) >> 5) -#define ScaleX(x) Scale(x) -#define ScaleY(y) Scale(y) +#define Scale(f) (((twin_fixed_t) (f) * path->state.font_size) >> 6) #define Hint(p) (((p)->state.font_style & TWIN_TEXT_UNHINTED) == 0) @@ -46,18 +44,10 @@ twin_has_ucs4 (twin_ucs4_t ucs4) return ucs4 <= TWIN_FONT_MAX && _twin_glyph_offsets[ucs4] != 0; } -static int -compare_snap (const void *av, const void *bv) -{ - const twin_gfixed_t *a = av; - const twin_gfixed_t *b = bv; - - return (int) (*a - *b); -} - -#define SNAPI(path,p) (Hint(path) ? (((p) + 0x7fff) & ~0xffff) : (p)) -#define SNAPH(path,p) (Hint(path) ? (((p) + 0x3fff) & ~0x7fff) : (p)) +#define SNAPI(p) (((p) + 0x7fff) & ~0xffff) +#define SNAPH(p) (((p) + 0x3fff) & ~0x7fff) +#if 0 static twin_fixed_t _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) { @@ -72,8 +62,8 @@ _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) twin_fixed_t before = Scale(snap[s]); twin_fixed_t after = Scale(snap[s+1]); twin_fixed_t dist = after - before; - twin_fixed_t snap_before = SNAPI(path, before); - twin_fixed_t snap_after = SNAPI(path, after); + twin_fixed_t snap_before = SNAPI(before); + twin_fixed_t snap_after = SNAPI(after); twin_fixed_t move_before = snap_before - before; twin_fixed_t move_after = snap_after - after; twin_fixed_t dist_before = v - before; @@ -92,22 +82,11 @@ _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) DBGMSG (("_snap: %d => %9.4f\n", g, F(v))); return v; } +#endif #define SNAPX(p) _snap (path, p, snap_x, nsnap_x) #define SNAPY(p) _snap (path, p, snap_y, nsnap_y) -static int -_add_snap (twin_gfixed_t *snaps, int nsnap, twin_fixed_t snap) -{ - int s; - - for (s = 0; s < nsnap; s++) - if (snaps[s] == snap) - return nsnap; - snaps[nsnap++] = snap; - return nsnap; -} - static const twin_gpoint_t * _twin_ucs4_base(twin_ucs4_t ucs4) { @@ -116,183 +95,409 @@ _twin_ucs4_base(twin_ucs4_t ucs4) return _twin_glyphs + _twin_glyph_offsets[ucs4]; } -#define TWIN_FONT_BASELINE 9 +static const signed char * +_twin_g_base (twin_ucs4_t ucs4) +{ + if (ucs4 > TWIN_FONT_MAX) ucs4 = 0; + + return _twin_gtable + _twin_g_offsets[ucs4]; +} static twin_fixed_t _twin_pen_size (twin_path_t *path) { twin_fixed_t pen_size; - pen_size = SNAPH(path, path->state.font_size / 24); - if (Hint (path) && pen_size < TWIN_FIXED_HALF) + pen_size = path->state.font_size / 24; + + if (Hint (path)) + { + pen_size = SNAPH(pen_size); + if( pen_size < TWIN_FIXED_HALF) pen_size = TWIN_FIXED_HALF; + } if (path->state.font_style & TWIN_TEXT_BOLD) { - twin_fixed_t pen_add = SNAPH(path, pen_size >> 1); - if (Hint (path) && pen_add == 0) - pen_add = TWIN_FIXED_HALF; + twin_fixed_t pen_add = pen_size >> 1; + + if (Hint (path)) + { + pen_add = SNAPH (pen_add); + if (pen_add == 0) + pen_add = TWIN_FIXED_HALF; + } pen_size += pen_add; } return pen_size; } +#define Margin(pen_size) ((pen_size) * 2) + void twin_text_metrics_ucs4 (twin_path_t *path, twin_ucs4_t ucs4, twin_text_metrics_t *m) { - const twin_gpoint_t *p = _twin_ucs4_base (ucs4); - twin_fixed_t x, y; - twin_fixed_t left, right; - twin_fixed_t top, bottom; + const signed char *g = _twin_g_base (ucs4); twin_fixed_t pen_size = _twin_pen_size (path); - twin_fixed_t baseline = SNAPI(path, Scale(TWIN_FONT_BASELINE)); - int i; - int skip_xi; - int skip_yi; - int next_xi; - int next_yi; + twin_fixed_t left = Scale(twin_glyph_left(g)); + twin_fixed_t right = Scale (twin_glyph_right(g)) + pen_size * 2; + twin_fixed_t ascent = Scale (twin_glyph_ascent(g)) + pen_size * 2; + twin_fixed_t descent = Scale (twin_glyph_descent(g)); + twin_fixed_t font_spacing = path->state.font_size; + twin_fixed_t font_descent = font_spacing / 3; + twin_fixed_t font_ascent = font_spacing - font_descent; + + if (Hint(path)) + { + left = SNAPI(left); + right = SNAPI(right); + ascent = SNAPI(ascent); + descent = SNAPI(descent); + font_descent = SNAPI(font_descent); + font_ascent = SNAPI(font_ascent); + } + m->left_side_bearing = left + Margin(pen_size); + m->right_side_bearing = right + Margin(pen_size); + m->ascent = ascent; + m->descent = descent; + m->width = m->right_side_bearing + Margin(pen_size); + m->font_ascent = font_ascent + Margin(pen_size); + m->font_descent = font_ascent + Margin(pen_size); +} + +#include <stdio.h> + +#define TWIN_MAX_POINTS 50 +#define TWIN_MAX_STROKE 50 + +typedef enum { twin_gmove, twin_gline, twin_gcurve } twin_gcmd_t; + +typedef struct _twin_gop { + twin_gcmd_t cmd; + twin_gpoint_t p[3]; +} twin_gop_t; - left = TWIN_FIXED_MAX; - top = TWIN_FIXED_MAX; - right = TWIN_FIXED_MIN; - bottom = TWIN_FIXED_MIN; - /* - * Locate horizontal and vertical segments - */ - skip_xi = 0; - skip_yi = 0; - for (i = 1; p[i].y != -64; i++) +typedef struct _twin_stroke { + int n; + twin_gpoint_t p[TWIN_MAX_STROKE]; +} twin_stroke_t; + +typedef struct _twin_snap { + int n; + twin_gfixed_t s[TWIN_MAX_POINTS]; +} twin_snap_t; + +typedef struct _twin_glyph { + twin_ucs4_t ucs4; + int offset; + twin_bool_t exists; + twin_gfixed_t left, right, top, bottom; + int n; + twin_stroke_t s[TWIN_MAX_STROKE]; + int nop; + twin_gop_t op[TWIN_MAX_STROKE]; + twin_snap_t snap_x; + twin_snap_t snap_y; +} twin_glyph_t; + +static twin_glyph_t glyphs[0x80]; + +static void +twin_add_snap (twin_snap_t *snap, twin_gfixed_t v) +{ + int n; + + for (n = 0; n < snap->n; n++) { - if (p[i].x == -64) - continue; - x = Scale (p[i].x); - y = Scale (p[i].y); - next_xi = skip_xi; - next_yi = skip_yi; - if (Hint (path) && p[i+1].y != -64 && p[i+1].x != -64) + if (snap->s[n] == v) + return; + if (snap->s[n] > v) + break; + } + memmove (&snap->s[n+1], &snap->s[n], snap->n - n); + snap->s[n] = v; + snap->n++; +} + +static int +twin_n_in_spline (twin_gpoint_t *p, int n) +{ + return 0; +} + +static void +twin_spline_fit (twin_gpoint_t *p, int n, twin_gpoint_t *c1, twin_gpoint_t *c2) +{ +} + +static char * +_ucs4_string (twin_ucs4_t ucs4) +{ + static char buf[10]; + if (ucs4 < ' ' || ucs4 > '~') + { + if (!ucs4) + return "\\0"; + sprintf (buf, "\\0%o", ucs4); + return buf; + } + sprintf (buf, "%c", ucs4); + return buf; +} + +static twin_gfixed_t +px (const twin_gpoint_t *p, int i) +{ + return p[i].x << 1; +} + +static twin_gfixed_t +py (const twin_gpoint_t *p, int i) +{ + return p[i].y << 1; +} + +static void +twin_dump_glyphs (void) +{ + twin_ucs4_t ucs4; + int offset = 0; + int i, j; + twin_gop_t *gop; + + for (ucs4 = 0; ucs4 < 0x80; ucs4++) + { + const twin_gpoint_t *p = _twin_ucs4_base (ucs4); + twin_glyph_t *g = &glyphs[ucs4]; + twin_stroke_t *s; + twin_gfixed_t origin; + twin_gfixed_t left, right, top, bottom; + twin_gfixed_t baseline; + twin_gfixed_t x, y; + twin_bool_t move; + + g->ucs4 = ucs4; + g->n = 0; + + if (ucs4 && p == _twin_glyphs) continue; + + if (p[1].y == -64) { - if (p[i].x == p[i+1].x) + origin = 0; + left = 0; + right = 4; + top = 18; + bottom = 18; + baseline = 18; + } + else + { + origin = 64; + left = 64; + right = -64; + top = 64; + bottom = -64; + baseline = 18; + for (i = 1, move = TWIN_TRUE; p[i].y != -64; i++) { - x = SNAPI(path, x); - skip_xi = i + 2; + if (p[i].x == -64) { move = TWIN_TRUE; continue; } + if (py(p,i) <= baseline && px(p,i) < origin) origin = px(p,i); + if (px(p,i) < left) left = px(p,i); + if (px(p,i) > right) right = px(p,i); + if (py(p,i) < top) top = py(p,i); + if (py(p,i) > bottom) bottom = py(p,i); + move = TWIN_FALSE; } - if (p[i].y == p[i+1].y) + } + left -= origin; + right -= origin;; + bottom -= baseline; + top -= baseline; + + /* + * Convert from hershey format to internal format + */ + for (i = 1, move = TWIN_TRUE; p[i].y != -64; i++) + { + if (p[i].x == -64) { move = TWIN_TRUE; continue; } + + x = px(p,i) - origin; + y = py(p,i) - baseline; + if (move) + if (g->s[g->n].n) + ++g->n; + s = &g->s[g->n]; + s->p[s->n].x = x; + s->p[s->n].y = y; + s->n++; + + move = TWIN_FALSE; + } + if (g->s[g->n].n) + ++g->n; + + g->left = left; + g->right = right; + g->top = top; + g->bottom = bottom; + + /* + * Find snap points + */ + twin_add_snap (&g->snap_x, 0); /* origin */ + twin_add_snap (&g->snap_x, right); /* right */ + + twin_add_snap (&g->snap_y, 0); /* baseline */ + twin_add_snap (&g->snap_y, -15); /* x height */ + twin_add_snap (&g->snap_y, -21); /* cap height */ + + for (i = 0; i < g->n; i++) + { + s = &g->s[i]; + for (j = 0; j < s->n - 1; j++) { - y = SNAPI(path, y); - skip_yi = i + 2; + if (s->p[j].x == s->p[j+1].x) + twin_add_snap (&g->snap_x, s->p[j].x); + if (s->p[j].y == s->p[j+1].y) + twin_add_snap (&g->snap_y, s->p[j].y); } } - if (i >= next_xi) + + /* + * Now convert to gops and try to locate splines + */ + + gop = &g->op[0]; + for (i = 0; i < g->n; i++) { - if (x < left) - left = x; - if (x > right) - right = x; + s = &g->s[i]; + gop->cmd = twin_gmove; + gop->p[0] = s->p[0]; + gop++; + for (j = 0; j < s->n - 1;) + { + int ns = twin_n_in_spline (s->p + j, s->n - j); + + if (ns) + { + twin_spline_fit (s->p + j, ns, + &gop->p[0], &gop->p[1]); + gop->cmd = twin_gcurve; + gop->p[2] = s->p[j + ns - 1]; + gop++; + j += ns; + } + else + { + gop->cmd = twin_gline; + gop->p[0] = s->p[j+1]; + gop++; + j++; + } + } } - if (i >= next_yi) + g->nop = gop - &g->op[0]; + g->exists = TWIN_TRUE; + } + + printf ("const signed char _twin_gtable[] = {\n"); + for (ucs4 = 0; ucs4 < 0x80; ucs4++) + { + twin_glyph_t *g = &glyphs[ucs4]; + + if (!g->exists) continue; + + g->offset = offset; + + printf ("/* 0x%x '%s' */\n", g->ucs4, _ucs4_string (g->ucs4)); + printf (" %d, %d, %d, %d, %d, %d,\n", + g->left, g->right, -g->top, g->bottom, g->snap_x.n, g->snap_y.n); + + offset += 6; + + printf (" "); + for (i = 0; i < g->snap_x.n; i++) + printf (" %d,", g->snap_x.s[i]); + printf (" /* snap_x */\n"); + + offset += g->snap_x.n; + + printf (" "); + for (i = 0; i < g->snap_y.n; i++) + printf (" %d,", g->snap_y.s[i]); + printf (" /* snap_y */\n"); + + offset += g->snap_y.n; + +#define CO(n) gop->p[n].x, gop->p[n].y + for (i = 0; i < g->nop; i++) { - if (y < top) - top = y; - if (y > bottom) - bottom = y; + gop = &g->op[i]; + switch (gop->cmd) { + case twin_gmove: + printf (" 'm', %d, %d,\n", CO(0)); + offset += 3; + break; + case twin_gline: + printf (" 'l', %d, %d,\n", CO(0)); + offset += 3; + break; + case twin_gcurve: + printf (" 'c', %d, %d, %d, %d, %d, %d,\n", + CO(0), CO(1), CO(2)); + offset += 7; + break; + } } + printf (" 'e',\n"); + offset++; } - - left -= pen_size * 2; - right += pen_size * 2; - - if (i == 1) + printf ("};\n\n"); + printf ("const uint16_t _twin_g_offsets[] = {"); + for (ucs4 = 0; ucs4 < 0x80; ucs4++) { - left = Scale(p[0].x); - top = bottom = baseline; - right = Scale(p[0].y); + twin_glyph_t *g = &glyphs[ucs4]; + + if ((ucs4 & 7) == 0) + printf ("\n "); + else + printf (" "); + printf ("%4d,", g->offset); } - m->left_side_bearing = SNAPI(path, -left); - m->right_side_bearing = SNAPI(path,right); - m->width = m->left_side_bearing + m->right_side_bearing; - m->ascent = baseline - SNAPI(path, top); - m->descent = SNAPI(path, bottom) - baseline; - m->font_descent = SNAPI(path, path->state.font_size / 3); - m->font_ascent = SNAPI(path,path->state.font_size) - m->font_descent; + printf ("\n};\n"); + fflush (stdout); + exit (0); } void twin_path_ucs4 (twin_path_t *path, twin_ucs4_t ucs4) { - const twin_gpoint_t *p = _twin_ucs4_base (ucs4); - int i; + const signed char *b = _twin_g_base (ucs4); + const signed char *g = twin_glyph_draw(b); twin_spoint_t origin; - twin_fixed_t xc, yc; - twin_sfixed_t sx, sy; + twin_fixed_t x1, y1, x2, y2, x3, y3; + twin_fixed_t xo, yo; twin_path_t *stroke; twin_path_t *pen; - twin_fixed_t w; - twin_fixed_t x, y; - twin_fixed_t pen_size; + twin_fixed_t pen_size = _twin_pen_size (path); twin_matrix_t pen_matrix; - twin_fixed_t pen_adjust; - twin_gfixed_t snap_x[TWIN_GLYPH_MAX_POINTS]; - twin_gfixed_t snap_y[TWIN_GLYPH_MAX_POINTS]; twin_text_metrics_t metrics; - int nsnap_x = 0, nsnap_y = 0; + if (0) + { + static int been_here = 0; + if (!been_here) { been_here = 1; twin_dump_glyphs (); } + } + twin_text_metrics_ucs4 (path, ucs4, &metrics); origin = _twin_path_current_spoint (path); - if (Hint (path)) - { - nsnap_x = 0; - nsnap_y = 0; - - /* snap left and right boundaries */ - - nsnap_x = _add_snap (snap_x, nsnap_x, p[0].x); - nsnap_x = _add_snap (snap_x, nsnap_x, p[0].y); - - /* snap baseline, x height and cap height */ - nsnap_y = _add_snap (snap_y, nsnap_y, 9); - nsnap_y = _add_snap (snap_y, nsnap_y, -5); - nsnap_y = _add_snap (snap_y, nsnap_y, -12); - - /* - * Locate horizontal and vertical segments - */ - for (i = 1; p[i].y != -64 && p[i+1].y != -64; i++) - { - if (p[i].x == -64 || p[i+1].x == -64) - continue; - if (p[i].x == p[i+1].x) - nsnap_x = _add_snap (snap_x, nsnap_x, p[i].x); - if (p[i].y == p[i+1].y) - nsnap_y = _add_snap (snap_y, nsnap_y, p[i].y); - } - - qsort (snap_x, nsnap_x, sizeof (twin_gfixed_t), compare_snap); - qsort (snap_y, nsnap_y, sizeof (twin_gfixed_t), compare_snap); - - DBGMSG (("snap_x:")); - for (i = 0; i < nsnap_x; i++) - DBGMSG ((" %d", snap_x[i])); - DBGMSG (("\n")); - - DBGMSG (("snap_y:")); - for (i = 0; i < nsnap_y; i++) - DBGMSG ((" %d", snap_y[i])); - DBGMSG (("\n")); - } - stroke = twin_path_create (); - twin_path_set_matrix (stroke, twin_path_current_matrix (path)); - pen_size = _twin_pen_size (path); - - if (Hint (path)) - pen_adjust = pen_size & TWIN_FIXED_HALF; - else - pen_adjust = 0; + twin_path_set_matrix (stroke, twin_path_current_matrix (path)); pen = twin_path_create (); pen_matrix = twin_path_current_matrix (path); @@ -303,35 +508,55 @@ twin_path_ucs4 (twin_path_t *path, twin_ucs4_t ucs4) twin_path_circle (pen, pen_size); - xc = metrics.left_side_bearing + pen_adjust; - yc = SNAPY(TWIN_FONT_BASELINE) + pen_adjust; +#define PX(_x,_y) (origin.x + _twin_matrix_dx (&path->state.matrix, _x, _y)) +#define PY(_x,_y) (origin.y + _twin_matrix_dy (&path->state.matrix, _x, _y)) - for (i = 1; p[i].y != -64; i++) - if (p[i].x == -64) - twin_path_close (stroke); - else - { - x = xc + SNAPX(p[i].x); - y = yc + SNAPY(p[i].y); - + xo = pen_size * 3; + yo = -pen_size; + + for (;;) { + switch (*g++) { + case 'm': + x1 = Scale (*g++) + xo; + y1 = Scale (*g++) + yo; + if (path->state.font_style & TWIN_TEXT_OBLIQUE) + x1 -= y1 >> 2; + _twin_path_smove (stroke, PX(x1,y1), PY(x1,y1)); + continue; + case 'l': + x1 = Scale (*g++) + xo; + y1 = Scale (*g++) + yo; + if (path->state.font_style & TWIN_TEXT_OBLIQUE) + x1 -= y1 >> 2; + _twin_path_sdraw (stroke, PX(x1,y1), PY(x1,y1)); + continue; + case 'c': + x1 = Scale (*g++) + xo; + y1 = Scale (*g++) + yo; + x2 = Scale (*g++) + xo; + y2 = Scale (*g++) + yo; + x3 = Scale (*g++) + xo; + y3 = Scale (*g++) + yo; if (path->state.font_style & TWIN_TEXT_OBLIQUE) - x -= y / 4; - sx = origin.x + _twin_matrix_dx (&path->state.matrix, x, y); - sy = origin.y + _twin_matrix_dy (&path->state.matrix, x, y); - DBGMSG(("x: %9.4f, y: %9.4f -> sx: %9.4f, sy: %9.4f\n", - F(x), F(y), S(sx), S(sy))); - _twin_path_sdraw (stroke, sx, sy); + { + x1 -= y1 >> 2; + x2 -= y2 >> 2; + x3 -= y3 >> 2; + } + _twin_path_scurve (stroke, PX(x1,y1), PY(x1,y1), + PX(x2,y2), PY(x2,y2), PX(x3,y3), PY(x3,y3)); + continue; + case 'e': + break; } + break; + } twin_path_convolve (path, stroke, pen); twin_path_destroy (stroke); twin_path_destroy (pen); - w = metrics.width; - - _twin_path_smove (path, - origin.x + _twin_matrix_dx (&path->state.matrix, w, 0), - origin.y + _twin_matrix_dy (&path->state.matrix, w, 0)); + _twin_path_smove (path, PX(metrics.width, 0), PY(metrics.width,0)); } twin_fixed_t @@ -454,20 +679,23 @@ twin_text_metrics_utf8 (twin_path_t *path, { twin_text_metrics_ucs4 (path, ucs4, &c); if (first) + { *m = c; + first = TWIN_FALSE; + } else { c.left_side_bearing += w; c.right_side_bearing += w; c.width += w; - if (c.left_side_bearing > m->left_side_bearing) + if (c.left_side_bearing < m->left_side_bearing) m->left_side_bearing = c.left_side_bearing; if (c.right_side_bearing > m->right_side_bearing) m->right_side_bearing = c.right_side_bearing; if (c.width > m->width) m->width = c.width; - if (c.ascent < m->ascent) + if (c.ascent > m->ascent) m->ascent = c.ascent; if (c.descent > m->descent) m->descent = c.descent; diff --git a/twin_glyphs.c b/twin_glyphs.c index 0c3c598..1dfe1ab 100644 --- a/twin_glyphs.c +++ b/twin_glyphs.c @@ -446,3 +446,1567 @@ const uint16_t _twin_glyph_offsets[] = { /* 0x78 */ 1233, 1240, 1251, 1261, 1274, 1278, 1291, 0, }; + +const signed char _twin_gtable[] = { +/* 0x0 '\0' */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, -2, + 'l', 0, -42, + 'l', 24, -42, + 'l', 24, 0, + 'l', 0, 0, + 'e', +/* 0x20 ' ' */ + 0, 4, 0, 0, 2, 3, + -128, 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'e', +/* 0x21 '!' */ + 0, 4, 42, 0, 3, 3, + 0, 2, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -42, + 'l', 2, -14, + 'm', 2, -4, + 'l', 0, -2, + 'l', 2, 0, + 'l', 4, -2, + 'l', 2, -4, + 'e', +/* 0x22 '"' */ + 0, 16, 42, -28, 2, 3, + 0, 16, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, -28, + 'm', 16, -42, + 'l', 16, -28, + 'e', +/* 0x23 '#' */ + 0, 30, 50, 14, 2, 5, + 0, 30, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 16, -50, + 'l', 2, 14, + 'm', 28, -50, + 'l', 14, 14, + 'm', 2, -24, + 'l', 30, -24, + 'm', 0, -12, + 'l', 28, -12, + 'e', +/* 0x24 '$' */ + 0, 28, 50, 8, 4, 4, + 0, 10, 18, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 10, -50, + 'l', 10, 8, + 'm', 18, -50, + 'l', 18, 8, + 'm', 28, -36, + 'l', 24, -40, + 'l', 18, -42, + 'l', 10, -42, + 'l', 4, -40, + 'l', 0, -36, + 'l', 0, -32, + 'l', 2, -28, + 'l', 4, -26, + 'l', 8, -24, + 'l', 20, -20, + 'l', 24, -18, + 'l', 26, -16, + 'l', 28, -12, + 'l', 28, -6, + 'l', 24, -2, + 'l', 18, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 0, -6, + 'e', +/* 0x25 '%' */ + 0, 36, 42, 0, 4, 7, + 0, 14, 22, 36, /* snap_x */ + -42, -38, -28, -21, -15, -14, 0, /* snap_y */ + 'm', 36, -42, + 'l', 0, 0, + 'm', 10, -42, + 'l', 14, -38, + 'l', 14, -34, + 'l', 12, -30, + 'l', 8, -28, + 'l', 4, -28, + 'l', 0, -32, + 'l', 0, -36, + 'l', 2, -40, + 'l', 6, -42, + 'l', 10, -42, + 'l', 14, -40, + 'l', 20, -38, + 'l', 26, -38, + 'l', 32, -40, + 'l', 36, -42, + 'm', 28, -14, + 'l', 24, -12, + 'l', 22, -8, + 'l', 22, -4, + 'l', 26, 0, + 'l', 30, 0, + 'l', 34, -2, + 'l', 36, -6, + 'l', 36, -10, + 'l', 32, -14, + 'l', 28, -14, + 'e', +/* 0x26 '&' */ + 0, 40, 42, 0, 4, 4, + 0, 10, 22, 40, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 40, -24, + 'l', 40, -26, + 'l', 38, -28, + 'l', 36, -28, + 'l', 34, -26, + 'l', 32, -22, + 'l', 28, -12, + 'l', 24, -6, + 'l', 20, -2, + 'l', 16, 0, + 'l', 8, 0, + 'l', 4, -2, + 'l', 2, -4, + 'l', 0, -8, + 'l', 0, -12, + 'l', 2, -16, + 'l', 4, -18, + 'l', 18, -26, + 'l', 20, -28, + 'l', 22, -32, + 'l', 22, -36, + 'l', 20, -40, + 'l', 16, -42, + 'l', 12, -40, + 'l', 10, -36, + 'l', 10, -32, + 'l', 12, -26, + 'l', 16, -20, + 'l', 26, -6, + 'l', 30, -2, + 'l', 34, 0, + 'l', 38, 0, + 'l', 40, -2, + 'l', 40, -4, + 'e', +/* 0x27 ''' */ + 0, 4, 42, -30, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -38, + 'l', 0, -40, + 'l', 2, -42, + 'l', 4, -40, + 'l', 4, -36, + 'l', 2, -32, + 'l', 0, -30, + 'e', +/* 0x28 '(' */ + 0, 14, 50, 14, 2, 3, + 0, 14, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 14, -50, + 'l', 10, -46, + 'l', 6, -40, + 'l', 2, -32, + 'l', 0, -22, + 'l', 0, -14, + 'l', 2, -4, + 'l', 6, 4, + 'l', 10, 10, + 'l', 14, 14, + 'e', +/* 0x29 ')' */ + 0, 14, 50, 14, 2, 3, + 0, 14, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', 4, -46, + 'l', 8, -40, + 'l', 12, -32, + 'l', 14, -22, + 'l', 14, -14, + 'l', 12, -4, + 'l', 8, 4, + 'l', 4, 10, + 'l', 0, 14, + 'e', +/* 0x2a '*' */ + 0, 20, 30, -6, 3, 3, + 0, 10, 20, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 10, -30, + 'l', 10, -6, + 'm', 0, -24, + 'l', 20, -12, + 'm', 20, -24, + 'l', 0, -12, + 'e', +/* 0x2b '+' */ + 0, 36, 36, 0, 3, 4, + 0, 18, 36, /* snap_x */ + -21, -18, -15, 0, /* snap_y */ + 'm', 18, -36, + 'l', 18, 0, + 'm', 0, -18, + 'l', 36, -18, + 'e', +/* 0x2c ',' */ + 0, 4, 4, 8, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 4, -2, + 'l', 2, 0, + 'l', 0, -2, + 'l', 2, -4, + 'l', 4, -2, + 'l', 4, 2, + 'l', 2, 6, + 'l', 0, 8, + 'e', +/* 0x2d '-' */ + 0, 36, 18, -18, 2, 4, + 0, 36, /* snap_x */ + -21, -18, -15, 0, /* snap_y */ + 'm', 0, -18, + 'l', 36, -18, + 'e', +/* 0x2e '.' */ + 0, 4, 4, 0, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -4, + 'l', 0, -2, + 'l', 2, 0, + 'l', 4, -2, + 'l', 2, -4, + 'e', +/* 0x2f '/' */ + -36, 0, 50, 14, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', -36, 14, + 'e', +/* 0x30 '0' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 12, -42, + 'l', 6, -40, + 'l', 2, -34, + 'l', 0, -24, + 'l', 0, -18, + 'l', 2, -8, + 'l', 6, -2, + 'l', 12, 0, + 'l', 16, 0, + 'l', 22, -2, + 'l', 26, -8, + 'l', 28, -18, + 'l', 28, -24, + 'l', 26, -34, + 'l', 22, -40, + 'l', 16, -42, + 'l', 12, -42, + 'e', +/* 0x31 '1' */ + 0, 10, 42, 0, 2, 3, + 0, 10, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -34, + 'l', 4, -36, + 'l', 10, -42, + 'l', 10, 0, + 'e', +/* 0x32 '2' */ + 0, 28, 42, 0, 4, 4, + 0, 2, 26, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 2, -32, + 'l', 2, -34, + 'l', 4, -38, + 'l', 6, -40, + 'l', 10, -42, + 'l', 18, -42, + 'l', 22, -40, + 'l', 24, -38, + 'l', 26, -34, + 'l', 26, -30, + 'l', 24, -26, + 'l', 20, -20, + 'l', 0, 0, + 'l', 28, 0, + 'e', +/* 0x33 '3' */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -26, -21, -15, 0, /* snap_y */ + 'm', 4, -42, + 'l', 26, -42, + 'l', 14, -26, + 'l', 20, -26, + 'l', 24, -24, + 'l', 26, -22, + 'l', 28, -16, + 'l', 28, -12, + 'l', 26, -6, + 'l', 22, -2, + 'l', 16, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 2, -4, + 'l', 0, -8, + 'e', +/* 0x34 '4' */ + 0, 30, 42, 0, 3, 4, + 0, 20, 30, /* snap_x */ + -21, -15, -14, 0, /* snap_y */ + 'm', 20, -42, + 'l', 0, -14, + 'l', 30, -14, + 'm', 20, -42, + 'l', 20, 0, + 'e', +/* 0x35 '5' */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -28, -21, -15, 0, /* snap_y */ + 'm', 24, -42, + 'l', 4, -42, + 'l', 2, -24, + 'l', 4, -26, + 'l', 10, -28, + 'l', 16, -28, + 'l', 22, -26, + 'l', 26, -22, + 'l', 28, -16, + 'l', 28, -12, + 'l', 26, -6, + 'l', 22, -2, + 'l', 16, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 2, -4, + 'l', 0, -8, + 'e', +/* 0x36 '6' */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -26, -21, -15, 0, /* snap_y */ + 'm', 24, -36, + 'l', 22, -40, + 'l', 16, -42, + 'l', 12, -42, + 'l', 6, -40, + 'l', 2, -34, + 'l', 0, -24, + 'l', 0, -14, + 'l', 2, -6, + 'l', 6, -2, + 'l', 12, 0, + 'l', 14, 0, + 'l', 20, -2, + 'l', 24, -6, + 'l', 26, -12, + 'l', 26, -14, + 'l', 24, -20, + 'l', 20, -24, + 'l', 14, -26, + 'l', 12, -26, + 'l', 6, -24, + 'l', 2, -20, + 'l', 0, -14, + 'e', +/* 0x37 '7' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 28, -42, + 'l', 8, 0, + 'm', 0, -42, + 'l', 28, -42, + 'e', +/* 0x38 '8' */ + 0, 28, 42, 0, 4, 4, + 0, 2, 26, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 10, -42, + 'l', 4, -40, + 'l', 2, -36, + 'l', 2, -32, + 'l', 4, -28, + 'l', 8, -26, + 'l', 16, -24, + 'l', 22, -22, + 'l', 26, -18, + 'l', 28, -14, + 'l', 28, -8, + 'l', 26, -4, + 'l', 24, -2, + 'l', 18, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 2, -4, + 'l', 0, -8, + 'l', 0, -14, + 'l', 2, -18, + 'l', 6, -22, + 'l', 12, -24, + 'l', 20, -26, + 'l', 24, -28, + 'l', 26, -32, + 'l', 26, -36, + 'l', 24, -40, + 'l', 18, -42, + 'l', 10, -42, + 'e', +/* 0x39 '9' */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -21, -16, -15, 0, /* snap_y */ + 'm', 26, -28, + 'l', 24, -22, + 'l', 20, -18, + 'l', 14, -16, + 'l', 12, -16, + 'l', 6, -18, + 'l', 2, -22, + 'l', 0, -28, + 'l', 0, -30, + 'l', 2, -36, + 'l', 6, -40, + 'l', 12, -42, + 'l', 14, -42, + 'l', 20, -40, + 'l', 24, -36, + 'l', 26, -28, + 'l', 26, -18, + 'l', 24, -8, + 'l', 20, -2, + 'l', 14, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 2, -6, + 'e', +/* 0x3a ':' */ + 0, 4, 28, 0, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -28, + 'l', 0, -26, + 'l', 2, -24, + 'l', 4, -26, + 'l', 2, -28, + 'm', 2, -4, + 'l', 0, -2, + 'l', 2, 0, + 'l', 4, -2, + 'l', 2, -4, + 'e', +/* 0x3b ';' */ + 0, 4, 28, 8, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 2, -28, + 'l', 0, -26, + 'l', 2, -24, + 'l', 4, -26, + 'l', 2, -28, + 'm', 4, -2, + 'l', 2, 0, + 'l', 0, -2, + 'l', 2, -4, + 'l', 4, -2, + 'l', 4, 2, + 'l', 2, 6, + 'l', 0, 8, + 'e', +/* 0x3c '<' */ + 0, 32, 36, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 32, -36, + 'l', 0, -18, + 'l', 32, 0, + 'e', +/* 0x3d '=' */ + 0, 36, 24, -12, 2, 5, + 0, 36, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 0, -24, + 'l', 36, -24, + 'm', 0, -12, + 'l', 36, -12, + 'e', +/* 0x3e '>' */ + 0, 32, 36, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -36, + 'l', 32, -18, + 'l', 0, 0, + 'e', +/* 0x3f '?' */ + 0, 24, 42, 0, 3, 4, + 0, 12, 24, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, -32, + 'l', 0, -34, + 'l', 2, -38, + 'l', 4, -40, + 'l', 8, -42, + 'l', 16, -42, + 'l', 20, -40, + 'l', 22, -38, + 'l', 24, -34, + 'l', 24, -30, + 'l', 22, -26, + 'l', 20, -24, + 'l', 12, -20, + 'l', 12, -14, + 'm', 12, -4, + 'l', 10, -2, + 'l', 12, 0, + 'l', 14, -2, + 'l', 12, -4, + 'e', +/* 0x40 '@' */ + 0, 42, 42, 0, 1, 6, + 30, /* snap_x */ + -42, -32, -21, -15, -10, 0, /* snap_y */ + 'm', 30, -26, + 'l', 28, -30, + 'l', 24, -32, + 'l', 18, -32, + 'l', 14, -30, + 'l', 12, -28, + 'l', 10, -22, + 'l', 10, -16, + 'l', 12, -12, + 'l', 16, -10, + 'l', 22, -10, + 'l', 26, -12, + 'l', 28, -16, + 'm', 18, -32, + 'l', 14, -28, + 'l', 12, -22, + 'l', 12, -16, + 'l', 14, -12, + 'l', 16, -10, + 'm', 30, -32, + 'l', 28, -16, + 'l', 28, -12, + 'l', 32, -10, + 'l', 36, -10, + 'l', 40, -14, + 'l', 42, -20, + 'l', 42, -24, + 'l', 40, -30, + 'l', 38, -34, + 'l', 34, -38, + 'l', 30, -40, + 'l', 24, -42, + 'l', 18, -42, + 'l', 12, -40, + 'l', 8, -38, + 'l', 4, -34, + 'l', 2, -30, + 'l', 0, -24, + 'l', 0, -18, + 'l', 2, -12, + 'l', 4, -8, + 'l', 8, -4, + 'l', 12, -2, + 'l', 18, 0, + 'l', 24, 0, + 'l', 30, -2, + 'l', 34, -4, + 'l', 36, -6, + 'm', 32, -32, + 'l', 30, -16, + 'l', 30, -12, + 'l', 32, -10, + 'e', +/* 0x41 'A' */ + 0, 32, 42, 0, 2, 4, + 0, 32, /* snap_x */ + -21, -15, -14, 0, /* snap_y */ + 'm', 16, -42, + 'l', 0, 0, + 'm', 16, -42, + 'l', 32, 0, + 'm', 6, -14, + 'l', 26, -14, + 'e', +/* 0x42 'B' */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 18, -42, + 'l', 24, -40, + 'l', 26, -38, + 'l', 28, -34, + 'l', 28, -30, + 'l', 26, -26, + 'l', 24, -24, + 'l', 18, -22, + 'm', 0, -22, + 'l', 18, -22, + 'l', 24, -20, + 'l', 26, -18, + 'l', 28, -14, + 'l', 28, -8, + 'l', 26, -4, + 'l', 24, -2, + 'l', 18, 0, + 'l', 0, 0, + 'e', +/* 0x43 'C' */ + 0, 30, 42, 0, 2, 4, + 0, 30, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 30, -32, + 'l', 28, -36, + 'l', 24, -40, + 'l', 20, -42, + 'l', 12, -42, + 'l', 8, -40, + 'l', 4, -36, + 'l', 2, -32, + 'l', 0, -26, + 'l', 0, -16, + 'l', 2, -10, + 'l', 4, -6, + 'l', 8, -2, + 'l', 12, 0, + 'l', 20, 0, + 'l', 24, -2, + 'l', 28, -6, + 'l', 30, -10, + 'e', +/* 0x44 'D' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 14, -42, + 'l', 20, -40, + 'l', 24, -36, + 'l', 26, -32, + 'l', 28, -26, + 'l', 28, -16, + 'l', 26, -10, + 'l', 24, -6, + 'l', 20, -2, + 'l', 14, 0, + 'l', 0, 0, + 'e', +/* 0x45 'E' */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 26, -42, + 'm', 0, -22, + 'l', 16, -22, + 'm', 0, 0, + 'l', 26, 0, + 'e', +/* 0x46 'F' */ + 0, 26, 42, 0, 2, 5, + 0, 26, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 26, -42, + 'm', 0, -22, + 'l', 16, -22, + 'e', +/* 0x47 'G' */ + 0, 30, 42, 0, 2, 5, + 0, 30, /* snap_x */ + -42, -21, -16, -15, 0, /* snap_y */ + 'm', 30, -32, + 'l', 28, -36, + 'l', 24, -40, + 'l', 20, -42, + 'l', 12, -42, + 'l', 8, -40, + 'l', 4, -36, + 'l', 2, -32, + 'l', 0, -26, + 'l', 0, -16, + 'l', 2, -10, + 'l', 4, -6, + 'l', 8, -2, + 'l', 12, 0, + 'l', 20, 0, + 'l', 24, -2, + 'l', 28, -6, + 'l', 30, -10, + 'l', 30, -16, + 'm', 20, -16, + 'l', 30, -16, + 'e', +/* 0x48 'H' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 28, -42, + 'l', 28, 0, + 'm', 0, -22, + 'l', 28, -22, + 'e', +/* 0x49 'I' */ + 0, 0, 42, 0, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'e', +/* 0x4a 'J' */ + 0, 20, 42, 0, 2, 3, + 0, 20, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 20, -42, + 'l', 20, -10, + 'l', 18, -4, + 'l', 16, -2, + 'l', 12, 0, + 'l', 8, 0, + 'l', 4, -2, + 'l', 2, -4, + 'l', 0, -10, + 'l', 0, -14, + 'e', +/* 0x4b 'K' */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 28, -42, + 'l', 0, -14, + 'm', 10, -24, + 'l', 28, 0, + 'e', +/* 0x4c 'L' */ + 0, 24, 42, 0, 2, 3, + 0, 24, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, 0, + 'l', 24, 0, + 'e', +/* 0x4d 'M' */ + 0, 32, 42, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 16, 0, + 'm', 32, -42, + 'l', 16, 0, + 'm', 32, -42, + 'l', 32, 0, + 'e', +/* 0x4e 'N' */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 28, 0, + 'm', 28, -42, + 'l', 28, 0, + 'e', +/* 0x4f 'O' */ + 0, 32, 42, 0, 2, 4, + 0, 32, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 12, -42, + 'l', 8, -40, + 'l', 4, -36, + 'l', 2, -32, + 'l', 0, -26, + 'l', 0, -16, + 'l', 2, -10, + 'l', 4, -6, + 'l', 8, -2, + 'l', 12, 0, + 'l', 20, 0, + 'l', 24, -2, + 'l', 28, -6, + 'l', 30, -10, + 'l', 32, -16, + 'l', 32, -26, + 'l', 30, -32, + 'l', 28, -36, + 'l', 24, -40, + 'l', 20, -42, + 'l', 12, -42, + 'e', +/* 0x50 'P' */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -21, -20, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 18, -42, + 'l', 24, -40, + 'l', 26, -38, + 'l', 28, -34, + 'l', 28, -28, + 'l', 26, -24, + 'l', 24, -22, + 'l', 18, -20, + 'l', 0, -20, + 'e', +/* 0x51 'Q' */ + 0, 32, 42, 4, 2, 4, + 0, 32, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 12, -42, + 'l', 8, -40, + 'l', 4, -36, + 'l', 2, -32, + 'l', 0, -26, + 'l', 0, -16, + 'l', 2, -10, + 'l', 4, -6, + 'l', 8, -2, + 'l', 12, 0, + 'l', 20, 0, + 'l', 24, -2, + 'l', 28, -6, + 'l', 30, -10, + 'l', 32, -16, + 'l', 32, -26, + 'l', 30, -32, + 'l', 28, -36, + 'l', 24, -40, + 'l', 20, -42, + 'l', 12, -42, + 'm', 18, -8, + 'l', 30, 4, + 'e', +/* 0x52 'R' */ + 0, 28, 42, 0, 2, 5, + 0, 28, /* snap_x */ + -42, -22, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 18, -42, + 'l', 24, -40, + 'l', 26, -38, + 'l', 28, -34, + 'l', 28, -30, + 'l', 26, -26, + 'l', 24, -24, + 'l', 18, -22, + 'l', 0, -22, + 'm', 14, -22, + 'l', 28, 0, + 'e', +/* 0x53 'S' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 28, -36, + 'l', 24, -40, + 'l', 18, -42, + 'l', 10, -42, + 'l', 4, -40, + 'l', 0, -36, + 'l', 0, -32, + 'l', 2, -28, + 'l', 4, -26, + 'l', 8, -24, + 'l', 20, -20, + 'l', 24, -18, + 'l', 26, -16, + 'l', 28, -12, + 'l', 28, -6, + 'l', 24, -2, + 'l', 18, 0, + 'l', 10, 0, + 'l', 4, -2, + 'l', 0, -6, + 'e', +/* 0x54 'T' */ + 0, 28, 42, 0, 3, 4, + 0, 14, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 14, -42, + 'l', 14, 0, + 'm', 0, -42, + 'l', 28, -42, + 'e', +/* 0x55 'U' */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 12, 0, + 'l', 16, 0, + 'l', 22, -2, + 'l', 26, -6, + 'l', 28, -12, + 'l', 28, -42, + 'e', +/* 0x56 'V' */ + 0, 32, 42, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 16, 0, + 'm', 32, -42, + 'l', 16, 0, + 'e', +/* 0x57 'W' */ + 0, 40, 42, 0, 2, 3, + 0, 40, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 10, 0, + 'm', 20, -42, + 'l', 10, 0, + 'm', 20, -42, + 'l', 30, 0, + 'm', 40, -42, + 'l', 30, 0, + 'e', +/* 0x58 'X' */ + 0, 28, 42, 0, 2, 3, + 0, 28, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 28, 0, + 'm', 28, -42, + 'l', 0, 0, + 'e', +/* 0x59 'Y' */ + 0, 32, 42, 0, 3, 3, + 0, 16, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 16, -22, + 'l', 16, 0, + 'm', 32, -42, + 'l', 16, -22, + 'e', +/* 0x5a 'Z' */ + 0, 28, 42, 0, 2, 4, + 0, 28, /* snap_x */ + -42, -21, -15, 0, /* snap_y */ + 'm', 28, -42, + 'l', 0, 0, + 'm', 0, -42, + 'l', 28, -42, + 'm', 0, 0, + 'l', 28, 0, + 'e', +/* 0x5b '[' */ + 0, 14, 44, 0, 2, 4, + 0, 14, /* snap_x */ + -44, -21, -15, 0, /* snap_y */ + 'm', 14, -44, + 'l', 0, -44, + 'l', 0, 0, + 'l', 14, 0, + 'e', +/* 0x5c '\' */ + 0, 36, 50, 14, 2, 3, + 0, 36, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', 36, 14, + 'e', +/* 0x5d ']' */ + 0, 14, 44, 0, 2, 4, + 0, 14, /* snap_x */ + -44, -21, -15, 0, /* snap_y */ + 'm', 0, -44, + 'l', 14, -44, + 'l', 14, 0, + 'l', 0, 0, + 'e', +/* 0x5e '^' */ + 0, 32, 46, -18, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 16, -46, + 'l', 0, -18, + 'm', 16, -46, + 'l', 32, -18, + 'e', +/* 0x5f '_' */ + 0, 36, 0, 0, 2, 3, + 0, 36, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, 0, + 'l', 36, 0, + 'e', +/* 0x60 '`' */ + 0, 4, 42, -30, 2, 3, + 0, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 4, -42, + 'l', 2, -40, + 'l', 0, -36, + 'l', 0, -32, + 'l', 2, -30, + 'l', 4, -32, + 'l', 2, -34, + 'e', +/* 0x61 'a' */ + 0, 24, 28, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -28, + 'l', 24, 0, + 'm', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x62 'b' */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -22, + 'l', 4, -26, + 'l', 8, -28, + 'l', 14, -28, + 'l', 18, -26, + 'l', 22, -22, + 'l', 24, -16, + 'l', 24, -12, + 'l', 22, -6, + 'l', 18, -2, + 'l', 14, 0, + 'l', 8, 0, + 'l', 4, -2, + 'l', 0, -6, + 'e', +/* 0x63 'c' */ + 0, 24, 28, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x64 'd' */ + 0, 24, 42, 0, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -42, + 'l', 24, 0, + 'm', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x65 'e' */ + 0, 24, 28, 0, 2, 5, + 0, 24, /* snap_x */ + -28, -21, -16, -15, 0, /* snap_y */ + 'm', 0, -16, + 'l', 24, -16, + 'l', 24, -20, + 'l', 22, -24, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x66 'f' */ + 0, 16, 42, 0, 3, 5, + 0, 6, 16, /* snap_x */ + -42, -28, -21, -15, 0, /* snap_y */ + 'm', 16, -42, + 'l', 12, -42, + 'l', 8, -40, + 'l', 6, -34, + 'l', 6, 0, + 'm', 0, -28, + 'l', 14, -28, + 'e', +/* 0x67 'g' */ + 0, 24, 28, 14, 2, 5, + 0, 24, /* snap_x */ + -28, -21, -15, 0, 14, /* snap_y */ + 'm', 24, -28, + 'l', 24, 4, + 'l', 22, 10, + 'l', 20, 12, + 'l', 16, 14, + 'l', 10, 14, + 'l', 6, 12, + 'm', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x68 'h' */ + 0, 22, 42, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 0, -20, + 'l', 6, -26, + 'l', 10, -28, + 'l', 16, -28, + 'l', 20, -26, + 'l', 22, -20, + 'l', 22, 0, + 'e', +/* 0x69 'i' */ + 0, 4, 44, 0, 3, 3, + 0, 2, 4, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 2, -40, + 'l', 4, -42, + 'l', 2, -44, + 'l', 0, -42, + 'm', 2, -28, + 'l', 2, 0, + 'e', +/* 0x6a 'j' */ + -8, 4, 44, 14, 3, 4, + 0, 2, 4, /* snap_x */ + -21, -15, 0, 14, /* snap_y */ + 'm', 0, -42, + 'l', 2, -40, + 'l', 4, -42, + 'l', 2, -44, + 'l', 0, -42, + 'm', 2, -28, + 'l', 2, 6, + 'l', 0, 12, + 'l', -4, 14, + 'l', -8, 14, + 'e', +/* 0x6b 'k' */ + 0, 22, 42, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'm', 20, -28, + 'l', 0, -8, + 'm', 8, -16, + 'l', 22, 0, + 'e', +/* 0x6c 'l' */ + 0, 0, 42, 0, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -42, + 'l', 0, 0, + 'e', +/* 0x6d 'm' */ + 0, 44, 28, 0, 3, 4, + 0, 22, 44, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -20, + 'l', 6, -26, + 'l', 10, -28, + 'l', 16, -28, + 'l', 20, -26, + 'l', 22, -20, + 'l', 22, 0, + 'm', 22, -20, + 'l', 28, -26, + 'l', 32, -28, + 'l', 38, -28, + 'l', 42, -26, + 'l', 44, -20, + 'l', 44, 0, + 'e', +/* 0x6e 'n' */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -20, + 'l', 6, -26, + 'l', 10, -28, + 'l', 16, -28, + 'l', 20, -26, + 'l', 22, -20, + 'l', 22, 0, + 'e', +/* 0x6f 'o' */ + 0, 26, 28, 0, 2, 4, + 0, 26, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ +#define DX (6) +#define DY (9) +#if 1 + 'm', 13, -28, + 'c', 13-DX, -28, + 0, -14-DY, + 0, -14, +#else + 'm', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, +#endif +#if 1 + 'c', 0, -14+DY, + 13-DX, 0, + 13, 0, +#else + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, +#endif +#if 1 + 'c', 13+DX, 0, + 26, -14+DY, + 26, -14, +#else + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'l', 26, -12, +#endif +#if 1 + 'c', 26, -14-DY, + 13+DX, -28, + 13, -28, +#else + 'l', 26, -16, + 'l', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, +#endif + 'e', +#if 1 + 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', + 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', +#endif +/* 0x70 'p' */ + 0, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 14, + 'm', 0, -22, + 'l', 4, -26, + 'l', 8, -28, + 'l', 14, -28, + 'l', 18, -26, + 'l', 22, -22, + 'l', 24, -16, + 'l', 24, -12, + 'l', 22, -6, + 'l', 18, -2, + 'l', 14, 0, + 'l', 8, 0, + 'l', 4, -2, + 'l', 0, -6, + 'e', +/* 0x71 'q' */ + 0, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 24, -28, + 'l', 24, 14, + 'm', 24, -22, + 'l', 20, -26, + 'l', 16, -28, + 'l', 10, -28, + 'l', 6, -26, + 'l', 2, -22, + 'l', 0, -16, + 'l', 0, -12, + 'l', 2, -6, + 'l', 6, -2, + 'l', 10, 0, + 'l', 16, 0, + 'l', 20, -2, + 'l', 24, -6, + 'e', +/* 0x72 'r' */ + 0, 16, 28, 0, 2, 4, + 0, 16, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, 0, + 'm', 0, -16, + 'l', 2, -22, + 'l', 6, -26, + 'l', 10, -28, + 'l', 16, -28, + 'e', +/* 0x73 's' */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 22, -22, + 'l', 20, -26, + 'l', 14, -28, + 'l', 8, -28, + 'l', 2, -26, + 'l', 0, -22, + 'l', 2, -18, + 'l', 6, -16, + 'l', 16, -14, + 'l', 20, -12, + 'l', 22, -8, + 'l', 22, -6, + 'l', 20, -2, + 'l', 14, 0, + 'l', 8, 0, + 'l', 2, -2, + 'l', 0, -6, + 'e', +/* 0x74 't' */ + 0, 16, 42, 0, 3, 4, + 0, 6, 16, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 6, -42, + 'l', 6, -8, + 'l', 8, -2, + 'l', 12, 0, + 'l', 16, 0, + 'm', 0, -28, + 'l', 14, -28, + 'e', +/* 0x75 'u' */ + 0, 22, 28, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 0, -8, + 'l', 2, -2, + 'l', 6, 0, + 'l', 12, 0, + 'l', 16, -2, + 'l', 22, -8, + 'm', 22, -28, + 'l', 22, 0, + 'e', +/* 0x76 'v' */ + 0, 24, 28, 0, 2, 3, + 0, 24, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 12, 0, + 'm', 24, -28, + 'l', 12, 0, + 'e', +/* 0x77 'w' */ + 0, 32, 28, 0, 2, 3, + 0, 32, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 8, 0, + 'm', 16, -28, + 'l', 8, 0, + 'm', 16, -28, + 'l', 24, 0, + 'm', 32, -28, + 'l', 24, 0, + 'e', +/* 0x78 'x' */ + 0, 22, 28, 0, 2, 3, + 0, 22, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -28, + 'l', 22, 0, + 'm', 22, -28, + 'l', 0, 0, + 'e', +/* 0x79 'y' */ + -2, 24, 28, 14, 2, 4, + 0, 24, /* snap_x */ + -21, -15, 0, 14, /* snap_y */ + 'm', 0, -28, + 'l', 12, 0, + 'm', 24, -28, + 'l', 12, 0, + 'l', 8, 8, + 'l', 4, 12, + 'l', 0, 14, + 'l', -2, 14, + 'e', +/* 0x7a 'z' */ + 0, 22, 28, 0, 2, 4, + 0, 22, /* snap_x */ + -28, -21, -15, 0, /* snap_y */ + 'm', 22, -28, + 'l', 0, 0, + 'm', 0, -28, + 'l', 22, -28, + 'm', 0, 0, + 'l', 22, 0, + 'e', +/* 0x7b '{' */ + 0, 16, 44, 0, 3, 5, + 0, 6, 16, /* snap_x */ + -44, -24, -21, -15, 0, /* snap_y */ + 'm', 16, -44, + 'l', 12, -44, + 'l', 8, -42, + 'l', 6, -36, + 'l', 6, -24, + 'l', 0, -24, + 'l', 6, -24, + 'l', 6, -8, + 'l', 8, -2, + 'l', 12, 0, + 'l', 16, 0, + 'e', +/* 0x7c '|' */ + 0, 0, 50, 14, 1, 3, + 0, /* snap_x */ + -21, -15, 0, /* snap_y */ + 'm', 0, -50, + 'l', 0, 14, + 'e', +/* 0x7d '}' */ + 0, 16, 44, 0, 3, 5, + 0, 10, 16, /* snap_x */ + -44, -24, -21, -15, 0, /* snap_y */ + 'm', 0, -44, + 'l', 4, -44, + 'l', 8, -42, + 'l', 10, -36, + 'l', 10, -24, + 'l', 16, -24, + 'l', 10, -24, + 'l', 10, -8, + 'l', 8, -2, + 'l', 4, 0, + 'l', 0, 0, + 'e', +/* 0x7e '~' */ + 0, 36, 24, -12, 2, 5, + 0, 36, /* snap_x */ + -24, -21, -15, -12, 0, /* snap_y */ + 'm', 0, -14, + 'l', 0, -16, + 'l', 2, -22, + 'l', 6, -24, + 'l', 10, -24, + 'l', 14, -22, + 'l', 22, -14, + 'l', 26, -12, + 'l', 30, -12, + 'l', 34, -14, + 'l', 36, -20, + 'l', 36, -22, + 'e', +}; + +const uint16_t _twin_g_offsets[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 40, 74, 98, 136, 223, 328, 445, + 478, 520, 562, 593, 619, 655, 674, 701, + 718, 782, 806, 863, 922, 951, 1016, 1099, + 1124, 1226, 1309, 1351, 1402, 1423, 1449, 1470, + 1541, 1711, 1742, 1819, 1886, 1941, 1979, 2011, + 2088, 2119, 2136, 2178, 2208, 2232, 2268, 2298, + 2374, 2424, 2506, 2562, 2635, 2661, 2703, 2727, + 2763, 2787, 2815, 2846, 2871, 2889, 2914, 2938, + 2956, 2989, 3050, 3111, 3166, 3227, 3292, 3328, + 3405, 3445, 3479, 3523, 3553, 3570, 3632, 3672, + 3736, 3797, 3858, 3892, 3956, 3991, 4030, 4054, + 4090, 4114, 4151, 4182, 4230, 4247, 4295, 0, +}; diff --git a/twin_matrix.c b/twin_matrix.c index 618b311..0de1572 100644 --- a/twin_matrix.c +++ b/twin_matrix.c @@ -119,6 +119,21 @@ _twin_matrix_determinant (twin_matrix_t *matrix) return det; } +twin_point_t +_twin_matrix_expand (twin_matrix_t *matrix) +{ + twin_fixed_t a = matrix->m[0][0]; + twin_fixed_t d = matrix->m[1][1]; + twin_fixed_t aa = twin_fixed_mul (a,a); + twin_fixed_t dd = twin_fixed_mul (d,d); + twin_point_t expand; + + expand.x = twin_fixed_sqrt (aa + dd); + expand.y = twin_fixed_div (_twin_matrix_determinant (matrix), + expand.x); + return expand; +} + void twin_matrix_rotate (twin_matrix_t *m, twin_angle_t a) { diff --git a/twin_path.c b/twin_path.c index b542a7d..f26f61d 100644 --- a/twin_path.c +++ b/twin_path.c @@ -115,6 +115,17 @@ twin_path_move (twin_path_t *path, twin_fixed_t x, twin_fixed_t y) } void +twin_path_rmove (twin_path_t *path, twin_fixed_t dx, twin_fixed_t dy) +{ + twin_spoint_t here = _twin_path_current_spoint (path); + _twin_path_smove (path, + here.x + + _twin_matrix_dx (&path->state.matrix, dx, dy), + here.y + + _twin_matrix_dy (&path->state.matrix, dx, dy)); +} + +void twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y) { _twin_path_sdraw (path, @@ -123,6 +134,17 @@ twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y) } void +twin_path_rdraw (twin_path_t *path, twin_fixed_t dx, twin_fixed_t dy) +{ + twin_spoint_t here = _twin_path_current_spoint (path); + _twin_path_sdraw (path, + here.x + + _twin_matrix_dx (&path->state.matrix, dx, dy), + here.y + + _twin_matrix_dy (&path->state.matrix, dx, dy)); +} + +void twin_path_close (twin_path_t *path) { switch (_twin_current_subpath_len(path)) { diff --git a/twin_spline.c b/twin_spline.c index 0413ef6..f90625b 100644 --- a/twin_spline.c +++ b/twin_spline.c @@ -102,7 +102,7 @@ _twin_spline_decompose (twin_path_t *path, } } -static void +void _twin_path_scurve (twin_path_t *path, twin_sfixed_t x1, twin_sfixed_t y1, twin_sfixed_t x2, twin_sfixed_t y2, diff --git a/twin_trig.c b/twin_trig.c index 0997107..10519d5 100644 --- a/twin_trig.c +++ b/twin_trig.c @@ -24,45 +24,149 @@ #include "twinint.h" -#define TWIN_LOG2_SIN 8 +#define TWIN_LOG2_SIN 10 + +/* + * construction: + int s = 10; for (int i = 0; i < (1 << s); i++) { + if (i % 8 == 0) printf ("\n "); + printf (" 0x%04x,", floor (sin(pi/2 * i / (1 << s)) * 2**16 + 0.5)); + } + */ static const uint16_t _twin_sin_table[1 << TWIN_LOG2_SIN] = { - 0x0000, 0x0192, 0x0324, 0x04b6, 0x0648, 0x07da, 0x096c, 0x0afe, - 0x0c90, 0x0e21, 0x0fb3, 0x1144, 0x12d5, 0x1466, 0x15f7, 0x1787, - 0x1918, 0x1aa8, 0x1c38, 0x1dc7, 0x1f56, 0x20e5, 0x2274, 0x2402, - 0x2590, 0x271e, 0x28ab, 0x2a38, 0x2bc4, 0x2d50, 0x2edc, 0x3067, - 0x31f1, 0x337c, 0x3505, 0x368e, 0x3817, 0x399f, 0x3b27, 0x3cae, - 0x3e34, 0x3fba, 0x413f, 0x42c3, 0x4447, 0x45cb, 0x474d, 0x48cf, - 0x4a50, 0x4bd1, 0x4d50, 0x4ecf, 0x504d, 0x51cb, 0x5348, 0x54c3, - 0x563e, 0x57b9, 0x5932, 0x5aaa, 0x5c22, 0x5d99, 0x5f0f, 0x6084, - 0x61f8, 0x636b, 0x64dd, 0x664e, 0x67be, 0x692d, 0x6a9b, 0x6c08, - 0x6d74, 0x6edf, 0x7049, 0x71b2, 0x731a, 0x7480, 0x75e6, 0x774a, - 0x78ad, 0x7a10, 0x7b70, 0x7cd0, 0x7e2f, 0x7f8c, 0x80e8, 0x8243, - 0x839c, 0x84f5, 0x864c, 0x87a1, 0x88f6, 0x8a49, 0x8b9a, 0x8ceb, - 0x8e3a, 0x8f88, 0x90d4, 0x921f, 0x9368, 0x94b0, 0x95f7, 0x973c, - 0x9880, 0x99c2, 0x9b03, 0x9c42, 0x9d80, 0x9ebc, 0x9ff7, 0xa130, - 0xa268, 0xa39e, 0xa4d2, 0xa605, 0xa736, 0xa866, 0xa994, 0xaac1, - 0xabeb, 0xad14, 0xae3c, 0xaf62, 0xb086, 0xb1a8, 0xb2c9, 0xb3e8, - 0xb505, 0xb620, 0xb73a, 0xb852, 0xb968, 0xba7d, 0xbb8f, 0xbca0, - 0xbdaf, 0xbebc, 0xbfc7, 0xc0d1, 0xc1d8, 0xc2de, 0xc3e2, 0xc4e4, - 0xc5e4, 0xc6e2, 0xc7de, 0xc8d9, 0xc9d1, 0xcac7, 0xcbbc, 0xccae, - 0xcd9f, 0xce8e, 0xcf7a, 0xd065, 0xd14d, 0xd234, 0xd318, 0xd3fb, - 0xd4db, 0xd5ba, 0xd696, 0xd770, 0xd848, 0xd91e, 0xd9f2, 0xdac4, - 0xdb94, 0xdc62, 0xdd2d, 0xddf7, 0xdebe, 0xdf83, 0xe046, 0xe107, - 0xe1c6, 0xe282, 0xe33c, 0xe3f4, 0xe4aa, 0xe55e, 0xe610, 0xe6bf, - 0xe76c, 0xe817, 0xe8bf, 0xe966, 0xea0a, 0xeaab, 0xeb4b, 0xebe8, - 0xec83, 0xed1c, 0xedb3, 0xee47, 0xeed9, 0xef68, 0xeff5, 0xf080, - 0xf109, 0xf18f, 0xf213, 0xf295, 0xf314, 0xf391, 0xf40c, 0xf484, - 0xf4fa, 0xf56e, 0xf5df, 0xf64e, 0xf6ba, 0xf724, 0xf78c, 0xf7f1, - 0xf854, 0xf8b4, 0xf913, 0xf96e, 0xf9c8, 0xfa1f, 0xfa73, 0xfac5, - 0xfb15, 0xfb62, 0xfbad, 0xfbf5, 0xfc3b, 0xfc7f, 0xfcc0, 0xfcfe, - 0xfd3b, 0xfd74, 0xfdac, 0xfde1, 0xfe13, 0xfe43, 0xfe71, 0xfe9c, - 0xfec4, 0xfeeb, 0xff0e, 0xff30, 0xff4e, 0xff6b, 0xff85, 0xff9c, - 0xffb1, 0xffc4, 0xffd4, 0xffe1, 0xffec, 0xfff5, 0xfffb, 0xffff, + 0x0000, 0x0065, 0x00c9, 0x012e, 0x0192, 0x01f7, 0x025b, 0x02c0, + 0x0324, 0x0389, 0x03ed, 0x0452, 0x04b6, 0x051b, 0x057f, 0x05e4, + 0x0648, 0x06ad, 0x0711, 0x0776, 0x07da, 0x083f, 0x08a3, 0x0908, + 0x096c, 0x09d1, 0x0a35, 0x0a9a, 0x0afe, 0x0b62, 0x0bc7, 0x0c2b, + 0x0c90, 0x0cf4, 0x0d59, 0x0dbd, 0x0e21, 0x0e86, 0x0eea, 0x0f4e, + 0x0fb3, 0x1017, 0x107b, 0x10e0, 0x1144, 0x11a8, 0x120d, 0x1271, + 0x12d5, 0x1339, 0x139e, 0x1402, 0x1466, 0x14ca, 0x152e, 0x1593, + 0x15f7, 0x165b, 0x16bf, 0x1723, 0x1787, 0x17eb, 0x1850, 0x18b4, + 0x1918, 0x197c, 0x19e0, 0x1a44, 0x1aa8, 0x1b0c, 0x1b70, 0x1bd4, + 0x1c38, 0x1c9b, 0x1cff, 0x1d63, 0x1dc7, 0x1e2b, 0x1e8f, 0x1ef3, + 0x1f56, 0x1fba, 0x201e, 0x2082, 0x20e5, 0x2149, 0x21ad, 0x2210, + 0x2274, 0x22d7, 0x233b, 0x239f, 0x2402, 0x2466, 0x24c9, 0x252d, + 0x2590, 0x25f4, 0x2657, 0x26ba, 0x271e, 0x2781, 0x27e4, 0x2848, + 0x28ab, 0x290e, 0x2971, 0x29d5, 0x2a38, 0x2a9b, 0x2afe, 0x2b61, + 0x2bc4, 0x2c27, 0x2c8a, 0x2ced, 0x2d50, 0x2db3, 0x2e16, 0x2e79, + 0x2edc, 0x2f3f, 0x2fa1, 0x3004, 0x3067, 0x30ca, 0x312c, 0x318f, + 0x31f1, 0x3254, 0x32b7, 0x3319, 0x337c, 0x33de, 0x3440, 0x34a3, + 0x3505, 0x3568, 0x35ca, 0x362c, 0x368e, 0x36f1, 0x3753, 0x37b5, + 0x3817, 0x3879, 0x38db, 0x393d, 0x399f, 0x3a01, 0x3a63, 0x3ac5, + 0x3b27, 0x3b88, 0x3bea, 0x3c4c, 0x3cae, 0x3d0f, 0x3d71, 0x3dd2, + 0x3e34, 0x3e95, 0x3ef7, 0x3f58, 0x3fba, 0x401b, 0x407c, 0x40de, + 0x413f, 0x41a0, 0x4201, 0x4262, 0x42c3, 0x4324, 0x4385, 0x43e6, + 0x4447, 0x44a8, 0x4509, 0x456a, 0x45cb, 0x462b, 0x468c, 0x46ec, + 0x474d, 0x47ae, 0x480e, 0x486f, 0x48cf, 0x492f, 0x4990, 0x49f0, + 0x4a50, 0x4ab0, 0x4b10, 0x4b71, 0x4bd1, 0x4c31, 0x4c90, 0x4cf0, + 0x4d50, 0x4db0, 0x4e10, 0x4e70, 0x4ecf, 0x4f2f, 0x4f8e, 0x4fee, + 0x504d, 0x50ad, 0x510c, 0x516c, 0x51cb, 0x522a, 0x5289, 0x52e8, + 0x5348, 0x53a7, 0x5406, 0x5464, 0x54c3, 0x5522, 0x5581, 0x55e0, + 0x563e, 0x569d, 0x56fc, 0x575a, 0x57b9, 0x5817, 0x5875, 0x58d4, + 0x5932, 0x5990, 0x59ee, 0x5a4c, 0x5aaa, 0x5b08, 0x5b66, 0x5bc4, + 0x5c22, 0x5c80, 0x5cde, 0x5d3b, 0x5d99, 0x5df6, 0x5e54, 0x5eb1, + 0x5f0f, 0x5f6c, 0x5fc9, 0x6026, 0x6084, 0x60e1, 0x613e, 0x619b, + 0x61f8, 0x6254, 0x62b1, 0x630e, 0x636b, 0x63c7, 0x6424, 0x6480, + 0x64dd, 0x6539, 0x6595, 0x65f2, 0x664e, 0x66aa, 0x6706, 0x6762, + 0x67be, 0x681a, 0x6876, 0x68d1, 0x692d, 0x6989, 0x69e4, 0x6a40, + 0x6a9b, 0x6af6, 0x6b52, 0x6bad, 0x6c08, 0x6c63, 0x6cbe, 0x6d19, + 0x6d74, 0x6dcf, 0x6e2a, 0x6e85, 0x6edf, 0x6f3a, 0x6f94, 0x6fef, + 0x7049, 0x70a3, 0x70fe, 0x7158, 0x71b2, 0x720c, 0x7266, 0x72c0, + 0x731a, 0x7373, 0x73cd, 0x7427, 0x7480, 0x74da, 0x7533, 0x758d, + 0x75e6, 0x763f, 0x7698, 0x76f1, 0x774a, 0x77a3, 0x77fc, 0x7855, + 0x78ad, 0x7906, 0x795f, 0x79b7, 0x7a10, 0x7a68, 0x7ac0, 0x7b18, + 0x7b70, 0x7bc8, 0x7c20, 0x7c78, 0x7cd0, 0x7d28, 0x7d7f, 0x7dd7, + 0x7e2f, 0x7e86, 0x7edd, 0x7f35, 0x7f8c, 0x7fe3, 0x803a, 0x8091, + 0x80e8, 0x813f, 0x8195, 0x81ec, 0x8243, 0x8299, 0x82f0, 0x8346, + 0x839c, 0x83f2, 0x8449, 0x849f, 0x84f5, 0x854a, 0x85a0, 0x85f6, + 0x864c, 0x86a1, 0x86f7, 0x874c, 0x87a1, 0x87f6, 0x884c, 0x88a1, + 0x88f6, 0x894a, 0x899f, 0x89f4, 0x8a49, 0x8a9d, 0x8af2, 0x8b46, + 0x8b9a, 0x8bef, 0x8c43, 0x8c97, 0x8ceb, 0x8d3f, 0x8d93, 0x8de6, + 0x8e3a, 0x8e8d, 0x8ee1, 0x8f34, 0x8f88, 0x8fdb, 0x902e, 0x9081, + 0x90d4, 0x9127, 0x9179, 0x91cc, 0x921f, 0x9271, 0x92c4, 0x9316, + 0x9368, 0x93ba, 0x940c, 0x945e, 0x94b0, 0x9502, 0x9554, 0x95a5, + 0x95f7, 0x9648, 0x969a, 0x96eb, 0x973c, 0x978d, 0x97de, 0x982f, + 0x9880, 0x98d0, 0x9921, 0x9972, 0x99c2, 0x9a12, 0x9a63, 0x9ab3, + 0x9b03, 0x9b53, 0x9ba3, 0x9bf2, 0x9c42, 0x9c92, 0x9ce1, 0x9d31, + 0x9d80, 0x9dcf, 0x9e1e, 0x9e6d, 0x9ebc, 0x9f0b, 0x9f5a, 0x9fa8, + 0x9ff7, 0xa045, 0xa094, 0xa0e2, 0xa130, 0xa17e, 0xa1cc, 0xa21a, + 0xa268, 0xa2b5, 0xa303, 0xa350, 0xa39e, 0xa3eb, 0xa438, 0xa485, + 0xa4d2, 0xa51f, 0xa56c, 0xa5b8, 0xa605, 0xa652, 0xa69e, 0xa6ea, + 0xa736, 0xa782, 0xa7ce, 0xa81a, 0xa866, 0xa8b2, 0xa8fd, 0xa949, + 0xa994, 0xa9df, 0xaa2a, 0xaa76, 0xaac1, 0xab0b, 0xab56, 0xaba1, + 0xabeb, 0xac36, 0xac80, 0xacca, 0xad14, 0xad5e, 0xada8, 0xadf2, + 0xae3c, 0xae85, 0xaecf, 0xaf18, 0xaf62, 0xafab, 0xaff4, 0xb03d, + 0xb086, 0xb0ce, 0xb117, 0xb160, 0xb1a8, 0xb1f0, 0xb239, 0xb281, + 0xb2c9, 0xb311, 0xb358, 0xb3a0, 0xb3e8, 0xb42f, 0xb477, 0xb4be, + 0xb505, 0xb54c, 0xb593, 0xb5da, 0xb620, 0xb667, 0xb6ad, 0xb6f4, + 0xb73a, 0xb780, 0xb7c6, 0xb80c, 0xb852, 0xb898, 0xb8dd, 0xb923, + 0xb968, 0xb9ae, 0xb9f3, 0xba38, 0xba7d, 0xbac1, 0xbb06, 0xbb4b, + 0xbb8f, 0xbbd4, 0xbc18, 0xbc5c, 0xbca0, 0xbce4, 0xbd28, 0xbd6b, + 0xbdaf, 0xbdf2, 0xbe36, 0xbe79, 0xbebc, 0xbeff, 0xbf42, 0xbf85, + 0xbfc7, 0xc00a, 0xc04c, 0xc08f, 0xc0d1, 0xc113, 0xc155, 0xc197, + 0xc1d8, 0xc21a, 0xc25c, 0xc29d, 0xc2de, 0xc31f, 0xc360, 0xc3a1, + 0xc3e2, 0xc423, 0xc463, 0xc4a4, 0xc4e4, 0xc524, 0xc564, 0xc5a4, + 0xc5e4, 0xc624, 0xc663, 0xc6a3, 0xc6e2, 0xc721, 0xc761, 0xc7a0, + 0xc7de, 0xc81d, 0xc85c, 0xc89a, 0xc8d9, 0xc917, 0xc955, 0xc993, + 0xc9d1, 0xca0f, 0xca4d, 0xca8a, 0xcac7, 0xcb05, 0xcb42, 0xcb7f, + 0xcbbc, 0xcbf9, 0xcc35, 0xcc72, 0xccae, 0xcceb, 0xcd27, 0xcd63, + 0xcd9f, 0xcddb, 0xce17, 0xce52, 0xce8e, 0xcec9, 0xcf04, 0xcf3f, + 0xcf7a, 0xcfb5, 0xcff0, 0xd02a, 0xd065, 0xd09f, 0xd0d9, 0xd113, + 0xd14d, 0xd187, 0xd1c1, 0xd1fa, 0xd234, 0xd26d, 0xd2a6, 0xd2df, + 0xd318, 0xd351, 0xd38a, 0xd3c2, 0xd3fb, 0xd433, 0xd46b, 0xd4a3, + 0xd4db, 0xd513, 0xd54b, 0xd582, 0xd5ba, 0xd5f1, 0xd628, 0xd65f, + 0xd696, 0xd6cd, 0xd703, 0xd73a, 0xd770, 0xd7a6, 0xd7dc, 0xd812, + 0xd848, 0xd87e, 0xd8b4, 0xd8e9, 0xd91e, 0xd954, 0xd989, 0xd9be, + 0xd9f2, 0xda27, 0xda5c, 0xda90, 0xdac4, 0xdaf8, 0xdb2c, 0xdb60, + 0xdb94, 0xdbc8, 0xdbfb, 0xdc2f, 0xdc62, 0xdc95, 0xdcc8, 0xdcfb, + 0xdd2d, 0xdd60, 0xdd92, 0xddc5, 0xddf7, 0xde29, 0xde5b, 0xde8c, + 0xdebe, 0xdef0, 0xdf21, 0xdf52, 0xdf83, 0xdfb4, 0xdfe5, 0xe016, + 0xe046, 0xe077, 0xe0a7, 0xe0d7, 0xe107, 0xe137, 0xe167, 0xe196, + 0xe1c6, 0xe1f5, 0xe224, 0xe253, 0xe282, 0xe2b1, 0xe2df, 0xe30e, + 0xe33c, 0xe36b, 0xe399, 0xe3c7, 0xe3f4, 0xe422, 0xe450, 0xe47d, + 0xe4aa, 0xe4d7, 0xe504, 0xe531, 0xe55e, 0xe58b, 0xe5b7, 0xe5e3, + 0xe610, 0xe63c, 0xe667, 0xe693, 0xe6bf, 0xe6ea, 0xe716, 0xe741, + 0xe76c, 0xe797, 0xe7c2, 0xe7ec, 0xe817, 0xe841, 0xe86b, 0xe895, + 0xe8bf, 0xe8e9, 0xe913, 0xe93c, 0xe966, 0xe98f, 0xe9b8, 0xe9e1, + 0xea0a, 0xea32, 0xea5b, 0xea83, 0xeaab, 0xead4, 0xeafc, 0xeb23, + 0xeb4b, 0xeb73, 0xeb9a, 0xebc1, 0xebe8, 0xec0f, 0xec36, 0xec5d, + 0xec83, 0xecaa, 0xecd0, 0xecf6, 0xed1c, 0xed42, 0xed68, 0xed8d, + 0xedb3, 0xedd8, 0xedfd, 0xee22, 0xee47, 0xee6b, 0xee90, 0xeeb4, + 0xeed9, 0xeefd, 0xef21, 0xef45, 0xef68, 0xef8c, 0xefaf, 0xefd2, + 0xeff5, 0xf018, 0xf03b, 0xf05e, 0xf080, 0xf0a3, 0xf0c5, 0xf0e7, + 0xf109, 0xf12b, 0xf14c, 0xf16e, 0xf18f, 0xf1b1, 0xf1d2, 0xf1f3, + 0xf213, 0xf234, 0xf254, 0xf275, 0xf295, 0xf2b5, 0xf2d5, 0xf2f5, + 0xf314, 0xf334, 0xf353, 0xf372, 0xf391, 0xf3b0, 0xf3cf, 0xf3ed, + 0xf40c, 0xf42a, 0xf448, 0xf466, 0xf484, 0xf4a2, 0xf4bf, 0xf4dd, + 0xf4fa, 0xf517, 0xf534, 0xf551, 0xf56e, 0xf58a, 0xf5a6, 0xf5c3, + 0xf5df, 0xf5fb, 0xf616, 0xf632, 0xf64e, 0xf669, 0xf684, 0xf69f, + 0xf6ba, 0xf6d5, 0xf6ef, 0xf70a, 0xf724, 0xf73e, 0xf758, 0xf772, + 0xf78c, 0xf7a5, 0xf7bf, 0xf7d8, 0xf7f1, 0xf80a, 0xf823, 0xf83b, + 0xf854, 0xf86c, 0xf885, 0xf89d, 0xf8b4, 0xf8cc, 0xf8e4, 0xf8fb, + 0xf913, 0xf92a, 0xf941, 0xf958, 0xf96e, 0xf985, 0xf99b, 0xf9b2, + 0xf9c8, 0xf9de, 0xf9f3, 0xfa09, 0xfa1f, 0xfa34, 0xfa49, 0xfa5e, + 0xfa73, 0xfa88, 0xfa9c, 0xfab1, 0xfac5, 0xfad9, 0xfaed, 0xfb01, + 0xfb15, 0xfb28, 0xfb3c, 0xfb4f, 0xfb62, 0xfb75, 0xfb88, 0xfb9a, + 0xfbad, 0xfbbf, 0xfbd1, 0xfbe3, 0xfbf5, 0xfc07, 0xfc18, 0xfc2a, + 0xfc3b, 0xfc4c, 0xfc5d, 0xfc6e, 0xfc7f, 0xfc8f, 0xfca0, 0xfcb0, + 0xfcc0, 0xfcd0, 0xfcdf, 0xfcef, 0xfcfe, 0xfd0e, 0xfd1d, 0xfd2c, + 0xfd3b, 0xfd49, 0xfd58, 0xfd66, 0xfd74, 0xfd83, 0xfd90, 0xfd9e, + 0xfdac, 0xfdb9, 0xfdc7, 0xfdd4, 0xfde1, 0xfdee, 0xfdfa, 0xfe07, + 0xfe13, 0xfe1f, 0xfe2b, 0xfe37, 0xfe43, 0xfe4f, 0xfe5a, 0xfe66, + 0xfe71, 0xfe7c, 0xfe87, 0xfe91, 0xfe9c, 0xfea6, 0xfeb0, 0xfeba, + 0xfec4, 0xfece, 0xfed8, 0xfee1, 0xfeeb, 0xfef4, 0xfefd, 0xff06, + 0xff0e, 0xff17, 0xff1f, 0xff28, 0xff30, 0xff38, 0xff3f, 0xff47, + 0xff4e, 0xff56, 0xff5d, 0xff64, 0xff6b, 0xff71, 0xff78, 0xff7e, + 0xff85, 0xff8b, 0xff91, 0xff96, 0xff9c, 0xffa2, 0xffa7, 0xffac, + 0xffb1, 0xffb6, 0xffbb, 0xffbf, 0xffc4, 0xffc8, 0xffcc, 0xffd0, + 0xffd4, 0xffd7, 0xffdb, 0xffde, 0xffe1, 0xffe4, 0xffe7, 0xffea, + 0xffec, 0xffef, 0xfff1, 0xfff3, 0xfff5, 0xfff7, 0xfff8, 0xfffa, + 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, }; /* - * angles are measured from -512 .. 512 + * angles are measured from -2048 .. 2048 */ #if 0 @@ -75,7 +75,7 @@ _twin_x11_put_span (int x, if (tx->iy == tx->image->height) { XPutImage (tx->dpy, tx->win, tx->gc, tx->image, 0, 0, - x, y - tx->iy, width, tx->image->height); + x, (y + 1) - tx->iy, width, tx->image->height); XDestroyImage (tx->image); tx->image = 0; } @@ -126,9 +126,7 @@ twin_x11_screen_damaged (void *closure) { twin_x11_t *tx = closure; - pthread_mutex_unlock (&tx->screen->screen_mutex); pthread_cond_broadcast (&tx->damage_cond); - pthread_mutex_unlock (&tx->screen->screen_mutex); } twin_x11_t * @@ -210,8 +208,10 @@ twin_x11_destroy (twin_x11_t *tx) void twin_x11_damage (twin_x11_t *tx, XExposeEvent *ev) { + twin_screen_lock (tx->screen); twin_screen_damage (tx->screen, ev->x, ev->y, ev->x + ev->width, ev->y + ev->height); + twin_screen_unlock (tx->screen); } void @@ -118,7 +118,7 @@ typedef void twin_op_func (twin_pointer_t dst, /* Geometrical objects */ -typedef struct _twin_point { +typedef struct _twin_spoint { twin_sfixed_t x, y; } twin_spoint_t; @@ -311,6 +311,8 @@ _twin_matrix_determinant (twin_matrix_t *matrix); twin_sfixed_t _twin_matrix_len (twin_matrix_t *m, twin_fixed_t dx, twin_fixed_t dy); +twin_point_t +_twin_matrix_expand (twin_matrix_t *matrix); /* * Path stuff */ @@ -331,6 +333,12 @@ _twin_path_smove (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y); void _twin_path_sdraw (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y); +void +_twin_path_scurve (twin_path_t *path, + twin_sfixed_t x1, twin_sfixed_t y1, + twin_sfixed_t x2, twin_sfixed_t y2, + twin_sfixed_t x3, twin_sfixed_t y3); + /* * Glyph stuff. Coordinates are stored in 2.6 fixed point format */ @@ -342,4 +350,17 @@ extern const uint16_t _twin_glyph_offsets[]; #define TWIN_GLYPH_MAX_POINTS 56 +extern const signed char _twin_gtable[]; +extern const uint16_t _twin_g_offsets[]; + +#define twin_glyph_left(g) ((g)[0]) +#define twin_glyph_right(g) ((g)[1]) +#define twin_glyph_ascent(g) ((g)[2]) +#define twin_glyph_descent(g) ((g)[3]) +#define twin_glyph_n_snap_x(g) ((g)[4]) +#define twin_glyph_n_snap_y(g) ((g)[5]) +#define twin_glyph_snap_x(g) (&g[6]) +#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g)) +#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g)) + #endif /* _TWININT_H_ */ @@ -34,13 +34,16 @@ #define TWIN_CLOCK_BACKGROUND 0xff3b80ae #define TWIN_CLOCK_HOUR 0x80808080 -#define TWIN_CLOCK_HOUR_OUT 0xffdedede +#define TWIN_CLOCK_HOUR_OUT 0x30000000 #define TWIN_CLOCK_MINUTE 0x80808080 -#define TWIN_CLOCK_MINUTE_OUT 0xffdedede +#define TWIN_CLOCK_MINUTE_OUT 0x30000000 #define TWIN_CLOCK_SECOND 0x80808080 +#define TWIN_CLOCK_SECOND_OUT 0x30000000 #define TWIN_CLOCK_TIC 0xffbababa #define TWIN_CLOCK_NUMBERS 0xffdedede -#define TWIN_CLOCK_WATER 0x40404040 +#define TWIN_CLOCK_WATER 0x40000000 +#define TWIN_CLOCK_WATER_OUT 0x40404040 +#define TWIN_CLOCK_WATER_UNDER 0xcccc0000 #define TWIN_CLOCK_BORDER 0xffbababa #define TWIN_CLOCK_BORDER_WIDTH D(0.01) @@ -97,26 +100,6 @@ twin_clock_hand (twin_pixmap_t *clock, twin_path_destroy (stroke); } -static void -twin_clock_sec (twin_pixmap_t *clock, - twin_angle_t angle, - twin_fixed_t len, - twin_fixed_t width, - twin_argb32_t pixel) -{ - twin_path_t *stroke = twin_path_create (); - - twin_clock_set_transform (clock, stroke); - - twin_path_rotate (stroke, angle); - twin_path_move (stroke, D(0), D(0)); - twin_path_draw (stroke, len, D(0)); - - twin_paint_stroke (clock, pixel, stroke, width); - - twin_path_destroy (stroke); -} - static twin_angle_t twin_clock_minute_angle (int min) { @@ -141,7 +124,7 @@ twin_clock_face (twin_pixmap_t *clock) { twin_state_t state = twin_path_save (path); twin_text_metrics_t metrics; - twin_fixed_t height; + twin_fixed_t height, width; static char *label = "twin"; twin_path_empty (path); @@ -150,8 +133,14 @@ twin_clock_face (twin_pixmap_t *clock) twin_path_set_font_style (path, TWIN_TEXT_UNHINTED|TWIN_TEXT_OBLIQUE); twin_text_metrics_utf8 (path, label, &metrics); height = metrics.ascent + metrics.descent; -/* twin_path_move (path, -metrics.width / 2, height / 2 - metrics.ascent);*/ - twin_path_move (path, -D(.4), -D(.16)); + width = metrics.right_side_bearing - metrics.left_side_bearing; + + twin_path_move (path, -width / 2, metrics.ascent - height/2); + twin_path_draw (path, width / 2, metrics.ascent - height/2); + twin_paint_stroke (clock, TWIN_CLOCK_WATER_UNDER, path, D(0.02)); + twin_path_empty (path); + + twin_path_move (path, -width / 2 - metrics.left_side_bearing, metrics.ascent - height/2); twin_path_utf8 (path, label); twin_paint_path (clock, TWIN_CLOCK_WATER, path); twin_path_restore (path, &state); @@ -173,12 +162,16 @@ twin_clock_face (twin_pixmap_t *clock) } else { - char hour[3]; + char hour[3]; + twin_text_metrics_t metrics; + twin_fixed_t width; + twin_fixed_t left; - twin_fixed_t w; sprintf (hour, "%d", m / 5); - w = twin_width_utf8 (path, hour); - twin_path_move (path, -(w/2), -D(0.95)); + twin_text_metrics_utf8 (path, hour, &metrics); + width = metrics.right_side_bearing - metrics.left_side_bearing; + left = -width / 2 - metrics.left_side_bearing; + twin_path_move (path, left, -D(0.98) + metrics.ascent); twin_path_utf8 (path, hour); twin_paint_path (clock, TWIN_CLOCK_NUMBERS, path); } @@ -197,19 +190,11 @@ twin_clock (twin_screen_t *screen, int x, int y, int w, int h) struct timeval tv; struct tm t; twin_angle_t hour_angle, minute_angle, second_angle; -#if 0 - int i; -#endif - printf ("twin clock\n"); twin_pixmap_move (clock, x, y); twin_pixmap_show (clock, screen, 0); -#if 0 - for (i = 0; i < 5; i++) -#else for (;;) -#endif { twin_pixmap_disable_update (clock); twin_fill (clock, 0x00000000, TWIN_SOURCE, 0, 0, @@ -222,15 +207,16 @@ twin_clock (twin_screen_t *screen, int x, int y, int w, int h) second_angle = ((t.tm_sec * 100 + tv.tv_usec / 10000) * TWIN_ANGLE_360) / 6000 - TWIN_ANGLE_90; minute_angle = twin_clock_minute_angle (t.tm_min) + second_angle / 60; - hour_angle = t.tm_hour * TWIN_ANGLE_360 / 12 - TWIN_ANGLE_90 + minute_angle / 12; - + hour_angle = (t.tm_hour * TWIN_ANGLE_360 / 12 + + (minute_angle + TWIN_ANGLE_90) / 12 - + TWIN_ANGLE_90); twin_clock_face (clock); twin_clock_hand (clock, hour_angle, D(0.4), D(0.07), D(0.01), TWIN_CLOCK_HOUR, TWIN_CLOCK_HOUR_OUT); twin_clock_hand (clock, minute_angle, D(0.8), D(0.05), D(0.01), TWIN_CLOCK_MINUTE, TWIN_CLOCK_MINUTE_OUT); - twin_clock_sec (clock, second_angle, D(0.9), D(0.02), - TWIN_CLOCK_SECOND); + twin_clock_hand (clock, second_angle, D(0.9), D(0.01), D(0.01), + TWIN_CLOCK_SECOND, TWIN_CLOCK_SECOND_OUT); twin_pixmap_enable_update (clock); @@ -392,7 +378,7 @@ main (int argc, char **argv) twin_path_convolve (path, extra, pen); #endif -#if 1 +#if 0 { twin_state_t state = twin_path_save (path); twin_path_translate (path, D(300), D(300)); @@ -409,12 +395,12 @@ main (int argc, char **argv) } #endif #if 1 - fx = D(3); + fx = D(10); fy = 0; - for (g = 8; g < 30; g += 4) + for (g = 90; g < 91; g += 4) { twin_path_set_font_size (path, D(g)); -#if 1 +#if 0 fy += D(g+2); twin_path_move (path, fx, fy); twin_path_utf8 (path, @@ -443,7 +429,30 @@ main (int argc, char **argv) #if 0 fy += D(g); twin_path_move (path, fx, fy); - twin_path_utf8 (path, "t"); +#define TEXT "jelly world" + twin_path_utf8 (path, TEXT); + { + twin_text_metrics_t m; + + stroke = twin_path_create (); + twin_path_set_matrix (stroke, twin_path_current_matrix (path)); + twin_text_metrics_utf8 (path, TEXT, &m); + twin_path_move (stroke, fx, fy); + twin_path_draw (stroke, fx + m.width, fy); + twin_paint_stroke (red, 0xffff0000, stroke, D(1)); + twin_path_empty (stroke); + twin_path_move (stroke, + fx + m.left_side_bearing, fy - m.ascent); + twin_path_draw (stroke, + fx + m.right_side_bearing, fy - m.ascent); + twin_path_draw (stroke, + fx + m.right_side_bearing, fy + m.descent); + twin_path_draw (stroke, + fx + m.left_side_bearing, fy + m.descent); + twin_path_draw (stroke, + fx + m.left_side_bearing, fy - m.ascent); + twin_paint_stroke (red, 0xff00ff00, stroke, D(1)); + } #endif } #endif @@ -461,7 +470,7 @@ main (int argc, char **argv) fy += D(g); } #endif - twin_fill_path (alpha, path); + twin_fill_path (alpha, path, 0, 0); twin_path_destroy (path); @@ -610,53 +619,20 @@ main (int argc, char **argv) twin_pixmap_move (blue, 100, 100); twin_pixmap_show (red, x11->screen, 0); twin_pixmap_show (blue, x11->screen, 0); + ++nclock; #endif - twin_start_clock (x11->screen, 0, 0, 512, 512); -/* twin_start_clock (x11->screen, 256, 0, 256, 256); + +#if 1 + twin_start_clock (x11->screen, 0, 0, 256, 256); +#endif +#if 0 + twin_start_clock (x11->screen, 0, 0, 256, 256); + twin_start_clock (x11->screen, 256, 0, 256, 256); twin_start_clock (x11->screen, 0, 256, 256, 256); - twin_start_clock (x11->screen, 256, 256, 256, 256); */ + twin_start_clock (x11->screen, 256, 256, 256, 256); +#endif while (nclock) sleep (1); -#if 0 - had_motion = TWIN_FALSE; - for (;;) - { - if (had_motion) - { - x = motion.xmotion.x - 50; - y = motion.xmotion.y - 50; - if (motion.xmotion.state & Button1Mask) - twin_pixmap_move (red, x, y); - if (motion.xmotion.state & Button3Mask) - twin_pixmap_move (blue, x, y); - had_motion = TWIN_FALSE; - } - if (twin_screen_damaged (x11->screen)) - twin_x11_update (x11); - XSync (dpy, False); - do { - XNextEvent (dpy, &ev); - switch (ev.type) { - case Expose: - twin_x11_damage (x11, &ev.xexpose); - break; - case ButtonPress: - if (ev.xbutton.button == 2) - { - if (red->higher == 0) - twin_pixmap_show (red, x11->screen, 0); - else - twin_pixmap_show (blue, x11->screen, 0); - } - break; - case MotionNotify: - had_motion = TWIN_TRUE; - motion = ev; - break; - } - } while (QLength (dpy)); - } -#endif return 0; } |