static void DrawPolyPolygonRaw(Draw& draw, const Point *vertices, int vertex_count, const int *subpolygon_counts, int subpolygon_count_count, bool is_inside, int outline_width, Color outline_color ) { #ifdef SYSTEMDRAW SystemDraw *w = dynamic_cast<SystemDraw *>(&draw); if(w) { SystemDraw& draw = *w; #endif draw.SetDrawPen(outline_width, outline_color); ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not enum { MAX_POLY = 8000 }; if(subpolygon_count_count == 1 && vertex_count < MAX_POLY) Polygon(draw, (const POINT *)vertices, vertex_count); else if(vertex_count < MAX_POLY) PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, subpolygon_count_count); else { if(is_inside) { draw.SetDrawPen(PEN_NULL, Black); Vector<Point> split_vertices; Vector<int> split_counts; #ifdef SYSTEMDRAW SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, split_vertices, split_counts, Size(9999, 9999)); #else SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, split_vertices, split_counts, draw.GetClip()); #endif //!! todo: maxcount for splitpolygon const Point *sv = split_vertices.Begin(); for(const int *sc = split_counts.Begin(), *se = split_counts.End(); sc < se; sc++) { Polygon(draw, (const POINT *)sv, *sc); sv += *sc; } } if(outline_width != PEN_NULL) { draw.DrawPolyPolyline(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, outline_width, outline_color, Null); Buffer<Point> finish(2 * subpolygon_count_count); Buffer<int> counts(subpolygon_count_count); Fill(&counts[0], &counts[subpolygon_count_count], 2); Point *d = finish; const Point *p = vertices; const int *c = subpolygon_counts, *e = c + subpolygon_count_count; while(c < e) { *d++ = *p; *d++ = (p += *c++)[-1]; } draw.DrawPolyPolyline(finish, 2 * subpolygon_count_count, counts, subpolygon_count_count, outline_width, outline_color, Null); } draw.SetDrawPen(outline_width, outline_color); } #ifdef SYSTEMDRAW } #endif }
void Paint(Draw &w) { Size sz = GetSize(); Rect rc = w.GetClip(); static bool first = true; DUMP(rc); if(first) { w.DrawRect(sz, SGreen); first = false; } else for(int i = rc.left; i <= rc.right; i++) w.DrawLine(i, rc.top , i, rc.bottom, 0, (i & 1) ? SWhite : SBlack); }
void DrawPolyPolyPolygon(Draw& draw, const Point *vertices, int vertex_count, const int *subpolygon_counts, int subpolygon_count_count, const int *disjunct_polygon_counts, int disjunct_polygon_count_count, Color color, int width, Color outline, uint64 pattern, Color doxor) { if(vertex_count == 0) return; #ifdef PLATFORM_WIN32_ //!!TODO if(PdfDraw *pdf = dynamic_cast<PdfDraw *>(&draw)) { pdf->DrawPolyPolyPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, disjunct_polygon_counts, disjunct_polygon_count_count, color, width, outline, pattern, doxor); return; } #endif // LOG("DrawPolyPolyPolygon: drawing = " << (draw.IsDrawing() ? "yes" : "no") // << ", backdraw = " << (draw.IsBack() ? "yes" : "no") // << ", " << (draw.Dots() ? "dots" : "pixels") // << ", printer = " << (draw.IsPrinter() ? "yes" : "no")); // LOG("#vertices = " << vertex_count << ", #subpolygons = " << subpolygon_count_count // << ", #disjunct polygons = " << disjunct_polygon_count_count); // LOG("color = " << Dump(color) << ", width = " << width << ", outline = " << Dump(outline) // << ", pattern = " << Dump(pattern) << ", doxor = " << doxor); #ifdef _DEBUG // for(int v = 0; v < vertex_count; v++) // if(abs2(vertices[v] - vertices[(v ? v : vertex_count) - 1]) >= 500 * 500) // NEVER(); #endif if(!dynamic_cast<SystemDraw *>(&draw)) { draw.DrawPolyPolyPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, disjunct_polygon_counts, disjunct_polygon_count_count, color, width, outline, pattern, doxor); return; } // TIMING("DrawPolyPolygon/hdc"); bool is_xor = !IsNull(doxor); #ifdef PLATFORM_X11 unsigned xor_pixel = (is_xor ? GetXPixel(doxor) : 0); XGCValues gcv; gcv.function = is_xor ? X11_ROP2_XOR : X11_ROP2_COPY; GC fill_gc = NULL; Image pattern_image; if(!IsNull(color)) { gcv.foreground = GetXPixel(color) ^ xor_pixel; int fmask = GCForeground | GCFunction; if(pattern) { pattern_image = GetPatternImage(pattern); gcv.stipple = pattern_image.GetMaskPixmap(); gcv.fill_style = FillStippled; fmask |= GCStipple | GCFillStyle; } fill_gc = XCreateGC(Xdisplay, draw.GetDrawable(), fmask, &gcv); } GC line_gc = NULL; if(!IsNull(outline)) { gcv.foreground = GetXPixel(outline) ^ xor_pixel; gcv.line_width = width; line_gc = XCreateGC(Xdisplay, draw.GetDrawable(), GCForeground | GCFunction | GCLineWidth, &gcv); Point offset = draw.GetOffset(); } #endif for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++) { int poly = *disjunct_polygon_counts; int sub = 1; if(*subpolygon_counts < poly) if(disjunct_polygon_count_count > 1) { const int *se = subpolygon_counts; int total = 0; while(total < poly) total += *se++; sub = se - subpolygon_counts; } else sub = subpolygon_count_count; if(sub > poly) { vertices += poly; subpolygon_counts += sub; continue; } #if defined(PLATFORM_WIN32) #ifdef SYSTEMDRAW SystemDraw *w = dynamic_cast<SystemDraw *>(&draw); if(w) { SystemDraw& draw = *w; #endif if(pattern) { int old_rop = GetROP2(draw); HGDIOBJ old_brush = GetCurrentObject(draw, OBJ_BRUSH); word wpat[8] = { (byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32), (byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0), }; HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat); HBRUSH brush = ::CreatePatternBrush(bitmap); COLORREF old_bk = GetBkColor(draw); COLORREF old_fg = GetTextColor(draw); if(!is_xor) { SetROP2(draw, R2_MASKPEN); SelectObject(draw, brush); SetTextColor(draw, Black()); SetBkColor(draw, White()); DrawPolyPolygonRaw(draw, vertices, poly, subpolygon_counts, sub, true, PEN_NULL, Null); SetROP2(draw, R2_MERGEPEN); SetTextColor(draw, color); SetBkColor(draw, Black()); } else { // xor fill with pattern data SetROP2(draw, R2_XORPEN); SelectObject(draw, brush); } DrawPolyPolygonRaw(draw, vertices, poly, subpolygon_counts, sub, true, PEN_NULL, Null); SelectObject(draw, old_brush); SetTextColor(draw, old_fg); SetBkColor(draw, old_bk); SetROP2(draw, old_rop); DeleteObject(brush); DeleteObject(bitmap); if(!IsNull(outline)) { draw.SetColor(Null); draw.SetDrawPen(width, outline); ASSERT(sizeof(POINT) == sizeof(Point)); PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, sub); } } else { // simple fill // RTIMING("AreaTool::Fill(solid color)"); int out_wd = (IsNull(width) || IsNull(outline) ? PEN_NULL : width); Color out_co = Nvl(outline, Black); draw.SetDrawPen(out_wd, out_co); if(is_xor) { color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB()); SetROP2(draw, R2_XORPEN); } HGDIOBJ old_brush = 0; if(IsNull(color)) { static HGDIOBJ null_brush = GetStockObject(NULL_BRUSH); old_brush = SelectObject(draw, null_brush); } else draw.SetColor(color); DrawPolyPolygonRaw(draw, vertices, poly, subpolygon_counts, sub, !IsNull(color), out_wd, out_co); if(old_brush) SelectObject(draw, old_brush); if(is_xor) SetROP2(draw, R2_COPYPEN); } #ifdef SYSTEMDRAW } #endif #elif defined(PLATFORM_X11) if(fill_gc) FillPolyPolygonRaw(fill_gc, draw.GetDrawable(), draw.GetClip(), draw.GetOffset(), vertices, poly, subpolygon_counts, sub); if(line_gc) DrawPolyPolygonRaw(line_gc, draw.GetDrawable(), draw.GetOffset(), vertices, poly, subpolygon_counts, sub); #else #error #endif vertices += poly; subpolygon_counts += sub; }