00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <ctype.h>
00004 #include <string.h>
00005 #include <cairo.h>
00006 #include "mb_types.h"
00007 #include "mb_redraw_man.h"
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 typedef struct _sh_path {
00020 shape_t shape;
00021 int cmd_len;
00022 int arg_len;
00023 int fix_arg_len;
00024 char *user_data;
00025 char *dev_data;
00026 } sh_path_t;
00027 #define RESERVED_AIXS sizeof(co_aix[2])
00028
00029 #define ASSERT(x)
00030 #define SKIP_SPACE(x) while(*(x) && (isspace(*(x)) || *(x) == ',')) { (x)++; }
00031 #define SKIP_NUM(x) \
00032 while(*(x) && \
00033 (isdigit(*(x)) || \
00034 *(x) == 'e' || \
00035 *(x) == 'E' || \
00036 *(x) == '-' || \
00037 *(x) == '+' || \
00038 *(x) == '.')) { \
00039 (x)++; \
00040 }
00041 #define OK 0
00042 #define ERR -1
00043 #define PI 3.1415926
00044
00045
00046
00047
00048 #include <math.h>
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 static int calc_center_and_x_aix(co_aix x0, co_aix y0,
00085 co_aix x, co_aix y,
00086 co_aix rx, co_aix ry,
00087 co_aix x_rotate,
00088 int large, int sweep,
00089 co_aix *cx, co_aix *cy,
00090 co_aix *xx, co_aix *xy) {
00091 co_aix nrx, nry, nrx0, nry0;
00092 co_aix udx, udy, udx2, udy2;
00093 co_aix umx, umy;
00094 co_aix udcx, udcy;
00095 co_aix nrcx, nrcy;
00096 co_aix udl2;
00097 float _sin = sinf(x_rotate);
00098 float _cos = cosf(x_rotate);
00099 int reflect;
00100
00101 nrx = x * _cos + y * _sin;
00102 nry = x * -_sin + y * _cos;
00103 nrx0 = x0 * _cos + y0 * _sin;
00104 nry0 = x0 * -_sin + y0 * _cos;
00105
00106 udx = (nrx - nrx0) / 2 / rx;
00107 udy = (nry - nry0) / 2 / ry;
00108 umx = (nrx + nrx0) / 2 / rx;
00109 umy = (nry + nry0) / 2 / ry;
00110
00111 udx2 = udx * udx;
00112 udy2 = udy * udy;
00113 udl2 = udx2 + udy2;
00114
00115 if(udy != 0) {
00116 udcx = -sqrtf((1 - udl2) * udl2) / (udy + udx2 / udy);
00117 udcy = -udcx * udx / udy;
00118 } else {
00119 udcx = 0;
00120 udcy = sqrtf((1 - udl2) * udl2) / udx;
00121 }
00122
00123 reflect = 0;
00124 if(large)
00125 reflect ^= 1;
00126 if(sweep != 1)
00127 reflect ^= 1;
00128 if(reflect) {
00129 udcx = -udcx;
00130 udcy = -udcy;
00131 }
00132
00133 nrcx = rx * (udcx + umx);
00134 nrcy = ry * (udcy + umy);
00135
00136 *cx = nrcx * _cos - nrcy * _sin;
00137 *cy = nrcx * _sin + nrcy * _cos;
00138
00139 *xx = rx * _cos + *cx;
00140 *xy = rx * _sin + *cy;
00141
00142 return OK;
00143 }
00144
00145
00146 #define TAKE_NUM(r) do { \
00147 SKIP_SPACE(p); \
00148 old = p; \
00149 SKIP_NUM(p); \
00150 if(p == old) \
00151 return ERR; \
00152 r = atof(old); \
00153 } while(0);
00154
00155 static int sh_path_arc_cmd_arg_fill(char cmd, char **cmds_p,
00156 const char **data_p,
00157 co_aix **args_p,
00158 int **fix_args_p) {
00159 co_aix rx, ry;
00160 co_aix x_rotate;
00161 int large, sweep;
00162 co_aix x, y, x0, y0, cx, cy, xx, xy;
00163 co_aix *args = *args_p;
00164 const char *old;
00165 const char *p;
00166 char *cmds;
00167 int *fix_args;
00168
00169 p = *data_p;
00170 cmds = *cmds_p;
00171 fix_args = *fix_args_p;
00172 while(*p) {
00173 SKIP_SPACE(p);
00174 old = p;
00175 SKIP_NUM(p);
00176 if(p == old)
00177 break;
00178 rx = atof(old);
00179
00180 TAKE_NUM(ry);
00181 TAKE_NUM(x_rotate);
00182 TAKE_NUM(large);
00183 TAKE_NUM(sweep);
00184 TAKE_NUM(x);
00185 TAKE_NUM(y)
00186
00187 x0 = *(args - 2);
00188 y0 = *(args - 1);
00189
00190 if(islower(cmd)) {
00191 x += x0;
00192 y += y0;
00193 }
00194
00195 calc_center_and_x_aix(x0, y0, x, y,
00196 rx, ry,
00197 x_rotate, large, sweep,
00198 &cx, &cy, &xx, &xy);
00199
00200 *(args++) = cx;
00201 *(args++) = cy;
00202 *(args++) = xx;
00203 *(args++) = xy;
00204 *(args++) = x;
00205 *(args++) = y;
00206
00207 *cmds++ = toupper(cmd);
00208 *fix_args++ = sweep;
00209 }
00210
00211 *data_p = p;
00212 *args_p = args;
00213 *cmds_p = cmds;
00214 *fix_args_p = fix_args;
00215
00216 return OK;
00217 }
00218
00219 #define INNER(x1, y1, x2, y2) ((x1) * (x2) + (y1) * (y2))
00220 #define CROSS(x1, y1, x2, y2) ((x1) * (y2) - (y1) * (x2))
00221
00222
00223
00224 void sh_path_arc_path(cairo_t *cr, const co_aix **args_p,
00225 const int **fix_args_p) {
00226 co_aix cx, cy, x0, y0, x, y, xx, xy;
00227 co_aix dx, dy, dx0, dy0, dxx, dxy;
00228 co_aix xyratio;
00229 co_aix rx;
00230 co_aix rx2;
00231 co_aix inner0, cross0;
00232 co_aix circle_h0;
00233 co_aix inner, cross;
00234 co_aix angle, angle0;
00235 co_aix rotate;
00236 const co_aix *args = *args_p;
00237 const int *fix_args = *fix_args_p;
00238 int sweep;
00239
00240 x0 = *(args - 2);
00241 y0 = *(args - 1);
00242 cx = *args++;
00243 cy = *args++;
00244 xx = *args++;
00245 xy = *args++;
00246 x = *args++;
00247 y = *args++;
00248 sweep = *fix_args++;
00249
00250 dx = x - cx;
00251 dy = y - cy;
00252 dx0 = x0 - cx;
00253 dy0 = y0 - cy;
00254 dxx = xx - cx;
00255 dxy = xy - cy;
00256
00257 rx2 = dxx * dxx + dxy * dxy;
00258 rx = sqrtf(rx2);
00259
00260
00261
00262
00263
00264
00265 inner0 = INNER(dxx, dxy, dx0, dy0);
00266 cross0 = CROSS(dxx, dxy, dx0, dy0);
00267 circle_h0 = sqrtf(rx2 - inner0 * inner0 / rx2);
00268 xyratio = cross0 / rx / circle_h0;
00269 if(xyratio < 0)
00270 xyratio = -xyratio;
00271
00272 angle0 = acos(inner0 / rx2);
00273 if(cross0 < 0)
00274 angle0 = PI * 2 - angle0;
00275
00276 inner = INNER(dxx, dxy, dx, dy);
00277 cross = CROSS(dxx, dxy, dx, dy);
00278 angle = acos(inner / rx2);
00279 if(cross < 0)
00280 angle = PI * 2 - angle;
00281
00282
00283 rotate = acos(dxx / rx);
00284 cairo_save(cr);
00285 cairo_translate(cr, cx, cy);
00286 cairo_rotate(cr, rotate);
00287 cairo_scale(cr, 1.0, xyratio);
00288 if(sweep)
00289 cairo_arc(cr, 0, 0, rx, angle0, angle);
00290 else
00291 cairo_arc_negative(cr, 0, 0, rx, angle0, angle);
00292 cairo_restore(cr);
00293
00294 *args_p = args;
00295 *fix_args_p = fix_args;
00296 }
00297
00298
00299
00300 static void sh_path_free(shape_t *shape) {
00301 sh_path_t *path = (sh_path_t *)shape;
00302 if(path->user_data)
00303 free(path->user_data);
00304 free(path);
00305 }
00306
00307
00308
00309
00310
00311 static int sh_path_cmd_arg_cnt(char *data, int *cmd_cntp, int *arg_cntp,
00312 int *fix_arg_cntp) {
00313 char *p, *old;
00314 int cmd_cnt, arg_cnt, fix_arg_cnt;
00315 int i;
00316
00317 cmd_cnt = arg_cnt = fix_arg_cnt = 0;
00318 p = data;
00319 SKIP_SPACE(p);
00320 while(*p) {
00321 switch(*p++) {
00322 case 'c':
00323 case 'C':
00324 while(*p) {
00325 old = p;
00326 SKIP_SPACE(p);
00327 old = p;
00328 SKIP_NUM(p);
00329 if(p == old)
00330 break;
00331 arg_cnt++;
00332
00333 SKIP_SPACE(p);
00334 old = p;
00335 SKIP_NUM(p);
00336 if(p == old)
00337 return ERR;
00338 arg_cnt++;
00339
00340 SKIP_SPACE(p);
00341 old = p;
00342 SKIP_NUM(p);
00343 if(p == old)
00344 return ERR;
00345 arg_cnt++;
00346
00347 SKIP_SPACE(p);
00348 old = p;
00349 SKIP_NUM(p);
00350 if(p == old)
00351 return ERR;
00352 arg_cnt++;
00353 SKIP_SPACE(p);
00354 old = p;
00355 SKIP_NUM(p);
00356 if(p == old)
00357 return ERR;
00358 arg_cnt++;
00359
00360 SKIP_SPACE(p);
00361 old = p;
00362 SKIP_NUM(p);
00363 if(p == old)
00364 return ERR;
00365 arg_cnt++;
00366
00367 cmd_cnt++;
00368 }
00369 break;
00370 case 's':
00371 case 'S':
00372 case 'q':
00373 case 'Q':
00374 while(*p) {
00375 old = p;
00376 SKIP_SPACE(p);
00377 old = p;
00378 SKIP_NUM(p);
00379 if(p == old)
00380 break;
00381 arg_cnt++;
00382
00383 SKIP_SPACE(p);
00384 old = p;
00385 SKIP_NUM(p);
00386 if(p == old)
00387 return ERR;
00388 arg_cnt++;
00389
00390 SKIP_SPACE(p);
00391 old = p;
00392 SKIP_NUM(p);
00393 if(p == old)
00394 return ERR;
00395 arg_cnt++;
00396
00397 SKIP_SPACE(p);
00398 old = p;
00399 SKIP_NUM(p);
00400 if(p == old)
00401 return ERR;
00402 arg_cnt++;
00403
00404 cmd_cnt++;
00405 }
00406 break;
00407 case 'm':
00408 case 'M':
00409 case 'l':
00410 case 'L':
00411 case 't':
00412 case 'T':
00413 while(*p) {
00414 old = p;
00415 SKIP_SPACE(p);
00416 old = p;
00417 SKIP_NUM(p);
00418 if(p == old)
00419 break;
00420 arg_cnt++;
00421
00422 SKIP_SPACE(p);
00423 old = p;
00424 SKIP_NUM(p);
00425 if(p == old)
00426 return ERR;
00427 arg_cnt++;
00428
00429 cmd_cnt++;
00430 }
00431 break;
00432 case 'h':
00433 case 'H':
00434 case 'v':
00435 case 'V':
00436 while(*p) {
00437 SKIP_SPACE(p);
00438 old = p;
00439 SKIP_NUM(p);
00440 if(p == old)
00441 break;
00442 arg_cnt += 2;
00443
00444 cmd_cnt++;
00445 }
00446 break;
00447 case 'A':
00448 case 'a':
00449 while(*p) {
00450 SKIP_SPACE(p);
00451 old = p;
00452 SKIP_NUM(p);
00453 if(p == old)
00454 break;
00455
00456 for(i = 0; i < 6; i++) {
00457 SKIP_SPACE(p);
00458 old = p;
00459 SKIP_NUM(p);
00460 if(p == old)
00461 return ERR;
00462 }
00463
00464 arg_cnt += 6;
00465 fix_arg_cnt++;
00466
00467 cmd_cnt++;
00468 }
00469 break;
00470 case 'z':
00471 case 'Z':
00472 cmd_cnt++;
00473 break;
00474 default:
00475 return ERR;
00476 }
00477
00478 SKIP_SPACE(p);
00479 }
00480
00481 *cmd_cntp = cmd_cnt;
00482 *arg_cntp = arg_cnt;
00483 *fix_arg_cntp = fix_arg_cnt;
00484 return OK;
00485 }
00486
00487 #define TO_ABSX islower(cmd)? x + atof(old): atof(old)
00488 #define TO_ABSY islower(cmd)? y + atof(old): atof(old)
00489
00490 static int sh_path_cmd_arg_fill(char *data, sh_path_t *path) {
00491 char *p, *old;
00492 char *cmds;
00493 char cmd;
00494 co_aix *args;
00495 int *fix_args;
00496 co_aix x, y;
00497 int r;
00498
00499 cmds = path->user_data;
00500 args = (co_aix *)(cmds + path->cmd_len);
00501 fix_args = (int *)(cmds + path->cmd_len +
00502 path->arg_len * sizeof(co_aix));
00503 p = data;
00504 SKIP_SPACE(p);
00505 while(*p) {
00506
00507 x = *(args - 2);
00508 y = *(args - 1);
00509
00510 switch((cmd = *p++)) {
00511 case 'c':
00512 case 'C':
00513 while(*p) {
00514 old = p;
00515 SKIP_SPACE(p);
00516 old = p;
00517 SKIP_NUM(p);
00518 if(p == old)
00519 break;
00520 *args = TO_ABSX;
00521 args++;
00522
00523 SKIP_SPACE(p);
00524 old = p;
00525 SKIP_NUM(p);
00526 if(p == old)
00527 return ERR;
00528 *args = TO_ABSY;
00529 args++;
00530
00531 SKIP_SPACE(p);
00532 old = p;
00533 SKIP_NUM(p);
00534 if(p == old)
00535 return ERR;
00536 *args = TO_ABSX;
00537 args++;
00538
00539 SKIP_SPACE(p);
00540 old = p;
00541 SKIP_NUM(p);
00542 if(p == old)
00543 return ERR;
00544 *args = TO_ABSY;
00545 args++;
00546 SKIP_SPACE(p);
00547 old = p;
00548 SKIP_NUM(p);
00549 if(p == old)
00550 return ERR;
00551 *args = TO_ABSX;
00552 args++;
00553
00554 SKIP_SPACE(p);
00555 old = p;
00556 SKIP_NUM(p);
00557 if(p == old)
00558 return ERR;
00559 *args = TO_ABSY;
00560 args++;
00561
00562 *cmds++ = toupper(cmd);
00563 }
00564 break;
00565 case 's':
00566 case 'S':
00567 case 'q':
00568 case 'Q':
00569 while(*p) {
00570 old = p;
00571 SKIP_SPACE(p);
00572 old = p;
00573 SKIP_NUM(p);
00574 if(p == old)
00575 break;
00576 *args = TO_ABSX;
00577 args++;
00578
00579 SKIP_SPACE(p);
00580 old = p;
00581 SKIP_NUM(p);
00582 if(p == old)
00583 return ERR;
00584 *args = TO_ABSY;
00585 args++;
00586
00587 SKIP_SPACE(p);
00588 old = p;
00589 SKIP_NUM(p);
00590 if(p == old)
00591 return ERR;
00592 *args = TO_ABSX;
00593 args++;
00594
00595 SKIP_SPACE(p);
00596 old = p;
00597 SKIP_NUM(p);
00598 if(p == old)
00599 return ERR;
00600 *args = TO_ABSY;
00601 args++;
00602
00603 *cmds++ = toupper(cmd);
00604 }
00605 break;
00606 case 'm':
00607 case 'M':
00608 case 'l':
00609 case 'L':
00610 case 't':
00611 case 'T':
00612 while(*p) {
00613 old = p;
00614 SKIP_SPACE(p);
00615 old = p;
00616 SKIP_NUM(p);
00617 if(p == old)
00618 break;
00619 *args = TO_ABSX;
00620 args++;
00621
00622 SKIP_SPACE(p);
00623 old = p;
00624 SKIP_NUM(p);
00625 if(p == old)
00626 return ERR;
00627 *args = TO_ABSY;
00628 args++;
00629
00630 *cmds++ = toupper(cmd);
00631 }
00632 break;
00633 case 'h':
00634 case 'H':
00635 case 'v':
00636 case 'V':
00637
00638 return ERR;
00639
00640 case 'A':
00641 case 'a':
00642 r = sh_path_arc_cmd_arg_fill(cmd, &cmds,
00643 (const char **)&p, &args,
00644 &fix_args);
00645 if(r != OK)
00646 return ERR;
00647 break;
00648
00649 case 'z':
00650 case 'Z':
00651 *cmds++ = toupper(cmd);
00652 break;
00653 default:
00654 return ERR;
00655 }
00656 SKIP_SPACE(p);
00657 }
00658
00659 return OK;
00660 }
00661
00662
00663
00664 shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data) {
00665 sh_path_t *path;
00666 int cmd_cnt, arg_cnt, fix_arg_cnt;
00667 int msz;
00668 int r;
00669
00670 r = sh_path_cmd_arg_cnt(data, &cmd_cnt, &arg_cnt, &fix_arg_cnt);
00671 if(r == ERR)
00672 return NULL;
00673
00674
00675
00676
00677
00678 cmd_cnt += RESERVED_AIXS;
00679 cmd_cnt = (cmd_cnt + 3) & ~0x3;
00680
00681
00682 path = (sh_path_t *)malloc(sizeof(sh_path_t));
00683
00684 memset(&path->shape, 0, sizeof(shape_t));
00685 path->shape.sh_type = SHT_PATH;
00686 path->cmd_len = cmd_cnt;
00687 path->arg_len = arg_cnt;
00688 path->fix_arg_len = fix_arg_cnt;
00689
00690 msz = cmd_cnt + sizeof(co_aix) * arg_cnt + sizeof(int) * fix_arg_cnt;
00691 path->user_data = (char *)malloc(msz * 2);
00692 if(path->user_data == NULL) {
00693 free(path);
00694 return NULL;
00695 }
00696
00697 path->dev_data = path->user_data + msz;
00698
00699 r = sh_path_cmd_arg_fill(data, path);
00700 if(r == ERR) {
00701 free(path->user_data);
00702 free(path);
00703 return NULL;
00704 }
00705 memcpy(path->dev_data, path->user_data, msz);
00706
00707 path->shape.free = sh_path_free;
00708
00709 #ifndef UNITTEST
00710 rdman_shape_man(rdman, (shape_t *)path);
00711 #endif
00712
00713 return (shape_t *)path;
00714 }
00715
00716
00717
00718
00719 void sh_path_transform(shape_t *shape) {
00720 sh_path_t *path;
00721 co_aix *user_args, *dev_args;
00722 co_aix (*poses)[2];
00723 area_t *area;
00724 int arg_len;
00725 int i;
00726
00727 ASSERT(shape->type == SHT_PATH);
00728 ASSERT((shape->arg_len & 0x1) == 0);
00729
00730 path = (sh_path_t *)shape;
00731 user_args = (co_aix *)(path->user_data + path->cmd_len);
00732 dev_args = (co_aix *)(path->dev_data + path->cmd_len);
00733 arg_len = path->arg_len;
00734 for(i = 0; i < arg_len; i += 2) {
00735 dev_args[0] = *user_args++;
00736 dev_args[1] = *user_args++;
00737 coord_trans_pos(shape->coord, dev_args, dev_args + 1);
00738 dev_args += 2;
00739 }
00740
00741 if(path->shape.geo) {
00742 poses = (co_aix (*)[2])(path->dev_data + path->cmd_len);
00743 geo_from_positions(path->shape.geo, arg_len / 2, poses);
00744 area = shape->geo->cur_area;
00745 area->x -= shape->stroke_width/2 + 1;
00746 area->y -= shape->stroke_width/2 + 1;
00747 area->w += shape->stroke_width + 2;
00748 area->h += shape->stroke_width + 2;
00749 }
00750 }
00751
00752 static void sh_path_path(shape_t *shape, cairo_t *cr) {
00753 sh_path_t *path;
00754 int cmd_len;
00755 char *cmds, cmd;
00756 const co_aix *args;
00757 const int *fix_args;
00758 co_aix x, y, x1, y1, x2, y2;
00759 int i;
00760
00761 ASSERT(shape->type == SHT_PATH);
00762
00763 path = (sh_path_t *)shape;
00764 cmd_len = path->cmd_len;
00765 cmds = path->dev_data;
00766 args = (co_aix *)(cmds + cmd_len);
00767 fix_args = (int *)(cmds + cmd_len + path->arg_len * sizeof(co_aix));
00768 x = y = x1 = y1 = x2 = y2 = 0;
00769 for(i = 0; i < cmd_len; i++) {
00770
00771
00772
00773 cmd = *cmds++;
00774 switch(cmd) {
00775 case 'M':
00776 x = *args++;
00777 y = *args++;
00778 cairo_move_to(cr, x, y);
00779 break;
00780 case 'L':
00781 x = *args++;
00782 y = *args++;
00783 cairo_line_to(cr, x, y);
00784 break;
00785 case 'C':
00786 x1 = *args++;
00787 y1 = *args++;
00788 x2 = *args++;
00789 y2 = *args++;
00790 x = *args++;
00791 y = *args++;
00792 cairo_curve_to(cr, x1, y1, x2, y2, x, y);
00793 break;
00794 case 'S':
00795 x1 = x + x - x2;
00796 y1 = y + y - y2;
00797 x2 = *args++;
00798 y2 = *args++;
00799 x = *args++;
00800 y = *args++;
00801 cairo_curve_to(cr, x1, y1, x2, y2, x, y);
00802 break;
00803 case 'Q':
00804 x1 = *args++;
00805 y1 = *args++;
00806 x2 = x1;
00807 y2 = y1;
00808 x = *args++;
00809 y = *args++;
00810 cairo_curve_to(cr, x1, y1, x2, y2, x, y);
00811 break;
00812 case 'T':
00813 x1 = x + x - x2;
00814 y1 = y + y - y2;
00815 x2 = x1;
00816 y2 = y1;
00817 x = *args++;
00818 y = *args++;
00819 cairo_curve_to(cr, x1, y1, x2, y2, x, y);
00820 break;
00821 case 'A':
00822 sh_path_arc_path(cr, &args, &fix_args);
00823 break;
00824 case 'Z':
00825 cairo_close_path(cr);
00826 break;
00827 case '\x0':
00828 i = cmd_len;
00829 break;
00830 }
00831 }
00832 }
00833
00834 void sh_path_draw(shape_t *shape, cairo_t *cr) {
00835 sh_path_path(shape, cr);
00836 }
00837
00838 #ifdef UNITTEST
00839
00840 #include <CUnit/Basic.h>
00841
00842 void test_rdman_shape_path_new(void) {
00843 sh_path_t *path;
00844 co_aix *args;
00845
00846 path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55c 33 87 44 22 55 99L33 77z");
00847 CU_ASSERT(path != NULL);
00848 CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3));
00849 CU_ASSERT(path->arg_len == 12);
00850 CU_ASSERT(strncmp(path->user_data, "MLCLZ", 5) == 0);
00851 CU_ASSERT(strncmp(path->dev_data, "MLCLZ", 5) == 0);
00852
00853 args = (co_aix *)(path->user_data + path->cmd_len);
00854 CU_ASSERT(args[0] == 33);
00855 CU_ASSERT(args[1] == 25);
00856 CU_ASSERT(args[2] == 66);
00857 CU_ASSERT(args[3] == 80);
00858 CU_ASSERT(args[4] == 99);
00859 CU_ASSERT(args[5] == 167);
00860 CU_ASSERT(args[6] == 110);
00861 CU_ASSERT(args[7] == 102);
00862 CU_ASSERT(args[8] == 121);
00863 CU_ASSERT(args[9] == 179);
00864 CU_ASSERT(args[10] == 33);
00865 CU_ASSERT(args[11] == 77);
00866 sh_path_free((shape_t *)path);
00867 }
00868
00869 void test_path_transform(void) {
00870 sh_path_t *path;
00871 co_aix *args;
00872 coord_t coord;
00873 geo_t geo;
00874
00875 path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55C 33 87 44 22 55 99L33 77z");
00876 CU_ASSERT(path != NULL);
00877 CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3));
00878 CU_ASSERT(path->arg_len == 12);
00879 CU_ASSERT(strncmp(path->user_data, "MLCLZ", 5) == 0);
00880 CU_ASSERT(strncmp(path->dev_data, "MLCLZ", 5) == 0);
00881
00882 geo_init(&geo);
00883 path->shape.geo = &geo;
00884 geo.shape = (shape_t *)path;
00885
00886 coord.aggr_matrix[0] = 1;
00887 coord.aggr_matrix[1] = 0;
00888 coord.aggr_matrix[2] = 1;
00889 coord.aggr_matrix[3] = 0;
00890 coord.aggr_matrix[4] = 2;
00891 coord.aggr_matrix[5] = 0;
00892 path->shape.coord = &coord;
00893 sh_path_transform((shape_t *)path);
00894
00895 args = (co_aix *)(path->dev_data + path->cmd_len);
00896 CU_ASSERT(args[0] == 34);
00897 CU_ASSERT(args[1] == 50);
00898 CU_ASSERT(args[2] == 67);
00899 CU_ASSERT(args[3] == 160);
00900 CU_ASSERT(args[4] == 34);
00901 CU_ASSERT(args[5] == 174);
00902 CU_ASSERT(args[6] == 45);
00903 CU_ASSERT(args[7] == 44);
00904 CU_ASSERT(args[8] == 56);
00905 CU_ASSERT(args[9] == 198);
00906 CU_ASSERT(args[10] == 34);
00907 CU_ASSERT(args[11] == 154);
00908
00909 sh_path_free((shape_t *)path);
00910 }
00911
00912 void test_spaces_head_tail(void) {
00913 sh_path_t *path;
00914
00915 path = (sh_path_t *)
00916 rdman_shape_path_new(NULL,
00917 " M 33 25l33 55C 33 87 44 22 55 99L33 77z ");
00918 CU_ASSERT(path != NULL);
00919 sh_path_free((shape_t *)path);
00920 }
00921
00922 CU_pSuite get_shape_path_suite(void) {
00923 CU_pSuite suite;
00924
00925 suite = CU_add_suite("Suite_shape_path", NULL, NULL);
00926 CU_ADD_TEST(suite, test_rdman_shape_path_new);
00927 CU_ADD_TEST(suite, test_path_transform);
00928
00929 return suite;
00930 }
00931
00932 #endif