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 
10 static COLORREF sLightGray;
11 
GetVirtualScreenArea()12 Rect SystemDraw::GetVirtualScreenArea()
13 {
14 	GuiLock __;
15 	return RectC(GetSystemMetrics(SM_XVIRTUALSCREEN),
16 		GetSystemMetrics(SM_YVIRTUALSCREEN),
17 		GetSystemMetrics(SM_CXVIRTUALSCREEN),
18 		GetSystemMetrics(SM_CYVIRTUALSCREEN));
19 }
20 
GetInfo() const21 dword SystemDraw::GetInfo() const
22 {
23 	return DATABANDS|(native || !(style & DOTS) ? style|NATIVE : style);
24 }
25 
GetPageSize() const26 Size SystemDraw::GetPageSize() const
27 {
28 	return native && Dots() ? nativeSize : pageSize;
29 }
30 
GetNativeDpi() const31 Size SystemDraw::GetNativeDpi() const
32 {
33 	return nativeDpi;
34 }
35 
36 #ifndef PLATFORM_WINCE
Add(LOGPALETTE * pal,int r,int g,int b)37 void Add(LOGPALETTE *pal, int r, int g, int b)
38 {
39 	pal->palPalEntry[pal->palNumEntries].peRed   = min(r, 255);
40 	pal->palPalEntry[pal->palNumEntries].peGreen = min(g, 255);
41 	pal->palPalEntry[pal->palNumEntries].peBlue  = min(b, 255);
42 	pal->palPalEntry[pal->palNumEntries++].peFlags = PC_NOCOLLAPSE;
43 }
44 
GetQlibPalette()45 HPALETTE GetQlibPalette()
46 {
47 	static HPALETTE hQlibPalette;
48 	if(hQlibPalette) return hQlibPalette;
49 	SystemDraw::InitColors();
50 	LOGPALETTE *pal = (LOGPALETTE *) new byte[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
51 	pal->palNumEntries = 0;
52 	pal->palVersion    = 0x300;
53 	for(int r = 0; r < 6; r++)
54 		for(int g = 0; g < 6; g++)
55 			for(int b = 0; b < 6; b++)
56 				Add(pal, 255 * r / 5, 255 * g / 5, 255 * b / 5);
57 	for(int q = 0; q <= 16; q++)
58 		Add(pal, 16 * q, 16 * q, 16 * q);
59 	Add(pal, GetRValue(sLightGray), GetGValue(sLightGray), GetBValue(sLightGray));
60 	hQlibPalette = CreatePalette(pal);
61 	delete[] pal;
62 	return hQlibPalette;
63 }
64 #endif
65 
ScreenInfo()66 SystemDraw& ScreenInfo()
67 {
68 	static ScreenDraw sd(true);
69 	return sd;
70 }
71 
ScreenHDC()72 HDC ScreenHDC()
73 {
74 	static HDC hdc;
75 	ONCELOCK {
76 		hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
77 	}
78 	return hdc;
79 }
80 
81 static bool _AutoPalette = true;
AutoPalette()82 bool SystemDraw::AutoPalette() { return _AutoPalette; }
SetAutoPalette(bool ap)83 void SystemDraw::SetAutoPalette(bool ap) { _AutoPalette = ap; }
84 
GetColor(Color c) const85 COLORREF SystemDraw::GetColor(Color c) const {
86 	COLORREF color = c;
87 #ifdef PLATFORM_WINCE
88 	return color;
89 #else
90 	if(!palette)
91 		return color;
92 	static Index<dword> *SColor;
93 	ONCELOCK {
94 		static Index<dword> StaticColor;
95 		StaticColor << RGB(0x00, 0x00, 0x00) << RGB(0x80, 0x00, 0x00) << RGB(0x00, 0x80, 0x00)
96 					<< RGB(0x80, 0x80, 0x00) << RGB(0x00, 0x00, 0x80) << RGB(0x80, 0x00, 0x80)
97 					<< RGB(0x00, 0x80, 0x80) << RGB(0xC0, 0xC0, 0xC0) << RGB(0xC0, 0xDC, 0xC0)
98 					<< RGB(0xA6, 0xCA, 0xF0) << RGB(0xFF, 0xFB, 0xF0) << RGB(0xA0, 0xA0, 0xA4)
99 					<< RGB(0x80, 0x80, 0x80) << RGB(0xFF, 0x00, 0x00) << RGB(0x00, 0xFF, 0x00)
100 					<< RGB(0xFF, 0xFF, 0x00) << RGB(0x00, 0x00, 0xFF) << RGB(0xFF, 0x00, 0xFF)
101 					<< RGB(0x00, 0xFF, 0xFF) << RGB(0xFF, 0xFF, 0xFF);
102 		SColor = &StaticColor;
103 	}
104 	if(color16 || !AutoPalette())
105 		return GetNearestColor(handle, color);
106 	if(SColor->Find(color) >= 0)
107 		return color;
108 	if(color == sLightGray)
109 		return PALETTEINDEX(216 + 17);
110 	int r = GetRValue(color);
111 	int g = GetGValue(color);
112 	int b = GetBValue(color);
113 	return PALETTEINDEX(r == g && g == b ? (r + 8) / 16 + 216
114 		                                 : (r + 25) / 51 * 36 +
115 		                                   (g + 25) / 51 * 6 +
116 		                                   (b + 25) / 51);
117 #endif
118 }
119 
InitColors()120 void SystemDraw::InitColors()
121 {
122 }
123 
SetColor(Color color)124 void SystemDraw::SetColor(Color color)
125 {
126 	GuiLock __;
127 	LLOG("SetColor " << color);
128 	if(color != lastColor) {
129 		LLOG("Setting, lastColor:" << FormatIntHex(lastColor.GetRaw())
130 			<< " color:" << FormatIntHex(color.GetRaw()) <<
131 		     " GetColor:" << FormatIntHex(GetColor(color)) << " palette:" << palette);
132 		HBRUSH oldBrush = actBrush;
133 		HBRUSH h;
134 		if(!IsNull(color))
135 			h = (HBRUSH) SelectObject(handle, actBrush = CreateSolidBrush(GetColor(color)));
136 		else {
137 			HGDIOBJ empty = GetStockObject(HOLLOW_BRUSH);
138 			h = (HBRUSH) SelectObject(handle, empty);
139 			actBrush = NULL;
140 		}
141 		ASSERT(h);
142 		if(!orgBrush) orgBrush = h;
143 		if(oldBrush) DeleteObject(oldBrush);
144 		lastColor = color;
145 	}
146 }
147 
SetDrawPen(int width,Color color)148 void SystemDraw::SetDrawPen(int width, Color color) {
149 	GuiLock __;
150 	if(IsNull(width))
151 		width = PEN_NULL;
152 	if(width != lastPen || color != lastPenColor) {
153 		static int penstyle[] = {
154 			PS_NULL, PS_SOLID, PS_DASH,
155 		#ifndef PLATFORM_WINCE
156 			PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
157 		#endif
158 		};
159 		HPEN oldPen = actPen;
160 		actPen = CreatePen(width < 0 ? penstyle[-width - 1] : PS_SOLID,
161 			               width < 0 ? 0 : width, GetColor(color));
162 		HPEN h = (HPEN) SelectObject(handle, actPen);
163 		if(!orgPen) orgPen = h;
164 		if(oldPen) DeleteObject(oldPen);
165 		lastPen = width;
166 		lastPenColor = color;
167 	}
168 }
169 
SetOrg()170 void SystemDraw::SetOrg() {
171 	GuiLock __;
172 #ifdef PLATFORM_WINCE
173 	::SetViewportOrgEx(handle, actual_offset.x, actual_offset.y, 0);
174 #else
175 	LLOG("SystemDraw::SetOrg: clip = " << GetClip() << ", offset = " << actual_offset);
176 	::SetWindowOrgEx(handle, -actual_offset.x, -actual_offset.y, 0);
177 	LLOG("//SystemDraw::SetOrg: clip = " << GetClip());
178 #endif
179 }
180 
181 #ifndef PLATFORM_WINCE
LPtoDP(Point p) const182 Point SystemDraw::LPtoDP(Point p) const {
183 	GuiLock __;
184 	::LPtoDP(handle, p, 1);
185 	return p;
186 }
187 
DPtoLP(Point p) const188 Point SystemDraw::DPtoLP(Point p) const {
189 	GuiLock __;
190 	::DPtoLP(handle, p, 1);
191 	return p;
192 }
193 
LPtoDP(const Rect & r) const194 Rect  SystemDraw::LPtoDP(const Rect& r) const {
195 	GuiLock __;
196 	Rect w = r;
197 	::LPtoDP(handle, reinterpret_cast<POINT *>(&w), 2);
198 	return w;
199 }
200 
DPtoLP(const Rect & r) const201 Rect  SystemDraw::DPtoLP(const Rect& r) const {
202 	GuiLock __;
203 	Rect w = r;
204 	::LPtoDP(handle, reinterpret_cast<POINT *>(&w), 2);
205 	return w;
206 }
207 #endif
208 
GetSizeCaps(int i,int j) const209 Size SystemDraw::GetSizeCaps(int i, int j) const {
210 	GuiLock __;
211 	return Size(GetDeviceCaps(handle, i), GetDeviceCaps(handle, j));
212 }
213 
DotsMode()214 void SystemDraw::DotsMode()
215 {
216 	::SetMapMode(handle, MM_ANISOTROPIC);
217 	::SetViewportExtEx(handle, nativeDpi.cx, nativeDpi.cy, NULL);
218 	::SetViewportOrgEx(handle, 0, 0, NULL);
219 	::SetWindowExtEx(handle, 600, 600, NULL);
220 	::SetWindowOrgEx(handle, 0, 0, NULL);
221 }
222 
BeginNative()223 void SystemDraw::BeginNative()
224 {
225 	if(GetPixelsPerInch() != nativeDpi && ++native == 1) {
226 		::SetMapMode(handle, MM_TEXT);
227 		actual_offset_bak = actual_offset;
228 		Native(actual_offset);
229 		SetOrg();
230 	}
231 }
232 
EndNative()233 void SystemDraw::EndNative()
234 {
235 	if(GetPixelsPerInch() == nativeDpi && --native == 0) {
236 		DotsMode();
237 		actual_offset = actual_offset_bak;
238 		SetOrg();
239 	}
240 }
241 
GetCloffLevel() const242 int SystemDraw::GetCloffLevel() const
243 {
244 	return cloff.GetCount();
245 }
246 
LoadCaps()247 void SystemDraw::LoadCaps() {
248 	GuiLock __;
249 	color16 = false;
250 	palette = (GetDeviceCaps(handle, RASTERCAPS) & RC_PALETTE);
251 	if(palette)
252 		color16 = GetDeviceCaps(handle, SIZEPALETTE) != 256;
253 	nativeSize = pageSize = GetSizeCaps(HORZRES, VERTRES);
254 	nativeDpi = GetSizeCaps(LOGPIXELSX, LOGPIXELSY);
255 	is_mono = GetDeviceCaps(handle, BITSPIXEL) == 1 && GetDeviceCaps(handle, PLANES) == 1;
256 }
257 
Cinit()258 void SystemDraw::Cinit() {
259 	GuiLock __;
260 	lastColor = Color::FromCR(COLORREF(-5));
261 	lastPenColor = Color::FromCR(COLORREF(-5));
262 	lastTextColor = COLORREF(-1);
263 	lastPen = Null;
264 	actBrush = orgBrush = NULL;
265 	actPen = orgPen = NULL;
266 }
267 
Init()268 void SystemDraw::Init() {
269 	GuiLock __;
270 	drawingclip = Rect(-(INT_MAX >> 1), -(INT_MAX >> 1), +(INT_MAX >> 1), +(INT_MAX >> 1));
271 	Cinit();
272 	SetBkMode(handle, TRANSPARENT);
273 	::SetTextAlign(handle, TA_BASELINE);
274 #ifdef PLATFORM_WINCE
275 	actual_offset = Point(0, 0);
276 #else
277 	::GetViewportOrgEx(handle, actual_offset);
278 #endif
279 	LoadCaps();
280 }
281 
InitClip(const Rect & clip)282 void SystemDraw::InitClip(const Rect& clip)
283 {
284 	drawingclip = clip;
285 }
286 
Reset()287 void SystemDraw::Reset() {
288 	GuiLock __;
289 	style = 0;
290 }
291 
SystemDraw()292 SystemDraw::SystemDraw() {
293 	GuiLock __;
294 	native = 0;
295 	InitColors();
296 	actual_offset = Point(0, 0);
297 	Reset();
298 	handle = NULL;
299 	dcMem = NULL;
300 }
301 
SystemDraw(HDC hdc)302 SystemDraw::SystemDraw(HDC hdc) {
303 	GuiLock __;
304 	native = 0;
305 	InitColors();
306 	Reset();
307 	Attach(hdc);
308 }
309 
Unselect0()310 void SystemDraw::Unselect0() {
311 	GuiLock __;
312 	if(orgPen) SelectObject(handle, orgPen);
313 	if(orgBrush) SelectObject(handle, orgBrush);
314 	if(actPen) DeleteObject(actPen);
315 	if(actBrush) DeleteObject(actBrush);
316 	Cinit();
317 }
318 
Unselect()319 void SystemDraw::Unselect() {
320 	GuiLock __;
321 	while(cloff.GetCount())
322 		End();
323 	Unselect0();
324 }
325 
Attach(HDC ahandle)326 void  SystemDraw::Attach(HDC ahandle)
327 {
328 	handle = ahandle;
329 	dcMem = ::CreateCompatibleDC(handle);
330 	Init();
331 }
332 
Detach()333 HDC   SystemDraw::Detach()
334 {
335 	Unselect();
336 	HDC h = handle;
337 	handle = NULL;
338 	::DeleteDC(dcMem);
339 	dcMem = NULL;
340 	return h;
341 }
342 
~SystemDraw()343 SystemDraw::~SystemDraw() {
344 	GuiLock __;
345 	Detach();
346 }
347 
BeginGdi()348 HDC SystemDraw::BeginGdi() {
349 	GuiLock __;
350 	Begin();
351 	return handle;
352 }
353 
EndGdi()354 void SystemDraw::EndGdi() {
355 	GuiLock __;
356 	Unselect0();
357 	End();
358 }
359 
Create(SystemDraw & w,int cx,int cy)360 void BackDraw::Create(SystemDraw& w, int cx, int cy) {
361 	ASSERT(w.GetHandle());
362 	GuiLock __;
363 	Destroy();
364 	size.cx = cx;
365 	size.cy = cy;
366 	hbmp = ::CreateCompatibleBitmap(w.GetHandle(), cx, cy);
367 	handle = ::CreateCompatibleDC(w.GetHandle());
368 	dcMem = ::CreateCompatibleDC(handle);
369 	ASSERT(hbmp);
370 	ASSERT(handle);
371 #ifndef PLATFORM_WINCE
372 	if(AutoPalette()) {
373 		::SelectPalette(handle, GetQlibPalette(), FALSE);
374 		::RealizePalette(handle);
375 	}
376 #endif
377 	hbmpold = (HBITMAP) ::SelectObject(handle, hbmp);
378 	Init();
379 	InitClip(size);
380 }
381 
Put(SystemDraw & w,int x,int y)382 void BackDraw::Put(SystemDraw& w, int x, int y) {
383 	GuiLock __;
384 	ASSERT(handle);
385 	LTIMING("BackDraw::Put");
386 #ifdef PLATFORM_WINCE
387 	::SetViewportOrgEx(handle, 0, 0, 0);
388 #else
389 	::SetWindowOrgEx(handle, 0, 0, NULL);
390 #endif
391 	::BitBlt(w, x, y, size.cx, size.cy, *this, 0, 0, SRCCOPY);
392 }
393 
Destroy()394 void BackDraw::Destroy() {
395 	GuiLock __;
396 	if(handle) {
397 		Unselect();
398 		::SelectObject(handle, hbmpold);
399 		::DeleteDC(handle);
400 		::DeleteObject(hbmp);
401 		handle = NULL;
402 		::DeleteDC(dcMem);
403 		dcMem = NULL;
404 	}
405 }
406 
ScreenDraw(bool ic)407 ScreenDraw::ScreenDraw(bool ic) {
408 	GuiLock __;
409 #ifdef PLATFORM_WINCE
410 	Attach(CreateDC(NULL, NULL, NULL, NULL));
411 #else
412 	Attach(ic ? CreateIC("DISPLAY", NULL, NULL, NULL) : CreateDC("DISPLAY", NULL, NULL, NULL));
413 	InitClip(GetVirtualScreenArea());
414 	if(AutoPalette()) {
415 		SelectPalette(handle, GetQlibPalette(), TRUE);
416 		RealizePalette(handle);
417 	}
418 #endif
419 }
420 
~ScreenDraw()421 ScreenDraw::~ScreenDraw() {
422 	GuiLock __;
423 	Unselect();
424 	DeleteDC(handle);
425 }
426 
427 #ifndef PLATFORM_WINCE
428 
InitPrinter()429 void PrintDraw::InitPrinter()
430 {
431 	GuiLock __;
432 	Init();
433 	style = PRINTER|DOTS;
434 	DotsMode();
435 	native = 0;
436 	actual_offset = Point(0, 0);
437 	aborted = false;
438 	pageSize.cx = 600 * nativeSize.cx / nativeDpi.cx;
439 	pageSize.cy = 600 * nativeSize.cy / nativeDpi.cy;
440 	InitClip(pageSize);
441 }
442 
StartPage()443 void PrintDraw::StartPage()
444 {
445 	GuiLock __;
446 	if(aborted) return;
447 	Unselect();
448 	if(::StartPage(handle) <= 0)
449 		aborted = true;
450 	else
451 		InitPrinter();
452 }
453 
EndPage()454 void PrintDraw::EndPage()
455 {
456 	GuiLock __;
457 	if(aborted) return;
458 	Unselect();
459 	if(::EndPage(handle) <= 0)
460 		aborted = true;
461 }
462 
PrintDraw(HDC hdc,const char * docname)463 PrintDraw::PrintDraw(HDC hdc, const char *docname)
464    : SystemDraw(hdc)
465 {
466 	GuiLock __;
467 	DOCINFO di;
468 	memset(&di, 0, sizeof(di));
469 	di.cbSize = sizeof(di);
470 	String sys_docname = ToSystemCharset(docname);
471 	di.lpszDocName = ~sys_docname;
472 	if(::StartDoc(hdc, &di) <= 0)
473 		aborted = true;
474 	else
475 		InitPrinter();
476 }
477 
~PrintDraw()478 PrintDraw::~PrintDraw() {
479 	GuiLock __;
480 	if(aborted)
481 		::AbortDoc(handle);
482 	else
483 		::EndDoc(handle);
484 }
485 #endif
486 
487 }
488 
489 #endif
490