diff options
author | Keith Packard <keithp@keithp.com> | 2004-10-05 18:42:53 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2004-10-05 18:42:53 +0000 |
commit | a8611583a5e0e2539be9841c8d5a6e37b7cff7a6 (patch) | |
tree | b32b6bb4ee9d250511beb2d7daf3399f28de1d2b | |
parent | 2dd498a0b7c3f3e8de3451f881f0e0de62f05ff0 (diff) |
Update API to use twin_ types for most everything.
Rework snapping to correctly snap vertical and horizontal text on pixel
boundaries.
Change clock watermark
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | twin.h | 146 | ||||
-rw-r--r-- | twin_draw.c | 76 | ||||
-rw-r--r-- | twin_font.c | 388 | ||||
-rw-r--r-- | twin_matrix.c | 14 | ||||
-rw-r--r-- | twin_path.c | 60 | ||||
-rw-r--r-- | twin_pixmap.c | 15 | ||||
-rw-r--r-- | twin_poly.c | 3 | ||||
-rw-r--r-- | twin_screen.c | 18 | ||||
-rw-r--r-- | twin_x11.c | 20 | ||||
-rw-r--r-- | twinint.h | 8 | ||||
-rw-r--r-- | xtwin.c | 39 |
12 files changed, 555 insertions, 259 deletions
@@ -1,3 +1,30 @@ +2004-10-05 Keith Packard <keithp@keithp.com> + + * twin.h: + * twin_draw.c: (twin_composite), (twin_fill): + * twin_matrix.c: (twin_matrix_multiply), (twin_matrix_translate), + (twin_matrix_scale), (twin_matrix_rotate): + * twin_path.c: (twin_path_ellipse), (twin_path_set_font_style), + (twin_composite_path), (twin_composite_stroke): + * twin_pixmap.c: (twin_pixmap_create), (twin_pixmap_pointer), + (twin_pixmap_damage), (twin_pixmap_move): + * twin_poly.c: (twin_fill_path): + * twin_screen.c: (twin_screen_create), (twin_screen_damage), + (twin_screen_resize), (twin_screen_update): + * twin_x11.c: (_twin_x11_put_begin), (_twin_x11_put_span): + * twinint.h: + Update API to use twin_ types for most everything. + + * twin_font.c: (_twin_text_compute_info), + (_twin_text_compute_snap), (_twin_text_compute_pen), (_twin_snap), + (twin_has_ucs4), (_twin_glyph_width), (twin_text_metrics_ucs4), + (twin_path_ucs4): + Rework snapping to correctly snap vertical and horizontal text + on pixel boundaries. + + * xtwin.c: (main): + Change clock watermark + 2004-10-04 Keith Packard <keithp@keithp.com> * twin_primitive.c: (in_over), (over): @@ -38,13 +38,18 @@ typedef uint16_t twin_rgb16_t; typedef uint32_t twin_argb32_t; typedef uint32_t twin_ucs4_t; typedef int twin_bool_t; +typedef int16_t twin_coord_t; +typedef int16_t twin_style_t; +typedef int16_t twin_count_t; +typedef int16_t twin_keysym_t; +typedef int32_t twin_area_t; #define TWIN_FALSE 0 #define TWIN_TRUE 1 typedef enum { TWIN_A8, TWIN_RGB16, TWIN_ARGB32 } twin_format_t; -#define twin_bytes_per_pixel(format) (1 << (int) (format)) +#define twin_bytes_per_pixel(format) (1 << (twin_coord_t) (format)) /* * Angles @@ -64,7 +69,7 @@ typedef int16_t twin_angle_t; /* -2048 .. 2048 for -180 .. 180 */ * A rectangle */ typedef struct _twin_rect { - int left, right, top, bottom; + twin_coord_t left, right, top, bottom; } twin_rect_t; typedef union _twin_pointer { @@ -83,7 +88,7 @@ typedef struct _twin_pixmap { * Screen showing these pixels */ struct _twin_screen *screen; - int disable; + twin_count_t disable; /* * List of displayed pixmaps */ @@ -91,32 +96,32 @@ typedef struct _twin_pixmap { /* * Screen position */ - int x, y; + twin_coord_t x, y; /* * Pixmap layout */ - twin_format_t format; - int width; /* pixels */ - int height; /* pixels */ - int stride; /* bytes */ + twin_format_t format; + twin_coord_t width; /* pixels */ + twin_coord_t height; /* pixels */ + twin_coord_t stride; /* bytes */ /* * Pixels */ - twin_pointer_t p; + twin_pointer_t p; } twin_pixmap_t; /* * twin_put_begin_t: called before data are drawn to the screen * twin_put_span_t: called for each scanline drawn */ -typedef void (*twin_put_begin_t) (int x, - int y, - int width, - int height, +typedef void (*twin_put_begin_t) (twin_coord_t x, + twin_coord_t y, + twin_coord_t width, + twin_coord_t height, void *closure); -typedef void (*twin_put_span_t) (int x, - int y, - int width, +typedef void (*twin_put_span_t) (twin_coord_t x, + twin_coord_t y, + twin_coord_t width, twin_argb32_t *pixels, void *closure); @@ -131,14 +136,14 @@ typedef struct _twin_screen { /* * Output size */ - int width, height; + twin_coord_t width, height; /* * Damage */ twin_rect_t damage; void (*damaged) (void *); void *damaged_closure; - int disable; + twin_count_t disable; #if HAVE_PTHREAD_H pthread_mutex_t screen_mutex; #endif @@ -190,15 +195,15 @@ typedef struct _twin_point { * Place matrices in structures so they can be easily copied */ typedef struct _twin_matrix { - twin_fixed_t m[3][2]; + twin_fixed_t m[3][2]; } twin_matrix_t; typedef struct _twin_path twin_path_t; typedef struct _twin_state { - twin_matrix_t matrix; - twin_fixed_t font_size; - int font_style; + twin_matrix_t matrix; + twin_fixed_t font_size; + twin_style_t font_style; } twin_state_t; /* @@ -216,6 +221,34 @@ typedef struct _twin_text_metrics { } twin_text_metrics_t; /* + * Events + */ + +typedef enum _twin_event_kind { + EventButtonDown, EventButtonUp, EventMotion, + EventKeyDown, EventKeyUp, EventUcs4 +} twin_event_kind_t; + +typedef struct _twin_event { + twin_event_kind_t kind; + union { + struct { + twin_coord_t x, y; + twin_count_t button; + } button; + struct { + twin_coord_t x, y; + } motion; + struct { + twin_keysym_t key; + } key; + struct { + twin_ucs4_t ucs4; + } ucs4; + } u; +} twin_event_t; + +/* * twin_convolve.c */ void @@ -229,26 +262,26 @@ twin_path_convolve (twin_path_t *dest, void twin_composite (twin_pixmap_t *dst, - int dst_x, - int dst_y, + twin_coord_t dst_x, + twin_coord_t dst_y, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_operand_t *msk, - int msk_x, - int msk_y, + twin_coord_t msk_x, + twin_coord_t msk_y, twin_operator_t operator, - int width, - int height); + twin_coord_t width, + twin_coord_t height); void twin_fill (twin_pixmap_t *dst, twin_argb32_t pixel, twin_operator_t operator, - int x, - int y, - int width, - int height); + twin_coord_t x, + twin_coord_t y, + twin_coord_t width, + twin_coord_t height); /* * twin_fixed.c @@ -330,6 +363,11 @@ twin_matrix_scale (twin_matrix_t *m, twin_fixed_t sx, twin_fixed_t sy); void twin_matrix_rotate (twin_matrix_t *m, twin_angle_t a); +void +twin_matrix_multiply (twin_matrix_t *result, + const twin_matrix_t *a, + const twin_matrix_t *b); + /* * twin_path.c */ @@ -350,6 +388,10 @@ void twin_path_circle(twin_path_t *path, twin_fixed_t radius); void +twin_path_ellipse (twin_path_t *path, + twin_fixed_t x_radius, + twin_fixed_t y_radius); +void twin_path_close (twin_path_t *path); void @@ -391,11 +433,11 @@ twin_path_current_font_size (twin_path_t *path); void twin_path_set_font_size (twin_path_t *path, twin_fixed_t font_size); -int +twin_style_t twin_path_current_font_style (twin_path_t *path); void -twin_path_set_font_style (twin_path_t *path, int font_style); +twin_path_set_font_style (twin_path_t *path, twin_style_t font_style); twin_state_t twin_path_save (twin_path_t *path); @@ -406,8 +448,8 @@ twin_path_restore (twin_path_t *path, twin_state_t *state); void twin_composite_path (twin_pixmap_t *dst, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_path_t *path, twin_operator_t operator); void @@ -418,8 +460,8 @@ twin_paint_path (twin_pixmap_t *dst, void twin_composite_stroke (twin_pixmap_t *dst, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_path_t *stroke, twin_fixed_t pen_width, twin_operator_t operator); @@ -435,7 +477,9 @@ twin_paint_stroke (twin_pixmap_t *dst, */ twin_pixmap_t * -twin_pixmap_create (twin_format_t format, int width, int height); +twin_pixmap_create (twin_format_t format, + twin_coord_t width, + twin_coord_t height); void twin_pixmap_destroy (twin_pixmap_t *pixmap); @@ -456,7 +500,8 @@ twin_pixmap_disable_update (twin_pixmap_t *pixmap); void twin_pixmap_damage (twin_pixmap_t *pixmap, - int x1, int y1, int x2, int y2); + twin_coord_t x1, twin_coord_t y1, + twin_coord_t x2, twin_coord_t y2); void twin_pixmap_lock (twin_pixmap_t *pixmap); @@ -465,24 +510,25 @@ void twin_pixmap_unlock (twin_pixmap_t *pixmap); void -twin_pixmap_move (twin_pixmap_t *pixmap, int x, int y); +twin_pixmap_move (twin_pixmap_t *pixmap, twin_coord_t x, twin_coord_t y); twin_pointer_t -twin_pixmap_pointer (twin_pixmap_t *pixmap, int x, int y); +twin_pixmap_pointer (twin_pixmap_t *pixmap, twin_coord_t x, twin_coord_t y); /* * twin_poly.c */ void -twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, int dx, int dy); +twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, + twin_coord_t dx, twin_coord_t dy); /* * twin_screen.c */ twin_screen_t * -twin_screen_create (int width, - int height, +twin_screen_create (twin_coord_t width, + twin_coord_t height, twin_put_begin_t put_begin, twin_put_span_t put_span, void *closure); @@ -498,7 +544,8 @@ twin_screen_disable_update (twin_screen_t *screen); void twin_screen_damage (twin_screen_t *screen, - int x1, int y1, int x2, int y2); + twin_coord_t left, twin_coord_t top, + twin_coord_t right, twin_coord_t bottom); void twin_screen_register_damaged (twin_screen_t *screen, @@ -506,7 +553,8 @@ twin_screen_register_damaged (twin_screen_t *screen, void *closure); void -twin_screen_resize (twin_screen_t *screen, int width, int height); +twin_screen_resize (twin_screen_t *screen, + twin_coord_t width, twin_coord_t height); twin_bool_t twin_screen_damaged (twin_screen_t *screen); diff --git a/twin_draw.c b/twin_draw.c index c18c4b9..505eed7 100644 --- a/twin_draw.c +++ b/twin_draw.c @@ -261,45 +261,48 @@ static twin_src_msk_op comp3[2][4][4][3] = { void twin_composite (twin_pixmap_t *dst, - int dst_x, - int dst_y, + twin_coord_t dst_x, + twin_coord_t dst_y, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_operand_t *msk, - int msk_x, - int msk_y, + twin_coord_t msk_x, + twin_coord_t msk_y, twin_operator_t operator, - int width, - int height) + twin_coord_t width, + twin_coord_t height) { - int iy; - int left, right, top, bottom; + twin_coord_t iy; + twin_coord_t left, right, top, bottom; + + left = dst_x; + right = dst_x + width; + top = dst_y; + bottom = dst_y + height; + if (left < 0) + left = 0; + if (right > dst->width) + right = dst->width; + if (top < 0) + top = 0; + if (bottom > dst->height) + bottom = dst->height; + if (left >= right || top >= bottom) + return; twin_pixmap_lock (dst); if (msk) { twin_src_msk_op op; twin_source_u s, m; - int sdx, sdy, mdx, mdy; + twin_coord_t sdx, sdy, mdx, mdy; sdx = src_x - dst_x; sdy = src_y - dst_y; mdx = msk_x - dst_x; mdy = msk_y - dst_y; - left = dst_x; - right = dst_x + width; - top = dst_y; - bottom = dst_y + height; - if (left < 0) - left = 0; - if (right > dst->width) - right = dst->width; - if (top < 0) - top = 0; - if (bottom > dst->height) - bottom = dst->height; op = comp3[operator][operand_index(src)][operand_index(msk)][dst->format]; if (op) @@ -326,24 +329,11 @@ twin_composite (twin_pixmap_t *dst, { twin_src_op op; twin_source_u s; - int sdx, sdy; + twin_coord_t sdx, sdy; sdx = src_x - dst_x; sdy = src_y - dst_y; - left = dst_x; - right = dst_x + width; - top = dst_y; - bottom = dst_y + height; - if (left < 0) - left = 0; - if (right > dst->width) - right = dst->width; - if (top < 0) - top = 0; - if (top > dst->height) - top = dst->height; - op = comp2[operator][operand_index(src)][dst->format]; if (src->source_kind == TWIN_SOLID) s.c = src->u.argb; @@ -380,15 +370,15 @@ void twin_fill (twin_pixmap_t *dst, twin_argb32_t pixel, twin_operator_t operator, - int x, - int y, - int width, - int height) + twin_coord_t x, + twin_coord_t y, + twin_coord_t width, + twin_coord_t height) { twin_src_op op; twin_source_u src; - int iy; - int left, right, top, bottom; + twin_coord_t iy; + twin_coord_t left, right, top, bottom; twin_pixmap_lock (dst); src.c = pixel; diff --git a/twin_font.c b/twin_font.c index c23c291..cc8d461 100644 --- a/twin_font.c +++ b/twin_font.c @@ -34,33 +34,185 @@ #define DBGMSG(x) #endif -#define Scale(f) (((twin_fixed_t) (f) * path->state.font_size) >> 6) +#define SNAPI(p) (((p) + 0x8000) & ~0xffff) +#define SNAPH(p) (((p) + 0x4000) & ~0x7fff) +#define FX(g,i) (((g) * (i)->scale.x) >> 6) +#define FY(g,i) (((g) * (i)->scale.y) >> 6) -#define Hint(p) (((p)->state.font_style & TWIN_TEXT_UNHINTED) == 0) +typedef struct _twin_text_info { + twin_point_t scale; + twin_point_t pen; + twin_point_t margin; + twin_point_t reverse_scale; + twin_bool_t snap; + twin_matrix_t matrix; + twin_matrix_t pen_matrix; + int n_snap_x; + twin_fixed_t snap_x[TWIN_GLYPH_MAX_SNAP_X]; + int n_snap_y; + twin_fixed_t snap_y[TWIN_GLYPH_MAX_SNAP_Y]; +} twin_text_info_t; -twin_bool_t -twin_has_ucs4 (twin_ucs4_t ucs4) +static void +_twin_text_compute_info (twin_path_t *path, twin_text_info_t *info) { - return ucs4 <= TWIN_FONT_MAX && _twin_g_offsets[ucs4] != 0; + twin_spoint_t origin = _twin_path_current_spoint (path); + + /* + * Only hint axis aligned text + */ + if ((path->state.font_style & TWIN_TEXT_UNHINTED) == 0 && + ((path->state.matrix.m[0][1] == 0 && + path->state.matrix.m[1][0] == 0) || + (path->state.matrix.m[0][0] == 0 && + path->state.matrix.m[1][1] == 0))) + { + int xi, yi; + + if (path->state.matrix.m[0][0] != 0) + xi = 0; + else + xi = 1; + yi = 1-xi; + info->snap = TWIN_TRUE; + info->matrix.m[xi][0] = TWIN_FIXED_ONE; + info->matrix.m[xi][1] = 0; + info->matrix.m[yi][0] = 0; + info->matrix.m[yi][1] = TWIN_FIXED_ONE; + info->matrix.m[2][0] = twin_sfixed_to_fixed (origin.x); + info->matrix.m[2][1] = twin_sfixed_to_fixed (origin.y); + info->scale.x = twin_fixed_mul (path->state.font_size, + path->state.matrix.m[0][xi]); + info->reverse_scale.x = twin_fixed_div (TWIN_FIXED_ONE, + path->state.matrix.m[0][xi]); + if (info->scale.x < 0) + { + info->scale.x = -info->scale.x; + info->reverse_scale.x = -info->reverse_scale.x; + info->matrix.m[0][xi] = -info->matrix.m[0][xi]; + info->matrix.m[1][xi] = -info->matrix.m[1][xi]; + } + info->scale.y = twin_fixed_mul (path->state.font_size, + path->state.matrix.m[1][yi]); + info->reverse_scale.y = twin_fixed_div (TWIN_FIXED_ONE, + path->state.matrix.m[1][yi]); + if (info->scale.y < 0) + { + info->scale.y = -info->scale.y; + info->reverse_scale.y = -info->reverse_scale.y; + info->matrix.m[0][yi] = -info->matrix.m[0][yi]; + info->matrix.m[1][yi] = -info->matrix.m[1][yi]; + } + + info->pen.x = SNAPH(info->scale.x / 24); + info->pen.y = SNAPH(info->scale.y / 24); + if (info->pen.x < TWIN_FIXED_HALF) + info->pen.x = TWIN_FIXED_HALF; + if (info->pen.y < TWIN_FIXED_HALF) + info->pen.y = TWIN_FIXED_HALF; + info->margin.x = info->pen.x; + info->margin.y = info->pen.y; + if (path->state.font_style & TWIN_TEXT_BOLD) + { + twin_fixed_t pen_x_add = SNAPH(info->pen.x >> 1); + twin_fixed_t pen_y_add = SNAPH(info->pen.y >> 1); + + if (pen_x_add < TWIN_FIXED_HALF) + pen_x_add = TWIN_FIXED_HALF; + if (pen_y_add < TWIN_FIXED_HALF) + pen_y_add = TWIN_FIXED_HALF; + info->pen.x += pen_x_add; + info->pen.y += pen_y_add; + } + DBGMSG (("pen: %9.4f %9.4f\n", F(info->pen.x), F(info->pen.y))); + + twin_matrix_translate (&info->matrix, + SNAPI(info->margin.x) + info->pen.x, + -info->pen.y); + info->pen_matrix = info->matrix; + } + else + { + info->snap = TWIN_FALSE; + info->matrix = path->state.matrix; + info->matrix.m[2][0] = twin_sfixed_to_fixed (origin.x); + info->matrix.m[2][1] = twin_sfixed_to_fixed (origin.y); + info->scale.x = path->state.font_size; + info->scale.y = path->state.font_size; + + if (path->state.font_style & TWIN_TEXT_BOLD) + info->pen.x = path->state.font_size / 16; + else + info->pen.x = path->state.font_size / 24; + info->pen.y = info->pen.x; + + info->margin.x = path->state.font_size / 24; + info->margin.y = info->margin.x; + + info->pen_matrix = path->state.matrix; + twin_matrix_translate (&info->matrix, + info->margin.x + info->pen.x, -info->pen.y); + } + info->pen_matrix.m[2][0] = 0; info->pen_matrix.m[2][1] = 0; + twin_matrix_scale (&info->pen_matrix, info->pen.x, info->pen.y); + + if (path->state.font_style & TWIN_TEXT_OBLIQUE) + { + twin_matrix_t m; + + m.m[0][0] = TWIN_FIXED_ONE; m.m[0][1] = 0; + m.m[1][0] = -TWIN_FIXED_ONE / 4; m.m[1][1] = TWIN_FIXED_ONE; + m.m[2][0] = 0; m.m[2][1] = 0; + twin_matrix_multiply (&info->matrix, &m, &info->matrix); + } + DBGMSG (("%9.4f %9.4f\n", F(info->matrix.m[0][0]), F(info->matrix.m[0][1]))); + DBGMSG (("%9.4f %9.4f\n", F(info->matrix.m[1][0]), F(info->matrix.m[1][1]))); + DBGMSG (("%9.4f %9.4f\n", F(info->matrix.m[2][0]), F(info->matrix.m[2][1]))); } -#define SNAPI(p) (((p) + 0x7fff) & ~0xffff) -#define SNAPH(p) (((p) + 0x3fff) & ~0x7fff) +static void +_twin_text_compute_snap (twin_text_info_t *info, + const signed char *b) +{ + int s, n; + const signed char *snap; + + snap = twin_glyph_snap_x (b); + n = twin_glyph_n_snap_x (b); + info->n_snap_x = n; + for (s = 0; s < n; s++) + info->snap_x[s] = FX(snap[s], info); + + snap = twin_glyph_snap_y (b); + n = twin_glyph_n_snap_y (b); + info->n_snap_y = n; + for (s = 0; s < n; s++) + info->snap_y[s] = FY(snap[s], info); +} + +static twin_path_t * +_twin_text_compute_pen (twin_text_info_t *info) +{ + twin_path_t *pen = twin_path_create (); + + twin_path_set_matrix (pen, info->pen_matrix); + twin_path_circle (pen, TWIN_FIXED_ONE); + return pen; +} -#if 0 static twin_fixed_t -_snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) +_twin_snap (twin_fixed_t v, + twin_fixed_t *snap, + int n) { - int s; - twin_fixed_t v; + int s; - v = Scale(g); - for (s = 0; s < nsnap - 1; s++) + for (s = 0; s < n - 1; s++) { - if (snap[s] <= g && g <= snap[s+1]) + if (snap[s] <= v && v <= snap[s+1]) { - twin_fixed_t before = Scale(snap[s]); - twin_fixed_t after = Scale(snap[s+1]); + twin_fixed_t before = snap[s]; + twin_fixed_t after = snap[s+1]; twin_fixed_t dist = after - before; twin_fixed_t snap_before = SNAPI(before); twin_fixed_t snap_after = SNAPI(after); @@ -70,7 +222,6 @@ _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) twin_fixed_t dist_after = after - v; twin_fixed_t move = ((int64_t) dist_before * move_after + (int64_t) dist_after * move_before) / dist; - DBGMSG (("%d <= %d <= %d\n", snap[s], g, snap[s+1])); DBGMSG (("%9.4f <= %9.4f <= %9.4f\n", F(before), F(v), F(after))); DBGMSG (("before: %9.4f -> %9.4f\n", F(before), F(snap_before))); DBGMSG (("after: %9.4f -> %9.4f\n", F(after), F(snap_after))); @@ -79,10 +230,14 @@ _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap) break; } } - DBGMSG (("_snap: %d => %9.4f\n", g, F(v))); return v; } -#endif + +twin_bool_t +twin_has_ucs4 (twin_ucs4_t ucs4) +{ + return ucs4 <= TWIN_FONT_MAX && _twin_g_offsets[ucs4] != 0; +} #define SNAPX(p) _snap (path, p, snap_x, nsnap_x) #define SNAPY(p) _snap (path, p, snap_y, nsnap_y) @@ -96,67 +251,73 @@ _twin_g_base (twin_ucs4_t ucs4) } static twin_fixed_t -_twin_pen_size (twin_path_t *path) +_twin_glyph_width (twin_text_info_t *info, + const signed char *b) { - twin_fixed_t pen_size; - - 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 = pen_size >> 1; + twin_fixed_t right = FX(twin_glyph_right(b), info) + info->pen.x * 2; + twin_fixed_t right_side_bearing; + twin_fixed_t width; - if (Hint (path)) - { - pen_add = SNAPH (pen_add); - if (pen_add == 0) - pen_add = TWIN_FIXED_HALF; - } - pen_size += pen_add; - } - return pen_size; + if (info->snap) + right = SNAPI(_twin_snap (right, info->snap_x, info->n_snap_x)); + + right_side_bearing = right + info->margin.x; + width = right_side_bearing + info->margin.x; + return width; } -#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 signed char *g = _twin_g_base (ucs4); - twin_fixed_t pen_size = _twin_pen_size (path); - 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)) + const signed char *b = _twin_g_base (ucs4); + twin_text_info_t info; + twin_fixed_t left, right, ascent, descent; + twin_fixed_t font_spacing; + twin_fixed_t font_descent; + twin_fixed_t font_ascent; + twin_fixed_t margin_x, margin_y; + + _twin_text_compute_info (path, &info); + if (info.snap) + _twin_text_compute_snap (&info, b); + + left = FX(twin_glyph_left(b), &info); + right = FX(twin_glyph_right(b), &info) + info.pen.x * 2; + ascent = FY(twin_glyph_ascent(b), &info) + info.pen.y * 2; + descent = FY(twin_glyph_descent(b), &info); + margin_x = info.margin.x; + margin_y = info.margin.y; + + font_spacing = FY(TWIN_GFIXED_ONE, &info); + font_descent = font_spacing / 3; + font_ascent = font_spacing - font_descent; + if (info.snap) { - left = SNAPI(left); - right = SNAPI(right); - ascent = SNAPI(ascent); - descent = SNAPI(descent); + left = SNAPI(_twin_snap (left, info.snap_x, info.n_snap_x)); + right = SNAPI(_twin_snap (right, info.snap_x, info.n_snap_x)); + ascent = SNAPI(_twin_snap (ascent, info.snap_y, info.n_snap_y)); + descent = SNAPI(_twin_snap (descent, info.snap_y, info.n_snap_y)); font_descent = SNAPI(font_descent); font_ascent = SNAPI(font_ascent); + + left = twin_fixed_mul (left, info.reverse_scale.x); + right = twin_fixed_mul (right, info.reverse_scale.x); + ascent = twin_fixed_mul (ascent, info.reverse_scale.y); + descent = twin_fixed_mul (descent, info.reverse_scale.y); + font_descent = twin_fixed_mul (font_descent, info.reverse_scale.y); + font_ascent = twin_fixed_mul (font_ascent, info.reverse_scale.y); + margin_x = twin_fixed_mul (margin_x, info.reverse_scale.x); + margin_y = twin_fixed_mul (margin_y, info.reverse_scale.y); } - m->left_side_bearing = left + Margin(pen_size); - m->right_side_bearing = right + Margin(pen_size); + m->left_side_bearing = left + margin_x; + m->right_side_bearing = right + margin_x; 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); + m->width = m->right_side_bearing + margin_x; + m->font_ascent = font_ascent + margin_y; + m->font_descent = font_descent + margin_y; } void @@ -166,67 +327,66 @@ twin_path_ucs4 (twin_path_t *path, twin_ucs4_t ucs4) const signed char *g = twin_glyph_draw(b); twin_spoint_t origin; 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 pen_size = _twin_pen_size (path); - twin_matrix_t pen_matrix; - twin_text_metrics_t metrics; - - twin_text_metrics_ucs4 (path, ucs4, &metrics); + twin_fixed_t width; + twin_text_info_t info; + _twin_text_compute_info (path, &info); + if (info.snap) + _twin_text_compute_snap (&info, b); + origin = _twin_path_current_spoint (path); stroke = twin_path_create (); - - twin_path_set_matrix (stroke, twin_path_current_matrix (path)); - - pen = twin_path_create (); - pen_matrix = twin_path_current_matrix (path); - /* eliminate translation part */ - pen_matrix.m[2][0] = 0; - pen_matrix.m[2][1] = 0; - twin_path_set_matrix (pen, pen_matrix); - - twin_path_circle (pen, pen_size); - -#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)) - - xo = pen_size * 3; - yo = -pen_size; + twin_path_set_matrix (stroke, info.matrix); + pen = _twin_text_compute_pen (&info); 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)); + x1 = FX(*g++, &info); + y1 = FY(*g++, &info); + if (info.snap) + { + x1 = _twin_snap (x1, info.snap_x, info.n_snap_x); + y1 = _twin_snap (y1, info.snap_y, info.n_snap_y); + } + DBGMSG (("m %9.4f %9.4f\n", + S(_twin_matrix_x (&stroke->state.matrix, x1, y1)), + S(_twin_matrix_y (&stroke->state.matrix, x1, y1)))); + twin_path_move (stroke, 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)); + x1 = FX(*g++, &info); + y1 = FY(*g++, &info); + if (info.snap) + { + x1 = _twin_snap (x1, info.snap_x, info.n_snap_x); + y1 = _twin_snap (y1, info.snap_y, info.n_snap_y); + } + DBGMSG (("l %9.4f %9.4f\n", + S(_twin_matrix_x (&stroke->state.matrix, x1, y1)), + S(_twin_matrix_y (&stroke->state.matrix, x1, y1)))); + twin_path_draw (stroke, 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) + x1 = FX(*g++, &info); + y1 = FY(*g++, &info); + x2 = FX(*g++, &info); + y2 = FY(*g++, &info); + x3 = FX(*g++, &info); + y3 = FY(*g++, &info); + if (info.snap) { - x1 -= y1 >> 2; - x2 -= y2 >> 2; - x3 -= y3 >> 2; + x1 = _twin_snap (x1, info.snap_x, info.n_snap_x); + y1 = _twin_snap (y1, info.snap_y, info.n_snap_y); + x2 = _twin_snap (x2, info.snap_x, info.n_snap_x); + y2 = _twin_snap (y2, info.snap_y, info.n_snap_y); + x3 = _twin_snap (x3, info.snap_x, info.n_snap_x); + y3 = _twin_snap (y3, info.snap_y, info.n_snap_y); } - _twin_path_scurve (stroke, PX(x1,y1), PY(x1,y1), - PX(x2,y2), PY(x2,y2), PX(x3,y3), PY(x3,y3)); + twin_path_curve (stroke, x1, y1, x2, y2, x3, y3); continue; case 'e': break; @@ -235,10 +395,14 @@ twin_path_ucs4 (twin_path_t *path, twin_ucs4_t ucs4) } twin_path_convolve (path, stroke, pen); - twin_path_destroy (stroke); twin_path_destroy (pen); + twin_path_destroy (stroke); + + width = _twin_glyph_width (&info, b); - _twin_path_smove (path, PX(metrics.width, 0), PY(metrics.width,0)); + _twin_path_smove (path, + origin.x + _twin_matrix_dx (&info.matrix, width, 0), + origin.y + _twin_matrix_dy (&info.matrix, width, 0)); } twin_fixed_t diff --git a/twin_matrix.c b/twin_matrix.c index 0de1572..9dbb43c 100644 --- a/twin_matrix.c +++ b/twin_matrix.c @@ -49,10 +49,10 @@ _twin_dump_matrix (char *name, const twin_matrix_t *m) #define _twin_dump_matrix(n,m) #endif -static void -_twin_matrix_multiply (twin_matrix_t *result, - const twin_matrix_t *a, - const twin_matrix_t *b) +void +twin_matrix_multiply (twin_matrix_t *result, + const twin_matrix_t *a, + const twin_matrix_t *b) { twin_matrix_t r; int row, col, n; @@ -91,7 +91,7 @@ twin_matrix_translate (twin_matrix_t *m, twin_fixed_t tx, twin_fixed_t ty) t.m[0][0] = TWIN_FIXED_ONE; t.m[0][1] = 0; t.m[1][0] = 0; t.m[1][1] = TWIN_FIXED_ONE; t.m[2][0] = tx; t.m[2][1] = ty; - _twin_matrix_multiply (m, &t, m); + twin_matrix_multiply (m, &t, m); } void @@ -102,7 +102,7 @@ twin_matrix_scale (twin_matrix_t *m, twin_fixed_t sx, twin_fixed_t sy) t.m[0][0] = sx; t.m[0][1] = 0; t.m[1][0] = 0; t.m[1][1] = sy; t.m[2][0] = 0; t.m[2][1] = 0; - _twin_matrix_multiply (m, &t, m); + twin_matrix_multiply (m, &t, m); } twin_fixed_t @@ -144,7 +144,7 @@ twin_matrix_rotate (twin_matrix_t *m, twin_angle_t a) t.m[0][0] = c; t.m[0][1] = s; t.m[1][0] = -s; t.m[1][1] = c; t.m[2][0] = 0; t.m[2][1] = 0; - _twin_matrix_multiply (m, &t, m); + twin_matrix_multiply (m, &t, m); } twin_sfixed_t diff --git a/twin_path.c b/twin_path.c index f26f61d..468e22e 100644 --- a/twin_path.c +++ b/twin_path.c @@ -185,7 +185,6 @@ _twin_matrix_max_radius (twin_matrix_t *m) twin_fixed_abs (m->m[1][0]) + twin_fixed_abs (m->m[1][1])); } - void twin_path_circle (twin_path_t *path, twin_fixed_t radius) { @@ -230,6 +229,51 @@ twin_path_circle (twin_path_t *path, twin_fixed_t radius) } void +twin_path_ellipse (twin_path_t *path, + twin_fixed_t x_radius, + twin_fixed_t y_radius) +{ + int sides; + int n; + twin_spoint_t center; + int i; + twin_matrix_t save; + twin_fixed_t max_radius; + + save = twin_path_current_matrix (path); + + twin_path_scale (path, x_radius, y_radius); + + center = _twin_path_current_spoint (path); + + twin_path_close (path); + + max_radius = _twin_matrix_max_radius (&path->state.matrix); + + sides = max_radius / twin_sfixed_to_fixed (TWIN_SFIXED_TOLERANCE); + + if (sides > 1024) sides = 1024; + + n = 2; + while ((1 << n) < sides) + n++; + + for (i = 0; i <= (1 << n); i++) + { + twin_angle_t a = (i * TWIN_ANGLE_360) >> n; + twin_fixed_t x = twin_cos (a); + twin_fixed_t y = twin_sin (a); + + _twin_path_sdraw (path, + center.x + _twin_matrix_dx (&path->state.matrix, x, y), + center.y + _twin_matrix_dy (&path->state.matrix, x, y)); + } + + twin_path_close (path); + twin_path_set_matrix (path, save); +} + +void twin_path_set_matrix (twin_path_t *path, twin_matrix_t matrix) { path->state.matrix = matrix; @@ -278,12 +322,12 @@ twin_path_current_font_size (twin_path_t *path) } void -twin_path_set_font_style (twin_path_t *path, int font_style) +twin_path_set_font_style (twin_path_t *path, twin_style_t font_style) { path->state.font_style = font_style; } -int +twin_style_t twin_path_current_font_style (twin_path_t *path) { return path->state.font_style; @@ -380,15 +424,15 @@ twin_path_destroy (twin_path_t *path) void twin_composite_path (twin_pixmap_t *dst, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_path_t *path, twin_operator_t operator) { twin_rect_t bounds; twin_pixmap_t *mask; twin_operand_t msk; - int width, height; + twin_coord_t width, height; twin_path_bounds (path, &bounds); if (bounds.left == bounds.right) @@ -424,8 +468,8 @@ twin_paint_path (twin_pixmap_t *dst, void twin_composite_stroke (twin_pixmap_t *dst, twin_operand_t *src, - int src_x, - int src_y, + twin_coord_t src_x, + twin_coord_t src_y, twin_path_t *stroke, twin_fixed_t pen_width, twin_operator_t operator) diff --git a/twin_pixmap.c b/twin_pixmap.c index 83a9a95..5882bfe 100644 --- a/twin_pixmap.c +++ b/twin_pixmap.c @@ -25,10 +25,12 @@ #include "twinint.h" twin_pixmap_t * -twin_pixmap_create (twin_format_t format, int width, int height) +twin_pixmap_create (twin_format_t format, + twin_coord_t width, + twin_coord_t height) { - int stride = twin_bytes_per_pixel (format) * width; - int size = sizeof (twin_pixmap_t) + stride * height; + twin_coord_t stride = twin_bytes_per_pixel (format) * width; + twin_area_t size = sizeof (twin_pixmap_t) + (twin_area_t) stride * height; twin_pixmap_t *pixmap = malloc (size); if (!pixmap) return 0; @@ -99,7 +101,7 @@ twin_pixmap_hide (twin_pixmap_t *pixmap) } twin_pointer_t -twin_pixmap_pointer (twin_pixmap_t *pixmap, int x, int y) +twin_pixmap_pointer (twin_pixmap_t *pixmap, twin_coord_t x, twin_coord_t y) { twin_pointer_t p; @@ -131,7 +133,8 @@ twin_pixmap_disable_update (twin_pixmap_t *pixmap) void twin_pixmap_damage (twin_pixmap_t *pixmap, - int x1, int y1, int x2, int y2) + twin_coord_t x1, twin_coord_t y1, + twin_coord_t x2, twin_coord_t y2) { if (pixmap->screen) twin_screen_damage (pixmap->screen, @@ -156,7 +159,7 @@ twin_pixmap_unlock (twin_pixmap_t *pixmap) } void -twin_pixmap_move (twin_pixmap_t *pixmap, int x, int y) +twin_pixmap_move (twin_pixmap_t *pixmap, twin_coord_t x, twin_coord_t y) { twin_pixmap_damage (pixmap, 0, 0, pixmap->width, pixmap->height); pixmap->x = x; diff --git a/twin_poly.c b/twin_poly.c index cacc327..2de4023 100644 --- a/twin_poly.c +++ b/twin_poly.c @@ -348,7 +348,8 @@ _twin_edge_fill (twin_pixmap_t *pixmap, twin_edge_t *edges, int nedges) } void -twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, int dx, int dy) +twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, + twin_coord_t dx, twin_coord_t dy) { twin_edge_t *edges; int nedges, n; diff --git a/twin_screen.c b/twin_screen.c index cc69ab0..1821cc6 100644 --- a/twin_screen.c +++ b/twin_screen.c @@ -25,8 +25,8 @@ #include "twinint.h" twin_screen_t * -twin_screen_create (int width, - int height, +twin_screen_create (twin_coord_t width, + twin_coord_t height, twin_put_begin_t put_begin, twin_put_span_t put_span, void *closure) @@ -106,7 +106,8 @@ twin_screen_disable_update (twin_screen_t *screen) void twin_screen_damage (twin_screen_t *screen, - int left, int top, int right, int bottom) + twin_coord_t left, twin_coord_t top, + twin_coord_t right, twin_coord_t bottom) { if (screen->damage.left == screen->damage.right) { @@ -131,7 +132,8 @@ twin_screen_damage (twin_screen_t *screen, } void -twin_screen_resize (twin_screen_t *screen, int width, int height) +twin_screen_resize (twin_screen_t *screen, + twin_coord_t width, twin_coord_t height) { screen->width = width; screen->height = height; @@ -152,10 +154,10 @@ twin_screen_update (twin_screen_t *screen) screen->damage.left < screen->damage.right && screen->damage.top < screen->damage.bottom) { - int x = screen->damage.left; - int y = screen->damage.top; - int width = screen->damage.right - screen->damage.left; - int height = screen->damage.bottom - screen->damage.top; + twin_coord_t x = screen->damage.left; + twin_coord_t y = screen->damage.top; + twin_coord_t width = screen->damage.right - screen->damage.left; + twin_coord_t height = screen->damage.bottom - screen->damage.top; twin_argb32_t *span; twin_pixmap_t *p; @@ -26,11 +26,11 @@ #include "twinint.h" static void -_twin_x11_put_begin (int x, - int y, - int width, - int height, - void *closure) +_twin_x11_put_begin (twin_coord_t x, + twin_coord_t y, + twin_coord_t width, + twin_coord_t height, + void *closure) { twin_x11_t *tx = closure; @@ -49,15 +49,15 @@ _twin_x11_put_begin (int x, } static void -_twin_x11_put_span (int x, - int y, - int width, +_twin_x11_put_span (twin_coord_t x, + twin_coord_t y, + twin_coord_t width, twin_argb32_t *pixels, void *closure) { twin_x11_t *tx = closure; - int ix = 0; - int iw = width; + twin_coord_t ix = 0; + twin_coord_t iw = width; if (!tx->image) return; @@ -66,6 +66,8 @@ typedef int32_t twin_dfixed_t; /* 24.8 format (12.4 * 12.4) */ typedef signed char twin_gfixed_t; +#define TWIN_GFIXED_ONE (0x40) + /* * Compositing stuff */ @@ -357,6 +359,12 @@ extern const uint16_t _twin_glyph_offsets[]; extern const signed char _twin_gtable[]; extern const uint16_t _twin_g_offsets[]; +/* + * Check these whenever glyphs are changed + */ +#define TWIN_GLYPH_MAX_SNAP_X 4 +#define TWIN_GLYPH_MAX_SNAP_Y 7 + #define twin_glyph_left(g) ((g)[0]) #define twin_glyph_right(g) ((g)[1]) #define twin_glyph_ascent(g) ((g)[2]) @@ -41,9 +41,9 @@ #define TWIN_CLOCK_SECOND_OUT 0x30000000 #define TWIN_CLOCK_TIC 0xffbababa #define TWIN_CLOCK_NUMBERS 0xffdedede -#define TWIN_CLOCK_WATER 0x40000000 +#define TWIN_CLOCK_WATER 0x60200000 #define TWIN_CLOCK_WATER_OUT 0x40404040 -#define TWIN_CLOCK_WATER_UNDER 0xcccc0000 +#define TWIN_CLOCK_WATER_UNDER 0x60400000 #define TWIN_CLOCK_BORDER 0xffbababa #define TWIN_CLOCK_BORDER_WIDTH D(0.01) @@ -278,8 +278,8 @@ int styles[] = { TWIN_TEXT_BOLD|TWIN_TEXT_OBLIQUE }; -#define WIDTH 256 -#define HEIGHT 256 +#define WIDTH 512 +#define HEIGHT 512 int main (int argc, char **argv) @@ -349,7 +349,7 @@ main (int argc, char **argv) stroke = twin_path_create (); twin_path_move (stroke, D(30), D(400)); twin_path_set_font_size (stroke, D(100)); - twin_path_utf8 (stroke, "jelly world."); + twin_path_utf8 (stroke, "jelly HEzt/[]."); twin_path_convolve (path, stroke, pen); /* twin_path_append (path, stroke); */ twin_path_destroy (stroke); @@ -397,12 +397,21 @@ main (int argc, char **argv) } #endif #if 1 - fx = D(10); + fx = D(15); fy = 0; - for (g = 10; g <= 38; g += 4) + twin_path_translate (path, 0, D(HEIGHT)); + twin_path_rotate (path, -twin_degrees_to_angle (90)); + twin_path_scale (path, D(1), D(0.5)); + twin_path_set_font_style (path, TWIN_TEXT_OBLIQUE); + for (g = 40; g <= 60; 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, "H"); +#endif +#if 0 fy += D(g+2); twin_path_move (path, fx, fy); twin_path_utf8 (path, @@ -428,10 +437,11 @@ main (int argc, char **argv) "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG."); } #endif -#if 0 - fy += D(g); +#if 1 + fy += D(g + 2); twin_path_move (path, fx, fy); -#define TEXT "jelly world" +#define TEXT "jelly HEzt/[]." +/* twin_path_set_font_style (path, TWIN_TEXT_UNHINTED); */ twin_path_utf8 (path, TEXT); { twin_text_metrics_t m; @@ -439,6 +449,7 @@ main (int argc, char **argv) stroke = twin_path_create (); twin_path_set_matrix (stroke, twin_path_current_matrix (path)); twin_text_metrics_utf8 (path, TEXT, &m); + twin_path_translate (stroke, TWIN_FIXED_HALF, TWIN_FIXED_HALF); twin_path_move (stroke, fx, fy); twin_path_draw (stroke, fx + m.width, fy); twin_paint_stroke (red, 0xffff0000, stroke, D(1)); @@ -624,9 +635,8 @@ main (int argc, char **argv) ++nclock; #endif -#if 1 - twin_start_clock (x11->screen, 0, 0, WIDTH, HEIGHT); -#endif + if (!nclock) + twin_start_clock (x11->screen, 0, 0, WIDTH, HEIGHT); #if 0 twin_start_clock (x11->screen, 0, 0, 256, 256); twin_start_clock (x11->screen, 256, 0, 256, 256); @@ -637,4 +647,3 @@ main (int argc, char **argv) sleep (1); return 0; } - |