1 #include "Draw.h"
2 
3 namespace Upp {
4 
5 #define LTIMING(x) // TIMING(x)
6 
AddNotEmpty(Vector<Rect> & result,int left,int right,int top,int bottom)7 void AddNotEmpty(Vector<Rect>& result, int left, int right, int top, int bottom)
8 {
9 	if(left < right && top < bottom)
10 		result.Add(Rect(left, top, right, bottom));
11 }
12 
Subtract(const Rect & r,const Rect & sub,Vector<Rect> & result)13 bool Subtract(const Rect& r, const Rect& sub, Vector<Rect>& result)
14 {
15 	LTIMING("SubtractRect0");
16 	Rect is = r & sub;
17 	if(!is.IsEmpty()) {
18 		AddNotEmpty(result, r.left, is.left, r.top, is.top);
19 		AddNotEmpty(result, is.left, is.right, r.top, is.top);
20 		AddNotEmpty(result, is.right, r.right, r.top, is.top);
21 		AddNotEmpty(result, r.left, is.left, is.top, is.bottom);
22 		AddNotEmpty(result, is.right, r.right, is.top, is.bottom);
23 		AddNotEmpty(result, r.left, is.left, is.bottom, r.bottom);
24 		AddNotEmpty(result, is.left, is.right, is.bottom, r.bottom);
25 		AddNotEmpty(result, is.right, r.right, is.bottom, r.bottom);
26 		return true;
27 	}
28 	else {
29 		result.Add(r);
30 		return false;
31 	}
32 }
33 
Subtract(const Vector<Rect> & rr,const Rect & sub,Vector<Rect> & result)34 bool Subtract(const Vector<Rect>& rr, const Rect& sub, Vector<Rect>& result)
35 {
36 	LTIMING("SubtractRect");
37 	bool changed = false;
38 	for(int i = 0; i < rr.GetCount(); i++) {
39 		const Rect& r = rr[i];
40 		if(Subtract(r, sub, result))
41 			changed = true;
42 	}
43 	return changed;
44 }
45 
Subtract(const Vector<Rect> & rr,const Rect & sub,bool & changed)46 Vector<Rect> Subtract(const Vector<Rect>& rr, const Rect& sub, bool& changed)
47 {
48 	Vector<Rect> result;
49 	if(Subtract(rr, sub, result))
50 		changed = true;
51 	return result;
52 }
53 
Subtract(Vector<Rect> & rr,const Rect & sub)54 void Subtract(Vector<Rect>& rr, const Rect& sub)
55 {
56 	LTIMING("Subtract");
57 	if(sub.IsEmpty())
58 		return;
59 	bool dummy;
60 	rr = Subtract(rr, sub, dummy);
61 }
62 
Union(Vector<Rect> & rr,const Rect & add)63 void Union(Vector<Rect>& rr, const Rect& add)
64 {
65 	LTIMING("Union");
66 	if(add.IsEmpty())
67 		return;
68 	Vector<Rect> r;
69 	r.Add(add);
70 	for(int i = 0; i < rr.GetCount() && r.GetCount(); i++)
71 		Subtract(r, rr[i]);
72 	for(int i = 0; i < r.GetCount(); i++)
73 		rr.Add(r[i]);
74 }
75 
Intersect(const Vector<Rect> & b,const Rect & a,bool & changed)76 Vector<Rect> Intersect(const Vector<Rect>& b, const Rect& a, bool& changed)
77 {
78 	Vector<Rect> result;
79 	for(int i = 0; i < b.GetCount(); i++) {
80 		Rect r = b[i] & a;
81 		if(r.IsEmpty())
82 			changed = true;
83 		else {
84 			if(r != b[i]) changed = true;
85 			result.Add(r);
86 		}
87 	}
88 	return result;
89 }
90 
Intersection(const Vector<Rect> & b,const Rect & a)91 Vector<Rect> Intersection(const Vector<Rect>& b, const Rect& a)
92 {
93 	bool dummy;
94 	return Intersect(b, a, dummy);
95 }
96 
AddRefreshRect(Vector<Rect> & invalid,const Rect & _r)97 void AddRefreshRect(Vector<Rect>& invalid, const Rect& _r)
98 {
99 	Vector<Rect> inv;
100 	Rect r = _r;
101 	int ra = r.Width() * r.Height();
102 	for(int i = 0; i < invalid.GetCount(); i++) {
103 		const Rect& ir = invalid[i];
104 		Rect ur = r | ir;
105 		if(ur.Width() * ur.Height() < 2 * (ir.Width() * ir.Height() + ra))
106 			r = ur;
107 		else
108 		if(!r.Contains(ir))
109 			inv.Add(ir);
110 	}
111 	Vector<Rect> rs;
112 	rs.Add(r);
113 	for(int i = 0; i < inv.GetCount(); i++) {
114 		bool ch = false;
115 		Vector<Rect> rs1 = Subtract(rs, inv[i], ch);
116 		if(ch) rs = pick(rs1);
117 	}
118 	inv.AppendPick(pick(rs));
119 	invalid = pick(inv);
120 }
121 
DrawFatFrame(Draw & w,int x,int y,int cx,int cy,Color color,int n)122 void DrawFatFrame(Draw& w, int x, int y, int cx, int cy, Color color, int n) {
123 	if(n < 0) {
124 		x += n;
125 		y += n;
126 		n = -n;
127 		cx += 2 * n;
128 		cy += 2 * n;
129 	}
130 	w.DrawRect(x, y, cx, n, color);
131 	w.DrawRect(x, y + n, n, cy - n, color);
132 	w.DrawRect(x + cx - n, y + n, n, cy - n, color);
133 	w.DrawRect(x + n, y + cy - n, cx - 2 * n, n, color);
134 }
135 
DrawFatFrame(Draw & w,const Rect & r,Color color,int n)136 void DrawFatFrame(Draw& w, const Rect& r, Color color, int n) {
137 	DrawFatFrame(w, r.left, r.top, r.Width(), r.Height(), color, n);
138 }
139 
DrawFrame(Draw & w,int x,int y,int cx,int cy,Color leftcolor,Color topcolor,Color rightcolor,Color bottomcolor)140 void DrawFrame(Draw& w, int x, int y, int cx, int cy,
141 			   Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor)
142 {
143 	w.DrawRect(x, y, cx - 1, 1, topcolor);
144 	w.DrawRect(x, y, 1, cy - 1, leftcolor);
145 	w.DrawRect(x + cx - 1, y, 1, cy, rightcolor);
146 	w.DrawRect(x, y + cy - 1, cx, 1, bottomcolor);
147 }
148 
DrawFrame(Draw & w,const Rect & r,Color leftcolor,Color topcolor,Color rightcolor,Color bottomcolor)149 void DrawFrame(Draw& w, const Rect& r,
150 			   Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor)
151 {
152 	DrawFrame(w, r.left, r.top, r.Width(), r.Height(),
153 		      leftcolor, topcolor, rightcolor, bottomcolor);
154 }
155 
DrawFrame(Draw & w,int x,int y,int cx,int cy,Color topleftcolor,Color bottomrightcolor)156 void DrawFrame(Draw& w, int x, int y, int cx, int cy,
157 			   Color topleftcolor, Color bottomrightcolor)
158 {
159 	DrawFrame(w, x, y, cx, cy, topleftcolor, topleftcolor, bottomrightcolor, bottomrightcolor);
160 }
161 
DrawFrame(Draw & w,const Rect & r,Color topleftcolor,Color bottomrightcolor)162 void DrawFrame(Draw& w, const Rect& r,
163 			   Color topleftcolor, Color bottomrightcolor) {
164 	DrawFrame(w, r, topleftcolor, topleftcolor, bottomrightcolor, bottomrightcolor);
165 }
166 
DrawFrame(Draw & w,int x,int y,int cx,int cy,Color color)167 void DrawFrame(Draw& w, int x, int y, int cx, int cy, Color color) {
168 	DrawFrame(w, x, y, cx, cy, color, color);
169 }
170 
DrawFrame(Draw & w,const Rect & r,Color color)171 void DrawFrame(Draw& w, const Rect& r, Color color) {
172 	DrawFrame(w, r, color, color);
173 }
174 
DrawBorder(Draw & w,int x,int y,int cx,int cy,const ColorF * c)175 void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *c) {
176 	if(!c) return;
177 	int n = (int)(uintptr_t)*c;
178 	c++;
179 	while(n--) {
180 		if(cx <= 0 || cy <= 0)
181 			break;
182 		DrawFrame(w, x, y, cx, cy, c[0], c[1], c[2], c[3]);
183 		x += 1;
184 		y += 1;
185 		cx -= 2;
186 		cy -= 2;
187 		c += 4;
188 	}
189 }
190 
DrawBorder(Draw & w,const Rect & r,const ColorF * c)191 void DrawBorder(Draw& w, const Rect& r, const ColorF *c) {
192 	DrawBorder(w, r.left, r.top, r.Width(), r.Height(), c);
193 }
194 
BlackBorder()195 const ColorF *BlackBorder()
196 {
197 	static ColorF data[] = {
198 		(ColorF)1,
199 		&SColorText, &SColorText, &SColorText, &SColorText,
200 	};
201 	return data;
202 }
203 
WhiteBorder()204 const ColorF *WhiteBorder()
205 {
206 	static ColorF data[] = {
207 		(ColorF)1,
208 		&SColorPaper, &SColorPaper, &SColorPaper, &SColorPaper,
209 	};
210 	return data;
211 }
212 
213 #define SColorEdge Black // for now
214 
DefButtonBorder()215 const ColorF *DefButtonBorder()
216 {
217 	static ColorF data[] = {
218 		(ColorF)3,
219 		&SColorEdge, &SColorEdge, &SColorEdge, &SColorEdge,
220 		&SColorLight, &SColorLight, &SColorEdge, &SColorEdge,
221 		&SColorLtFace, &SColorLtFace, &SColorShadow, &SColorShadow,
222 	};
223 	return data;
224 }
225 
ButtonBorder()226 const ColorF *ButtonBorder()
227 {
228 	static ColorF data[] = {
229 		(ColorF)2,
230 		&SColorLight, &SColorLight, &SColorEdge, &SColorEdge,
231 		&SColorLtFace, &SColorLtFace, &SColorShadow, &SColorShadow,
232 	};
233 	return data;
234 }
235 
EdgeButtonBorder()236 const ColorF *EdgeButtonBorder()
237 {
238 	static ColorF data[] = {
239 		(ColorF)2,
240 		&SColorLtFace, &SColorLtFace, &SColorEdge, &SColorEdge,
241 		&SColorLight, &SColorLight, &SColorShadow, &SColorShadow,
242 	};
243 	return data;
244 }
245 
ButtonPushBorder()246 const ColorF *ButtonPushBorder()
247 {
248 	static ColorF data[] = {
249 		(ColorF)2,
250 		&SColorEdge, &SColorEdge, &SColorEdge, &SColorEdge,
251 		&SColorShadow, &SColorShadow, &SColorEdge, &SColorEdge
252 	};
253 	return data;
254 }
255 
InsetBorder()256 const ColorF *InsetBorder()
257 {
258 	static ColorF data[] = {
259 		(ColorF)2,
260 		&SColorShadow, &SColorShadow, &SColorLight, &SColorLight,
261 		&SColorEdge, &SColorEdge, &SColorFace, &SColorFace
262 	};
263 	return data;
264 }
265 
OutsetBorder()266 const ColorF *OutsetBorder()
267 {
268 	static ColorF data[] = {
269 		(ColorF)2,
270 		&SColorFace, &SColorFace, &SColorEdge, &SColorEdge,
271 		&SColorLight, &SColorLight, &SColorShadow, &SColorShadow,
272 	};
273 	return data;
274 }
275 
ThinOutsetBorder()276 const ColorF *ThinOutsetBorder()
277 {
278 	static ColorF data[] = {
279 		(ColorF)1,
280 		&SColorLight, &SColorLight, &SColorShadow, &SColorShadow,
281 	};
282 	return data;
283 }
284 
ThinInsetBorder()285 const ColorF *ThinInsetBorder()
286 {
287 	static ColorF data[] = {
288 		(ColorF)1,
289 		&SColorShadow, &SColorShadow, &SColorLight, &SColorLight,
290 	};
291 	return data;
292 }
293 
DrawBorder(Draw & w,int x,int y,int cx,int cy,const ColorF * (* colors_ltrd)())294 void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *(*colors_ltrd)())
295 {
296 	DrawBorder(w, x, y, cx, cy, (*colors_ltrd)());
297 }
298 
DrawBorder(Draw & w,const Rect & r,const ColorF * (* colors_ltrd)())299 void DrawBorder(Draw& w, const Rect& r, const ColorF *(*colors_ltrd)())
300 {
301 	DrawBorder(w, r, (*colors_ltrd)());
302 }
303 
DrawRectMinusRect(Draw & w,const Rect & rect,const Rect & inner,Color color)304 void DrawRectMinusRect(Draw& w, const Rect& rect, const Rect& inner, Color color) {
305 	Rect r = rect;
306 	r.bottom = inner.top;
307 	w.DrawRect(r, color);
308 	r = inner;
309 	r.right = r.left;
310 	r.left = rect.left;
311 	w.DrawRect(r, color);
312 	r.left = inner.right;
313 	r.right = rect.right;
314 	w.DrawRect(r, color);
315 	r = rect;
316 	r.top = inner.bottom;
317 	w.DrawRect(r, color);
318 }
319 
DrawRect(Draw & w,int x,int y,int cx,int cy,const Image & img,bool ra)320 void DrawRect(Draw& w, int x, int y, int cx, int cy, const Image& img, bool ra) {
321 	w.Clip(x, y, cx, cy);
322 	Size sz = img.GetSize();
323 	for(int a = ra ? x : x / sz.cx * sz.cx; a < x + cx; a += sz.cx)
324 		for(int b = ra ? y : y / sz.cy * sz.cy ; b < y + cy; b += sz.cy)
325 			w.DrawImage(a, b, img);
326 	w.End();
327 }
328 
DrawRect(Draw & w,const Rect & rect,const Image & img,bool ralgn)329 void DrawRect(Draw& w, const Rect& rect, const Image& img, bool ralgn)
330 {
331 	DrawRect(w, rect.left, rect.top, rect.Width(), rect.Height(), img, ralgn);
332 }
333 
DrawDragLine(Draw & w,bool horz,int x,int y,int len,int n,const int * pattern,Color color,int animation)334 void DrawDragLine(Draw& w, bool horz, int x, int y, int len, int n, const int *pattern, Color color, int animation)
335 {
336 	if(len <= 0)
337 		return;
338 	if(horz)
339 		w.Clip(x, y, len, n);
340 	else
341 		w.Clip(x, y, n, len);
342 
343 	Color color2 = IsDark(color) ? White() : Black();
344 	(horz ? x : y) -= animation;
345 	len += animation;
346 	bool ch = false;
347 	while(len > 0) {
348 		int segment = pattern[ch];
349 		int pause = pattern[2];
350 		if(horz) {
351 			w.DrawRect(x, y, segment, n, color);
352 			x += segment;
353 			w.DrawRect(x, y, pause, n, color2);
354 			x += pause;
355 		}
356 		else {
357 			w.DrawRect(x, y, n, segment, color);
358 			y += segment;
359 			w.DrawRect(x, y, n, pause, color2);
360 			y += pause;
361 		}
362 		len -= pause + segment;
363 		ch = !ch;
364 	}
365 	w.End();
366 }
367 
DrawDragFrame(Draw & w,const Rect & r,int n,const int * pattern,Color color,int animation)368 void DrawDragFrame(Draw& w, const Rect& r, int n, const int *pattern, Color color, int animation)
369 {
370 	DrawDragLine(w, true, r.left, r.top, r.GetWidth(), n, pattern, color, animation);
371 	DrawDragLine(w, false, r.left, r.top + n, r.GetHeight() - 2 * n, n, pattern, color, animation);
372 	if(r.right - n != r.left)
373 		DrawDragLine(w, false, r.right - n, r.top + n, r.GetHeight() - 2 * n, n, pattern, color, animation);
374 	if(r.bottom - n != r.top)
375 		DrawDragLine(w, true, r.left, r.bottom - n, r.GetWidth(), n, pattern, color, animation);
376 }
377 
DrawDragFrame(Draw & w,const Rect & r,int n,int pattern,Color color,int animation)378 void DrawDragFrame(Draw& w, const Rect& r, int n, int pattern, Color color, int animation)
379 {
380 	static int dashes[3][3] = {
381 		{ 32, 32, 0 },
382 		{ 1, 1, 1 },
383 		{ 5, 1, 2 },
384 	};
385 	DrawDragFrame(w, r, n, dashes[clamp(pattern, 0, 2)], color, animation);
386 }
387 
DrawTiles(Draw & w,int x,int y,int cx,int cy,const Image & img)388 void DrawTiles(Draw& w, int x, int y, int cx, int cy, const Image& img) {
389 	w.Clip(x, y, cx, cy);
390 	Size sz = img.GetSize();
391 	for(int a = x; a < x + cx; a += sz.cx)
392 		for(int b = y; b < y + cy; b += sz.cy)
393 			w.DrawImage(a, b, img);
394 	w.End();
395 }
396 
DrawTiles(Draw & w,const Rect & rect,const Image & img)397 void DrawTiles(Draw& w, const Rect& rect, const Image& img)
398 {
399 	DrawTiles(w, rect.left, rect.top, rect.GetWidth(), rect.GetHeight(), img);
400 }
401 
DrawHighlightImage(Draw & w,int x,int y,const Image & img,bool highlight,bool enabled,Color maskcolor)402 void DrawHighlightImage(Draw& w, int x, int y, const Image& img, bool highlight,
403                         bool enabled, Color maskcolor)
404 {
405 	if(highlight) {
406 		w.DrawImage(x + 1, y, img, maskcolor);
407 		w.DrawImage(x - 1, y, img, maskcolor);
408 		w.DrawImage(x, y + 1, img, maskcolor);
409 		w.DrawImage(x, y - 1, img, maskcolor);
410 	}
411 	w.DrawImage(x, y, enabled ? img : MakeImage(img, Etched));
412 }
413 
GradientColor(Color fc,Color tc,int i,int n)414 Color GradientColor(Color fc, Color tc, int i, int n)
415 {
416 	return Color(
417 			fc.GetR() + i * (tc.GetR() - fc.GetR()) / n,
418 			fc.GetG() + i * (tc.GetG() - fc.GetG()) / n,
419 			fc.GetB() + i * (tc.GetB() - fc.GetB()) / n
420 	);
421 }
422 
PaintButtonRect(Draw & w,Rect & r,Color left,Color top,Color right,Color bottom,Color & topleft,Color & topright,Color & bottomleft,Color & bottomright)423 void PaintButtonRect(Draw& w, Rect& r,
424                      Color left, Color top, Color right, Color bottom,
425                      Color& topleft, Color& topright, Color& bottomleft, Color& bottomright)
426 {
427 	w.DrawRect(r.left, r.top, 1, 1, topleft);
428 	w.DrawRect(r.right - 1, r.top, 1, 1, topright);
429 	w.DrawRect(r.left, r.bottom - 1, 1, 1, bottomleft);
430 	w.DrawRect(r.right - 1, r.bottom - 1, 1, 1, bottomright);
431 
432 	Color b1, b2;
433 	w.DrawRect(r.left + 1, r.top, 1, 1, b1 = Blend(topleft, top, 160));
434 	w.DrawRect(r.left, r.top + 1, 1, 1, b2 = Blend(topleft, left, 160));
435 	w.DrawRect(r.left + 2, r.top, 1, 1, Blend(b1, top));
436 	w.DrawRect(r.left, r.top + 2, 1, 1, Blend(b2, left));
437 	topleft = Blend(b1, b2);
438 
439 	w.DrawRect(r.right - 2, r.top, 1, 1, b1 = Blend(topright, top, 160));
440 	w.DrawRect(r.right - 1, r.top + 1, 1, 1, b2 = Blend(topright, right, 160));
441 	w.DrawRect(r.right - 3, r.top, 1, 1, Blend(b1, top));
442 	w.DrawRect(r.right - 1, r.top + 2, 1, 1, Blend(b2, right));
443 	topright = Blend(b1, b2);
444 
445 	w.DrawRect(r.left + 1, r.bottom - 1, 1, 1, b1 = Blend(bottomleft, bottom, 160));
446 	w.DrawRect(r.left, r.bottom - 2, 1, 1, b2 = Blend(bottomleft, left, 160));
447 	w.DrawRect(r.left + 2, r.bottom - 1, 1, 1, Blend(b1, bottom));
448 	w.DrawRect(r.left, r.bottom - 3, 1, 1, Blend(b2, left));
449 	bottomleft = Blend(b1, b2);
450 
451 	w.DrawRect(r.right - 2, r.bottom - 1, 1, 1, b1 = Blend(bottomright, bottom, 160));
452 	w.DrawRect(r.right - 1, r.bottom - 2, 1, 1, b2 = Blend(bottomright, right, 160));
453 	w.DrawRect(r.right - 3, r.bottom - 1, 1, 1, Blend(b1, bottom));
454 	w.DrawRect(r.right - 1, r.bottom - 3, 1, 1, Blend(b2, right));
455 	bottomright = Blend(b1, b2);
456 
457 	w.DrawRect(r.left + 3, r.top, r.Width() - 6, 1, top);
458 	w.DrawRect(r.left, r.top + 3, 1, r.Height() - 6, left);
459 	w.DrawRect(r.right - 1, r.top + 3, 1, r.Height() - 6, right);
460 	w.DrawRect(r.left + 3, r.bottom - 1, r.Width() - 6, 1, bottom);
461 
462 	r.Deflate(1, 1);
463 }
464 
DrawXPButton(Draw & w,Rect r,int type)465 void DrawXPButton(Draw& w, Rect r, int type)
466 {
467 	Color outlight = SColorLight;
468 	Color outshade = Blend(SColorShadow, SColorFace);
469 	Color light = SColorLight;
470 	Color shade = SColorShadow;
471 	Color frame = Blend(SColorHighlight, SColorText);
472 	Color mark = Null;
473 	Color topleft = SColorFace;
474 	int   markblend = 0;
475 
476 	if(type & BUTTON_EDGE)
477 		frame = Blend(SColorHighlight, SColorLight);
478 
479 	if(type & BUTTON_TOOL) {
480 		frame = SColorDisabled;
481 		light = Blend(SColorFace, light);
482 	}
483 
484 	if(type & BUTTON_SCROLL) {
485 		outlight = SColorFace;
486 		shade = outshade = SColorFace;
487 		frame = Blend(SColorHighlight, SColorShadow);
488 	}
489 
490 	switch(type & 15) {
491 	case BUTTON_OK:
492 		mark = Blend(Blue, SColorLight);
493 		markblend = 130;
494 		break;
495 	case BUTTON_HIGHLIGHT:
496 		if(!(type & BUTTON_SCROLL)) {
497 			mark = Blend(Yellow, LtRed, 100);
498 			markblend = 130;
499 		}
500 		break;
501 	case BUTTON_PUSH:
502 		light = shade = Blend(SColorHighlight, SColorFace, 235);
503 		break;
504 	case BUTTON_DISABLED:
505 		frame = SColorDisabled;
506 		outlight = outshade = light = shade = SColorFace;
507 		break;
508 	case BUTTON_CHECKED:
509 		if(type & BUTTON_TOOL)
510 			light = shade = SColorLight;
511 		else
512 			light = shade = Blend(SColorHighlight, SColorFace);
513 		break;
514 	}
515 
516 	Color topright = topleft;
517 	Color bottomleft = topleft;
518 	Color bottomright = topleft;
519 
520 	if(type & BUTTON_EDGE) {
521 		DrawFrame(w, r, frame);
522 		light = Blend(frame, SColorLight);
523 		shade = Blend(frame, SColorShadow);
524 		w.DrawRect(r.left, r.top, 1, 1, light);
525 		w.DrawRect(r.right - 1, r.top, 1, 1, light);
526 		w.DrawRect(r.left, r.bottom - 1, 1, 1, light);
527 		w.DrawRect(r.right - 1, r.bottom - 1, 1, 1, light);
528 		r.Deflate(1, 1);
529 		switch(type & 15) {
530 		case BUTTON_HIGHLIGHT:
531 			light = Blend(light, SColorLight);
532 			shade = Blend(shade, SColorLight);
533 			break;
534 		case BUTTON_PUSH:
535 			light = shade = Blend(SColorHighlight, SColorFace);
536 			break;
537 		}
538 	}
539 	else {
540 		if(!(type & BUTTON_TOOL))
541 			PaintButtonRect(w, r, outshade, outshade, outlight, outlight, topleft, topright, bottomleft, bottomright);
542 		PaintButtonRect(w, r, frame, frame, frame, frame, topleft, topright, bottomleft, bottomright);
543 		Color hc = Blend(light, mark, markblend);
544 		Color sc = Blend(shade, mark, markblend);
545 		PaintButtonRect(w, r, hc, hc, sc, sc, topleft, topright, bottomleft, bottomright);
546 		if(markblend) {
547 			DrawFrame(w, r, Blend(hc, mark, markblend), Blend(sc, mark, markblend));
548 			r.Deflate(1, 1);
549 		}
550 	}
551 
552 	if(type & BUTTON_SCROLL)
553 		switch(type & 15) {
554 		case BUTTON_PUSH:
555 			light = shade = Blend(SColorFace, SColorHighlight);
556 			break;
557 		case BUTTON_HIGHLIGHT:
558 			light = shade = Blend(SColorLight, SColorHighlight, 40);
559 			break;
560 		default:
561 			light = Blend(SColorLight, SColorHighlight, 80);
562 			shade = Blend(SColorFace, SColorHighlight, 80);
563 		}
564 
565 	Color b1 = Blend(light, shade, 80);
566 	Color bs = Blend(shade, SColorFace);
567 	if(type & BUTTON_VERTICAL) {
568 		int wd = r.Width();
569 		int w1 = 4 * wd / 5;
570 		for(int i = 0; i < wd; i++)
571 			w.DrawRect(r.left + i, r.top, 1, r.Height(), i < w1 ? Blend(light, b1, 255 * i / w1)
572 			                                                    : Blend(b1, bs, 255 * (i - w1) / (wd - w1)));
573 	}
574 	else {
575 		int h = r.Height();
576 		int h1 = 4 * h / 5;
577 		for(int i = 0; i < h; i++)
578 			w.DrawRect(r.left, r.top + i, r.Width(), 1, i < h1 ? Blend(light, b1, 255 * i / h1)
579 			                                                   : Blend(b1, bs, 255 * (i - h1) / (h - h1)));
580 	}
581 }
582 
583 static DrawingToPdfFnType sPdf;
584 
SetDrawingToPdfFn(DrawingToPdfFnType Pdf)585 void SetDrawingToPdfFn(DrawingToPdfFnType Pdf)
586 {
587 	sPdf = Pdf;
588 }
589 
GetDrawingToPdfFn()590 DrawingToPdfFnType GetDrawingToPdfFn()
591 {
592 	return sPdf;
593 }
594 
595 Image (*render_glyph)(int cx, int x, Font font, int chr, int py, int pcy);
596 
RenderGlyph(int cx,int x,Font font,int chr,int py,int pcy)597 Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy)
598 {
599 	if(render_glyph)
600 		return (*render_glyph)(cx, x, font, chr, py, pcy);
601 	if(ImageAnyDraw::IsAvailable()) {
602 		ImageAnyDraw iw(cx, pcy);
603 		iw.DrawRect(0, 0, cx, pcy, White);
604 		iw.DrawText(x, -py, WString(chr, 1), font, Black);
605 		return iw;
606 	}
607 	return Null;
608 }
609 
SetRenderGlyph(Image (* f)(int cx,int x,Font font,int chr,int py,int pcy))610 void SetRenderGlyph(Image (*f)(int cx, int x, Font font, int chr, int py, int pcy))
611 {
612 	render_glyph = f;
613 }
614 
615 
616 // this is nasty solution: We need to be able to restore GL viewport in GLTextureDraw for GLCtrl
617 // Draw is package used by both GLDraw and GLCtrl, so let us hide a little global function
618 // pointer here...
619 
__anonf48ec2370102null620 void (*restore_gl_viewport__)() = [] {};
621 
622 }
623