summaryrefslogtreecommitdiff
path: root/base/gxpath2.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-07-29 18:19:33 +0100
committerRobin Watts <robin.watts@artifex.com>2016-08-01 11:30:13 +0100
commitcc393ffc7b748c8f053eaf4028e8cf130fabbbf7 (patch)
tree0963dd2b2710e8ecbe237a737286bd16c46051d8 /base/gxpath2.c
parent1e214a7382f35f52ae1efe2b53169704913e4df5 (diff)
downloadghostpdl-cc393ffc7b748c8f053eaf4028e8cf130fabbbf7.tar.gz
Revised gx_subpath_is_rectangular.
This copes with more cases. For a given rectangle A, B, C, D, the original code coped with: Move A, Line B, Line C, Line D, close Move A, Line B, Line C, Line D, Move E, ... Move A, Line B, Line C, Line D, Line A Move A, Line B, Line C, Line D, Line A, Close Move A, Line B, Line C, Line D, Line A, Move E (and the flipped variants) We now cope with other cases including repeated corners: Move A, Line B, Line B, Line C, Line D, close etc and the case where the lines are curves that are really lines.
Diffstat (limited to 'base/gxpath2.c')
-rw-r--r--base/gxpath2.c134
1 files changed, 94 insertions, 40 deletions
diff --git a/base/gxpath2.c b/base/gxpath2.c
index ea3e9c17d..b479d04da 100644
--- a/base/gxpath2.c
+++ b/base/gxpath2.c
@@ -179,50 +179,104 @@ gx_subpath_is_rectangular(const subpath * pseg0, gs_fixed_rect * pbox,
const subpath ** ppnext)
{
const segment *pseg1, *pseg2, *pseg3, *pseg4;
- gx_path_rectangular_type type;
+ gx_path_rectangular_type type = prt_none;
+ fixed x0 = pseg0->pt.x, y0 = pseg0->pt.y;
+ fixed x1, y1, x2, y2, x3, y3;
+
+ pseg1 = (const segment *)pseg0;
+ do {
+ pseg1 = pseg1->next;
+ if (pseg1 == NULL)
+ return prt_none;
+ x1 = pseg1->pt.x;
+ y1 = pseg1->pt.y;
+ if (pseg1->type == s_curve) {
+ if (gx_curve_is_really_point(x0, y0, pseg1))
+ continue; /* Ignore this one and try again */
+ if (gx_curve_is_really_line(x0, y0, pseg1))
+ break; /* That'll do! */
+ return prt_none;
+ } else if (pseg1->type != s_line && pseg1->type != s_gap)
+ return prt_none;
+ } while (x1 == x0 && y1 == y0);
- if (pseg0->curve_count == 0 &&
- (pseg1 = pseg0->next) != 0 &&
- (pseg2 = pseg1->next) != 0 &&
- (pseg3 = pseg2->next) != 0
- ) {
- if ((pseg4 = pseg3->next) == 0 || pseg4->type == s_start)
- type = prt_open; /* M, L, L, L */
- else if (pseg4->type != s_line && pseg4->type != s_gap) /* must be s_line_close */
- type = prt_closed; /* M, L, L, L, C */
- else if (pseg4->pt.x != pseg0->pt.x ||
- pseg4->pt.y != pseg0->pt.y
- )
+ pseg2 = pseg1;
+ do {
+ pseg2 = pseg2->next;
+ if (pseg2 == NULL)
return prt_none;
- else if (pseg4->next == 0 || pseg4->next->type == s_start)
- type = prt_fake_closed; /* Mo, L, L, L, Lo */
- else if (pseg4->next->type != s_line && pseg4->next->type != s_gap) /* must be s_line_close */
- type = prt_closed; /* Mo, L, L, L, Lo, C */
- else
+ x2 = pseg2->pt.x;
+ y2 = pseg2->pt.y;
+ if (pseg2->type == s_curve) {
+ if (gx_curve_is_really_point(x1, y1, pseg2))
+ continue; /* Ignore this one and try again */
+ if (gx_curve_is_really_line(x1, y1, pseg2))
+ break; /* That'll do! */
return prt_none;
- {
- fixed x0 = pseg0->pt.x, y0 = pseg0->pt.y;
- fixed x2 = pseg2->pt.x, y2 = pseg2->pt.y;
-
- if ((x0 == pseg1->pt.x && pseg1->pt.y == y2 &&
- x2 == pseg3->pt.x && pseg3->pt.y == y0) ||
- (x0 == pseg3->pt.x && pseg3->pt.y == y2 &&
- x2 == pseg1->pt.x && pseg1->pt.y == y0)
- ) { /* Path is a rectangle. Return the bounding box. */
- if (x0 < x2)
- pbox->p.x = x0, pbox->q.x = x2;
- else
- pbox->p.x = x2, pbox->q.x = x0;
- if (y0 < y2)
- pbox->p.y = y0, pbox->q.y = y2;
- else
- pbox->p.y = y2, pbox->q.y = y0;
- while (pseg4 != 0 && pseg4->type != s_start)
- pseg4 = pseg4->next;
- *ppnext = (const subpath *)pseg4;
- return type;
- }
+ } else if (pseg2->type != s_line && pseg2->type != s_gap)
+ return prt_none;
+ } while (x2 == x1 && y2 == y1);
+
+ pseg3 = pseg2;
+ do {
+ pseg3 = pseg3->next;
+ if (pseg3 == NULL)
+ return prt_none;
+ x3 = pseg3->pt.x;
+ y3 = pseg3->pt.y;
+ if (pseg3->type == s_curve) {
+ if (gx_curve_is_really_point(x2, y2, pseg3))
+ continue; /* Ignore this one and try again */
+ if (gx_curve_is_really_line(x2, y2, pseg3))
+ break; /* That'll do! */
+ return prt_none;
+ } else if (pseg3->type != s_line && pseg3->type != s_gap)
+ return prt_none;
+ } while (x3 == x2 && y3 == y2);
+
+ pseg4 = pseg3;
+ do {
+ pseg4 = pseg4->next;
+ if (pseg4 == NULL || pseg4->type == s_start) {
+ type = prt_open; /* M, L, L, L */
+ goto type_known;
}
+ if (pseg4->type == s_curve) {
+ if (gx_curve_is_really_point(x3, y3, pseg4))
+ continue; /* Ignore this one and try again */
+ if (gx_curve_is_really_line(x3, y3, pseg4))
+ break; /* That'll do! */
+ return prt_none;
+ } else if (pseg4->type == s_line_close) {
+ type = prt_closed; /* M, L, L, L, C */
+ goto type_known;
+ }
+ } while (pseg4->pt.x == x3 && pseg4->pt.y == y3);
+
+ if (pseg4->pt.x != pseg0->pt.x || pseg4->pt.y != pseg0->pt.y)
+ return prt_none;
+ else if (pseg4->next == NULL || pseg4->next->type == s_start)
+ type = prt_fake_closed; /* Mo, L, L, L, L, Mo */
+ else
+ return prt_none;
+
+type_known:
+
+ if ((x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ||
+ (x0 == x3 && y3 == y2 && x2 == x1 && y1 == y0)) {
+ /* Path is a rectangle. Return the bounding box. */
+ if (x0 < x2)
+ pbox->p.x = x0, pbox->q.x = x2;
+ else
+ pbox->p.x = x2, pbox->q.x = x0;
+ if (y0 < y2)
+ pbox->p.y = y0, pbox->q.y = y2;
+ else
+ pbox->p.y = y2, pbox->q.y = y0;
+ while (pseg4 != 0 && pseg4->type != s_start)
+ pseg4 = pseg4->next;
+ *ppnext = (const subpath *)pseg4;
+ return type;
}
return prt_none;
}