作図ソフト dia の改良版
修訂 | 7e62f6e76dbd9329004b7d96a91dfc48e4133a19 (tree) |
---|---|
時間 | 2014-06-08 17:58:33 |
作者 | Hans Breuer <hans@breu...> |
Commiter | Hans Breuer |
Fix path_build_arc() and implement DiaPathRenderer:draw_rounded_rect()
Together this fixes two main issues open with convert-to-path.
@@ -269,18 +269,18 @@ _path_arc_segment (GArray *path, | ||
269 | 269 | real r_sin_B, r_cos_B; |
270 | 270 | real h; |
271 | 271 | |
272 | - r_sin_A = radius * sin (angle_A); | |
273 | - r_cos_A = radius * cos (angle_A); | |
274 | - r_sin_B = radius * sin (angle_B); | |
275 | - r_cos_B = radius * cos (angle_B); | |
272 | + r_sin_A = -radius * sin (angle_A); | |
273 | + r_cos_A = radius * cos (angle_A); | |
274 | + r_sin_B = -radius * sin (angle_B); | |
275 | + r_cos_B = radius * cos (angle_B); | |
276 | 276 | |
277 | 277 | h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0); |
278 | - | |
278 | + | |
279 | 279 | bp.type = BEZ_CURVE_TO; |
280 | - bp.p1.x = center->x + r_cos_A - h * r_sin_A; | |
281 | - bp.p1.y = center->y + r_sin_A + h * r_cos_A, | |
282 | - bp.p2.x = center->x + r_cos_B + h * r_sin_B, | |
283 | - bp.p2.y = center->y + r_sin_B - h * r_cos_B, | |
280 | + bp.p1.x = center->x + r_cos_A + h * r_sin_A; | |
281 | + bp.p1.y = center->y + r_sin_A - h * r_cos_A, | |
282 | + bp.p2.x = center->x + r_cos_B - h * r_sin_B, | |
283 | + bp.p2.y = center->y + r_sin_B + h * r_cos_B, | |
284 | 284 | bp.p3.x = center->x + r_cos_B; |
285 | 285 | bp.p3.y = center->y + r_sin_B; |
286 | 286 |
@@ -381,13 +381,19 @@ path_build_arc (GArray *path, | ||
381 | 381 | real ar2; |
382 | 382 | int i, segs; |
383 | 383 | real ars; |
384 | + real ctl; | |
385 | + gboolean ccw = angle2 > angle1; | |
384 | 386 | |
385 | 387 | ar1 = (M_PI / 180.0) * angle1; |
386 | 388 | ar2 = (M_PI / 180.0) * angle2; |
387 | 389 | /* one segment for ever 90 degrees */ |
388 | - segs = (int)(fabs(ar2 - ar1) / (M_PI/2)) + 1; | |
389 | - ars = - (ar2 - ar1) / segs; | |
390 | - | |
390 | + if (ccw) { | |
391 | + segs = (int)((ar2 - ar1) / (M_PI/2)) + 1; | |
392 | + ars = (ar2 - ar1) / segs; | |
393 | + } else { | |
394 | + segs = (int)((ar1 - ar2) / (M_PI/2)) + 1; | |
395 | + ars = -(ar1 - ar2) / segs; | |
396 | + } | |
391 | 397 | /* move to start point */ |
392 | 398 | start.x = center->x + (width / 2.0) * cos(ar1); |
393 | 399 | start.y = center->y - (height / 2.0) * sin(ar1); |
@@ -398,7 +404,8 @@ path_build_arc (GArray *path, | ||
398 | 404 | _path_arc_segment (path, center, radius, ar1, ar1 + ars); |
399 | 405 | } else { |
400 | 406 | _path_moveto (path, &start); |
401 | - _path_arc_segment (path, center, radius, ar1, ar2); | |
407 | + for (i = 0; i < segs; ++i, ar1 += ars) | |
408 | + _path_arc_segment (path, center, radius, ar1, ar2); | |
402 | 409 | _path_lineto (path, center); |
403 | 410 | _path_lineto (path, &start); |
404 | 411 | } |
@@ -406,8 +413,6 @@ path_build_arc (GArray *path, | ||
406 | 413 | |
407 | 414 | /*! |
408 | 415 | * \brief Convert an arc to some bezier curve-to |
409 | - * \bug For arcs going through angle 0 the result is wrong, | |
410 | - * kind of the opposite of the desired. | |
411 | 416 | * \protected \memberof _DiaPathRenderer |
412 | 417 | */ |
413 | 418 | static void |
@@ -644,6 +649,34 @@ draw_image(DiaRenderer *self, | ||
644 | 649 | _path_lineto (path, &to); |
645 | 650 | } |
646 | 651 | |
652 | +/*! | |
653 | + * \brief Create contour of the rounded rect | |
654 | + * | |
655 | + * This methods needs to be implemented to avoid the default | |
656 | + * implementation mixing calls of draw_arc, drar_line and fill_arc. | |
657 | + * We still use the default but only method but only for the outline. | |
658 | + */ | |
659 | +static void | |
660 | +draw_rounded_rect (DiaRenderer *self, | |
661 | + Point *ul_corner, Point *lr_corner, | |
662 | + Color *fill, Color *stroke, real radius) | |
663 | +{ | |
664 | + DiaPathRenderer *renderer = DIA_PATH_RENDERER (self); | |
665 | + real rx = (lr_corner->x - ul_corner->x) / 2; | |
666 | + real ry = (lr_corner->y - ul_corner->y) / 2; | |
667 | + /* limit radius to fit */ | |
668 | + if (radius > rx) | |
669 | + radius = rx; | |
670 | + if (radius > ry) | |
671 | + radius = ry; | |
672 | + DIA_RENDERER_CLASS(dia_path_renderer_parent_class)->draw_rounded_rect(self, | |
673 | + ul_corner, lr_corner, | |
674 | + NULL, stroke ? stroke : fill, radius); | |
675 | + /* stroke is set by the piecewise rendering above already */ | |
676 | + if (fill) | |
677 | + renderer->fill = *fill; | |
678 | +} | |
679 | + | |
647 | 680 | /*! |
648 | 681 | * \brief _DiaPathRenderer class initialization |
649 | 682 | * Overwrite methods of the base classes here. |
@@ -682,6 +715,8 @@ dia_path_renderer_class_init (DiaPathRendererClass *klass) | ||
682 | 715 | renderer_class->draw_bezier = draw_bezier; |
683 | 716 | renderer_class->draw_beziergon = draw_beziergon; |
684 | 717 | renderer_class->draw_text = draw_text; |
718 | + /* highest level function */ | |
719 | + renderer_class->draw_rounded_rect = draw_rounded_rect; | |
685 | 720 | /* other */ |
686 | 721 | renderer_class->is_capable_to = is_capable_to; |
687 | 722 | } |