1 #include "CtrlCore.h"
2 
3 #ifdef GUI_WIN
4 
5 namespace Upp {
6 
7 #define LLOG(x)      // LOG(x)
8 #define LTIMING(x)   // RTIMING(x)
9 
BeginOp()10 void SystemDraw::BeginOp()
11 {
12 	LTIMING("Begin");
13 	GuiLock __;
14 	Cloff& w = cloff.Add();
15 	w.org = actual_offset;
16 	w.drawingclip = drawingclip;
17 	w.hrgn = CreateRectRgn(0, 0, 0, 0);
18 	ASSERT(w.hrgn);
19 	int	q = ::GetClipRgn(handle, w.hrgn);
20 	ASSERT(q >= 0);
21 	if(q == 0) {
22 		DeleteObject(w.hrgn);
23 		w.hrgn = NULL;
24 	}
25 }
26 
OffsetOp(Point p)27 void SystemDraw::OffsetOp(Point p)
28 {
29 	GuiLock __;
30 	Begin();
31 	actual_offset += p;
32 	drawingclip -= p;
33 	LTIMING("Offset");
34 	SetOrg();
35 }
36 
ClipOp(const Rect & r)37 bool SystemDraw::ClipOp(const Rect& r)
38 {
39 	GuiLock __;
40 	Begin();
41 	LTIMING("Clip");
42 	return IntersectClip(r);
43 }
44 
ClipoffOp(const Rect & r)45 bool SystemDraw::ClipoffOp(const Rect& r)
46 {
47 	GuiLock __;
48 	Begin();
49 	LTIMING("Clipoff");
50 	LLOG("ClipoffOp " << r << ", GetClip() = " << GetClip() << ", actual_offset = " << actual_offset);
51 	actual_offset += r.TopLeft();
52 	bool q = IntersectClip(r);
53 	drawingclip -= r.TopLeft();
54 	SetOrg();
55 	LLOG("//ClipoffOp, GetClip() = " << GetClip() << ", actual_offset = " << actual_offset);
56 	return q;
57 }
58 
EndOp()59 void SystemDraw::EndOp()
60 {
61 	GuiLock __;
62 	LTIMING("End");
63 	ASSERT(cloff.GetCount());
64 	Cloff& w = cloff.Top();
65 	actual_offset = w.org;
66 	drawingclip = w.drawingclip;
67 	::SelectClipRgn(handle, w.hrgn);
68 	SetOrg();
69 	if(w.hrgn)
70 		::DeleteObject(w.hrgn);
71 	cloff.Drop();
72 }
73 
ExcludeClipOp(const Rect & r)74 bool SystemDraw::ExcludeClipOp(const Rect& r)
75 {
76 	GuiLock __;
77 #ifdef PLATFORM_WINCE
78 	int q = ExcludeClipRect(handle, r.left, r.top, r.right, r.bottom);
79 #else
80 	LTIMING("ExcludeClip");
81 	if(r.Contains(drawingclip))
82 		drawingclip = Rect(0, 0, 0, 0);
83 	Rect rr = LPtoDP(r);
84 	HRGN hrgn = ::CreateRectRgnIndirect(rr);
85 	int q = ::ExtSelectClipRgn(handle, hrgn, RGN_DIFF);
86 	ASSERT(q != ERROR);
87 	::DeleteObject(hrgn);
88 #endif
89 	return q == SIMPLEREGION || q == COMPLEXREGION;
90 }
91 
IntersectClipOp(const Rect & r)92 bool SystemDraw::IntersectClipOp(const Rect& r)
93 {
94 	GuiLock __;
95 #ifdef PLATFORM_WINCE
96 	int q = IntersectClipRect(handle, r.left, r.top, r.right, r.bottom);
97 #else
98 	LTIMING("Intersect");
99 	drawingclip &= r;
100 	Rect rr = LPtoDP(r);
101 	HRGN hrgn = ::CreateRectRgnIndirect(rr);
102 	int q = ::ExtSelectClipRgn(handle, hrgn, RGN_AND);
103 	ASSERT(q != ERROR);
104 	::DeleteObject(hrgn);
105 #endif
106 	return q == SIMPLEREGION || q == COMPLEXREGION;
107 }
108 
IsPaintingOp(const Rect & r) const109 bool SystemDraw::IsPaintingOp(const Rect& r) const
110 {
111 	GuiLock __;
112 	LTIMING("IsPainting");
113 	return ::RectVisible(handle, r);
114 }
115 
GetPaintRect() const116 Rect SystemDraw::GetPaintRect() const
117 {
118 	GuiLock __;
119 	LTIMING("GetPaintRect");
120 	return drawingclip;
121 }
122 
DrawRectOp(int x,int y,int cx,int cy,Color color)123 void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
124 {
125 	GuiLock __;
126 	LTIMING("DrawRect");
127 	LLOG("DrawRect " << RectC(x, y, cx, cy) << ": " << color);
128 	if(IsNull(color)) return;
129 	if(cx <= 0 || cy <= 0) return;
130 	if(color == InvertColor)
131 		::PatBlt(handle, x, y, cx, cy, DSTINVERT);
132 	else {
133 		SetColor(color);
134 		::PatBlt(handle, x, y, cx, cy, PATCOPY);
135 	}
136 }
137 
DrawLineOp(int x1,int y1,int x2,int y2,int width,Color color)138 void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
139 {
140 	GuiLock __;
141 	if(IsNull(width) || IsNull(color)) return;
142 	SetDrawPen(width, color);
143 	::MoveToEx(handle, x1, y1, NULL);
144 	::LineTo(handle, x2, y2);
145 }
146 
147 #ifndef PLATFORM_WINCE
148 
DrawPolyPolylineOp(const Point * vertices,int vertex_count,const int * counts,int count_count,int width,Color color,Color doxor)149 void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
150                             const int *counts, int count_count,
151 	                        int width, Color color, Color doxor)
152 {
153 	GuiLock __;
154 	ASSERT(count_count > 0 && vertex_count > 0);
155 	if(vertex_count < 2 || IsNull(color) || IsNull(width))
156 		return;
157 	bool is_xor = !IsNull(doxor);
158 	if(is_xor)
159 		color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB());
160 	if(is_xor)
161 		SetROP2(GetHandle(), R2_XORPEN);
162 	SetDrawPen(width, color);
163 	if(count_count == 1)
164 		::Polyline(GetHandle(), (const POINT *)vertices, vertex_count);
165 	else
166 		::PolyPolyline(GetHandle(), (const POINT *)vertices,
167 		               (const dword *)counts, count_count);
168 	if(is_xor)
169 		SetROP2(GetHandle(), R2_COPYPEN);
170 }
171 
DrawPolyPolyPolygonRaw(SystemDraw & 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)172 static void DrawPolyPolyPolygonRaw(
173 	SystemDraw& draw, const Point *vertices, int vertex_count,
174 	const int *subpolygon_counts, int subpolygon_count_count,
175 	const int *disjunct_polygon_counts, int disjunct_polygon_count_count)
176 {
177 	GuiLock __;
178 	for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++)
179 	{
180 		int poly = *disjunct_polygon_counts;
181 		int sub = 1;
182 		if(*subpolygon_counts < poly) {
183 			if(disjunct_polygon_count_count > 1)
184 			{
185 				const int *se = subpolygon_counts;
186 				int total = 0;
187 				while(total < poly)
188 					total += *se++;
189 				sub = (int)(se - subpolygon_counts);
190 			}
191 			else
192 				sub = subpolygon_count_count;
193 		}
194 		ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not
195 		if(sub == 1)
196 			Polygon(draw, (const POINT *)vertices, poly);
197 		else
198 			PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, sub);
199 		vertices += poly;
200 		subpolygon_counts += sub;
201 	}
202 }
203 
DrawPolyPolyPolygonOp(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)204 void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
205 	const int *subpolygon_counts, int subpolygon_count_count,
206 	const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
207 	Color color, int width, Color outline, uint64 pattern, Color doxor)
208 {
209 	GuiLock __;
210 	if(vertex_count == 0)
211 		return;
212 	bool is_xor = !IsNull(doxor);
213 	HDC hdc = GetHandle();
214 	if(pattern) {
215 		int old_rop = GetROP2(hdc);
216 		HGDIOBJ old_brush = GetCurrentObject(hdc, OBJ_BRUSH);
217 		word wpat[8] = {
218 			(byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32),
219 			(byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0),
220 		};
221 		HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat);
222 		HBRUSH brush = ::CreatePatternBrush(bitmap);
223 		COLORREF old_bk = GetBkColor(hdc);
224 		COLORREF old_fg = GetTextColor(hdc);
225 		if(!is_xor) {
226 			SetROP2(hdc, R2_MASKPEN);
227 			SelectObject(hdc, brush);
228 			SetTextColor(hdc, Black());
229 			SetBkColor(hdc, White());
230 			SetDrawPen(PEN_NULL, Black);
231 			DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
232 				subpolygon_counts, subpolygon_count_count,
233 				disjunct_polygon_counts, disjunct_polygon_count_count);
234 			SetROP2(hdc, R2_MERGEPEN);
235 			SetTextColor(hdc, color);
236 			SetBkColor(hdc, Black());
237 		}
238 		else {
239 			SetROP2(hdc, R2_XORPEN);
240 			SetTextColor(hdc, COLORREF(color) ^ COLORREF(doxor));
241 			SelectObject(hdc, brush);
242 		}
243 		DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
244 			subpolygon_counts, subpolygon_count_count,
245 			disjunct_polygon_counts, disjunct_polygon_count_count);
246 		SelectObject(hdc, old_brush);
247 		SetTextColor(hdc, old_fg);
248 		SetBkColor(hdc, old_bk);
249 		SetROP2(hdc, old_rop);
250 		DeleteObject(brush);
251 		DeleteObject(bitmap);
252 		if(!IsNull(outline)) {
253 			SetColor(Null);
254 			SetDrawPen(width, outline);
255 			ASSERT(sizeof(POINT) == sizeof(Point));
256 			DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
257 				subpolygon_counts, subpolygon_count_count,
258 				disjunct_polygon_counts, disjunct_polygon_count_count);
259 		}
260 	}
261 	else { // simple fill
262 		SetDrawPen(IsNull(outline) ? PEN_NULL : width, Nvl(outline, Black));
263 		int old_rop2;
264 		if(is_xor) {
265 			color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB());
266 			old_rop2 = SetROP2(hdc, R2_XORPEN);
267 		}
268 		SetColor(color);
269 		DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
270 			subpolygon_counts, subpolygon_count_count,
271 			disjunct_polygon_counts, disjunct_polygon_count_count);
272 		if(is_xor)
273 			SetROP2(hdc, old_rop2);
274 	}
275 }
276 
DrawArcOp(const Rect & rc,Point start,Point end,int width,Color color)277 void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
278 {
279 	GuiLock __;
280 	SetDrawPen(width, color);
281 	::Arc(GetHandle(), rc.left, rc.top, rc.right, rc.bottom, start.x, start.y, end.x, end.y);
282 }
283 
284 #endif
285 
DrawEllipseOp(const Rect & r,Color color,int width,Color pencolor)286 void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int width, Color pencolor)
287 {
288 	GuiLock __;
289 	SetColor(color);
290 	SetDrawPen(width, pencolor);
291 	::Ellipse(GetHandle(), r.left, r.top, r.right, r.bottom);
292 }
293 
294 }
295 
296 #endif
297