Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Window.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: Window.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Window class
13 */
14 
15 #include "MemDebug.h"
16 #include "Window.h"
17 #include "Bitmap.h"
18 #include "Color.h"
19 #include "Fix.h"
20 #include "Font.h"
21 #include "Polygon.h"
22 #include "Screen.h"
23 #include "Video.h"
24 #include "View.h"
25 
26 static VertexSet vset4(4);
27 
28 // +--------------------------------------------------------------------+
29 
30 Window::Window(Screen* s, int ax, int ay, int aw, int ah)
31 : screen(s), rect(ax, ay, aw, ah), shown(true), font(0)
32 { }
33 
34 // +--------------------------------------------------------------------+
35 
37 {
39 }
40 
41 // +--------------------------------------------------------------------+
42 
43 bool
45 {
46  if (!v) return false;
47 
48  if (!view_list.contains(v))
49  view_list.append(v);
50 
51  return true;
52 }
53 
54 bool
56 {
57  if (!v) return false;
58 
59  return view_list.remove(v) == v;
60 }
61 
62 void
64 {
65  if (rect.x == r.x &&
66  rect.y == r.y &&
67  rect.w == r.w &&
68  rect.h == r.h)
69  return;
70 
71  rect = r;
72 
74  while (++v)
75  v->OnWindowMove();
76 }
77 
78 // +--------------------------------------------------------------------+
79 
80 void
82 {
84  while (++v)
85  v->Refresh();
86 }
87 
88 // +--------------------------------------------------------------------+
89 
90 static inline void swap(int& a, int& b) { int tmp=a; a=b; b=tmp; }
91 static inline void sort(int& a, int& b) { if (a>b) swap(a,b); }
92 static inline void swap(double& a, double& b) { double tmp=a; a=b; b=tmp; }
93 static inline void sort(double& a, double& b) { if (a>b) swap(a,b); }
94 
95 Rect
97 {
98  Rect clip_rect = r;
99 
100  clip_rect.x += rect.x;
101  clip_rect.y += rect.y;
102 
103  if (clip_rect.x < rect.x) {
104  clip_rect.w -= rect.x - clip_rect.x;
105  clip_rect.x = rect.x;
106  }
107 
108  if (clip_rect.y < rect.y) {
109  clip_rect.h -= rect.y - clip_rect.y;
110  clip_rect.y = rect.y;
111  }
112 
113  if (clip_rect.x + clip_rect.w > rect.x + rect.w)
114  clip_rect.w = rect.x + rect.w - clip_rect.x;
115 
116  if (clip_rect.y + clip_rect.h > rect.y + rect.h)
117  clip_rect.h = rect.y + rect.h - clip_rect.y;
118 
119  return clip_rect;
120 }
121 
122 // +--------------------------------------------------------------------+
123 
124 bool
125 Window::ClipLine(int& x1, int& y1, int& x2, int& y2)
126 {
127  // vertical lines:
128  if (x1==x2) {
129  clip_vertical:
130  sort(y1,y2);
131  if (x1 < 0 || x1 >= rect.w) return false;
132  if (y1 < 0) y1 = 0;
133  if (y2 >= rect.h) y2 = rect.h;
134  return true;
135  }
136 
137  // horizontal lines:
138  if (y1==y2) {
139  clip_horizontal:
140  sort(x1,x2);
141  if (y1 < 0 || y1 >= rect.h) return false;
142  if (x1 < 0) x1 = 0;
143  if (x2 > rect.w) x2 = rect.w;
144  return true;
145  }
146 
147  // general lines:
148 
149  // sort left to right:
150  if (x1 > x2) {
151  swap(x1,x2);
152  swap(y1,y2);
153  }
154 
155  double m = (double)(y2-y1) / (double)(x2-x1);
156  double b = (double) y1 - (m * x1);
157 
158  // clip:
159  if (x1 < 0) { x1 = 0; y1 = (int) b; }
160  if (x1 >= rect.w) return false;
161  if (x2 < 0) return false;
162  if (x2 > rect.w-1) { x2 = rect.w-1; y2 = (int) (m * x2 + b); }
163 
164  if (y1 < 0 && y2 < 0) return false;
165  if (y1 >= rect.h && y2 >= rect.h) return false;
166 
167  if (y1 < 0) { y1 = 0; x1 = (int) (-b/m); }
168  if (y1 >= rect.h) { y1 = rect.h-1; x1 = (int) ((y1-b)/m); }
169  if (y2 < 0) { y2 = 0; x2 = (int) (-b/m); }
170  if (y2 >= rect.h) { y2 = rect.h-1; x2 = (int) ((y2-b)/m); }
171 
172  if (x1 == x2)
173  goto clip_vertical;
174 
175  if (y1 == y2)
176  goto clip_horizontal;
177 
178  return true;
179 }
180 
181 // +--------------------------------------------------------------------+
182 
183 bool
184 Window::ClipLine(double& x1, double& y1, double& x2, double& y2)
185 {
186  // vertical lines:
187  if (x1==x2) {
188  clip_vertical:
189  sort(y1,y2);
190  if (x1 < 0 || x1 >= rect.w) return false;
191  if (y1 < 0) y1 = 0;
192  if (y2 >= rect.h) y2 = rect.h;
193  return true;
194  }
195 
196  // horizontal lines:
197  if (y1==y2) {
198  clip_horizontal:
199  sort(x1,x2);
200  if (y1 < 0 || y1 >= rect.h) return false;
201  if (x1 < 0) x1 = 0;
202  if (x2 > rect.w) x2 = rect.w;
203  return true;
204  }
205 
206  // general lines:
207 
208  // sort left to right:
209  if (x1 > x2) {
210  swap(x1,x2);
211  swap(y1,y2);
212  }
213 
214  double m = (double)(y2-y1) / (double)(x2-x1);
215  double b = (double) y1 - (m * x1);
216 
217  // clip:
218  if (x1 < 0) { x1 = 0; y1 = b; }
219  if (x1 >= rect.w) return false;
220  if (x2 < 0) return false;
221  if (x2 > rect.w-1) { x2 = rect.w-1; y2 = (m * x2 + b); }
222 
223  if (y1 < 0 && y2 < 0) return false;
224  if (y1 >= rect.h && y2 >= rect.h) return false;
225 
226  if (y1 < 0) { y1 = 0; x1 = (-b/m); }
227  if (y1 >= rect.h) { y1 = rect.h-1; x1 = ((y1-b)/m); }
228  if (y2 < 0) { y2 = 0; x2 = (-b/m); }
229  if (y2 >= rect.h) { y2 = rect.h-1; x2 = ((y2-b)/m); }
230 
231  if (x1 == x2)
232  goto clip_vertical;
233 
234  if (y1 == y2)
235  goto clip_horizontal;
236 
237  return true;
238 }
239 
240 // +--------------------------------------------------------------------+
241 
242 void
243 Window::DrawLine(int x1, int y1, int x2, int y2, Color color, int blend)
244 {
245  if (!screen || !screen->GetVideo()) return;
246 
247  if (ClipLine(x1,y1,x2,y2)) {
248  float points[4];
249 
250  points[0] = (float) (rect.x + x1);
251  points[1] = (float) (rect.y + y1);
252  points[2] = (float) (rect.x + x2);
253  points[3] = (float) (rect.y + y2);
254 
255  Video* video = screen->GetVideo();
256  video->DrawScreenLines(1, points, color, blend);
257  }
258 }
259 
260 // +--------------------------------------------------------------------+
261 
262 void
263 Window::DrawRect(int x1, int y1, int x2, int y2, Color color, int blend)
264 {
265  if (!screen || !screen->GetVideo()) return;
266 
267  sort(x1,x2);
268  sort(y1,y2);
269 
270  if (x1 > rect.w || x2 < 0 || y1 > rect.h || y2 < 0)
271  return;
272 
273  float points[16];
274 
275  points[ 0] = (float) (rect.x + x1);
276  points[ 1] = (float) (rect.y + y1);
277  points[ 2] = (float) (rect.x + x2);
278  points[ 3] = (float) (rect.y + y1);
279 
280  points[ 4] = (float) (rect.x + x2);
281  points[ 5] = (float) (rect.y + y1);
282  points[ 6] = (float) (rect.x + x2);
283  points[ 7] = (float) (rect.y + y2);
284 
285  points[ 8] = (float) (rect.x + x2);
286  points[ 9] = (float) (rect.y + y2);
287  points[10] = (float) (rect.x + x1);
288  points[11] = (float) (rect.y + y2);
289 
290  points[12] = (float) (rect.x + x1);
291  points[13] = (float) (rect.y + y2);
292  points[14] = (float) (rect.x + x1);
293  points[15] = (float) (rect.y + y1);
294 
295  Video* video = screen->GetVideo();
296  video->DrawScreenLines(4, points, color, blend);
297 }
298 
299 void
300 Window::DrawRect(const Rect& r, Color color, int blend)
301 {
302  DrawRect(r.x, r.y, r.x+r.w, r.y+r.h, color, blend);
303 }
304 
305 // +--------------------------------------------------------------------+
306 
307 void
308 Window::FillRect(int x1, int y1, int x2, int y2, Color color, int blend)
309 {
310  if (!screen || !screen->GetVideo()) return;
311 
312  sort(x1,x2);
313  sort(y1,y2);
314 
315  if (x1 > rect.w || x2 < 0 || y1 > rect.h || y2 < 0)
316  return;
317 
319  for (int i = 0; i < 4; i++) {
320  vset4.diffuse[i] = color.Value();
321  }
322 
323  vset4.s_loc[0].x = (float) (rect.x + x1) - 0.5f;
324  vset4.s_loc[0].y = (float) (rect.y + y1) - 0.5f;
325  vset4.s_loc[0].z = 0.0f;
326  vset4.rw[0] = 1.0f;
327  vset4.tu[0] = 0.0f;
328  vset4.tv[0] = 0.0f;
329 
330  vset4.s_loc[1].x = (float) (rect.x + x2) - 0.5f;
331  vset4.s_loc[1].y = (float) (rect.y + y1) - 0.5f;
332  vset4.s_loc[1].z = 0.0f;
333  vset4.rw[1] = 1.0f;
334  vset4.tu[1] = 1.0f;
335  vset4.tv[1] = 0.0f;
336 
337  vset4.s_loc[2].x = (float) (rect.x + x2) - 0.5f;
338  vset4.s_loc[2].y = (float) (rect.y + y2) - 0.5f;
339  vset4.s_loc[2].z = 0.0f;
340  vset4.rw[2] = 1.0f;
341  vset4.tu[2] = 1.0f;
342  vset4.tv[2] = 1.0f;
343 
344  vset4.s_loc[3].x = (float) (rect.x + x1) - 0.5f;
345  vset4.s_loc[3].y = (float) (rect.y + y2) - 0.5f;
346  vset4.s_loc[3].z = 0.0f;
347  vset4.rw[3] = 1.0f;
348  vset4.tu[3] = 0.0f;
349  vset4.tv[3] = 1.0f;
350 
351  Poly poly(0);
352  poly.nverts = 4;
353  poly.vertex_set = &vset4;
354  poly.verts[0] = 0;
355  poly.verts[1] = 1;
356  poly.verts[2] = 2;
357  poly.verts[3] = 3;
358 
359  Video* video = screen->GetVideo();
360  video->DrawScreenPolys(1, &poly, blend);
361 }
362 
363 void
364 Window::FillRect(const Rect& r, Color color, int blend)
365 {
366  FillRect(r.x, r.y, r.x+r.w, r.y+r.h, color, blend);
367 }
368 
369 // +--------------------------------------------------------------------+
370 
371 void
372 Window::DrawLines(int nPts, POINT* pts, Color color, int blend)
373 {
374  if (nPts < 2 || nPts > 16)
375  return;
376 
377  if (!screen || !screen->GetVideo())
378  return;
379 
380  float f[64];
381  int n = 0;
382 
383  for (int i = 0; i < nPts-1; i++) {
384  f[n++] = (float) rect.x + pts[i].x;
385  f[n++] = (float) rect.y + pts[i].y;
386  f[n++] = (float) rect.x + pts[i+1].x;
387  f[n++] = (float) rect.y + pts[i+1].y;
388  }
389 
390  Video* video = screen->GetVideo();
391  video->DrawScreenLines(nPts-1, f, color, blend);
392 }
393 
394 void
395 Window::DrawPoly(int nPts, POINT* pts, Color color, int blend)
396 {
397  if (nPts < 3 || nPts > 8)
398  return;
399 
400  if (!screen || !screen->GetVideo())
401  return;
402 
403  float f[32];
404  int n = 0;
405 
406  for (int i = 0; i < nPts-1; i++) {
407  f[n++] = (float) rect.x + pts[i].x;
408  f[n++] = (float) rect.y + pts[i].y;
409  f[n++] = (float) rect.x + pts[i+1].x;
410  f[n++] = (float) rect.y + pts[i+1].y;
411  }
412 
413  f[n++] = (float) rect.x + pts[nPts-1].x;
414  f[n++] = (float) rect.y + pts[nPts-1].y;
415  f[n++] = (float) rect.x + pts[0].x;
416  f[n++] = (float) rect.y + pts[0].y;
417 
418  Video* video = screen->GetVideo();
419  video->DrawScreenLines(nPts, f, color, blend);
420 }
421 
422 void
423 Window::FillPoly(int nPts, POINT* pts, Color color, int blend)
424 {
425  if (nPts < 3 || nPts > 4)
426  return;
427 
428  if (!screen || !screen->GetVideo())
429  return;
430 
432  for (int i = 0; i < nPts; i++) {
433  vset4.diffuse[i] = color.Value();
434  vset4.s_loc[i].x = (float) (rect.x + pts[i].x) - 0.5f;
435  vset4.s_loc[i].y = (float) (rect.y + pts[i].y) - 0.5f;
436  vset4.s_loc[i].z = 0.0f;
437  vset4.rw[i] = 1.0f;
438  vset4.tu[i] = 0.0f;
439  vset4.tv[i] = 0.0f;
440  }
441 
442  Poly poly(0);
443  poly.nverts = nPts;
444  poly.vertex_set = &vset4;
445  poly.verts[0] = 0;
446  poly.verts[1] = 1;
447  poly.verts[2] = 2;
448  poly.verts[3] = 3;
449 
450  Video* video = screen->GetVideo();
451  video->DrawScreenPolys(1, &poly, blend);
452 }
453 
454 // +--------------------------------------------------------------------+
455 
456 void
457 Window::DrawBitmap(int x1, int y1, int x2, int y2, Bitmap* img, int blend)
458 {
459  Rect clip_rect;
460  clip_rect.w = rect.w;
461  clip_rect.h = rect.h;
462 
463  ClipBitmap(x1,y1,x2,y2,img,Color::White,blend,clip_rect);
464 }
465 
466 void
467 Window::FadeBitmap(int x1, int y1, int x2, int y2, Bitmap* img, Color c, int blend)
468 {
469  Rect clip_rect;
470  clip_rect.w = rect.w;
471  clip_rect.h = rect.h;
472 
473  ClipBitmap(x1,y1,x2,y2,img,c,blend,clip_rect);
474 }
475 
476 void
477 Window::ClipBitmap(int x1, int y1, int x2, int y2, Bitmap* img, Color c, int blend, const Rect& clip_rect)
478 {
479  if (!screen || !screen->GetVideo() || !img) return;
480 
481  Rect clip = clip_rect;
482 
483  // clip the clip rect to the window rect:
484  if (clip.x < 0) {
485  clip.w -= clip.x;
486  clip.x = 0;
487  }
488 
489  if (clip.x + clip.w > rect.w) {
490  clip.w -= (clip.x + clip.w - rect.w);
491  }
492 
493  if (clip.y < 0) {
494  clip.h -= clip.y;
495  clip.y = 0;
496  }
497 
498  if (clip.y + clip.h > rect.h) {
499  clip.h -= (clip.y + clip.h - rect.h);
500  }
501 
502  // now clip the bitmap to the validated clip rect:
503  sort(x1,x2);
504  sort(y1,y2);
505 
506  if (x1 > clip.x + clip.w || x2 < clip.x || y1 > clip.y + clip.h || y2 < clip.y)
507  return;
508 
510  for (int i = 0; i < 4; i++) {
511  vset4.diffuse[i] = c.Value();
512  }
513 
514  float u1 = 0.0f;
515  float u2 = 1.0f;
516  float v1 = 0.0f;
517  float v2 = 1.0f;
518  float iw = (float) (x2-x1);
519  float ih = (float) (y2-y1);
520  int x3 = clip.x + clip.w;
521  int y3 = clip.y + clip.h;
522 
523  if (x1 < clip.x) {
524  u1 = (clip.x - x1) / iw;
525  x1 = clip.x;
526  }
527 
528  if (x2 > x3) {
529  u2 = 1.0f - (x2 - x3) / iw;
530  x2 = x3;
531  }
532 
533  if (y1 < clip.y) {
534  v1 = (clip.y - y1) / ih;
535  y1 = clip.y;
536  }
537 
538  if (y2 > y3) {
539  v2 = 1.0f - (y2 - y3) / ih;
540  y2 = y3;
541  }
542 
543  vset4.s_loc[0].x = (float) (rect.x + x1) - 0.5f;
544  vset4.s_loc[0].y = (float) (rect.y + y1) - 0.5f;
545  vset4.s_loc[0].z = 0.0f;
546  vset4.rw[0] = 1.0f;
547  vset4.tu[0] = u1;
548  vset4.tv[0] = v1;
549 
550  vset4.s_loc[1].x = (float) (rect.x + x2) - 0.5f;
551  vset4.s_loc[1].y = (float) (rect.y + y1) - 0.5f;
552  vset4.s_loc[1].z = 0.0f;
553  vset4.rw[1] = 1.0f;
554  vset4.tu[1] = u2;
555  vset4.tv[1] = v1;
556 
557  vset4.s_loc[2].x = (float) (rect.x + x2) - 0.5f;
558  vset4.s_loc[2].y = (float) (rect.y + y2) - 0.5f;
559  vset4.s_loc[2].z = 0.0f;
560  vset4.rw[2] = 1.0f;
561  vset4.tu[2] = u2;
562  vset4.tv[2] = v2;
563 
564  vset4.s_loc[3].x = (float) (rect.x + x1) - 0.5f;
565  vset4.s_loc[3].y = (float) (rect.y + y2) - 0.5f;
566  vset4.s_loc[3].z = 0.0f;
567  vset4.rw[3] = 1.0f;
568  vset4.tu[3] = u1;
569  vset4.tv[3] = v2;
570 
571  Material mtl;
572  mtl.tex_diffuse = img;
573 
574  Poly poly(0);
575  poly.nverts = 4;
576  poly.vertex_set = &vset4;
577  poly.material = &mtl;
578  poly.verts[0] = 0;
579  poly.verts[1] = 1;
580  poly.verts[2] = 2;
581  poly.verts[3] = 3;
582 
583  Video* video = screen->GetVideo();
584 
586  video->DrawScreenPolys(1, &poly, blend);
588 }
589 
590 // +--------------------------------------------------------------------+
591 
592 void
593 Window::TileBitmap(int x1, int y1, int x2, int y2, Bitmap* img, int blend)
594 {
595  if (!screen || !screen->GetVideo()) return;
596  if (!img || !img->Width() || !img->Height()) return;
597 
599  for (int i = 0; i < 4; i++) {
600  vset4.diffuse[i] = Color::White.Value();
601  }
602 
603  float xscale = (float) rect.w / (float) img->Width();
604  float yscale = (float) rect.h / (float) img->Height();
605 
606  vset4.s_loc[0].x = (float) (rect.x + x1) - 0.5f;
607  vset4.s_loc[0].y = (float) (rect.y + y1) - 0.5f;
608  vset4.s_loc[0].z = 0.0f;
609  vset4.rw[0] = 1.0f;
610  vset4.tu[0] = 0.0f;
611  vset4.tv[0] = 0.0f;
612 
613  vset4.s_loc[1].x = (float) (rect.x + x2) - 0.5f;
614  vset4.s_loc[1].y = (float) (rect.y + y1) - 0.5f;
615  vset4.s_loc[1].z = 0.0f;
616  vset4.rw[1] = 1.0f;
617  vset4.tu[1] = xscale;
618  vset4.tv[1] = 0.0f;
619 
620  vset4.s_loc[2].x = (float) (rect.x + x2) - 0.5f;
621  vset4.s_loc[2].y = (float) (rect.y + y2) - 0.5f;
622  vset4.s_loc[2].z = 0.0f;
623  vset4.rw[2] = 1.0f;
624  vset4.tu[2] = xscale;
625  vset4.tv[2] = yscale;
626 
627  vset4.s_loc[3].x = (float) (rect.x + x1) - 0.5f;
628  vset4.s_loc[3].y = (float) (rect.y + y2) - 0.5f;
629  vset4.s_loc[3].z = 0.0f;
630  vset4.rw[3] = 1.0f;
631  vset4.tu[3] = 0.0f;
632  vset4.tv[3] = yscale;
633 
634  Material mtl;
635  mtl.tex_diffuse = img;
636 
637  Poly poly(0);
638  poly.nverts = 4;
639  poly.vertex_set = &vset4;
640  poly.material = &mtl;
641  poly.verts[0] = 0;
642  poly.verts[1] = 1;
643  poly.verts[2] = 2;
644  poly.verts[3] = 3;
645 
646  Video* video = screen->GetVideo();
647  video->DrawScreenPolys(1, &poly, blend);
648 }
649 
650 // +--------------------------------------------------------------------+
651 
652 static float ellipse_pts[256];
653 
654 void
655 Window::DrawEllipse(int x1, int y1, int x2, int y2, Color color, int blend)
656 {
657  Video* video = screen->GetVideo();
658 
659  if (!video)
660  return;
661 
662  sort(x1,x2);
663  sort(y1,y2);
664 
665  if (x1 > rect.w || x2 < 0 || y1 > rect.h || y2 < 0)
666  return;
667 
668  double w2 = (x2-x1)/2.0;
669  double h2 = (y2-y1)/2.0;
670  double cx = rect.x + x1 + w2;
671  double cy = rect.y + y1 + h2;
672  double r = w2;
673  int ns = 4;
674  int np = 0;
675 
676  if (h2 > r)
677  r = h2;
678 
679  if (r > 2*ns)
680  ns = (int) (r/2);
681 
682  if (ns > 64)
683  ns = 64;
684 
685  double theta = 0;
686  double dt = (PI/2) / ns;
687 
688  // quadrant 1 (lower right):
689  if (cx < (rect.x+rect.w) && cy < (rect.y + rect.h)) {
690  theta = 0;
691  np = 0;
692 
693  for (int i = 0; i < ns; i++) {
694  double ex1 = x1 + w2 + cos(theta) * w2;
695  double ey1 = y1 + h2 + sin(theta) * h2;
696 
697  theta += dt;
698 
699  double ex2 = x1 + w2 + cos(theta) * w2;
700  double ey2 = y1 + h2 + sin(theta) * h2;
701 
702  if (ClipLine(ex1, ey1, ex2, ey2)) {
703  ellipse_pts[np++] = (float) (rect.x + ex1);
704  ellipse_pts[np++] = (float) (rect.y + ey1);
705  ellipse_pts[np++] = (float) (rect.x + ex2);
706  ellipse_pts[np++] = (float) (rect.y + ey2);
707  }
708  }
709 
710  video->DrawScreenLines(np/4, ellipse_pts, color, blend);
711  }
712 
713  // quadrant 2 (lower left):
714  if (cx > rect.x && cy < (rect.y + rect.h)) {
715  theta = 90*DEGREES;
716  np = 0;
717 
718  for (int i = 0; i < ns; i++) {
719  double ex1 = x1 + w2 + cos(theta) * w2;
720  double ey1 = y1 + h2 + sin(theta) * h2;
721 
722  theta += dt;
723 
724  double ex2 = x1 + w2 + cos(theta) * w2;
725  double ey2 = y1 + h2 + sin(theta) * h2;
726 
727  if (ClipLine(ex1, ey1, ex2, ey2)) {
728  ellipse_pts[np++] = (float) (rect.x + ex1);
729  ellipse_pts[np++] = (float) (rect.y + ey1);
730  ellipse_pts[np++] = (float) (rect.x + ex2);
731  ellipse_pts[np++] = (float) (rect.y + ey2);
732  }
733  }
734 
735  video->DrawScreenLines(np/4, ellipse_pts, color, blend);
736  }
737 
738  // quadrant 3 (upper left):
739  if (cx > rect.x && cy > rect.y) {
740  theta = 180*DEGREES;
741  np = 0;
742 
743  for (int i = 0; i < ns; i++) {
744  double ex1 = x1 + w2 + cos(theta) * w2;
745  double ey1 = y1 + h2 + sin(theta) * h2;
746 
747  theta += dt;
748 
749  double ex2 = x1 + w2 + cos(theta) * w2;
750  double ey2 = y1 + h2 + sin(theta) * h2;
751 
752  if (ClipLine(ex1, ey1, ex2, ey2)) {
753  ellipse_pts[np++] = (float) (rect.x + ex1);
754  ellipse_pts[np++] = (float) (rect.y + ey1);
755  ellipse_pts[np++] = (float) (rect.x + ex2);
756  ellipse_pts[np++] = (float) (rect.y + ey2);
757  }
758  }
759 
760  video->DrawScreenLines(np/4, ellipse_pts, color, blend);
761  }
762 
763  // quadrant 4 (upper right):
764  if (cx < (rect.x+rect.w) && cy > rect.y) {
765  theta = 270*DEGREES;
766  np = 0;
767 
768  for (int i = 0; i < ns; i++) {
769  double ex1 = x1 + w2 + cos(theta) * w2;
770  double ey1 = y1 + h2 + sin(theta) * h2;
771 
772  theta += dt;
773 
774  double ex2 = x1 + w2 + cos(theta) * w2;
775  double ey2 = y1 + h2 + sin(theta) * h2;
776 
777  if (ClipLine(ex1, ey1, ex2, ey2)) {
778  ellipse_pts[np++] = (float) (rect.x + ex1);
779  ellipse_pts[np++] = (float) (rect.y + ey1);
780  ellipse_pts[np++] = (float) (rect.x + ex2);
781  ellipse_pts[np++] = (float) (rect.y + ey2);
782  }
783  }
784 
785  video->DrawScreenLines(np/4, ellipse_pts, color, blend);
786  }
787 
788 }
789 
790 void
791 Window::FillEllipse(int x1, int y1, int x2, int y2, Color color, int blend)
792 {
793  Video* video = screen->GetVideo();
794 
795  if (!video)
796  return;
797 
798  sort(x1,x2);
799  sort(y1,y2);
800 
801  if (x1 > rect.w || x2 < 0 || y1 > rect.h || y2 < 0)
802  return;
803 
804  double w2 = (x2-x1)/2.0;
805  double h2 = (y2-y1)/2.0;
806  double cx = x1 + w2;
807  double cy = y1 + h2;
808  double r = w2;
809  int ns = 4;
810  int np = 0;
811 
812  if (h2 > r)
813  r = h2;
814 
815  if (r > 2*ns)
816  ns = (int) (r/2);
817 
818  if (ns > 64)
819  ns = 64;
820 
821  double theta = -PI / 2;
822  double dt = PI / ns;
823 
824  for (int i = 0; i < ns; i++) {
825  double ex1 = cos(theta) * w2;
826  double ey1 = sin(theta) * h2;
827 
828  theta += dt;
829 
830  double ex2 = cos(theta) * w2;
831  double ey2 = sin(theta) * h2;
832 
833  POINT pts[4];
834 
835  pts[0].x = (int) (cx - ex1);
836  pts[0].y = (int) (cy + ey1);
837 
838  pts[1].x = (int) (cx + ex1);
839  pts[1].y = (int) (cy + ey1);
840 
841  pts[2].x = (int) (cx + ex2);
842  pts[2].y = (int) (cy + ey2);
843 
844  pts[3].x = (int) (cx - ex2);
845  pts[3].y = (int) (cy + ey2);
846 
847  if (pts[0].x > rect.w && pts[3].x > rect.w)
848  continue;
849 
850  if (pts[1].x < 0 && pts[2].x < 0)
851  continue;
852 
853  if (pts[0].y > rect.h)
854  return;
855 
856  if (pts[2].y < 0)
857  continue;
858 
859  if (pts[0].x < 0) pts[0].x = 0;
860  if (pts[3].x < 0) pts[3].x = 0;
861  if (pts[1].x > rect.w) pts[1].x = rect.w;
862  if (pts[2].x > rect.w) pts[2].x = rect.w;
863 
864  if (pts[0].y < 0) pts[0].y = 0;
865  if (pts[1].y < 0) pts[1].y = 0;
866  if (pts[2].y > rect.h) pts[2].y = rect.h;
867  if (pts[3].y > rect.h) pts[3].y = rect.h;
868 
869  FillPoly(4, pts, color, blend);
870  }
871 }
872 
873 // +--------------------------------------------------------------------+
874 
875 void
876 Window::Print(int x1, int y1, const char* fmt, ...)
877 {
878  if (!font || x1<0 || y1<0 || x1>=rect.w || y1>=rect.h || !fmt)
879  return;
880 
881  x1 += rect.x;
882  y1 += rect.y;
883 
884  char msgbuf[512];
885  vsprintf_s(msgbuf, fmt, (char *)(&fmt+1));
886  font->DrawString(msgbuf, strlen(msgbuf), x1, y1, rect);
887 }
888 
889 void
890 Window::DrawText(const char* txt, int count, Rect& txt_rect, DWORD flags)
891 {
892  if (!font)
893  return;
894 
895  if (txt && !count)
896  count = strlen(txt);
897 
898  // clip the rect:
899  Rect clip_rect = txt_rect;
900 
901  if (clip_rect.x < 0) {
902  int dx = -clip_rect.x;
903  clip_rect.x += dx;
904  clip_rect.w -= dx;
905  }
906 
907  if (clip_rect.y < 0) {
908  int dy = -clip_rect.y;
909  clip_rect.y += dy;
910  clip_rect.h -= dy;
911  }
912 
913  if (clip_rect.w < 1 || clip_rect.h < 1)
914  return;
915 
916  if (clip_rect.x + clip_rect.w > rect.w)
917  clip_rect.w = rect.w - clip_rect.x;
918 
919  if (clip_rect.y + clip_rect.h > rect.h)
920  clip_rect.h = rect.h - clip_rect.y;
921 
922  clip_rect.x += rect.x;
923  clip_rect.y += rect.y;
924 
925  if (font && txt && count) {
926  font->DrawText(txt, count, clip_rect, flags);
927  font->SetAlpha(1);
928  }
929 
930  // if calc only, update the rectangle:
931  if (flags & DT_CALCRECT) {
932  txt_rect.h = clip_rect.h;
933  txt_rect.w = clip_rect.w;
934  }
935 }
936