diff --git a/desmume/src/windows/agg/agg-2.5.vcproj b/desmume/src/windows/agg/agg-2.5.vcproj
index 4d4e94bfe..19ce703de 100644
--- a/desmume/src/windows/agg/agg-2.5.vcproj
+++ b/desmume/src/windows/agg/agg-2.5.vcproj
@@ -872,10 +872,6 @@
RelativePath=".\src\platform\win32\agg_win32_bmp.cpp"
>
-
-
diff --git a/desmume/src/windows/agg/gpc/VERSIONS.TXT b/desmume/src/windows/agg/gpc/VERSIONS.TXT
deleted file mode 100644
index 0b877b628..000000000
--- a/desmume/src/windows/agg/gpc/VERSIONS.TXT
+++ /dev/null
@@ -1,123 +0,0 @@
-
-Generic Polygon Clipper (gpc) Revision History
-==============================================
-
-
-v2.32 17th Dec 2004
----------------------
- Fixed occasional memory leak occurring when processing some
- degenerate polygon arrangements.
- Added explicit type casting to memory allocator in support of
- increased code portability.
-
-v2.31 4th Jun 1999
----------------------
- Separated edge merging measure based on a user-defined GPC_EPSILON
- value from general numeric equality testing and ordering, which now
- uses direct arithmetic comparison rather an EPSILON based proximity
- test.
- Fixed problem with numerical equality test during construction of
- local minima and scanbeam tables, leading to occasional crash.
- Fixed hole array memory leak in gpc_add_contour.
- Fixed uninitialised hole field bug in gpc_polygon_clip result.
-
-v2.30 11th Apr 1999
----------------------
- Major re-write.
- Minor API change: additional 'hole' array field added to gpc_polygon
- datatype to indicate which constituent contours are internal holes,
- and which form external boundaries.
- Minor API change: additional 'hole' argument to gpc_add_contour
- to indicate whether the new contour is a hole or external contour.
- Minor API change: additional parameter to gpc_read_polygon and
- gpc_write_polygon to indicate whether or not to read or write
- contour hole flags.
- Fixed NULL pointer bug in add/merge left/right operations.
- Fixed numerical problem in intersection table generation.
- Fixed zero byte malloc problem.
- Fixed problem producing occasional 2 vertex contours.
- Added bounding box test optimisations.
- Simplified edge bundle creation, detection of scanbeam internal
- edge intersections and tristrip scanbeam boundary code.
- Renamed 'class' variable to be C++ friendly.
-
-v2.22 17th Oct 1998
----------------------
- Re-implemented edge interpolation and intersection calculations
- to improve numerical robustness.
- Simplified setting of GPC_EPSILON.
-
-v2.21 19th Aug 1998
----------------------
- Fixed problem causing occasional incorrect output when processing
- self-intersecting polygons (bow-ties etc).
- Removed bug which may lead to non-generation of uppermost triangle
- in tristrip output.
-
-v2.20 26th May 1998
----------------------
- Major re-write.
- Added exclusive-or polygon set operation.
- Replaced table-based processing of edge intersections with
- rule-based system.
- Replaced two-pass approach to scanbeam interior processing with
- single pass method.
-
-v2.10a 14th May 1998
----------------------
- Minor bug-fixes to counter some v2.10 reliability problems.
-
-v2.10 11th May 1998
----------------------
- Major re-write.
- Incorporated edge bundle processing of AET to overcome coincident
- edge problems present in previous releases.
- Replaced Vatti's method for processing scanbeam interior regions
- with an adapted version of the scanbeam boundary processing
- algorithm.
-
-v2.02 16th Apr 1998 (unreleased)
-----------------------------------
- Fixed internal minimum vertex duplication in gpc_polygon_clip
- result.
- Improved line intersection code discourage superfluous
- intersections near line ends.
- Removed limited precision number formatting in gpc_write_polygon.
- Modification to allow subject or clip polygon to be reused as the
- result in gpc_polygon_clip without memory leakage.
-
-v2.01 23rd Feb 1998
----------------------
- Removed bug causing duplicated vertices in output polygon.
- Fixed scanbeam table index overrun problem.
-
-v2.00 25th Nov 1997
----------------------
- Major re-write.
- Replaced temporary horizontal edge work-around (using tilting)
- with true horizontal edge handling.
- Trapezoidal output replaced by tristrips.
- gpc_op constants now feature a `GPC_' prefix.
- Data structures now passed by reference to gpc functions.
- Replaced AET search by proxy addressing in polygon table.
- Eliminated most (all?) coincident vertex / edge crashes.
-
-v1.02 18th Oct 1997 (unreleased)
-----------------------------------
- Significantly reduced number of mallocs in build_lmt.
- Scanbeam table now built using heapsort rather than insertion
- sort.
-
-v1.01 12th Oct 1997
----------------------
- Fixed memory leak during output polygon build in
- gpc_clip_polygon.
- Removed superfluous logfile debug code.
- Commented out malloc counts.
- Added missing horizontal edge tilt-correction code in
- gpc_clip_polygon.
-
-v1.00 8th Oct 1997
---------------------
- First release.
-
diff --git a/desmume/src/windows/agg/gpc/copying.txt b/desmume/src/windows/agg/gpc/copying.txt
deleted file mode 100644
index 5f1e6bc46..000000000
--- a/desmume/src/windows/agg/gpc/copying.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-
- http://www.cs.man.ac.uk/aig/staff/alan/software/
-
-Author: Alan Murta (email: gpc@cs.man.ac.uk)
-Version: 2.31
-Date: 4th June 1999
-
-Copyright: (C) 1997-1999, Advanced Interfaces Group,
- University of Manchester.
-
- This software is free for non-commercial use. It may be copied,
- modified, and redistributed provided that this copyright notice
- is preserved on all copies. The intellectual property rights of
- the algorithms used reside with the University of Manchester
- Advanced Interfaces Group.
-
- You may not use this software, in whole or in part, in support
- of any commercial product without the express consent of the
- author.
-
- There is no warranty or other guarantee of fitness of this
- software for any purpose. It is provided solely "as is".
diff --git a/desmume/src/windows/agg/gpc/gpc.c b/desmume/src/windows/agg/gpc/gpc.c
deleted file mode 100644
index b25800bcf..000000000
--- a/desmume/src/windows/agg/gpc/gpc.c
+++ /dev/null
@@ -1,2472 +0,0 @@
-/*
-===========================================================================
-
-Project: Generic Polygon Clipper
-
- A new algorithm for calculating the difference, intersection,
- exclusive-or or union of arbitrary polygon sets.
-
-File: gpc.c
-Author: Alan Murta (email: gpc@cs.man.ac.uk)
-Version: 2.32
-Date: 17th December 2004
-
-Copyright: (C) 1997-2004, Advanced Interfaces Group,
- University of Manchester.
-
- This software is free for non-commercial use. It may be copied,
- modified, and redistributed provided that this copyright notice
- is preserved on all copies. The intellectual property rights of
- the algorithms used reside with the University of Manchester
- Advanced Interfaces Group.
-
- You may not use this software, in whole or in part, in support
- of any commercial product without the express consent of the
- author.
-
- There is no warranty or other guarantee of fitness of this
- software for any purpose. It is provided solely "as is".
-
-===========================================================================
-*/
-
-
-/*
-===========================================================================
- Includes
-===========================================================================
-*/
-
-#include "gpc.h"
-#include
-#include
-#include
-
-
-/*
-===========================================================================
- Constants
-===========================================================================
-*/
-
-#ifndef TRUE
-#define FALSE 0
-#define TRUE 1
-#endif
-
-#define LEFT 0
-#define RIGHT 1
-
-#define ABOVE 0
-#define BELOW 1
-
-#define CLIP 0
-#define SUBJ 1
-
-#define INVERT_TRISTRIPS FALSE
-
-
-/*
-===========================================================================
- Macros
-===========================================================================
-*/
-
-#define EQ(a, b) (fabs((a) - (b)) <= GPC_EPSILON)
-
-#define PREV_INDEX(i, n) ((i - 1 + n) % n)
-#define NEXT_INDEX(i, n) ((i + 1 ) % n)
-
-#define OPTIMAL(v, i, n) ((v[PREV_INDEX(i, n)].y != v[i].y) || \
- (v[NEXT_INDEX(i, n)].y != v[i].y))
-
-#define FWD_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y >= v[i].vertex.y) \
- && (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y))
-
-#define NOT_FMAX(v, i, n) (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y)
-
-#define REV_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) \
- && (v[NEXT_INDEX(i, n)].vertex.y >= v[i].vertex.y))
-
-#define NOT_RMAX(v, i, n) (v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y)
-
-#define VERTEX(e,p,s,x,y) {add_vertex(&((e)->outp[(p)]->v[(s)]), x, y); \
- (e)->outp[(p)]->active++;}
-
-#define P_EDGE(d,e,p,i,j) {(d)= (e); \
- do {(d)= (d)->prev;} while (!(d)->outp[(p)]); \
- (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);}
-
-#define N_EDGE(d,e,p,i,j) {(d)= (e); \
- do {(d)= (d)->next;} while (!(d)->outp[(p)]); \
- (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);}
-
-#define MALLOC(p, b, s, t) {if ((b) > 0) { \
- p= (t*)malloc(b); if (!(p)) { \
- fprintf(stderr, "gpc malloc failure: %s\n", s); \
- exit(0);}} else p= NULL;}
-
-#define FREE(p) {if (p) {free(p); (p)= NULL;}}
-
-
-/*
-===========================================================================
- Private Data Types
-===========================================================================
-*/
-
-typedef enum /* Edge intersection classes */
-{
- NUL, /* Empty non-intersection */
- EMX, /* External maximum */
- ELI, /* External left intermediate */
- TED, /* Top edge */
- ERI, /* External right intermediate */
- RED, /* Right edge */
- IMM, /* Internal maximum and minimum */
- IMN, /* Internal minimum */
- EMN, /* External minimum */
- EMM, /* External maximum and minimum */
- LED, /* Left edge */
- ILI, /* Internal left intermediate */
- BED, /* Bottom edge */
- IRI, /* Internal right intermediate */
- IMX, /* Internal maximum */
- FUL /* Full non-intersection */
-} vertex_type;
-
-typedef enum /* Horizontal edge states */
-{
- NH, /* No horizontal edge */
- BH, /* Bottom horizontal edge */
- TH /* Top horizontal edge */
-} h_state;
-
-typedef enum /* Edge bundle state */
-{
- UNBUNDLED, /* Isolated edge not within a bundle */
- BUNDLE_HEAD, /* Bundle head node */
- BUNDLE_TAIL /* Passive bundle tail node */
-} bundle_state;
-
-typedef struct v_shape /* Internal vertex list datatype */
-{
- double x; /* X coordinate component */
- double y; /* Y coordinate component */
- struct v_shape *next; /* Pointer to next vertex in list */
-} vertex_node;
-
-typedef struct p_shape /* Internal contour / tristrip type */
-{
- int active; /* Active flag / vertex count */
- int hole; /* Hole / external contour flag */
- vertex_node *v[2]; /* Left and right vertex list ptrs */
- struct p_shape *next; /* Pointer to next polygon contour */
- struct p_shape *proxy; /* Pointer to actual structure used */
-} polygon_node;
-
-typedef struct edge_shape
-{
- gpc_vertex vertex; /* Piggy-backed contour vertex data */
- gpc_vertex bot; /* Edge lower (x, y) coordinate */
- gpc_vertex top; /* Edge upper (x, y) coordinate */
- double xb; /* Scanbeam bottom x coordinate */
- double xt; /* Scanbeam top x coordinate */
- double dx; /* Change in x for a unit y increase */
- int type; /* Clip / subject edge flag */
- int bundle[2][2]; /* Bundle edge flags */
- int bside[2]; /* Bundle left / right indicators */
- bundle_state bstate[2]; /* Edge bundle state */
- polygon_node *outp[2]; /* Output polygon / tristrip pointer */
- struct edge_shape *prev; /* Previous edge in the AET */
- struct edge_shape *next; /* Next edge in the AET */
- struct edge_shape *pred; /* Edge connected at the lower end */
- struct edge_shape *succ; /* Edge connected at the upper end */
- struct edge_shape *next_bound; /* Pointer to next bound in LMT */
-} edge_node;
-
-typedef struct lmt_shape /* Local minima table */
-{
- double y; /* Y coordinate at local minimum */
- edge_node *first_bound; /* Pointer to bound list */
- struct lmt_shape *next; /* Pointer to next local minimum */
-} lmt_node;
-
-typedef struct sbt_t_shape /* Scanbeam tree */
-{
- double y; /* Scanbeam node y value */
- struct sbt_t_shape *less; /* Pointer to nodes with lower y */
- struct sbt_t_shape *more; /* Pointer to nodes with higher y */
-} sb_tree;
-
-typedef struct it_shape /* Intersection table */
-{
- edge_node *ie[2]; /* Intersecting edge (bundle) pair */
- gpc_vertex point; /* Point of intersection */
- struct it_shape *next; /* The next intersection table node */
-} it_node;
-
-typedef struct st_shape /* Sorted edge table */
-{
- edge_node *edge; /* Pointer to AET edge */
- double xb; /* Scanbeam bottom x coordinate */
- double xt; /* Scanbeam top x coordinate */
- double dx; /* Change in x for a unit y increase */
- struct st_shape *prev; /* Previous edge in sorted list */
-} st_node;
-
-typedef struct bbox_shape /* Contour axis-aligned bounding box */
-{
- double xmin; /* Minimum x coordinate */
- double ymin; /* Minimum y coordinate */
- double xmax; /* Maximum x coordinate */
- double ymax; /* Maximum y coordinate */
-} bbox;
-
-
-/*
-===========================================================================
- Global Data
-===========================================================================
-*/
-
-/* Horizontal edge state transitions within scanbeam boundary */
-const h_state next_h_state[3][6]=
-{
- /* ABOVE BELOW CROSS */
- /* L R L R L R */
- /* NH */ {BH, TH, TH, BH, NH, NH},
- /* BH */ {NH, NH, NH, NH, TH, TH},
- /* TH */ {NH, NH, NH, NH, BH, BH}
-};
-
-
-/*
-===========================================================================
- Private Functions
-===========================================================================
-*/
-
-static void reset_it(it_node **it)
-{
- it_node *itn;
-
- while (*it)
- {
- itn= (*it)->next;
- FREE(*it);
- *it= itn;
- }
-}
-
-
-static void reset_lmt(lmt_node **lmt)
-{
- lmt_node *lmtn;
-
- while (*lmt)
- {
- lmtn= (*lmt)->next;
- FREE(*lmt);
- *lmt= lmtn;
- }
-}
-
-
-static void insert_bound(edge_node **b, edge_node *e)
-{
- edge_node *existing_bound;
-
- if (!*b)
- {
- /* Link node e to the tail of the list */
- *b= e;
- }
- else
- {
- /* Do primary sort on the x field */
- if (e[0].bot.x < (*b)[0].bot.x)
- {
- /* Insert a new node mid-list */
- existing_bound= *b;
- *b= e;
- (*b)->next_bound= existing_bound;
- }
- else
- {
- if (e[0].bot.x == (*b)[0].bot.x)
- {
- /* Do secondary sort on the dx field */
- if (e[0].dx < (*b)[0].dx)
- {
- /* Insert a new node mid-list */
- existing_bound= *b;
- *b= e;
- (*b)->next_bound= existing_bound;
- }
- else
- {
- /* Head further down the list */
- insert_bound(&((*b)->next_bound), e);
- }
- }
- else
- {
- /* Head further down the list */
- insert_bound(&((*b)->next_bound), e);
- }
- }
- }
-}
-
-
-static edge_node **bound_list(lmt_node **lmt, double y)
-{
- lmt_node *existing_node;
-
- if (!*lmt)
- {
- /* Add node onto the tail end of the LMT */
- MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node);
- (*lmt)->y= y;
- (*lmt)->first_bound= NULL;
- (*lmt)->next= NULL;
- return &((*lmt)->first_bound);
- }
- else
- if (y < (*lmt)->y)
- {
- /* Insert a new LMT node before the current node */
- existing_node= *lmt;
- MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node);
- (*lmt)->y= y;
- (*lmt)->first_bound= NULL;
- (*lmt)->next= existing_node;
- return &((*lmt)->first_bound);
- }
- else
- if (y > (*lmt)->y)
- /* Head further up the LMT */
- return bound_list(&((*lmt)->next), y);
- else
- /* Use this existing LMT node */
- return &((*lmt)->first_bound);
-}
-
-
-static void add_to_sbtree(int *entries, sb_tree **sbtree, double y)
-{
- if (!*sbtree)
- {
- /* Add a new tree node here */
- MALLOC(*sbtree, sizeof(sb_tree), "scanbeam tree insertion", sb_tree);
- (*sbtree)->y= y;
- (*sbtree)->less= NULL;
- (*sbtree)->more= NULL;
- (*entries)++;
- }
- else
- {
- if ((*sbtree)->y > y)
- {
- /* Head into the 'less' sub-tree */
- add_to_sbtree(entries, &((*sbtree)->less), y);
- }
- else
- {
- if ((*sbtree)->y < y)
- {
- /* Head into the 'more' sub-tree */
- add_to_sbtree(entries, &((*sbtree)->more), y);
- }
- }
- }
-}
-
-
-static void build_sbt(int *entries, double *sbt, sb_tree *sbtree)
-{
- if (sbtree->less)
- build_sbt(entries, sbt, sbtree->less);
- sbt[*entries]= sbtree->y;
- (*entries)++;
- if (sbtree->more)
- build_sbt(entries, sbt, sbtree->more);
-}
-
-
-static void free_sbtree(sb_tree **sbtree)
-{
- if (*sbtree)
- {
- free_sbtree(&((*sbtree)->less));
- free_sbtree(&((*sbtree)->more));
- FREE(*sbtree);
- }
-}
-
-
-static int count_optimal_vertices(gpc_vertex_list c)
-{
- int result= 0, i;
-
- /* Ignore non-contributing contours */
- if (c.num_vertices > 0)
- {
- for (i= 0; i < c.num_vertices; i++)
- /* Ignore superfluous vertices embedded in horizontal edges */
- if (OPTIMAL(c.vertex, i, c.num_vertices))
- result++;
- }
- return result;
-}
-
-
-static edge_node *build_lmt(lmt_node **lmt, sb_tree **sbtree,
- int *sbt_entries, gpc_polygon *p, int type,
- gpc_op op)
-{
- int c, i, min, max, num_edges, v, num_vertices;
- int total_vertices= 0, e_index=0;
- edge_node *e, *edge_table;
-
- for (c= 0; c < p->num_contours; c++)
- total_vertices+= count_optimal_vertices(p->contour[c]);
-
- /* Create the entire input polygon edge table in one go */
- MALLOC(edge_table, total_vertices * sizeof(edge_node),
- "edge table creation", edge_node);
-
- for (c= 0; c < p->num_contours; c++)
- {
- if (p->contour[c].num_vertices < 0)
- {
- /* Ignore the non-contributing contour and repair the vertex count */
- p->contour[c].num_vertices= -p->contour[c].num_vertices;
- }
- else
- {
- /* Perform contour optimisation */
- num_vertices= 0;
- for (i= 0; i < p->contour[c].num_vertices; i++)
- if (OPTIMAL(p->contour[c].vertex, i, p->contour[c].num_vertices))
- {
- edge_table[num_vertices].vertex.x= p->contour[c].vertex[i].x;
- edge_table[num_vertices].vertex.y= p->contour[c].vertex[i].y;
-
- /* Record vertex in the scanbeam table */
- add_to_sbtree(sbt_entries, sbtree,
- edge_table[num_vertices].vertex.y);
-
- num_vertices++;
- }
-
- /* Do the contour forward pass */
- for (min= 0; min < num_vertices; min++)
- {
- /* If a forward local minimum... */
- if (FWD_MIN(edge_table, min, num_vertices))
- {
- /* Search for the next local maximum... */
- num_edges= 1;
- max= NEXT_INDEX(min, num_vertices);
- while (NOT_FMAX(edge_table, max, num_vertices))
- {
- num_edges++;
- max= NEXT_INDEX(max, num_vertices);
- }
-
- /* Build the next edge list */
- e= &edge_table[e_index];
- e_index+= num_edges;
- v= min;
- e[0].bstate[BELOW]= UNBUNDLED;
- e[0].bundle[BELOW][CLIP]= FALSE;
- e[0].bundle[BELOW][SUBJ]= FALSE;
- for (i= 0; i < num_edges; i++)
- {
- e[i].xb= edge_table[v].vertex.x;
- e[i].bot.x= edge_table[v].vertex.x;
- e[i].bot.y= edge_table[v].vertex.y;
-
- v= NEXT_INDEX(v, num_vertices);
-
- e[i].top.x= edge_table[v].vertex.x;
- e[i].top.y= edge_table[v].vertex.y;
- e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) /
- (e[i].top.y - e[i].bot.y);
- e[i].type= type;
- e[i].outp[ABOVE]= NULL;
- e[i].outp[BELOW]= NULL;
- e[i].next= NULL;
- e[i].prev= NULL;
- e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ?
- &(e[i + 1]) : NULL;
- e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL;
- e[i].next_bound= NULL;
- e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT;
- e[i].bside[SUBJ]= LEFT;
- }
- insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
- }
- }
-
- /* Do the contour reverse pass */
- for (min= 0; min < num_vertices; min++)
- {
- /* If a reverse local minimum... */
- if (REV_MIN(edge_table, min, num_vertices))
- {
- /* Search for the previous local maximum... */
- num_edges= 1;
- max= PREV_INDEX(min, num_vertices);
- while (NOT_RMAX(edge_table, max, num_vertices))
- {
- num_edges++;
- max= PREV_INDEX(max, num_vertices);
- }
-
- /* Build the previous edge list */
- e= &edge_table[e_index];
- e_index+= num_edges;
- v= min;
- e[0].bstate[BELOW]= UNBUNDLED;
- e[0].bundle[BELOW][CLIP]= FALSE;
- e[0].bundle[BELOW][SUBJ]= FALSE;
- for (i= 0; i < num_edges; i++)
- {
- e[i].xb= edge_table[v].vertex.x;
- e[i].bot.x= edge_table[v].vertex.x;
- e[i].bot.y= edge_table[v].vertex.y;
-
- v= PREV_INDEX(v, num_vertices);
-
- e[i].top.x= edge_table[v].vertex.x;
- e[i].top.y= edge_table[v].vertex.y;
- e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) /
- (e[i].top.y - e[i].bot.y);
- e[i].type= type;
- e[i].outp[ABOVE]= NULL;
- e[i].outp[BELOW]= NULL;
- e[i].next= NULL;
- e[i].prev= NULL;
- e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ?
- &(e[i + 1]) : NULL;
- e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL;
- e[i].next_bound= NULL;
- e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT;
- e[i].bside[SUBJ]= LEFT;
- }
- insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
- }
- }
- }
- }
- return edge_table;
-}
-
-
-static void add_edge_to_aet(edge_node **aet, edge_node *edge, edge_node *prev)
-{
- if (!*aet)
- {
- /* Append edge onto the tail end of the AET */
- *aet= edge;
- edge->prev= prev;
- edge->next= NULL;
- }
- else
- {
- /* Do primary sort on the xb field */
- if (edge->xb < (*aet)->xb)
- {
- /* Insert edge here (before the AET edge) */
- edge->prev= prev;
- edge->next= *aet;
- (*aet)->prev= edge;
- *aet= edge;
- }
- else
- {
- if (edge->xb == (*aet)->xb)
- {
- /* Do secondary sort on the dx field */
- if (edge->dx < (*aet)->dx)
- {
- /* Insert edge here (before the AET edge) */
- edge->prev= prev;
- edge->next= *aet;
- (*aet)->prev= edge;
- *aet= edge;
- }
- else
- {
- /* Head further into the AET */
- add_edge_to_aet(&((*aet)->next), edge, *aet);
- }
- }
- else
- {
- /* Head further into the AET */
- add_edge_to_aet(&((*aet)->next), edge, *aet);
- }
- }
- }
-}
-
-
-static void add_intersection(it_node **it, edge_node *edge0, edge_node *edge1,
- double x, double y)
-{
- it_node *existing_node;
-
- if (!*it)
- {
- /* Append a new node to the tail of the list */
- MALLOC(*it, sizeof(it_node), "IT insertion", it_node);
- (*it)->ie[0]= edge0;
- (*it)->ie[1]= edge1;
- (*it)->point.x= x;
- (*it)->point.y= y;
- (*it)->next= NULL;
- }
- else
- {
- if ((*it)->point.y > y)
- {
- /* Insert a new node mid-list */
- existing_node= *it;
- MALLOC(*it, sizeof(it_node), "IT insertion", it_node);
- (*it)->ie[0]= edge0;
- (*it)->ie[1]= edge1;
- (*it)->point.x= x;
- (*it)->point.y= y;
- (*it)->next= existing_node;
- }
- else
- /* Head further down the list */
- add_intersection(&((*it)->next), edge0, edge1, x, y);
- }
-}
-
-
-static void add_st_edge(st_node **st, it_node **it, edge_node *edge,
- double dy)
-{
- st_node *existing_node;
- double den, r, x, y;
-
- if (!*st)
- {
- /* Append edge onto the tail end of the ST */
- MALLOC(*st, sizeof(st_node), "ST insertion", st_node);
- (*st)->edge= edge;
- (*st)->xb= edge->xb;
- (*st)->xt= edge->xt;
- (*st)->dx= edge->dx;
- (*st)->prev= NULL;
- }
- else
- {
- den= ((*st)->xt - (*st)->xb) - (edge->xt - edge->xb);
-
- /* If new edge and ST edge don't cross */
- if ((edge->xt >= (*st)->xt) || (edge->dx == (*st)->dx) ||
- (fabs(den) <= DBL_EPSILON))
- {
- /* No intersection - insert edge here (before the ST edge) */
- existing_node= *st;
- MALLOC(*st, sizeof(st_node), "ST insertion", st_node);
- (*st)->edge= edge;
- (*st)->xb= edge->xb;
- (*st)->xt= edge->xt;
- (*st)->dx= edge->dx;
- (*st)->prev= existing_node;
- }
- else
- {
- /* Compute intersection between new edge and ST edge */
- r= (edge->xb - (*st)->xb) / den;
- x= (*st)->xb + r * ((*st)->xt - (*st)->xb);
- y= r * dy;
-
- /* Insert the edge pointers and the intersection point in the IT */
- add_intersection(it, (*st)->edge, edge, x, y);
-
- /* Head further into the ST */
- add_st_edge(&((*st)->prev), it, edge, dy);
- }
- }
-}
-
-
-static void build_intersection_table(it_node **it, edge_node *aet, double dy)
-{
- st_node *st, *stp;
- edge_node *edge;
-
- /* Build intersection table for the current scanbeam */
- reset_it(it);
- st= NULL;
-
- /* Process each AET edge */
- for (edge= aet; edge; edge= edge->next)
- {
- if ((edge->bstate[ABOVE] == BUNDLE_HEAD) ||
- edge->bundle[ABOVE][CLIP] || edge->bundle[ABOVE][SUBJ])
- add_st_edge(&st, it, edge, dy);
- }
-
- /* Free the sorted edge table */
- while (st)
- {
- stp= st->prev;
- FREE(st);
- st= stp;
- }
-}
-
-static int count_contours(polygon_node *polygon)
-{
- int nc, nv;
- vertex_node *v, *nextv;
-
- for (nc= 0; polygon; polygon= polygon->next)
- if (polygon->active)
- {
- /* Count the vertices in the current contour */
- nv= 0;
- for (v= polygon->proxy->v[LEFT]; v; v= v->next)
- nv++;
-
- /* Record valid vertex counts in the active field */
- if (nv > 2)
- {
- polygon->active= nv;
- nc++;
- }
- else
- {
- /* Invalid contour: just free the heap */
- for (v= polygon->proxy->v[LEFT]; v; v= nextv)
- {
- nextv= v->next;
- FREE(v);
- }
- polygon->active= 0;
- }
- }
- return nc;
-}
-
-
-static void add_left(polygon_node *p, double x, double y)
-{
- vertex_node *nv;
-
- /* Create a new vertex node and set its fields */
- MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
- nv->x= x;
- nv->y= y;
-
- /* Add vertex nv to the left end of the polygon's vertex list */
- nv->next= p->proxy->v[LEFT];
-
- /* Update proxy->[LEFT] to point to nv */
- p->proxy->v[LEFT]= nv;
-}
-
-
-static void merge_left(polygon_node *p, polygon_node *q, polygon_node *list)
-{
- polygon_node *target;
-
- /* Label contour as a hole */
- q->proxy->hole= TRUE;
-
- if (p->proxy != q->proxy)
- {
- /* Assign p's vertex list to the left end of q's list */
- p->proxy->v[RIGHT]->next= q->proxy->v[LEFT];
- q->proxy->v[LEFT]= p->proxy->v[LEFT];
-
- /* Redirect any p->proxy references to q->proxy */
-
- for (target= p->proxy; list; list= list->next)
- {
- if (list->proxy == target)
- {
- list->active= FALSE;
- list->proxy= q->proxy;
- }
- }
- }
-}
-
-
-static void add_right(polygon_node *p, double x, double y)
-{
- vertex_node *nv;
-
- /* Create a new vertex node and set its fields */
- MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
- nv->x= x;
- nv->y= y;
- nv->next= NULL;
-
- /* Add vertex nv to the right end of the polygon's vertex list */
- p->proxy->v[RIGHT]->next= nv;
-
- /* Update proxy->v[RIGHT] to point to nv */
- p->proxy->v[RIGHT]= nv;
-}
-
-
-static void merge_right(polygon_node *p, polygon_node *q, polygon_node *list)
-{
- polygon_node *target;
-
- /* Label contour as external */
- q->proxy->hole= FALSE;
-
- if (p->proxy != q->proxy)
- {
- /* Assign p's vertex list to the right end of q's list */
- q->proxy->v[RIGHT]->next= p->proxy->v[LEFT];
- q->proxy->v[RIGHT]= p->proxy->v[RIGHT];
-
- /* Redirect any p->proxy references to q->proxy */
- for (target= p->proxy; list; list= list->next)
- {
- if (list->proxy == target)
- {
- list->active= FALSE;
- list->proxy= q->proxy;
- }
- }
- }
-}
-
-
-static void add_local_min(polygon_node **p, edge_node *edge,
- double x, double y)
-{
- polygon_node *existing_min;
- vertex_node *nv;
-
- existing_min= *p;
-
- MALLOC(*p, sizeof(polygon_node), "polygon node creation", polygon_node);
-
- /* Create a new vertex node and set its fields */
- MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
- nv->x= x;
- nv->y= y;
- nv->next= NULL;
-
- /* Initialise proxy to point to p itself */
- (*p)->proxy= (*p);
- (*p)->active= TRUE;
- (*p)->next= existing_min;
-
- /* Make v[LEFT] and v[RIGHT] point to new vertex nv */
- (*p)->v[LEFT]= nv;
- (*p)->v[RIGHT]= nv;
-
- /* Assign polygon p to the edge */
- edge->outp[ABOVE]= *p;
-}
-
-
-static int count_tristrips(polygon_node *tn)
-{
- int total;
-
- for (total= 0; tn; tn= tn->next)
- if (tn->active > 2)
- total++;
- return total;
-}
-
-
-static void add_vertex(vertex_node **t, double x, double y)
-{
- if (!(*t))
- {
- MALLOC(*t, sizeof(vertex_node), "tristrip vertex creation", vertex_node);
- (*t)->x= x;
- (*t)->y= y;
- (*t)->next= NULL;
- }
- else
- /* Head further down the list */
- add_vertex(&((*t)->next), x, y);
-}
-
-
-static void new_tristrip(polygon_node **tn, edge_node *edge,
- double x, double y)
-{
- if (!(*tn))
- {
- MALLOC(*tn, sizeof(polygon_node), "tristrip node creation", polygon_node);
- (*tn)->next= NULL;
- (*tn)->v[LEFT]= NULL;
- (*tn)->v[RIGHT]= NULL;
- (*tn)->active= 1;
- add_vertex(&((*tn)->v[LEFT]), x, y);
- edge->outp[ABOVE]= *tn;
- }
- else
- /* Head further down the list */
- new_tristrip(&((*tn)->next), edge, x, y);
-}
-
-
-static bbox *create_contour_bboxes(gpc_polygon *p)
-{
- bbox *box;
- int c, v;
-
- MALLOC(box, p->num_contours * sizeof(bbox), "Bounding box creation", bbox);
-
- /* Construct contour bounding boxes */
- for (c= 0; c < p->num_contours; c++)
- {
- /* Initialise bounding box extent */
- box[c].xmin= DBL_MAX;
- box[c].ymin= DBL_MAX;
- box[c].xmax= -DBL_MAX;
- box[c].ymax= -DBL_MAX;
-
- for (v= 0; v < p->contour[c].num_vertices; v++)
- {
- /* Adjust bounding box */
- if (p->contour[c].vertex[v].x < box[c].xmin)
- box[c].xmin= p->contour[c].vertex[v].x;
- if (p->contour[c].vertex[v].y < box[c].ymin)
- box[c].ymin= p->contour[c].vertex[v].y;
- if (p->contour[c].vertex[v].x > box[c].xmax)
- box[c].xmax= p->contour[c].vertex[v].x;
- if (p->contour[c].vertex[v].y > box[c].ymax)
- box[c].ymax= p->contour[c].vertex[v].y;
- }
- }
- return box;
-}
-
-
-static void minimax_test(gpc_polygon *subj, gpc_polygon *clip, gpc_op op)
-{
- bbox *s_bbox, *c_bbox;
- int s, c, *o_table, overlap;
-
- s_bbox= create_contour_bboxes(subj);
- c_bbox= create_contour_bboxes(clip);
-
- MALLOC(o_table, subj->num_contours * clip->num_contours * sizeof(int),
- "overlap table creation", int);
-
- /* Check all subject contour bounding boxes against clip boxes */
- for (s= 0; s < subj->num_contours; s++)
- for (c= 0; c < clip->num_contours; c++)
- o_table[c * subj->num_contours + s]=
- (!((s_bbox[s].xmax < c_bbox[c].xmin) ||
- (s_bbox[s].xmin > c_bbox[c].xmax))) &&
- (!((s_bbox[s].ymax < c_bbox[c].ymin) ||
- (s_bbox[s].ymin > c_bbox[c].ymax)));
-
- /* For each clip contour, search for any subject contour overlaps */
- for (c= 0; c < clip->num_contours; c++)
- {
- overlap= 0;
- for (s= 0; (!overlap) && (s < subj->num_contours); s++)
- overlap= o_table[c * subj->num_contours + s];
-
- if (!overlap)
- /* Flag non contributing status by negating vertex count */
- clip->contour[c].num_vertices = -clip->contour[c].num_vertices;
- }
-
- if (op == GPC_INT)
- {
- /* For each subject contour, search for any clip contour overlaps */
- for (s= 0; s < subj->num_contours; s++)
- {
- overlap= 0;
- for (c= 0; (!overlap) && (c < clip->num_contours); c++)
- overlap= o_table[c * subj->num_contours + s];
-
- if (!overlap)
- /* Flag non contributing status by negating vertex count */
- subj->contour[s].num_vertices = -subj->contour[s].num_vertices;
- }
- }
-
- FREE(s_bbox);
- FREE(c_bbox);
- FREE(o_table);
-}
-
-
-/*
-===========================================================================
- Public Functions
-===========================================================================
-*/
-
-void gpc_free_polygon(gpc_polygon *p)
-{
- int c;
-
- for (c= 0; c < p->num_contours; c++)
- FREE(p->contour[c].vertex);
- FREE(p->hole);
- FREE(p->contour);
- p->num_contours= 0;
-}
-
-
-void gpc_read_polygon(FILE *fp, int read_hole_flags, gpc_polygon *p)
-{
- int c, v;
-
- fscanf(fp, "%d", &(p->num_contours));
- MALLOC(p->hole, p->num_contours * sizeof(int),
- "hole flag array creation", int);
- MALLOC(p->contour, p->num_contours
- * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
- for (c= 0; c < p->num_contours; c++)
- {
- fscanf(fp, "%d", &(p->contour[c].num_vertices));
-
- if (read_hole_flags)
- fscanf(fp, "%d", &(p->hole[c]));
- else
- p->hole[c]= FALSE; /* Assume all contours to be external */
-
- MALLOC(p->contour[c].vertex, p->contour[c].num_vertices
- * sizeof(gpc_vertex), "vertex creation", gpc_vertex);
- for (v= 0; v < p->contour[c].num_vertices; v++)
- fscanf(fp, "%lf %lf", &(p->contour[c].vertex[v].x),
- &(p->contour[c].vertex[v].y));
- }
-}
-
-
-void gpc_write_polygon(FILE *fp, int write_hole_flags, gpc_polygon *p)
-{
- int c, v;
-
- fprintf(fp, "%d\n", p->num_contours);
- for (c= 0; c < p->num_contours; c++)
- {
- fprintf(fp, "%d\n", p->contour[c].num_vertices);
-
- if (write_hole_flags)
- fprintf(fp, "%d\n", p->hole[c]);
-
- for (v= 0; v < p->contour[c].num_vertices; v++)
- fprintf(fp, "% .*lf % .*lf\n",
- DBL_DIG, p->contour[c].vertex[v].x,
- DBL_DIG, p->contour[c].vertex[v].y);
- }
-}
-
-
-void gpc_add_contour(gpc_polygon *p, gpc_vertex_list *new_contour, int hole)
-{
- int *extended_hole, c, v;
- gpc_vertex_list *extended_contour;
-
- /* Create an extended hole array */
- MALLOC(extended_hole, (p->num_contours + 1)
- * sizeof(int), "contour hole addition", int);
-
- /* Create an extended contour array */
- MALLOC(extended_contour, (p->num_contours + 1)
- * sizeof(gpc_vertex_list), "contour addition", gpc_vertex_list);
-
- /* Copy the old contour and hole data into the extended arrays */
- for (c= 0; c < p->num_contours; c++)
- {
- extended_hole[c]= p->hole[c];
- extended_contour[c]= p->contour[c];
- }
-
- /* Copy the new contour and hole onto the end of the extended arrays */
- c= p->num_contours;
- extended_hole[c]= hole;
- extended_contour[c].num_vertices= new_contour->num_vertices;
- MALLOC(extended_contour[c].vertex, new_contour->num_vertices
- * sizeof(gpc_vertex), "contour addition", gpc_vertex);
- for (v= 0; v < new_contour->num_vertices; v++)
- extended_contour[c].vertex[v]= new_contour->vertex[v];
-
- /* Dispose of the old contour */
- FREE(p->contour);
- FREE(p->hole);
-
- /* Update the polygon information */
- p->num_contours++;
- p->hole= extended_hole;
- p->contour= extended_contour;
-}
-
-
-void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
- gpc_polygon *result)
-{
- sb_tree *sbtree= NULL;
- it_node *it= NULL, *intersect;
- edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1;
- edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL;
- lmt_node *lmt= NULL, *local_min;
- polygon_node *out_poly= NULL, *p, *q, *poly, *npoly, *cf= NULL;
- vertex_node *vtx, *nv;
- h_state horiz[2];
- int in[2], exists[2], parity[2]= {LEFT, LEFT};
- int c, v, contributing, search, scanbeam= 0, sbt_entries= 0;
- int vclass, bl, br, tl, tr;
- double *sbt= NULL, xb, px, yb, yt, dy, ix, iy;
-
- /* Test for trivial NULL result cases */
- if (((subj->num_contours == 0) && (clip->num_contours == 0))
- || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF)))
- || ((clip->num_contours == 0) && (op == GPC_INT)))
- {
- result->num_contours= 0;
- result->hole= NULL;
- result->contour= NULL;
- return;
- }
-
- /* Identify potentialy contributing contours */
- if (((op == GPC_INT) || (op == GPC_DIFF))
- && (subj->num_contours > 0) && (clip->num_contours > 0))
- minimax_test(subj, clip, op);
-
- /* Build LMT */
- if (subj->num_contours > 0)
- s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op);
- if (clip->num_contours > 0)
- c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op);
-
- /* Return a NULL result if no contours contribute */
- if (lmt == NULL)
- {
- result->num_contours= 0;
- result->hole= NULL;
- result->contour= NULL;
- reset_lmt(&lmt);
- FREE(s_heap);
- FREE(c_heap);
- return;
- }
-
- /* Build scanbeam table from scanbeam tree */
- MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double);
- build_sbt(&scanbeam, sbt, sbtree);
- scanbeam= 0;
- free_sbtree(&sbtree);
-
- /* Allow pointer re-use without causing memory leak */
- if (subj == result)
- gpc_free_polygon(subj);
- if (clip == result)
- gpc_free_polygon(clip);
-
- /* Invert clip polygon for difference operation */
- if (op == GPC_DIFF)
- parity[CLIP]= RIGHT;
-
- local_min= lmt;
-
- /* Process each scanbeam */
- while (scanbeam < sbt_entries)
- {
- /* Set yb and yt to the bottom and top of the scanbeam */
- yb= sbt[scanbeam++];
- if (scanbeam < sbt_entries)
- {
- yt= sbt[scanbeam];
- dy= yt - yb;
- }
-
- /* === SCANBEAM BOUNDARY PROCESSING ================================ */
-
- /* If LMT node corresponding to yb exists */
- if (local_min)
- {
- if (local_min->y == yb)
- {
- /* Add edges starting at this local minimum to the AET */
- for (edge= local_min->first_bound; edge; edge= edge->next_bound)
- add_edge_to_aet(&aet, edge, NULL);
-
- local_min= local_min->next;
- }
- }
-
- /* Set dummy previous x value */
- px= -DBL_MAX;
-
- /* Create bundles within AET */
- e0= aet;
- e1= aet;
-
- /* Set up bundle fields of first edge */
- aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb);
- aet->bundle[ABOVE][!aet->type]= FALSE;
- aet->bstate[ABOVE]= UNBUNDLED;
-
- for (next_edge= aet->next; next_edge; next_edge= next_edge->next)
- {
- /* Set up bundle fields of next edge */
- next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb);
- next_edge->bundle[ABOVE][!next_edge->type]= FALSE;
- next_edge->bstate[ABOVE]= UNBUNDLED;
-
- /* Bundle edges above the scanbeam boundary if they coincide */
- if (next_edge->bundle[ABOVE][next_edge->type])
- {
- if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx)
- && (e0->top.y != yb))
- {
- next_edge->bundle[ABOVE][ next_edge->type]^=
- e0->bundle[ABOVE][ next_edge->type];
- next_edge->bundle[ABOVE][!next_edge->type]=
- e0->bundle[ABOVE][!next_edge->type];
- next_edge->bstate[ABOVE]= BUNDLE_HEAD;
- e0->bundle[ABOVE][CLIP]= FALSE;
- e0->bundle[ABOVE][SUBJ]= FALSE;
- e0->bstate[ABOVE]= BUNDLE_TAIL;
- }
- e0= next_edge;
- }
- }
-
- horiz[CLIP]= NH;
- horiz[SUBJ]= NH;
-
- /* Process each edge at this scanbeam boundary */
- for (edge= aet; edge; edge= edge->next)
- {
- exists[CLIP]= edge->bundle[ABOVE][CLIP] +
- (edge->bundle[BELOW][CLIP] << 1);
- exists[SUBJ]= edge->bundle[ABOVE][SUBJ] +
- (edge->bundle[BELOW][SUBJ] << 1);
-
- if (exists[CLIP] || exists[SUBJ])
- {
- /* Set bundle side */
- edge->bside[CLIP]= parity[CLIP];
- edge->bside[SUBJ]= parity[SUBJ];
-
- /* Determine contributing status and quadrant occupancies */
- switch (op)
- {
- case GPC_DIFF:
- case GPC_INT:
- contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ]))
- || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP]))
- || (exists[CLIP] && exists[SUBJ]
- && (parity[CLIP] == parity[SUBJ]));
- br= (parity[CLIP])
- && (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- && (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- case GPC_XOR:
- contributing= exists[CLIP] || exists[SUBJ];
- br= (parity[CLIP])
- ^ (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- case GPC_UNION:
- contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ]))
- || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP]))
- || (exists[CLIP] && exists[SUBJ]
- && (parity[CLIP] == parity[SUBJ]));
- br= (parity[CLIP])
- || (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- || (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- }
-
- /* Update parity */
- parity[CLIP]^= edge->bundle[ABOVE][CLIP];
- parity[SUBJ]^= edge->bundle[ABOVE][SUBJ];
-
- /* Update horizontal state */
- if (exists[CLIP])
- horiz[CLIP]=
- next_h_state[horiz[CLIP]]
- [((exists[CLIP] - 1) << 1) + parity[CLIP]];
- if (exists[SUBJ])
- horiz[SUBJ]=
- next_h_state[horiz[SUBJ]]
- [((exists[SUBJ] - 1) << 1) + parity[SUBJ]];
-
- vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
-
- if (contributing)
- {
- xb= edge->xb;
-
- switch (vclass)
- {
- case EMN:
- case IMN:
- add_local_min(&out_poly, edge, xb, yb);
- px= xb;
- cf= edge->outp[ABOVE];
- break;
- case ERI:
- if (xb != px)
- {
- add_right(cf, xb, yb);
- px= xb;
- }
- edge->outp[ABOVE]= cf;
- cf= NULL;
- break;
- case ELI:
- add_left(edge->outp[BELOW], xb, yb);
- px= xb;
- cf= edge->outp[BELOW];
- break;
- case EMX:
- if (xb != px)
- {
- add_left(cf, xb, yb);
- px= xb;
- }
- merge_right(cf, edge->outp[BELOW], out_poly);
- cf= NULL;
- break;
- case ILI:
- if (xb != px)
- {
- add_left(cf, xb, yb);
- px= xb;
- }
- edge->outp[ABOVE]= cf;
- cf= NULL;
- break;
- case IRI:
- add_right(edge->outp[BELOW], xb, yb);
- px= xb;
- cf= edge->outp[BELOW];
- edge->outp[BELOW]= NULL;
- break;
- case IMX:
- if (xb != px)
- {
- add_right(cf, xb, yb);
- px= xb;
- }
- merge_left(cf, edge->outp[BELOW], out_poly);
- cf= NULL;
- edge->outp[BELOW]= NULL;
- break;
- case IMM:
- if (xb != px)
- {
- add_right(cf, xb, yb);
- px= xb;
- }
- merge_left(cf, edge->outp[BELOW], out_poly);
- edge->outp[BELOW]= NULL;
- add_local_min(&out_poly, edge, xb, yb);
- cf= edge->outp[ABOVE];
- break;
- case EMM:
- if (xb != px)
- {
- add_left(cf, xb, yb);
- px= xb;
- }
- merge_right(cf, edge->outp[BELOW], out_poly);
- edge->outp[BELOW]= NULL;
- add_local_min(&out_poly, edge, xb, yb);
- cf= edge->outp[ABOVE];
- break;
- case LED:
- if (edge->bot.y == yb)
- add_left(edge->outp[BELOW], xb, yb);
- edge->outp[ABOVE]= edge->outp[BELOW];
- px= xb;
- break;
- case RED:
- if (edge->bot.y == yb)
- add_right(edge->outp[BELOW], xb, yb);
- edge->outp[ABOVE]= edge->outp[BELOW];
- px= xb;
- break;
- default:
- break;
- } /* End of switch */
- } /* End of contributing conditional */
- } /* End of edge exists conditional */
- } /* End of AET loop */
-
- /* Delete terminating edges from the AET, otherwise compute xt */
- for (edge= aet; edge; edge= edge->next)
- {
- if (edge->top.y == yb)
- {
- prev_edge= edge->prev;
- next_edge= edge->next;
- if (prev_edge)
- prev_edge->next= next_edge;
- else
- aet= next_edge;
- if (next_edge)
- next_edge->prev= prev_edge;
-
- /* Copy bundle head state to the adjacent tail edge if required */
- if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge)
- {
- if (prev_edge->bstate[BELOW] == BUNDLE_TAIL)
- {
- prev_edge->outp[BELOW]= edge->outp[BELOW];
- prev_edge->bstate[BELOW]= UNBUNDLED;
- if (prev_edge->prev)
- if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL)
- prev_edge->bstate[BELOW]= BUNDLE_HEAD;
- }
- }
- }
- else
- {
- if (edge->top.y == yt)
- edge->xt= edge->top.x;
- else
- edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y);
- }
- }
-
- if (scanbeam < sbt_entries)
- {
- /* === SCANBEAM INTERIOR PROCESSING ============================== */
-
- build_intersection_table(&it, aet, dy);
-
- /* Process each node in the intersection table */
- for (intersect= it; intersect; intersect= intersect->next)
- {
- e0= intersect->ie[0];
- e1= intersect->ie[1];
-
- /* Only generate output for contributing intersections */
- if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ])
- && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ]))
- {
- p= e0->outp[ABOVE];
- q= e1->outp[ABOVE];
- ix= intersect->point.x;
- iy= intersect->point.y + yb;
-
- in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP])
- || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP])
- || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP]
- && e0->bside[CLIP] && e1->bside[CLIP]);
- in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ])
- || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ])
- || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ]
- && e0->bside[SUBJ] && e1->bside[SUBJ]);
-
- /* Determine quadrant occupancies */
- switch (op)
- {
- case GPC_DIFF:
- case GPC_INT:
- tr= (in[CLIP])
- && (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- case GPC_XOR:
- tr= (in[CLIP])
- ^ (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- case GPC_UNION:
- tr= (in[CLIP])
- || (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- }
-
- vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
-
- switch (vclass)
- {
- case EMN:
- add_local_min(&out_poly, e0, ix, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- break;
- case ERI:
- if (p)
- {
- add_right(p, ix, iy);
- e1->outp[ABOVE]= p;
- e0->outp[ABOVE]= NULL;
- }
- break;
- case ELI:
- if (q)
- {
- add_left(q, ix, iy);
- e0->outp[ABOVE]= q;
- e1->outp[ABOVE]= NULL;
- }
- break;
- case EMX:
- if (p && q)
- {
- add_left(p, ix, iy);
- merge_right(p, q, out_poly);
- e0->outp[ABOVE]= NULL;
- e1->outp[ABOVE]= NULL;
- }
- break;
- case IMN:
- add_local_min(&out_poly, e0, ix, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- break;
- case ILI:
- if (p)
- {
- add_left(p, ix, iy);
- e1->outp[ABOVE]= p;
- e0->outp[ABOVE]= NULL;
- }
- break;
- case IRI:
- if (q)
- {
- add_right(q, ix, iy);
- e0->outp[ABOVE]= q;
- e1->outp[ABOVE]= NULL;
- }
- break;
- case IMX:
- if (p && q)
- {
- add_right(p, ix, iy);
- merge_left(p, q, out_poly);
- e0->outp[ABOVE]= NULL;
- e1->outp[ABOVE]= NULL;
- }
- break;
- case IMM:
- if (p && q)
- {
- add_right(p, ix, iy);
- merge_left(p, q, out_poly);
- add_local_min(&out_poly, e0, ix, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- }
- break;
- case EMM:
- if (p && q)
- {
- add_left(p, ix, iy);
- merge_right(p, q, out_poly);
- add_local_min(&out_poly, e0, ix, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- }
- break;
- default:
- break;
- } /* End of switch */
- } /* End of contributing intersection conditional */
-
- /* Swap bundle sides in response to edge crossing */
- if (e0->bundle[ABOVE][CLIP])
- e1->bside[CLIP]= !e1->bside[CLIP];
- if (e1->bundle[ABOVE][CLIP])
- e0->bside[CLIP]= !e0->bside[CLIP];
- if (e0->bundle[ABOVE][SUBJ])
- e1->bside[SUBJ]= !e1->bside[SUBJ];
- if (e1->bundle[ABOVE][SUBJ])
- e0->bside[SUBJ]= !e0->bside[SUBJ];
-
- /* Swap e0 and e1 bundles in the AET */
- prev_edge= e0->prev;
- next_edge= e1->next;
- if (next_edge)
- next_edge->prev= e0;
-
- if (e0->bstate[ABOVE] == BUNDLE_HEAD)
- {
- search= TRUE;
- while (search)
- {
- prev_edge= prev_edge->prev;
- if (prev_edge)
- {
- if (prev_edge->bstate[ABOVE] != BUNDLE_TAIL)
- search= FALSE;
- }
- else
- search= FALSE;
- }
- }
- if (!prev_edge)
- {
- aet->prev= e1;
- e1->next= aet;
- aet= e0->next;
- }
- else
- {
- prev_edge->next->prev= e1;
- e1->next= prev_edge->next;
- prev_edge->next= e0->next;
- }
- e0->next->prev= prev_edge;
- e1->next->prev= e1;
- e0->next= next_edge;
- } /* End of IT loop*/
-
- /* Prepare for next scanbeam */
- for (edge= aet; edge; edge= next_edge)
- {
- next_edge= edge->next;
- succ_edge= edge->succ;
-
- if ((edge->top.y == yt) && succ_edge)
- {
- /* Replace AET edge by its successor */
- succ_edge->outp[BELOW]= edge->outp[ABOVE];
- succ_edge->bstate[BELOW]= edge->bstate[ABOVE];
- succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
- succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
- prev_edge= edge->prev;
- if (prev_edge)
- prev_edge->next= succ_edge;
- else
- aet= succ_edge;
- if (next_edge)
- next_edge->prev= succ_edge;
- succ_edge->prev= prev_edge;
- succ_edge->next= next_edge;
- }
- else
- {
- /* Update this edge */
- edge->outp[BELOW]= edge->outp[ABOVE];
- edge->bstate[BELOW]= edge->bstate[ABOVE];
- edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
- edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
- edge->xb= edge->xt;
- }
- edge->outp[ABOVE]= NULL;
- }
- }
- } /* === END OF SCANBEAM PROCESSING ================================== */
-
- /* Generate result polygon from out_poly */
- result->contour= NULL;
- result->hole= NULL;
- result->num_contours= count_contours(out_poly);
- if (result->num_contours > 0)
- {
- MALLOC(result->hole, result->num_contours
- * sizeof(int), "hole flag table creation", int);
- MALLOC(result->contour, result->num_contours
- * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
-
- c= 0;
- for (poly= out_poly; poly; poly= npoly)
- {
- npoly= poly->next;
- if (poly->active)
- {
- result->hole[c]= poly->proxy->hole;
- result->contour[c].num_vertices= poly->active;
- MALLOC(result->contour[c].vertex,
- result->contour[c].num_vertices * sizeof(gpc_vertex),
- "vertex creation", gpc_vertex);
-
- v= result->contour[c].num_vertices - 1;
- for (vtx= poly->proxy->v[LEFT]; vtx; vtx= nv)
- {
- nv= vtx->next;
- result->contour[c].vertex[v].x= vtx->x;
- result->contour[c].vertex[v].y= vtx->y;
- FREE(vtx);
- v--;
- }
- c++;
- }
- FREE(poly);
- }
- }
- else
- {
- for (poly= out_poly; poly; poly= npoly)
- {
- npoly= poly->next;
- FREE(poly);
- }
- }
-
- /* Tidy up */
- reset_it(&it);
- reset_lmt(&lmt);
- FREE(c_heap);
- FREE(s_heap);
- FREE(sbt);
-}
-
-
-void gpc_free_tristrip(gpc_tristrip *t)
-{
- int s;
-
- for (s= 0; s < t->num_strips; s++)
- FREE(t->strip[s].vertex);
- FREE(t->strip);
- t->num_strips= 0;
-}
-
-
-void gpc_polygon_to_tristrip(gpc_polygon *s, gpc_tristrip *t)
-{
- gpc_polygon c;
-
- c.num_contours= 0;
- c.hole= NULL;
- c.contour= NULL;
- gpc_tristrip_clip(GPC_DIFF, s, &c, t);
-}
-
-
-void gpc_tristrip_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
- gpc_tristrip *result)
-{
- sb_tree *sbtree= NULL;
- it_node *it= NULL, *intersect;
- edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1;
- edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL, *cf;
- lmt_node *lmt= NULL, *local_min;
- polygon_node *tlist= NULL, *tn, *tnn, *p, *q;
- vertex_node *lt, *ltn, *rt, *rtn;
- h_state horiz[2];
- vertex_type cft;
- int in[2], exists[2], parity[2]= {LEFT, LEFT};
- int s, v, contributing, search, scanbeam= 0, sbt_entries= 0;
- int vclass, bl, br, tl, tr;
- double *sbt= NULL, xb, px, nx, yb, yt, dy, ix, iy;
-
- /* Test for trivial NULL result cases */
- if (((subj->num_contours == 0) && (clip->num_contours == 0))
- || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF)))
- || ((clip->num_contours == 0) && (op == GPC_INT)))
- {
- result->num_strips= 0;
- result->strip= NULL;
- return;
- }
-
- /* Identify potentialy contributing contours */
- if (((op == GPC_INT) || (op == GPC_DIFF))
- && (subj->num_contours > 0) && (clip->num_contours > 0))
- minimax_test(subj, clip, op);
-
- /* Build LMT */
- if (subj->num_contours > 0)
- s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op);
- if (clip->num_contours > 0)
- c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op);
-
- /* Return a NULL result if no contours contribute */
- if (lmt == NULL)
- {
- result->num_strips= 0;
- result->strip= NULL;
- reset_lmt(&lmt);
- FREE(s_heap);
- FREE(c_heap);
- return;
- }
-
- /* Build scanbeam table from scanbeam tree */
- MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double);
- build_sbt(&scanbeam, sbt, sbtree);
- scanbeam= 0;
- free_sbtree(&sbtree);
-
- /* Invert clip polygon for difference operation */
- if (op == GPC_DIFF)
- parity[CLIP]= RIGHT;
-
- local_min= lmt;
-
- /* Process each scanbeam */
- while (scanbeam < sbt_entries)
- {
- /* Set yb and yt to the bottom and top of the scanbeam */
- yb= sbt[scanbeam++];
- if (scanbeam < sbt_entries)
- {
- yt= sbt[scanbeam];
- dy= yt - yb;
- }
-
- /* === SCANBEAM BOUNDARY PROCESSING ================================ */
-
- /* If LMT node corresponding to yb exists */
- if (local_min)
- {
- if (local_min->y == yb)
- {
- /* Add edges starting at this local minimum to the AET */
- for (edge= local_min->first_bound; edge; edge= edge->next_bound)
- add_edge_to_aet(&aet, edge, NULL);
-
- local_min= local_min->next;
- }
- }
-
- /* Set dummy previous x value */
- px= -DBL_MAX;
-
- /* Create bundles within AET */
- e0= aet;
- e1= aet;
-
- /* Set up bundle fields of first edge */
- aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb);
- aet->bundle[ABOVE][!aet->type]= FALSE;
- aet->bstate[ABOVE]= UNBUNDLED;
-
- for (next_edge= aet->next; next_edge; next_edge= next_edge->next)
- {
- /* Set up bundle fields of next edge */
- next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb);
- next_edge->bundle[ABOVE][!next_edge->type]= FALSE;
- next_edge->bstate[ABOVE]= UNBUNDLED;
-
- /* Bundle edges above the scanbeam boundary if they coincide */
- if (next_edge->bundle[ABOVE][next_edge->type])
- {
- if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx)
- && (e0->top.y != yb))
- {
- next_edge->bundle[ABOVE][ next_edge->type]^=
- e0->bundle[ABOVE][ next_edge->type];
- next_edge->bundle[ABOVE][!next_edge->type]=
- e0->bundle[ABOVE][!next_edge->type];
- next_edge->bstate[ABOVE]= BUNDLE_HEAD;
- e0->bundle[ABOVE][CLIP]= FALSE;
- e0->bundle[ABOVE][SUBJ]= FALSE;
- e0->bstate[ABOVE]= BUNDLE_TAIL;
- }
- e0= next_edge;
- }
- }
-
- horiz[CLIP]= NH;
- horiz[SUBJ]= NH;
-
- /* Process each edge at this scanbeam boundary */
- for (edge= aet; edge; edge= edge->next)
- {
- exists[CLIP]= edge->bundle[ABOVE][CLIP] +
- (edge->bundle[BELOW][CLIP] << 1);
- exists[SUBJ]= edge->bundle[ABOVE][SUBJ] +
- (edge->bundle[BELOW][SUBJ] << 1);
-
- if (exists[CLIP] || exists[SUBJ])
- {
- /* Set bundle side */
- edge->bside[CLIP]= parity[CLIP];
- edge->bside[SUBJ]= parity[SUBJ];
-
- /* Determine contributing status and quadrant occupancies */
- switch (op)
- {
- case GPC_DIFF:
- case GPC_INT:
- contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ]))
- || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP]))
- || (exists[CLIP] && exists[SUBJ]
- && (parity[CLIP] == parity[SUBJ]));
- br= (parity[CLIP])
- && (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- && (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- case GPC_XOR:
- contributing= exists[CLIP] || exists[SUBJ];
- br= (parity[CLIP])
- ^ (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- case GPC_UNION:
- contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ]))
- || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP]))
- || (exists[CLIP] && exists[SUBJ]
- && (parity[CLIP] == parity[SUBJ]));
- br= (parity[CLIP])
- || (parity[SUBJ]);
- bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
- || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
- tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
- || (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
- tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
- || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
- break;
- }
-
- /* Update parity */
- parity[CLIP]^= edge->bundle[ABOVE][CLIP];
- parity[SUBJ]^= edge->bundle[ABOVE][SUBJ];
-
- /* Update horizontal state */
- if (exists[CLIP])
- horiz[CLIP]=
- next_h_state[horiz[CLIP]]
- [((exists[CLIP] - 1) << 1) + parity[CLIP]];
- if (exists[SUBJ])
- horiz[SUBJ]=
- next_h_state[horiz[SUBJ]]
- [((exists[SUBJ] - 1) << 1) + parity[SUBJ]];
-
- vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
-
- if (contributing)
- {
- xb= edge->xb;
-
- switch (vclass)
- {
- case EMN:
- new_tristrip(&tlist, edge, xb, yb);
- cf= edge;
- break;
- case ERI:
- edge->outp[ABOVE]= cf->outp[ABOVE];
- if (xb != cf->xb)
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
- cf= NULL;
- break;
- case ELI:
- VERTEX(edge, BELOW, LEFT, xb, yb);
- edge->outp[ABOVE]= NULL;
- cf= edge;
- break;
- case EMX:
- if (xb != cf->xb)
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- edge->outp[ABOVE]= NULL;
- cf= NULL;
- break;
- case IMN:
- if (cft == LED)
- {
- if (cf->bot.y != yb)
- VERTEX(cf, BELOW, LEFT, cf->xb, yb);
- new_tristrip(&tlist, cf, cf->xb, yb);
- }
- edge->outp[ABOVE]= cf->outp[ABOVE];
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
- break;
- case ILI:
- new_tristrip(&tlist, edge, xb, yb);
- cf= edge;
- cft= ILI;
- break;
- case IRI:
- if (cft == LED)
- {
- if (cf->bot.y != yb)
- VERTEX(cf, BELOW, LEFT, cf->xb, yb);
- new_tristrip(&tlist, cf, cf->xb, yb);
- }
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- edge->outp[ABOVE]= NULL;
- break;
- case IMX:
- VERTEX(edge, BELOW, LEFT, xb, yb);
- edge->outp[ABOVE]= NULL;
- cft= IMX;
- break;
- case IMM:
- VERTEX(edge, BELOW, LEFT, xb, yb);
- edge->outp[ABOVE]= cf->outp[ABOVE];
- if (xb != cf->xb)
- VERTEX(cf, ABOVE, RIGHT, xb, yb);
- cf= edge;
- break;
- case EMM:
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- edge->outp[ABOVE]= NULL;
- new_tristrip(&tlist, edge, xb, yb);
- cf= edge;
- break;
- case LED:
- if (edge->bot.y == yb)
- VERTEX(edge, BELOW, LEFT, xb, yb);
- edge->outp[ABOVE]= edge->outp[BELOW];
- cf= edge;
- cft= LED;
- break;
- case RED:
- edge->outp[ABOVE]= cf->outp[ABOVE];
- if (cft == LED)
- {
- if (cf->bot.y == yb)
- {
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- }
- else
- {
- if (edge->bot.y == yb)
- {
- VERTEX(cf, BELOW, LEFT, cf->xb, yb);
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- }
- }
- }
- else
- {
- VERTEX(edge, BELOW, RIGHT, xb, yb);
- VERTEX(edge, ABOVE, RIGHT, xb, yb);
- }
- cf= NULL;
- break;
- default:
- break;
- } /* End of switch */
- } /* End of contributing conditional */
- } /* End of edge exists conditional */
- } /* End of AET loop */
-
- /* Delete terminating edges from the AET, otherwise compute xt */
- for (edge= aet; edge; edge= edge->next)
- {
- if (edge->top.y == yb)
- {
- prev_edge= edge->prev;
- next_edge= edge->next;
- if (prev_edge)
- prev_edge->next= next_edge;
- else
- aet= next_edge;
- if (next_edge)
- next_edge->prev= prev_edge;
-
- /* Copy bundle head state to the adjacent tail edge if required */
- if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge)
- {
- if (prev_edge->bstate[BELOW] == BUNDLE_TAIL)
- {
- prev_edge->outp[BELOW]= edge->outp[BELOW];
- prev_edge->bstate[BELOW]= UNBUNDLED;
- if (prev_edge->prev)
- if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL)
- prev_edge->bstate[BELOW]= BUNDLE_HEAD;
- }
- }
- }
- else
- {
- if (edge->top.y == yt)
- edge->xt= edge->top.x;
- else
- edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y);
- }
- }
-
- if (scanbeam < sbt_entries)
- {
- /* === SCANBEAM INTERIOR PROCESSING ============================== */
-
- build_intersection_table(&it, aet, dy);
-
- /* Process each node in the intersection table */
- for (intersect= it; intersect; intersect= intersect->next)
- {
- e0= intersect->ie[0];
- e1= intersect->ie[1];
-
- /* Only generate output for contributing intersections */
- if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ])
- && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ]))
- {
- p= e0->outp[ABOVE];
- q= e1->outp[ABOVE];
- ix= intersect->point.x;
- iy= intersect->point.y + yb;
-
- in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP])
- || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP])
- || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP]
- && e0->bside[CLIP] && e1->bside[CLIP]);
- in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ])
- || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ])
- || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ]
- && e0->bside[SUBJ] && e1->bside[SUBJ]);
-
- /* Determine quadrant occupancies */
- switch (op)
- {
- case GPC_DIFF:
- case GPC_INT:
- tr= (in[CLIP])
- && (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- case GPC_XOR:
- tr= (in[CLIP])
- ^ (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- case GPC_UNION:
- tr= (in[CLIP])
- || (in[SUBJ]);
- tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
- br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
- || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
- break;
- }
-
- vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
-
- switch (vclass)
- {
- case EMN:
- new_tristrip(&tlist, e1, ix, iy);
- e0->outp[ABOVE]= e1->outp[ABOVE];
- break;
- case ERI:
- if (p)
- {
- P_EDGE(prev_edge, e0, ABOVE, px, iy);
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- e0->outp[ABOVE]= NULL;
- }
- break;
- case ELI:
- if (q)
- {
- N_EDGE(next_edge, e1, ABOVE, nx, iy);
- VERTEX(e1, ABOVE, LEFT, ix, iy);
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- e0->outp[ABOVE]= e1->outp[ABOVE];
- e1->outp[ABOVE]= NULL;
- }
- break;
- case EMX:
- if (p && q)
- {
- VERTEX(e0, ABOVE, LEFT, ix, iy);
- e0->outp[ABOVE]= NULL;
- e1->outp[ABOVE]= NULL;
- }
- break;
- case IMN:
- P_EDGE(prev_edge, e0, ABOVE, px, iy);
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
- N_EDGE(next_edge, e1, ABOVE, nx, iy);
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- new_tristrip(&tlist, prev_edge, px, iy);
- e1->outp[ABOVE]= prev_edge->outp[ABOVE];
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
- new_tristrip(&tlist, e0, ix, iy);
- next_edge->outp[ABOVE]= e0->outp[ABOVE];
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- break;
- case ILI:
- if (p)
- {
- VERTEX(e0, ABOVE, LEFT, ix, iy);
- N_EDGE(next_edge, e1, ABOVE, nx, iy);
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- e1->outp[ABOVE]= e0->outp[ABOVE];
- e0->outp[ABOVE]= NULL;
- }
- break;
- case IRI:
- if (q)
- {
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
- P_EDGE(prev_edge, e0, ABOVE, px, iy);
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
- e0->outp[ABOVE]= e1->outp[ABOVE];
- e1->outp[ABOVE]= NULL;
- }
- break;
- case IMX:
- if (p && q)
- {
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
- VERTEX(e1, ABOVE, LEFT, ix, iy);
- e0->outp[ABOVE]= NULL;
- e1->outp[ABOVE]= NULL;
- P_EDGE(prev_edge, e0, ABOVE, px, iy);
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
- new_tristrip(&tlist, prev_edge, px, iy);
- N_EDGE(next_edge, e1, ABOVE, nx, iy);
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- next_edge->outp[ABOVE]= prev_edge->outp[ABOVE];
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- }
- break;
- case IMM:
- if (p && q)
- {
- VERTEX(e0, ABOVE, RIGHT, ix, iy);
- VERTEX(e1, ABOVE, LEFT, ix, iy);
- P_EDGE(prev_edge, e0, ABOVE, px, iy);
- VERTEX(prev_edge, ABOVE, LEFT, px, iy);
- new_tristrip(&tlist, prev_edge, px, iy);
- N_EDGE(next_edge, e1, ABOVE, nx, iy);
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- e1->outp[ABOVE]= prev_edge->outp[ABOVE];
- VERTEX(e1, ABOVE, RIGHT, ix, iy);
- new_tristrip(&tlist, e0, ix, iy);
- next_edge->outp[ABOVE]= e0->outp[ABOVE];
- VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
- }
- break;
- case EMM:
- if (p && q)
- {
- VERTEX(e0, ABOVE, LEFT, ix, iy);
- new_tristrip(&tlist, e1, ix, iy);
- e0->outp[ABOVE]= e1->outp[ABOVE];
- }
- break;
- default:
- break;
- } /* End of switch */
- } /* End of contributing intersection conditional */
-
- /* Swap bundle sides in response to edge crossing */
- if (e0->bundle[ABOVE][CLIP])
- e1->bside[CLIP]= !e1->bside[CLIP];
- if (e1->bundle[ABOVE][CLIP])
- e0->bside[CLIP]= !e0->bside[CLIP];
- if (e0->bundle[ABOVE][SUBJ])
- e1->bside[SUBJ]= !e1->bside[SUBJ];
- if (e1->bundle[ABOVE][SUBJ])
- e0->bside[SUBJ]= !e0->bside[SUBJ];
-
- /* Swap e0 and e1 bundles in the AET */
- prev_edge= e0->prev;
- next_edge= e1->next;
- if (e1->next)
- e1->next->prev= e0;
-
- if (e0->bstate[ABOVE] == BUNDLE_HEAD)
- {
- search= TRUE;
- while (search)
- {
- prev_edge= prev_edge->prev;
- if (prev_edge)
- {
- if (prev_edge->bundle[ABOVE][CLIP]
- || prev_edge->bundle[ABOVE][SUBJ]
- || (prev_edge->bstate[ABOVE] == BUNDLE_HEAD))
- search= FALSE;
- }
- else
- search= FALSE;
- }
- }
- if (!prev_edge)
- {
- e1->next= aet;
- aet= e0->next;
- }
- else
- {
- e1->next= prev_edge->next;
- prev_edge->next= e0->next;
- }
- e0->next->prev= prev_edge;
- e1->next->prev= e1;
- e0->next= next_edge;
- } /* End of IT loop*/
-
- /* Prepare for next scanbeam */
- for (edge= aet; edge; edge= next_edge)
- {
- next_edge= edge->next;
- succ_edge= edge->succ;
-
- if ((edge->top.y == yt) && succ_edge)
- {
- /* Replace AET edge by its successor */
- succ_edge->outp[BELOW]= edge->outp[ABOVE];
- succ_edge->bstate[BELOW]= edge->bstate[ABOVE];
- succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
- succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
- prev_edge= edge->prev;
- if (prev_edge)
- prev_edge->next= succ_edge;
- else
- aet= succ_edge;
- if (next_edge)
- next_edge->prev= succ_edge;
- succ_edge->prev= prev_edge;
- succ_edge->next= next_edge;
- }
- else
- {
- /* Update this edge */
- edge->outp[BELOW]= edge->outp[ABOVE];
- edge->bstate[BELOW]= edge->bstate[ABOVE];
- edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
- edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
- edge->xb= edge->xt;
- }
- edge->outp[ABOVE]= NULL;
- }
- }
- } /* === END OF SCANBEAM PROCESSING ================================== */
-
- /* Generate result tristrip from tlist */
- result->strip= NULL;
- result->num_strips= count_tristrips(tlist);
- if (result->num_strips > 0)
- {
- MALLOC(result->strip, result->num_strips * sizeof(gpc_vertex_list),
- "tristrip list creation", gpc_vertex_list);
-
- s= 0;
- for (tn= tlist; tn; tn= tnn)
- {
- tnn= tn->next;
-
- if (tn->active > 2)
- {
- /* Valid tristrip: copy the vertices and free the heap */
- result->strip[s].num_vertices= tn->active;
- MALLOC(result->strip[s].vertex, tn->active * sizeof(gpc_vertex),
- "tristrip creation", gpc_vertex);
- v= 0;
- if (INVERT_TRISTRIPS)
- {
- lt= tn->v[RIGHT];
- rt= tn->v[LEFT];
- }
- else
- {
- lt= tn->v[LEFT];
- rt= tn->v[RIGHT];
- }
- while (lt || rt)
- {
- if (lt)
- {
- ltn= lt->next;
- result->strip[s].vertex[v].x= lt->x;
- result->strip[s].vertex[v].y= lt->y;
- v++;
- FREE(lt);
- lt= ltn;
- }
- if (rt)
- {
- rtn= rt->next;
- result->strip[s].vertex[v].x= rt->x;
- result->strip[s].vertex[v].y= rt->y;
- v++;
- FREE(rt);
- rt= rtn;
- }
- }
- s++;
- }
- else
- {
- /* Invalid tristrip: just free the heap */
- for (lt= tn->v[LEFT]; lt; lt= ltn)
- {
- ltn= lt->next;
- FREE(lt);
- }
- for (rt= tn->v[RIGHT]; rt; rt=rtn)
- {
- rtn= rt->next;
- FREE(rt);
- }
- }
- FREE(tn);
- }
- }
-
- /* Tidy up */
- reset_it(&it);
- reset_lmt(&lmt);
- FREE(c_heap);
- FREE(s_heap);
- FREE(sbt);
-}
-
-/*
-===========================================================================
- End of file: gpc.c
-===========================================================================
-*/
diff --git a/desmume/src/windows/agg/gpc/gpc.h b/desmume/src/windows/agg/gpc/gpc.h
deleted file mode 100644
index 593539839..000000000
--- a/desmume/src/windows/agg/gpc/gpc.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-===========================================================================
-
-Project: Generic Polygon Clipper
-
- A new algorithm for calculating the difference, intersection,
- exclusive-or or union of arbitrary polygon sets.
-
-File: gpc.h
-Author: Alan Murta (email: gpc@cs.man.ac.uk)
-Version: 2.32
-Date: 17th December 2004
-
-Copyright: (C) 1997-2004, Advanced Interfaces Group,
- University of Manchester.
-
- This software is free for non-commercial use. It may be copied,
- modified, and redistributed provided that this copyright notice
- is preserved on all copies. The intellectual property rights of
- the algorithms used reside with the University of Manchester
- Advanced Interfaces Group.
-
- You may not use this software, in whole or in part, in support
- of any commercial product without the express consent of the
- author.
-
- There is no warranty or other guarantee of fitness of this
- software for any purpose. It is provided solely "as is".
-
-===========================================================================
-*/
-
-#ifndef __gpc_h
-#define __gpc_h
-
-#include
-
-
-/*
-===========================================================================
- Constants
-===========================================================================
-*/
-
-/* Increase GPC_EPSILON to encourage merging of near coincident edges */
-
-#define GPC_EPSILON (DBL_EPSILON)
-
-#define GPC_VERSION "2.32"
-
-
-/*
-===========================================================================
- Public Data Types
-===========================================================================
-*/
-
-typedef enum /* Set operation type */
-{
- GPC_DIFF, /* Difference */
- GPC_INT, /* Intersection */
- GPC_XOR, /* Exclusive or */
- GPC_UNION /* Union */
-} gpc_op;
-
-typedef struct /* Polygon vertex structure */
-{
- double x; /* Vertex x component */
- double y; /* vertex y component */
-} gpc_vertex;
-
-typedef struct /* Vertex list structure */
-{
- int num_vertices; /* Number of vertices in list */
- gpc_vertex *vertex; /* Vertex array pointer */
-} gpc_vertex_list;
-
-typedef struct /* Polygon set structure */
-{
- int num_contours; /* Number of contours in polygon */
- int *hole; /* Hole / external contour flags */
- gpc_vertex_list *contour; /* Contour array pointer */
-} gpc_polygon;
-
-typedef struct /* Tristrip set structure */
-{
- int num_strips; /* Number of tristrips */
- gpc_vertex_list *strip; /* Tristrip array pointer */
-} gpc_tristrip;
-
-
-/*
-===========================================================================
- Public Function Prototypes
-===========================================================================
-*/
-
-void gpc_read_polygon (FILE *infile_ptr,
- int read_hole_flags,
- gpc_polygon *polygon);
-
-void gpc_write_polygon (FILE *outfile_ptr,
- int write_hole_flags,
- gpc_polygon *polygon);
-
-void gpc_add_contour (gpc_polygon *polygon,
- gpc_vertex_list *contour,
- int hole);
-
-void gpc_polygon_clip (gpc_op set_operation,
- gpc_polygon *subject_polygon,
- gpc_polygon *clip_polygon,
- gpc_polygon *result_polygon);
-
-void gpc_tristrip_clip (gpc_op set_operation,
- gpc_polygon *subject_polygon,
- gpc_polygon *clip_polygon,
- gpc_tristrip *result_tristrip);
-
-void gpc_polygon_to_tristrip (gpc_polygon *polygon,
- gpc_tristrip *tristrip);
-
-void gpc_free_polygon (gpc_polygon *polygon);
-
-void gpc_free_tristrip (gpc_tristrip *tristrip);
-
-#endif
-
-/*
-===========================================================================
- End of file: gpc.h
-===========================================================================
-*/