Mercurial > MadButterfly
changeset 458:bb4f651090bf
Use cairo to transform and draw arc.
- We move some values into float_args.
- fix_args is removed.
- args is rename to pnts.
- We still need to add corner points to pnts at sh_path_arc_cmd_arg_fill().
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Thu, 10 Sep 2009 17:36:45 +0800 |
parents | ea09fdab333a |
children | 8b155b77fa14 |
files | include/mb_graph_engine.h include/mb_shapes.h include/mb_types.h src/shape_path.c tools/mb_c_source.m4 tools/svg2code.py |
diffstat | 6 files changed, 469 insertions(+), 227 deletions(-) [+] |
line wrap: on
line diff
--- a/include/mb_graph_engine.h Thu Aug 06 15:38:08 2009 +0800 +++ b/include/mb_graph_engine.h Thu Sep 10 17:36:45 2009 +0800 @@ -47,7 +47,6 @@ #define mbe_fill_preserve cairo_fill_preserve #define mbe_set_operator cairo_set_operator #define mbe_get_operator cairo_get_operator -#define mbe_arc_negative cairo_arc_negative #define mbe_set_source cairo_set_source #define mbe_reset_clip cairo_reset_clip #define mbe_get_target cairo_get_target @@ -72,7 +71,6 @@ #define mbe_save cairo_save #define mbe_fill cairo_fill #define mbe_clip cairo_clip -#define mbe_arc cairo_arc typedef cairo_text_extents_t mbe_text_extents_t; typedef cairo_font_options_t mbe_font_options_t; @@ -84,6 +82,7 @@ typedef cairo_status_t mbe_status_t; typedef cairo_matrix_t mbe_matrix_t; typedef cairo_t mbe_t; +typedef float co_aix; static mbe_surface_t * mbe_image_surface_create_for_data(unsigned char *data, @@ -163,6 +162,29 @@ return cairo_image_surface_create(_fmt, width, height); } +static void +mbe_transform(mbe_t *mbe, const co_aix matrix[6]) { + cairo_matrix_t cmtx; + + cmtx.xx = matrix[0]; + cmtx.xy = matrix[1]; + cmtx.x0 = matrix[2]; + cmtx.yx = matrix[3]; + cmtx.yy = matrix[4]; + cmtx.y0 = matrix[5]; + + cairo_transform(mbe, &cmtx); +} + +static void +mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, + co_aix angle_start, co_aix angle_stop) { + if(angle_start <= angle_stop) + cairo_arc(mbe, x, y, radius, angle_start, angle_stop); + else + cairo_arc_negative(mbe, x, y, radius, angle_start, angle_stop); +} + /* @} */ #endif /* __MBE_H_ */
--- a/include/mb_shapes.h Thu Aug 06 15:38:08 2009 +0800 +++ b/include/mb_shapes.h Thu Sep 10 17:36:45 2009 +0800 @@ -61,7 +61,12 @@ * @{ */ extern shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data); -extern shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, char *commands, co_aix *arg,int arg_cnt,int *fix_arg,int fix_arg_cnt); +extern shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, + char *commands, + co_aix *pnts, + int pnt_cnt, + co_aix *float_args, + int float_arg_cnt); extern void sh_path_transform(shape_t *shape); extern void sh_path_draw(shape_t *shape, mbe_t *cr); /* @} */
--- a/include/mb_types.h Thu Aug 06 15:38:08 2009 +0800 +++ b/include/mb_types.h Thu Sep 10 17:36:45 2009 +0800 @@ -6,7 +6,6 @@ #include "mb_observer.h" #include "mb_prop.h" -typedef float co_aix; typedef struct _shape shape_t; typedef struct _geo geo_t; typedef struct _area area_t;
--- a/src/shape_path.c Thu Aug 06 15:38:08 2009 +0800 +++ b/src/shape_path.c Thu Sep 10 17:36:45 2009 +0800 @@ -19,8 +19,8 @@ typedef struct _sh_path { shape_t shape; int cmd_len; - int arg_len; - int fix_arg_len; + int pnt_len; + int float_arg_len; char *user_data; char *dev_data; /* device space data */ } sh_path_t; @@ -40,7 +40,7 @@ } #define OK 0 #define ERR -1 -#define PI 3.1415926 +#define PI 3.1415926535897931 #ifdef UNITTEST #undef rdman_shape_man @@ -93,13 +93,12 @@ * - cy = ry * ucy * - cy = ry * (udcy + umy) */ -static int calc_center_and_x_aix(co_aix x0, co_aix y0, - co_aix x, co_aix y, - co_aix rx, co_aix ry, - co_aix x_rotate, - int large, int sweep, - co_aix *cx, co_aix *cy, - co_aix *xx, co_aix *xy) { +static int _calc_center(co_aix x0, co_aix y0, + co_aix x, co_aix y, + co_aix rx, co_aix ry, + co_aix x_rotate, + int large, int sweep, + co_aix *cx, co_aix *cy) { co_aix nrx, nry, nrx0, nry0; co_aix udx, udy, udx2, udy2; co_aix umx, umy; @@ -110,6 +109,7 @@ float _cos = cosf(x_rotate); int reflect; + /* Compute center of the ellipse */ nrx = x * _cos + y * _sin; nry = x * -_sin + y * _cos; nrx0 = x0 * _cos + y0 * _sin; @@ -150,13 +150,33 @@ *cx = nrcx * _cos - nrcy * _sin; *cy = nrcx * _sin + nrcy * _cos; - *xx = rx * _cos + *cx; - *xy = rx * _sin + *cy; - return OK; } +static co_aix _angle_rotated_ellipse(co_aix x, co_aix y, + co_aix rx, co_aix ry, + co_aix x_rotate) { + co_aix nrx, nry; + co_aix _sin, _cos; + co_aix xy_tan; + co_aix angle; + + _sin = sinf(x_rotate); + _cos = cosf(x_rotate); + + nrx = (x * _cos + y * _sin) / rx; + nry = (-x * _sin + y * _cos) / ry; + xy_tan = nry / nrx; + + angle = atan(xy_tan); + + if(nrx < 0) + angle = PI + angle; + + return angle; +} + #define TAKE_NUM(r) do { \ SKIP_SPACE(p); \ old = p; \ @@ -168,21 +188,22 @@ static int sh_path_arc_cmd_arg_fill(char cmd, char **cmds_p, const char **data_p, - co_aix **args_p, - int **fix_args_p) { + co_aix **pnts_p, + co_aix **float_args_p) { co_aix rx, ry; co_aix x_rotate; int large, sweep; - co_aix x, y, x0, y0, cx, cy, xx, xy; - co_aix *args = *args_p; + co_aix x, y, x0, y0, cx, cy; + co_aix angle_start, angle_stop; + co_aix *pnts = *pnts_p; const char *old; const char *p; char *cmds; - int *fix_args; + co_aix *float_args; p = *data_p; cmds = *cmds_p; - fix_args = *fix_args_p; + float_args = *float_args_p; while(*p) { SKIP_SPACE(p); old = p; @@ -198,34 +219,45 @@ TAKE_NUM(x); TAKE_NUM(y) - x0 = *(args - 2); - y0 = *(args - 1); + x0 = *(pnts - 2); + y0 = *(pnts - 1); if(islower(cmd)) { x += x0; y += y0; } - calc_center_and_x_aix(x0, y0, x, y, - rx, ry, - x_rotate, large, sweep, - &cx, &cy, &xx, &xy); + _calc_center(x0, y0, x, y, rx, ry, x_rotate, large, + sweep, &cx, &cy); + pnts += 8; /*!< \note Add corners here. */ + *(pnts++) = x; + *(pnts++) = y; + + angle_start = _angle_rotated_ellipse(x0 - cx, y0 - cy, + rx, ry, x_rotate); + angle_stop = _angle_rotated_ellipse(x - cx, y - cy, + rx, ry, x_rotate); - *(args++) = cx; - *(args++) = cy; - *(args++) = xx; - *(args++) = xy; - *(args++) = x; - *(args++) = y; - + if(sweep && angle_start > angle_stop) + angle_stop += 2 * PI; + else if((!sweep) && angle_start < angle_stop) + angle_start += 2 * PI; + + *float_args++ = cx; + *float_args++ = cy; + *float_args++ = rx; + *float_args++ = ry; + *float_args++ = angle_start; + *float_args++ = angle_stop; + *float_args++ = x_rotate; + *cmds++ = toupper(cmd); - *fix_args++ = sweep; } *data_p = p; - *args_p = args; + *pnts_p = pnts; *cmds_p = cmds; - *fix_args_p = fix_args; + *float_args_p = float_args; return OK; } @@ -233,30 +265,109 @@ #define INNER(x1, y1, x2, y2) ((x1) * (x2) + (y1) * (y2)) #define CROSS(x1, y1, x2, y2) ((x1) * (y2) - (y1) * (x2)) +static co_aix distance_pow2(co_aix x, co_aix y) { + return x * x + y * y; +} + +static co_aix angle_diff(co_aix sx, co_aix sy, co_aix dx, co_aix dy) { + co_aix inner, cross; + co_aix angle; + co_aix rd2, rd; + + rd2 = distance_pow2(dx, dy); + rd = sqrtf(rd2); + + inner = INNER(sx, sy, dx, dy); + cross = CROSS(sx, sy, dx, dy); + angle = acos(inner / rd); + if(cross < 0) + angle = 2 * PI - angle; + + return angle; +} + /*! \brief Make path for arcs in a path. */ -void sh_path_arc_path(mbe_t *cr, const co_aix **args_p, +void _sh_path_arc_path(mbe_t *cr, sh_path_t *path, const co_aix **pnts_p, + const co_aix **float_args_p) { + co_aix cx, cy, x0, y0, x, y; + co_aix rx, ry; + co_aix xyratio; + co_aix angle_start, angle_stop; + co_aix x_rotate; + const co_aix *pnts; + const co_aix *float_args; + co_aix matrix[6]; + co_aix dev_matrix[6]; + co_aix *aggr; + co_aix _sin, _cos; + + pnts = *pnts_p; + float_args = *float_args_p; + x0 = *(pnts - 2); + y0 = *(pnts - 1); + pnts += 8; + x = *pnts++; + y = *pnts++; + + cx = *float_args++; + cy = *float_args++; + rx = *float_args++; + ry = *float_args++; + angle_start = *float_args++; + angle_stop = *float_args++; + x_rotate = *float_args++; + + _sin = sinf(x_rotate); + _cos = cosf(x_rotate); + + xyratio = ry / rx; + aggr = sh_get_aggr_matrix((shape_t *)path); + matrix[0] = _cos; + matrix[1] = -_sin * xyratio; + matrix[2] = cx; + matrix[3] = _sin; + matrix[4] = _cos * xyratio; + matrix[5] = cy; + + matrix_mul(aggr, matrix, dev_matrix); + mbe_save(cr); + mbe_transform(cr, dev_matrix); + mbe_arc(cr, 0, 0, rx, angle_start, angle_stop); + mbe_restore(cr); + + *pnts_p = pnts; + *float_args_p = float_args; +} + +#if 0 +void __sh_path_arc_path(mbe_t *cr, const co_aix **args_p, const int **fix_args_p) { - co_aix cx, cy, x0, y0, x, y, xx, xy; - co_aix dx, dy, dx0, dy0, dxx, dxy; + co_aix cx, cy, x0, y0, x, y; + co_aix dx, dy, dx0, dy0; + co_aix udxx, udxy; co_aix xyratio; co_aix rx; co_aix rx2; + co_aix dra45x, dra45y, udra45x, udra45y; + co_aix rra45, rra45_2; co_aix inner0, cross0; - co_aix circle_h0; co_aix inner, cross; co_aix angle, angle0; co_aix rotate; + co_aix _sqrt2; const co_aix *args = *args_p; const int *fix_args = *fix_args_p; int sweep; + _sqrt2 = sqrtf(2); + x0 = *(args - 2); y0 = *(args - 1); cx = *args++; cy = *args++; - xx = *args++; - xy = *args++; + ra45x = *args++; + ra45y = *args++; x = *args++; y = *args++; sweep = *fix_args++; @@ -265,36 +376,35 @@ dy = y - cy; dx0 = x0 - cx; dy0 = y0 - cy; - dxx = xx - cx; - dxy = xy - cy; + dra45x = ra45x - cx; + dra45y = ra45y - cy; - rx2 = dxx * dxx + dxy * dxy; - rx = sqrtf(rx2); + rra45_2 = dra45x * dra45x + dra45y * dra45y; + rra45 = sqrtf(rra45_2); + udra45x = dra45x / rra45; + udra45y = dra45y / rra45; + + udxx = (udra45x + udra45y) * _sqrt2; + udxy = (-udra45x + udra45y) * _sqrt2; /*! \note Why we calculate these numbers there? * If we compute it when filling arguments, sh_path_arc_cmd_arg_fill(), * we can avoid to recompute it for every drawing. But, transforming of * coordinate can effect value of the numbers. */ - inner0 = INNER(dxx, dxy, dx0, dy0); - cross0 = CROSS(dxx, dxy, dx0, dy0); - circle_h0 = sqrtf(rx2 - inner0 * inner0 / rx2); - xyratio = cross0 / rx / circle_h0; + rotate = acos(udxx); + if(udxy < 0) + rotate = 2 * PI - rotate; + + angle0 = angle_diff(udxx, udxy, dx0, dy0); + angle = angle_diff(udxx, udxy, dx, dy); + + ASSERT(rx != 0); + xyratio = udra45y / udra45x; if(xyratio < 0) xyratio = -xyratio; - angle0 = acos(inner0 / rx2); - if(cross0 < 0) - angle0 = PI * 2 - angle0; /* 3rd, 4th Quadrant */ - - inner = INNER(dxx, dxy, dx, dy); - cross = CROSS(dxx, dxy, dx, dy); - angle = acos(inner / rx2); - if(cross < 0) - angle = PI * 2 - angle; /* 3rd, 4th Quadrant */ - /* Make a path for arc */ - rotate = acos(dxx / rx); mbe_save(cr); mbe_translate(cr, cx, cy); mbe_rotate(cr, rotate); @@ -308,6 +418,7 @@ *args_p = args; *fix_args_p = fix_args; } +#endif /* ============================================================ */ @@ -322,13 +433,13 @@ * * \todo Notify programmers that syntax or value error of path data. */ -static int sh_path_cmd_arg_cnt(char *data, int *cmd_cntp, int *arg_cntp, - int *fix_arg_cntp) { +static int sh_path_cmd_arg_cnt(char *data, int *cmd_cntp, int *pnt_cntp, + int *float_arg_cntp) { char *p, *old; - int cmd_cnt, arg_cnt, fix_arg_cnt; + int cmd_cnt, pnt_cnt, float_arg_cnt; int i; - cmd_cnt = arg_cnt = fix_arg_cnt = 0; + cmd_cnt = pnt_cnt = float_arg_cnt = 0; p = data; SKIP_SPACE(p); while(*p) { @@ -342,41 +453,41 @@ SKIP_NUM(p); if(p == old) break; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; cmd_cnt++; } @@ -392,28 +503,28 @@ SKIP_NUM(p); if(p == old) break; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; cmd_cnt++; } @@ -431,14 +542,14 @@ SKIP_NUM(p); if(p == old) break; - arg_cnt++; + pnt_cnt++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - arg_cnt++; + pnt_cnt++; cmd_cnt++; } @@ -453,7 +564,7 @@ SKIP_NUM(p); if(p == old) break; - arg_cnt += 2; + pnt_cnt += 2; cmd_cnt++; } @@ -475,8 +586,8 @@ return ERR; } - arg_cnt += 6; - fix_arg_cnt++; + pnt_cnt += 10; + float_arg_cnt += 7; cmd_cnt++; } @@ -493,8 +604,8 @@ } *cmd_cntp = cmd_cnt; - *arg_cntp = arg_cnt; - *fix_arg_cntp = fix_arg_cnt; + *pnt_cntp = pnt_cnt; + *float_arg_cntp = float_arg_cnt; return OK; } @@ -505,21 +616,21 @@ char *p, *old; char *cmds; char cmd; - co_aix *args; - int *fix_args; + co_aix *pnts; + co_aix *float_args; co_aix x, y; int r; cmds = path->user_data; - args = (co_aix *)(cmds + path->cmd_len); - fix_args = (int *)(cmds + path->cmd_len + - path->arg_len * sizeof(co_aix)); + pnts = (co_aix *)(cmds + path->cmd_len); + float_args = (co_aix *)(cmds + path->cmd_len + + path->pnt_len * sizeof(co_aix)); p = data; SKIP_SPACE(p); while(*p) { /* Transform all relative to absolute, */ - x = *(args - 2); - y = *(args - 1); + x = *(pnts - 2); + y = *(pnts - 1); switch((cmd = *p++)) { case 'c': @@ -531,47 +642,47 @@ SKIP_NUM(p); if(p == old) break; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; *cmds++ = toupper(cmd); } @@ -587,32 +698,32 @@ SKIP_NUM(p); if(p == old) break; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; *cmds++ = toupper(cmd); } @@ -630,16 +741,16 @@ SKIP_NUM(p); if(p == old) break; - *args = TO_ABSX; - args++; + *pnts = TO_ABSX; + pnts++; SKIP_SPACE(p); old = p; SKIP_NUM(p); if(p == old) return ERR; - *args = TO_ABSY; - args++; + *pnts = TO_ABSY; + pnts++; *cmds++ = toupper(cmd); } @@ -654,8 +765,8 @@ case 'A': case 'a': r = sh_path_arc_cmd_arg_fill(cmd, &cmds, - (const char **)&p, &args, - &fix_args); + (const char **)&p, &pnts, + &float_args); if(r != OK) return ERR; break; @@ -677,11 +788,12 @@ */ shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data) { sh_path_t *path; - int cmd_cnt, arg_cnt, fix_arg_cnt; + int cmd_cnt, pnt_cnt, float_arg_cnt; int msz; int r; - r = sh_path_cmd_arg_cnt(data, &cmd_cnt, &arg_cnt, &fix_arg_cnt); + r = sh_path_cmd_arg_cnt(data, &cmd_cnt, &pnt_cnt, + &float_arg_cnt); if(r == ERR) return NULL; @@ -698,10 +810,11 @@ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); path->cmd_len = cmd_cnt; - path->arg_len = arg_cnt; - path->fix_arg_len = fix_arg_cnt; + path->pnt_len = pnt_cnt; + path->float_arg_len = float_arg_cnt; - msz = cmd_cnt + sizeof(co_aix) * arg_cnt + sizeof(int) * fix_arg_cnt; + msz = cmd_cnt + sizeof(co_aix) * pnt_cnt + + sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { free(path); @@ -725,7 +838,11 @@ return (shape_t *)path; } -shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, char *commands, co_aix *arg,int arg_cnt,int *fix_arg,int fix_arg_cnt) { +shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, + char *commands, + co_aix *pnts, int pnt_cnt, + co_aix *float_args, + int float_arg_cnt) { sh_path_t *path; int msz; int cmd_cnt = strlen(commands); @@ -735,10 +852,12 @@ /*! \todo Remove this memset()? */ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); - path->cmd_len = strlen(commands); - path->arg_len = arg_cnt; - path->fix_arg_len = fix_arg_cnt; - msz = cmd_cnt + sizeof(co_aix) * arg_cnt + sizeof(int) * fix_arg_cnt; + cmd_cnt = (cmd_cnt + 3) & ~0x3; + path->cmd_len = cmd_cnt; + path->pnt_len = pnt_cnt; + path->float_arg_len = float_arg_cnt; + msz = cmd_cnt + sizeof(co_aix) * pnt_cnt + + sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { free(path); @@ -746,13 +865,14 @@ } path->dev_data = path->user_data + msz; - memcpy(path->user_data,commands,cmd_cnt); - memcpy(path->user_data+cmd_cnt,arg, sizeof(co_aix)*arg_cnt); - memcpy(path->user_data+cmd_cnt+arg_cnt*sizeof(co_aix),fix_arg, sizeof(int)*fix_arg_cnt); + memcpy(path->user_data, commands, strlen(commands)); + memcpy(path->user_data + cmd_cnt, pnts, sizeof(co_aix) * pnt_cnt); + memcpy(path->user_data + cmd_cnt + pnt_cnt * sizeof(co_aix), + float_args, sizeof(co_aix) * float_arg_cnt); memcpy(path->dev_data, path->user_data, msz); - + path->shape.free = sh_path_free; - + rdman_shape_man(rdman, (shape_t *)path); return (shape_t *)path; @@ -764,29 +884,29 @@ */ void sh_path_transform(shape_t *shape) { sh_path_t *path; - co_aix *user_args, *dev_args; + co_aix *pnts, *dev_pnts; co_aix (*poses)[2]; area_t *area; - int arg_len; + int pnt_len; int i; ASSERT(shape->type == SHT_PATH); - ASSERT((shape->arg_len & 0x1) == 0); + ASSERT((shape->pnt_len & 0x1) == 0); path = (sh_path_t *)shape; - user_args = (co_aix *)(path->user_data + path->cmd_len); - dev_args = (co_aix *)(path->dev_data + path->cmd_len); - arg_len = path->arg_len; - for(i = 0; i < arg_len; i += 2) { - dev_args[0] = *user_args++; - dev_args[1] = *user_args++; - coord_trans_pos(shape->coord, dev_args, dev_args + 1); - dev_args += 2; + pnts = (co_aix *)(path->user_data + path->cmd_len); + dev_pnts = (co_aix *)(path->dev_data + path->cmd_len); + pnt_len = path->pnt_len; + for(i = 0; i < pnt_len; i += 2) { + dev_pnts[0] = *pnts++; + dev_pnts[1] = *pnts++; + coord_trans_pos(shape->coord, dev_pnts, dev_pnts + 1); + dev_pnts += 2; } if(path->shape.geo) { poses = (co_aix (*)[2])(path->dev_data + path->cmd_len); - geo_from_positions(path->shape.geo, arg_len / 2, poses); + geo_from_positions(path->shape.geo, pnt_len / 2, poses); area = shape->geo->cur_area; area->x -= shape->stroke_width / 2 + 0.5; area->y -= shape->stroke_width / 2 + 0.5; @@ -799,8 +919,8 @@ sh_path_t *path; int cmd_len; char *cmds, cmd; - const co_aix *args; - const int *fix_args; + const co_aix *pnts; + const co_aix *float_args; co_aix x, y, x1, y1, x2, y2; int i; @@ -809,8 +929,8 @@ path = (sh_path_t *)shape; cmd_len = path->cmd_len; cmds = path->dev_data; - args = (co_aix *)(cmds + cmd_len); - fix_args = (int *)(cmds + cmd_len + path->arg_len * sizeof(co_aix)); + pnts = (co_aix *)(cmds + cmd_len); + float_args = (co_aix *)(cmds + cmd_len + path->pnt_len * sizeof(co_aix)); x = y = x1 = y1 = x2 = y2 = 0; for(i = 0; i < cmd_len; i++) { /* All path commands and arguments are transformed @@ -819,40 +939,40 @@ cmd = *cmds++; switch(cmd) { case 'M': - x = *args++; - y = *args++; + x = *pnts++; + y = *pnts++; mbe_move_to(cr, x, y); break; case 'L': - x = *args++; - y = *args++; + x = *pnts++; + y = *pnts++; mbe_line_to(cr, x, y); break; case 'C': - x1 = *args++; - y1 = *args++; - x2 = *args++; - y2 = *args++; - x = *args++; - y = *args++; + x1 = *pnts++; + y1 = *pnts++; + x2 = *pnts++; + y2 = *pnts++; + x = *pnts++; + y = *pnts++; mbe_curve_to(cr, x1, y1, x2, y2, x, y); break; case 'S': x1 = x + x - x2; y1 = y + y - y2; - x2 = *args++; - y2 = *args++; - x = *args++; - y = *args++; + x2 = *pnts++; + y2 = *pnts++; + x = *pnts++; + y = *pnts++; mbe_curve_to(cr, x1, y1, x2, y2, x, y); break; case 'Q': - x1 = *args++; - y1 = *args++; + x1 = *pnts++; + y1 = *pnts++; x2 = x1; y2 = y1; - x = *args++; - y = *args++; + x = *pnts++; + y = *pnts++; mbe_curve_to(cr, x1, y1, x2, y2, x, y); break; case 'T': @@ -860,12 +980,12 @@ y1 = y + y - y2; x2 = x1; y2 = y1; - x = *args++; - y = *args++; + x = *pnts++; + y = *pnts++; mbe_curve_to(cr, x1, y1, x2, y2, x, y); break; case 'A': - sh_path_arc_path(cr, &args, &fix_args); + _sh_path_arc_path(cr, path, &pnts, &float_args); break; case 'Z': mbe_close_path(cr); @@ -887,41 +1007,41 @@ void test_rdman_shape_path_new(void) { sh_path_t *path; - co_aix *args; + co_aix *pnts; path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); - CU_ASSERT(path->arg_len == 12); + CU_ASSERT(path->pnt_len == 12); CU_ASSERT(strncmp(path->user_data, "MLCLZ", 5) == 0); CU_ASSERT(strncmp(path->dev_data, "MLCLZ", 5) == 0); - args = (co_aix *)(path->user_data + path->cmd_len); - CU_ASSERT(args[0] == 33); - CU_ASSERT(args[1] == 25); - CU_ASSERT(args[2] == 66); - CU_ASSERT(args[3] == 80); - CU_ASSERT(args[4] == 99); - CU_ASSERT(args[5] == 167); - CU_ASSERT(args[6] == 110); - CU_ASSERT(args[7] == 102); - CU_ASSERT(args[8] == 121); - CU_ASSERT(args[9] == 179); - CU_ASSERT(args[10] == 33); - CU_ASSERT(args[11] == 77); + pnts = (co_aix *)(path->user_data + path->cmd_len); + CU_ASSERT(pnts[0] == 33); + CU_ASSERT(pnts[1] == 25); + CU_ASSERT(pnts[2] == 66); + CU_ASSERT(pnts[3] == 80); + CU_ASSERT(pnts[4] == 99); + CU_ASSERT(pnts[5] == 167); + CU_ASSERT(pnts[6] == 110); + CU_ASSERT(pnts[7] == 102); + CU_ASSERT(pnts[8] == 121); + CU_ASSERT(pnts[9] == 179); + CU_ASSERT(pnts[10] == 33); + CU_ASSERT(pnts[11] == 77); sh_path_free((shape_t *)path); } void test_path_transform(void) { sh_path_t *path; - co_aix *args; + co_aix *pnts; coord_t coord; geo_t geo; path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); - CU_ASSERT(path->arg_len == 12); + CU_ASSERT(path->pnt_len == 12); CU_ASSERT(strncmp(path->user_data, "MLCLZ", 5) == 0); CU_ASSERT(strncmp(path->dev_data, "MLCLZ", 5) == 0); @@ -938,19 +1058,19 @@ path->shape.coord = &coord; sh_path_transform((shape_t *)path); - args = (co_aix *)(path->dev_data + path->cmd_len); - CU_ASSERT(args[0] == 34); - CU_ASSERT(args[1] == 50); - CU_ASSERT(args[2] == 67); - CU_ASSERT(args[3] == 160); - CU_ASSERT(args[4] == 34); - CU_ASSERT(args[5] == 174); - CU_ASSERT(args[6] == 45); - CU_ASSERT(args[7] == 44); - CU_ASSERT(args[8] == 56); - CU_ASSERT(args[9] == 198); - CU_ASSERT(args[10] == 34); - CU_ASSERT(args[11] == 154); + pnts = (co_aix *)(path->dev_data + path->cmd_len); + CU_ASSERT(pnts[0] == 34); + CU_ASSERT(pnts[1] == 50); + CU_ASSERT(pnts[2] == 67); + CU_ASSERT(pnts[3] == 160); + CU_ASSERT(pnts[4] == 34); + CU_ASSERT(pnts[5] == 174); + CU_ASSERT(pnts[6] == 45); + CU_ASSERT(pnts[7] == 44); + CU_ASSERT(pnts[8] == 56); + CU_ASSERT(pnts[9] == 198); + CU_ASSERT(pnts[10] == 34); + CU_ASSERT(pnts[11] == 154); sh_path_free((shape_t *)path); }
--- a/tools/mb_c_source.m4 Thu Aug 06 15:38:08 2009 +0800 +++ b/tools/mb_c_source.m4 Thu Sep 10 17:36:45 2009 +0800 @@ -136,9 +136,10 @@ define([S_ADD_PATH],[[ { char _cmds[] = "$3"; - float _args[] = {$4}; - int _fix_args[] = {$6}; - obj->$1 = rdman_shape_path_new_from_binary(rdman, _cmds,_args,$5,_fix_args,$7); + float _pnts[] = {$4}; + float _float_args[] = {$6}; + obj->$1 = rdman_shape_path_new_from_binary(rdman, _cmds, + _pnts, $5, _float_args, $7); rdman_add_shape(rdman, obj->$1, obj->$2); } ]])
--- a/tools/svg2code.py Thu Aug 06 15:38:08 2009 +0800 +++ b/tools/svg2code.py Thu Sep 10 17:36:45 2009 +0800 @@ -238,7 +238,7 @@ _sin = math.sin(x_rotate) _cos = math.cos(x_rotate) - nrx = x * _cos + y * _sin + nrx = x * _cos + y * _sin # Not Rotated X nry = x * -_sin + y * _cos nrx0 = x0 * _cos + y0 * _sin nry0 = x0 * -_sin + y0 * _cos @@ -251,6 +251,9 @@ udx2 = udx * udx udy2 = udy * udy udl2 = udx2 + udy2 + if udl2 > 1: # make sure never > 1 + udl2 = 1 + pass if udy != 0: # center is at left-side of arc @@ -280,9 +283,7 @@ cx = nrcx * _cos - nrcy * _sin cy = nrcx * _sin + nrcy * _cos - xx = rx * _cos + cx - xy = rx * _sin + cy - return cx, cy, xx, xy + return cx, cy # M x y : Move to (x,y) # Z : close path @@ -310,7 +311,36 @@ 'T': 2, 't':2, 'A': 7, 'a':7} -def translate_path_data(data,codefo): +def _angle_rotated_ellipse(x, y, rx, ry, x_rotate): + import math + + _cos = math.cos(x_rotate) + _sin = math.sin(x_rotate) + + nrx = (x * _cos + y * _sin) / rx + nry = (-x * _sin + y * _cos) / ry + + xy_tan = nry / nrx + xy_angle = math.atan(xy_tan) + + if nrx < 0: + xy_angle = math.pi + xy_angle + pass + + return xy_angle + +def rotate(x, y, angle): + import math + _cos = math.cos(angle) + _sin = math.sin(angle) + nx = x * _cos - y * _sin + ny = x * _sin + y * _cos + return nx, ny + +def translate_path_data(data, codefo): + import string + import math + temp = data.split() fields=[] for f in temp: @@ -320,8 +350,8 @@ cmd = '' cmd_args=0 commands='' - args=[] - fix_args=[] + pnts=[] + float_args=[] for f in fields: if f in command_length: if cmd_args != 0 and (narg % cmd_args) != 0: @@ -334,24 +364,87 @@ if (narg % cmd_args) == 0: commands = commands + cmd pass + + if cmd == 'H': + arg = float(f) + pnts.append(arg) + pnts.append(pnts[-2]) + continue + if cmd == 'h': + arg = float(f) + pnts.append(arg + pnts[-2]) + pnts.append(pnts[-2]) + continue + if cmd == 'V': + arg = float(f) + pnts.append(pnts[-2]) + pnts.append(arg) + continue + if cmd == 'v': + arg = float(f) + pnts.append(pnts[-2]) + pnts.append(arg + pnts[-2]) + continue + arg = float(f) - args.append(arg) + if (cmd not in 'am') and (cmd in string.lowercase): + # relative and not arc or moveto + arg = arg + pnts[-2] + pass + pnts.append(arg) narg = narg + 1 - + + # For arc curve if (narg % cmd_args) == 0 and (cmd in 'Aa'): x0, y0, rx, ry, x_rotate, large, sweep, x, y = \ - tuple(args[-9:]) + tuple(pnts[-9:]) + if cmd == 'a': + # relative position + abs_x = x + x0 + abs_y = y + y0 + else: + abs_x = x + abs_y = y + pass x_rotate = int(x_rotate) large = int(large) sweep = int(sweep) - cx, cy, xx, xy = _calc_ellipse_of_arc(x0, y0, rx, ry, - x_rotate, large, - sweep, x, y) - args[-7:] = [cx, cy, xx, xy, x, y] - fix_args.append(sweep) + cx, cy = _calc_ellipse_of_arc(x0, y0, rx, ry, + x_rotate, large, + sweep, abs_x, abs_y) + # Corners + c0x, c0y = rotate(-rx, -ry, x_rotate) + c0x, c0y = c0x + cx, c0y + cy + + c1x, c1y = rotate(rx, -ry, x_rotate) + c1x, c1y = c1x + cx, c1y + cy + + c2x, c2y = rotate(rx, ry, x_rotate) + c2x, c2y = c2x + cx, c2y + cy + + c3x, c3y = rotate(-rx, ry, x_rotate) + c3x, c3y = c3x + cx, c3y + cy + + pnts[-7:] = [c0x, c0y, c1x, c1y, c2x, c2y, c3x, c3y, abs_x, abs_y] + + start_angle = _angle_rotated_ellipse(x0 - cx, y0 - cy, + rx, ry, x_rotate) + stop_angle = _angle_rotated_ellipse(x - cx, y - cy, + rx, ry, x_rotate) + + # sweep == 1 for positive-angle direction + # sweep == 0 for negative-angle direction + if start_angle > stop_angle and sweep: + stop_angle = math.pi * 2 + stop_angle + elif start_angle < stop_angle and not sweep: + start_angle = math.pi * 2 + start_angle + pass + + float_args.extend([cx, cy, rx, ry, + start_angle, stop_angle, x_rotate]) pass pass - return commands, args, fix_args + return commands, pnts, float_args _id_sn = 0 @@ -389,17 +482,19 @@ path_id = path.getAttribute('id') d = path.getAttribute('d') - (commands,args,fix_args) = translate_path_data(d,codefo) + (commands, pnts, float_args) = translate_path_data(d, codefo) print >> codefo, 'dnl' #print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id) - sarg='' - for c in args: - sarg = sarg + "%f," % c - s_fix_arg='' - for c in fix_args: - s_fix_arg = s_fix_arg + ("%d," % c) + spnts='' + for c in pnts: + spnts = spnts + "%f," % c + s_float_arg='' + for c in float_args: + s_float_arg = s_float_arg + ("%f," % c) - print >> codefo, 'ADD_PATH([%s], [%s],[%s],[%s],[%d],[%s],[%d])dnl' % (path_id, coord_id,commands,sarg,len(args),s_fix_arg,len(fix_args)) + print >> codefo, 'ADD_PATH([%s], [%s], [%s], [%s], [%d], [%s], [%d])dnl' % ( + path_id, coord_id, commands, spnts, len(pnts), + s_float_arg, len(float_args)) translate_style(path, coord_id, codefo, doc, 'PATH_') pass