summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2004-10-04 07:49:49 +0000
committerKeith Packard <keithp@keithp.com>2004-10-04 07:49:49 +0000
commite27025eda79dbf6428c20d2d0dd635ddffaa3fba (patch)
treec63fc6037dc2e9c5e92086be642766669a56c11e
parent1b7271c78065d6a1ab3396df916529fc7958b0e2 (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--ChangeLog32
-rw-r--r--twin.h26
-rw-r--r--twin_draw.c4
-rw-r--r--twin_font.c578
-rw-r--r--twin_glyphs.c1564
-rw-r--r--twin_matrix.c15
-rw-r--r--twin_path.c22
-rw-r--r--twin_spline.c2
-rw-r--r--twin_trig.c172
-rw-r--r--twin_x11.c6
-rw-r--r--twinint.h23
-rw-r--r--xtwin.c158
12 files changed, 2287 insertions, 315 deletions
diff --git a/ChangeLog b/ChangeLog
index 8a73635..a9693bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
diff --git a/twin.h b/twin.h
index f91948d..276614b 100644
--- a/twin.h
+++ b/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
diff --git a/twin_x11.c b/twin_x11.c
index 9630e63..e2fcc4b 100644
--- a/twin_x11.c
+++ b/twin_x11.c
@@ -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
diff --git a/twinint.h b/twinint.h
index 7f930c1..92fe14b 100644
--- a/twinint.h
+++ b/twinint.h
@@ -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_ */
diff --git a/xtwin.c b/xtwin.c
index 1db18f2..8dcce03 100644
--- a/xtwin.c
+++ b/xtwin.c
@@ -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;
}