📄 polygon.c
字号:
} while (cur_index != max_index); for (i = 0; i < nr_hlines; i++) { cb (context, hlines [i].x1, hlines [i].x2, i + min_point_y); } /* Release the line list's memory and we're successfully done */ free (hlines); return TRUE;}/* _fill_edge_structure: * Polygon helper function: initialises an edge structure for the 2d * rasteriser. */void _fill_edge_structure (POLYGON_EDGE *edge, const int *i1, const int *i2){ if (i2[1] < i1[1]) { const int *it; it = i1; i1 = i2; i2 = it; } edge->top = i1[1]; edge->bottom = i2[1] - 1; edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) / (i2[1] - i1[1]); edge->x = (i1[0] << POLYGON_FIX_SHIFT) + (1<<(POLYGON_FIX_SHIFT-1)) - 1; edge->prev = NULL; edge->next = NULL; if (edge->dx < 0) edge->x += MIN(edge->dx+(1<<POLYGON_FIX_SHIFT), 0); edge->w = MAX(ABS(edge->dx)-(1<<POLYGON_FIX_SHIFT), 0);}/* _add_edge: * Adds an edge structure to a linked list, returning the new head pointer. */POLYGON_EDGE *_add_edge (POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x){ POLYGON_EDGE *pos = list; POLYGON_EDGE *prev = NULL; if (sort_by_x) { while ((pos) && ((pos->x + (pos->w + pos->dx) / 2) < (edge->x + (edge->w + edge->dx) / 2))) { prev = pos; pos = pos->next; } } else { while ((pos) && (pos->top < edge->top)) { prev = pos; pos = pos->next; } } edge->next = pos; edge->prev = prev; if (pos) pos->prev = edge; if (prev) { prev->next = edge; return list; } else return edge;}/* _remove_edge: * Removes an edge structure from a list, returning the new head pointer. */POLYGON_EDGE *_remove_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge){ if (edge->next) edge->next->prev = edge->prev; if (edge->prev) { edge->prev->next = edge->next; return list; } else return edge->next;}/* General polygon generator */BOOL GUIAPI PolygonGenerator (void* context, const POINT* pts, int vertices, CB_POLYGON cb){ int c; int top = INT_MAX; int bottom = INT_MIN; const int *i1, *i2; void* _scratch_mem; const int* points = (int*) pts; POLYGON_EDGE *edge, *next_edge; POLYGON_EDGE *active_edges = NULL; POLYGON_EDGE *inactive_edges = NULL; /* allocate some space and fill the edge table */ _scratch_mem = malloc (sizeof(POLYGON_EDGE) * vertices); if (!(edge = (POLYGON_EDGE *)_scratch_mem)) return FALSE; i1 = points; i2 = points + (vertices-1) * 2; for (c=0; c<vertices; c++) { if (i1[1] != i2[1]) { _fill_edge_structure (edge, i1, i2); if (edge->bottom >= edge->top) { if (edge->top < top) top = edge->top; if (edge->bottom > bottom) bottom = edge->bottom; inactive_edges = _add_edge(inactive_edges, edge, FALSE); edge++; } } i2 = i1; i1 += 2; } /* for each scanline in the polygon... */ for (c=top; c<=bottom; c++) { /* check for newly active edges */ edge = inactive_edges; while ((edge) && (edge->top == c)) { next_edge = edge->next; inactive_edges = _remove_edge(inactive_edges, edge); active_edges = _add_edge(active_edges, edge, TRUE); edge = next_edge; } /* draw horizontal line segments */ edge = active_edges; while ((edge) && (edge->next)) { int x1 = edge->x>>POLYGON_FIX_SHIFT; int x2 = ((edge->next->x+edge->next->w)>>POLYGON_FIX_SHIFT); cb (context, x1, x2, c); edge = edge->next->next; } /* update edges, sorting and removing dead ones */ edge = active_edges; while (edge) { next_edge = edge->next; if (c >= edge->bottom) { active_edges = _remove_edge(active_edges, edge); } else { edge->x += edge->dx; while ((edge->prev) && (edge->x+edge->w/2 < edge->prev->x+edge->prev->w/2)) { if (edge->next) edge->next->prev = edge->prev; edge->prev->next = edge->next; edge->next = edge->prev; edge->prev = edge->prev->prev; edge->next->prev = edge; if (edge->prev) edge->prev->next = edge; else active_edges = edge; } } edge = next_edge; } } free (_scratch_mem); return TRUE;}static POINT* convert_vertices (PDC pdc, const POINT* pts, int vertices, RECT* rcOutput){ int i; POINT* points; if (vertices < 3) return NULL; if (!(points = malloc (sizeof (POINT) * vertices))) { return NULL; } /* Transfer logical to device to screen and find rcOutput here. */ points [0] = pts [0]; coor_LP2SP (pdc, &points [0].x, &points [0].y); rcOutput->left = rcOutput->right = points [0].x; rcOutput->top = rcOutput->bottom = points [0].y; for (i = 1; i < vertices; i++) { points [i] = pts [i]; coor_LP2SP (pdc, &points [i].x, &points [i].y); if (points [i].x < rcOutput->left) { rcOutput->left = points [i].x; } else if (points [i].x > rcOutput->right) { rcOutput->right = points [i].x; } if (points [i].y < rcOutput->top) { rcOutput->top = points [i].y; } else if (points [i].y > rcOutput->bottom) { rcOutput->bottom = points [i].y; } } return points;}BOOL GUIAPI FillPolygon (HDC hdc, const POINT* pts, int vertices){ PDC pdc; RECT rc_tmp; POINT* points; BOOL is_mv; if (vertices < 3) return FALSE; if (!(pdc = check_ecrgn (hdc))) return TRUE; is_mv = PolygonIsMonotoneVertical (pts, vertices); if (!(points = convert_vertices (pdc, pts, vertices, &pdc->rc_output))) return FALSE; pdc->cur_pixel = pdc->brushcolor; pdc->cur_ban = NULL; rc_tmp = pdc->rc_output; pdc->rc_output.right ++; pdc->rc_output.bottom ++; ENTER_DRAWING (pdc); if (rc_tmp.left == rc_tmp.right) { _dc_draw_vline_clip (pdc, rc_tmp.top, rc_tmp.bottom, rc_tmp.left); } else if (rc_tmp.top == rc_tmp.bottom) { _dc_draw_hline_clip (pdc, rc_tmp.left, rc_tmp.right, rc_tmp.top); } else { if (is_mv) MonotoneVerticalPolygonGenerator (pdc, points, vertices, _dc_draw_hline_clip); else PolygonGenerator (pdc, points, vertices, _dc_draw_hline_clip); } LEAVE_DRAWING (pdc); UNLOCK_GCRINFO (pdc); free (points); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -