]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/ogl/misc.cpp
modification to wxSizer handler needed for wxWizard
[wxWidgets.git] / contrib / src / ogl / misc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: misc.cpp
3 // Purpose: Miscellaneous OGL support functions
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 12/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "misc.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #include <wx/deprecated/wxexpr.h>
28
29 #include <wx/types.h>
30
31 #ifdef new
32 #undef new
33 #endif
34
35 #include <ctype.h>
36 #include <math.h>
37 #include <stdlib.h>
38
39 #include <wx/ogl/basic.h>
40 #include <wx/ogl/basicp.h>
41 #include <wx/ogl/misc.h>
42 #include <wx/ogl/constrnt.h>
43 #include <wx/ogl/composit.h>
44
45 wxFont* g_oglNormalFont;
46 wxPen* g_oglBlackPen;
47 wxPen* g_oglTransparentPen;
48 wxPen* g_oglBlackForegroundPen;
49 wxPen* g_oglWhiteBackgroundPen;
50 wxBrush* g_oglWhiteBackgroundBrush;
51
52 char* oglBuffer = NULL;
53
54 wxList oglObjectCopyMapping(wxKEY_INTEGER);
55
56
57
58 void wxOGLInitialize()
59 {
60 g_oglNormalFont = wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxNORMAL);
61 g_oglBlackPen = wxThePenList->FindOrCreatePen(wxT("BLACK"), 1, wxSOLID);
62 g_oglTransparentPen = wxThePenList->FindOrCreatePen(wxT("WHITE"), 1, wxTRANSPARENT);
63 g_oglBlackForegroundPen = wxThePenList->FindOrCreatePen(wxT("BLACK"), 1, wxSOLID);
64 g_oglWhiteBackgroundPen = wxThePenList->FindOrCreatePen(wxT("WHITE"), 1, wxSOLID);
65 g_oglWhiteBackgroundBrush = wxTheBrushList->FindOrCreateBrush(wxT("WHITE"), wxSOLID);
66
67 OGLInitializeConstraintTypes();
68
69 // Initialize big buffer used when writing images
70 oglBuffer = new char[3000];
71
72 }
73
74 void wxOGLCleanUp()
75 {
76 if (oglBuffer)
77 {
78 delete[] oglBuffer;
79 oglBuffer = NULL;
80 }
81 oglBuffer = NULL;
82
83 g_oglNormalFont = NULL; // These will be cleaned up by their GDI list
84 g_oglBlackPen = NULL;
85 g_oglTransparentPen = NULL;
86 g_oglBlackForegroundPen = NULL;
87 g_oglWhiteBackgroundPen = NULL;
88 g_oglWhiteBackgroundBrush = NULL;
89
90 OGLCleanUpConstraintTypes();
91 }
92
93 wxFont *oglMatchFont(int point_size)
94 {
95 wxFont *font = wxTheFontList->FindOrCreateFont(point_size, wxSWISS, wxNORMAL, wxNORMAL);
96 #if 0
97 switch (point_size)
98 {
99 case 4:
100 font = swiss_font_4;
101 break;
102 case 6:
103 font = swiss_font_6;
104 break;
105 case 8:
106 font = swiss_font_8;
107 break;
108 case 12:
109 font = swiss_font_12;
110 break;
111 case 14:
112 font = swiss_font_14;
113 break;
114 case 18:
115 font = swiss_font_18;
116 break;
117 case 24:
118 font = swiss_font_24;
119 break;
120 default:
121 case 10:
122 font = swiss_font_10;
123 break;
124 }
125 #endif
126 return font;
127 }
128
129 int FontSizeDialog(wxFrame *parent, int old_size)
130 {
131 if (old_size <= 0)
132 old_size = 10;
133 wxString buf;
134 buf << old_size;
135 wxString ans = wxGetTextFromUser(wxT("Enter point size"), wxT("Font size"), buf, parent);
136 if (ans.Length() == 0)
137 return 0;
138
139 long new_size = 0;
140 ans.ToLong(&new_size);
141 if ((new_size <= 0) || (new_size > 40))
142 {
143 wxMessageBox(wxT("Invalid point size!"), wxT("Error"), wxOK);
144 return 0;
145 }
146 return new_size;
147 /*
148 char *strings[8];
149 strings[0] = "4";
150 strings[1] = "6";
151 strings[2] = "8";
152 strings[3] = "10";
153 strings[4] = "12";
154 strings[5] = "14";
155 strings[6] = "18";
156 strings[7] = "24";
157 char *ans = wxGetSingleChoice("Choose", "Choose a font size", 8, strings, parent);
158 if (ans)
159 {
160 int size;
161 sscanf(ans, "%d", &size);
162 return oglMatchFont(size);
163 }
164 else return NULL;
165 */
166 }
167
168 // Centre a list of strings in the given box. xOffset and yOffset are the
169 // the positions that these lines should be relative to, and this might be
170 // the same as m_xpos, m_ypos, but might be zero if formatting from left-justifying.
171 void oglCentreText(wxDC& dc, wxList *text_list,
172 double m_xpos, double m_ypos, double width, double height,
173 int formatMode)
174 {
175 int n = text_list->GetCount();
176
177 if (!text_list || (n == 0))
178 return;
179
180 // First, get maximum dimensions of box enclosing text
181
182 long char_height = 0;
183 long max_width = 0;
184 long current_width = 0;
185
186 // Store text extents for speed
187 double *widths = new double[n];
188
189 wxNode *current = text_list->GetFirst();
190 int i = 0;
191 while (current)
192 {
193 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
194 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
195 widths[i] = current_width;
196
197 if (current_width > max_width)
198 max_width = current_width;
199 current = current->GetNext();
200 i ++;
201 }
202
203 double max_height = n*char_height;
204
205 double xoffset, yoffset, xOffset, yOffset;
206
207 if (formatMode & FORMAT_CENTRE_VERT)
208 {
209 if (max_height < height)
210 yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
211 else
212 yoffset = (double)(m_ypos - (height/2.0));
213 yOffset = m_ypos;
214 }
215 else
216 {
217 yoffset = 0.0;
218 yOffset = 0.0;
219 }
220
221 if (formatMode & FORMAT_CENTRE_HORIZ)
222 {
223 xoffset = (double)(m_xpos - width/2.0);
224 xOffset = m_xpos;
225 }
226 else
227 {
228 xoffset = 0.0;
229 xOffset = 0.0;
230 }
231
232 current = text_list->GetFirst();
233 i = 0;
234
235 while (current)
236 {
237 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
238
239 double x;
240 if ((formatMode & FORMAT_CENTRE_HORIZ) && (widths[i] < width))
241 x = (double)((width - widths[i])/2.0 + xoffset);
242 else
243 x = xoffset;
244 double y = (double)(i*char_height + yoffset);
245
246 line->SetX( x - xOffset ); line->SetY( y - yOffset );
247 current = current->GetNext();
248 i ++;
249 }
250
251 delete widths;
252 }
253
254 // Centre a list of strings in the given box
255 void oglCentreTextNoClipping(wxDC& dc, wxList *text_list,
256 double m_xpos, double m_ypos, double width, double height)
257 {
258 int n = text_list->GetCount();
259
260 if (!text_list || (n == 0))
261 return;
262
263 // First, get maximum dimensions of box enclosing text
264
265 long char_height = 0;
266 long max_width = 0;
267 long current_width = 0;
268
269 // Store text extents for speed
270 double *widths = new double[n];
271
272 wxNode *current = text_list->GetFirst();
273 int i = 0;
274 while (current)
275 {
276 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
277 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
278 widths[i] = current_width;
279
280 if (current_width > max_width)
281 max_width = current_width;
282 current = current->GetNext();
283 i ++;
284 }
285
286 double max_height = n*char_height;
287
288 double yoffset = (double)(m_ypos - (height/2.0) + (height - max_height)/2.0);
289
290 double xoffset = (double)(m_xpos - width/2.0);
291
292 current = text_list->GetFirst();
293 i = 0;
294
295 while (current)
296 {
297 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
298
299 double x = (double)((width - widths[i])/2.0 + xoffset);
300 double y = (double)(i*char_height + yoffset);
301
302 line->SetX( x - m_xpos ); line->SetY( y - m_ypos );
303 current = current->GetNext();
304 i ++;
305 }
306 delete widths;
307 }
308
309 void oglGetCentredTextExtent(wxDC& dc, wxList *text_list,
310 double m_xpos, double m_ypos, double width, double height,
311 double *actual_width, double *actual_height)
312 {
313 int n = text_list->GetCount();
314
315 if (!text_list || (n == 0))
316 {
317 *actual_width = 0;
318 *actual_height = 0;
319 return;
320 }
321
322 // First, get maximum dimensions of box enclosing text
323
324 long char_height = 0;
325 long max_width = 0;
326 long current_width = 0;
327
328 wxNode *current = text_list->GetFirst();
329 int i = 0;
330 while (current)
331 {
332 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
333 dc.GetTextExtent(line->GetText(), &current_width, &char_height);
334
335 if (current_width > max_width)
336 max_width = current_width;
337 current = current->GetNext();
338 i ++;
339 }
340
341 *actual_height = n*char_height;
342 *actual_width = max_width;
343 }
344
345 // Format a string to a list of strings that fit in the given box.
346 // Interpret %n and 10 or 13 as a new line.
347 wxStringList *oglFormatText(wxDC& dc, const wxString& text, double width, double height, int formatMode)
348 {
349 // First, parse the string into a list of words
350 wxStringList word_list;
351
352 // Make new lines into NULL strings at this point
353 int i = 0; int j = 0; int len = text.Length();
354 wxChar word[200]; word[0] = 0;
355 bool end_word = FALSE; bool new_line = FALSE;
356 while (i < len)
357 {
358 switch (text[i])
359 {
360 case wxT('%'):
361 {
362 i ++;
363 if (i == len)
364 { word[j] = wxT('%'); j ++; }
365 else
366 {
367 if (text[i] == wxT('n'))
368 { new_line = TRUE; end_word = TRUE; i++; }
369 else
370 { word[j] = wxT('%'); j ++; word[j] = text[i]; j ++; i ++; }
371 }
372 break;
373 }
374 case 10:
375 {
376 new_line = TRUE; end_word = TRUE; i++;
377 break;
378 }
379 case 13:
380 {
381 new_line = TRUE; end_word = TRUE; i++;
382 }
383 case wxT(' '):
384 {
385 end_word = TRUE;
386 i ++;
387 break;
388 }
389 default:
390 {
391 word[j] = text[i];
392 j ++; i ++;
393 break;
394 }
395 }
396 if (i == len) end_word = TRUE;
397 if (end_word)
398 {
399 word[j] = 0;
400 j = 0;
401 word_list.Add(word);
402 end_word = FALSE;
403 }
404 if (new_line)
405 {
406 word_list.Append(NULL);
407 new_line = FALSE;
408 }
409 }
410 // Now, make a list of strings which can fit in the box
411 wxStringList *string_list = new wxStringList;
412
413 wxString buffer;
414 wxNode *node = (wxNode*)word_list.GetFirst();
415 long x, y;
416
417 while (node)
418 {
419 wxString oldBuffer(buffer);
420
421 wxChar *s = (wxChar *)node->GetData();
422 if (!s)
423 {
424 // FORCE NEW LINE
425 if (buffer.Length() > 0)
426 string_list->Add(buffer);
427
428 buffer.Empty();
429 }
430 else
431 {
432 if (buffer.Length() != 0)
433 buffer += wxT(" ");
434
435 buffer += s;
436 dc.GetTextExtent(buffer, &x, &y);
437
438 // Don't fit within the bounding box if we're fitting shape to contents
439 if ((x > width) && !(formatMode & FORMAT_SIZE_TO_CONTENTS))
440 {
441 // Deal with first word being wider than box
442 if (oldBuffer.Length() > 0)
443 string_list->Add(oldBuffer);
444
445 buffer.Empty();
446 buffer += s;
447 }
448 }
449
450 node = node->GetNext();
451 }
452 if (buffer.Length() != 0)
453 string_list->Add(buffer);
454
455 return string_list;
456 }
457
458 void oglDrawFormattedText(wxDC& dc, wxList *text_list,
459 double m_xpos, double m_ypos, double width, double height,
460 int formatMode)
461 {
462 double xoffset, yoffset;
463 if (formatMode & FORMAT_CENTRE_HORIZ)
464 xoffset = m_xpos;
465 else
466 xoffset = (double)(m_xpos - (width / 2.0));
467
468 if (formatMode & FORMAT_CENTRE_VERT)
469 yoffset = m_ypos;
470 else
471 yoffset = (double)(m_ypos - (height / 2.0));
472
473 dc.SetClippingRegion(
474 (long)(m_xpos - width/2.0), (long)(m_ypos - height/2.0),
475 (long)width, (long)height);
476
477 wxNode *current = text_list->GetFirst();
478 while (current)
479 {
480 wxShapeTextLine *line = (wxShapeTextLine *)current->GetData();
481
482 dc.DrawText(line->GetText(), WXROUND(xoffset + line->GetX()), WXROUND(yoffset + line->GetY()));
483 current = current->GetNext();
484 }
485
486 dc.DestroyClippingRegion();
487 }
488
489 /*
490 * Find centroid given list of points comprising polyline
491 *
492 */
493
494 void oglFindPolylineCentroid(wxList *points, double *x, double *y)
495 {
496 double xcount = 0;
497 double ycount = 0;
498
499 wxNode *node = points->GetFirst();
500 while (node)
501 {
502 wxRealPoint *point = (wxRealPoint *)node->GetData();
503 xcount += point->x;
504 ycount += point->y;
505 node = node->GetNext();
506 }
507
508 *x = (xcount/points->GetCount());
509 *y = (ycount/points->GetCount());
510 }
511
512 /*
513 * Check that (x1, y1) -> (x2, y2) hits (x3, y3) -> (x4, y4).
514 * If so, ratio1 gives the proportion along the first line
515 * that the intersection occurs (or something like that).
516 * Used by functions below.
517 *
518 */
519 void oglCheckLineIntersection(double x1, double y1, double x2, double y2,
520 double x3, double y3, double x4, double y4,
521 double *ratio1, double *ratio2)
522 {
523 double denominator_term = (y4 - y3)*(x2 - x1) - (y2 - y1)*(x4 - x3);
524 double numerator_term = (x3 - x1)*(y4 - y3) + (x4 - x3)*(y1 - y3);
525
526 double line_constant;
527 double length_ratio = 1.0;
528 double k_line = 1.0;
529
530 // Check for parallel lines
531 if ((denominator_term < 0.005) && (denominator_term > -0.005))
532 line_constant = -1.0;
533 else
534 line_constant = numerator_term/denominator_term;
535
536 // Check for intersection
537 if ((line_constant < 1.0) && (line_constant > 0.0))
538 {
539 // Now must check that other line hits
540 if (((y4 - y3) < 0.005) && ((y4 - y3) > -0.005))
541 k_line = ((x1 - x3) + line_constant*(x2 - x1))/(x4 - x3);
542 else
543 k_line = ((y1 - y3) + line_constant*(y2 - y1))/(y4 - y3);
544
545 if ((k_line >= 0.0) && (k_line < 1.0))
546 length_ratio = line_constant;
547 else
548 k_line = 1.0;
549 }
550 *ratio1 = length_ratio;
551 *ratio2 = k_line;
552 }
553
554 /*
555 * Find where (x1, y1) -> (x2, y2) hits one of the lines in xvec, yvec.
556 * (*x3, *y3) is the point where it hits.
557 *
558 */
559 void oglFindEndForPolyline(double n, double xvec[], double yvec[],
560 double x1, double y1, double x2, double y2, double *x3, double *y3)
561 {
562 int i;
563 double lastx = xvec[0];
564 double lasty = yvec[0];
565
566 double min_ratio = 1.0;
567 double line_ratio;
568 double other_ratio;
569
570 for (i = 1; i < n; i++)
571 {
572 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i],
573 &line_ratio, &other_ratio);
574 lastx = xvec[i];
575 lasty = yvec[i];
576
577 if (line_ratio < min_ratio)
578 min_ratio = line_ratio;
579 }
580
581 // Do last (implicit) line if last and first doubles are not identical
582 if (!(xvec[0] == lastx && yvec[0] == lasty))
583 {
584 oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0],
585 &line_ratio, &other_ratio);
586
587 if (line_ratio < min_ratio)
588 min_ratio = line_ratio;
589 }
590
591 *x3 = (x1 + (x2 - x1)*min_ratio);
592 *y3 = (y1 + (y2 - y1)*min_ratio);
593
594 }
595
596 /*
597 * Find where the line hits the box.
598 *
599 */
600
601 void oglFindEndForBox(double width, double height,
602 double x1, double y1, // Centre of box (possibly)
603 double x2, double y2, // other end of line
604 double *x3, double *y3) // End on box edge
605 {
606 double xvec[5];
607 double yvec[5];
608
609 xvec[0] = (double)(x1 - width/2.0);
610 yvec[0] = (double)(y1 - height/2.0);
611 xvec[1] = (double)(x1 - width/2.0);
612 yvec[1] = (double)(y1 + height/2.0);
613 xvec[2] = (double)(x1 + width/2.0);
614 yvec[2] = (double)(y1 + height/2.0);
615 xvec[3] = (double)(x1 + width/2.0);
616 yvec[3] = (double)(y1 - height/2.0);
617 xvec[4] = (double)(x1 - width/2.0);
618 yvec[4] = (double)(y1 - height/2.0);
619
620 oglFindEndForPolyline(5, xvec, yvec, x2, y2, x1, y1, x3, y3);
621 }
622
623 /*
624 * Find where the line hits the circle.
625 *
626 */
627
628 void oglFindEndForCircle(double radius,
629 double x1, double y1, // Centre of circle
630 double x2, double y2, // Other end of line
631 double *x3, double *y3)
632 {
633 double H = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
634
635 if (H == 0.0)
636 {
637 *x3 = x1;
638 *y3 = y1;
639 }
640 else
641 {
642 *y3 = radius * (y2 - y1)/H + y1;
643 *x3 = radius * (x2 - x1)/H + x1;
644 }
645 }
646
647 /*
648 * Given the line (x1, y1) -> (x2, y2), and an arrow size of given length and width,
649 * return the position of the tip of the arrow and the left and right vertices of the arrow.
650 *
651 */
652
653 void oglGetArrowPoints(double x1, double y1, double x2, double y2,
654 double length, double width,
655 double *tip_x, double *tip_y,
656 double *side1_x, double *side1_y,
657 double *side2_x, double *side2_y)
658 {
659 double l = (double)sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
660
661 if (l < 0.01)
662 l = (double) 0.01;
663
664 double i_bar = (x2 - x1)/l;
665 double j_bar = (y2 - y1)/l;
666
667 double x3 = (- length*i_bar) + x2;
668 double y3 = (- length*j_bar) + y2;
669
670 *side1_x = width*(-j_bar) + x3;
671 *side1_y = width*i_bar + y3;
672
673 *side2_x = -width*(-j_bar) + x3;
674 *side2_y = -width*i_bar + y3;
675
676 *tip_x = x2; *tip_y = y2;
677 }
678
679 /*
680 * Given an ellipse and endpoints of a line, returns the point at which
681 * the line touches the ellipse in values x4, y4.
682 * This function assumes that the centre of the ellipse is at x1, y1, and the
683 * ellipse has a width of width1 and a height of height1. It also assumes you are
684 * wanting to draw an arc FROM point x2, y2 TOWARDS point x3, y3.
685 * This function calculates the x,y coordinates of the intersection point of
686 * the arc with the ellipse.
687 * Author: Ian Harrison
688 */
689
690 void oglDrawArcToEllipse(double x1, double y1, double width1, double height1, double x2, double y2, double x3, double y3,
691 double *x4, double *y4)
692 {
693 double a1 = (double)(width1/2.0);
694 double b1 = (double)(height1/2.0);
695
696 // These are required to give top left x and y coordinates for DrawEllipse
697 // double top_left_x1 = (double)(x1 - a1);
698 // double top_left_y1 = (double)(y1 - b1);
699 /*
700 // Check for vertical line
701 if (fabs(x2 - x3) < 0.05)
702 {
703 *x4 = x3;
704 if (y2 < y3)
705 *y4 = (double)(y1 - b1);
706 else
707 *y4 = (double)(y1 + b1);
708 return;
709 }
710 */
711 // Check that x2 != x3
712 if (fabs(x2 - x3) < 0.05)
713 {
714 *x4 = x2;
715 if (y3 > y2)
716 *y4 = (double)(y1 - sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
717 else
718 *y4 = (double)(y1 + sqrt((b1*b1 - (((x2-x1)*(x2-x1))*(b1*b1)/(a1*a1)))));
719 return;
720 }
721
722 // Calculate the x and y coordinates of the point where arc intersects ellipse
723
724 double A, B, C, D, E, F, G, H, K;
725 double ellipse1_x, ellipse1_y;
726
727 A = (double)(1/(a1 * a1));
728 B = (double)((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1);
729 C = (double)(2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1);
730 D = (double)((y2 - y1) * (y2 - y1)) / (b1 * b1);
731 E = (double)(A + B);
732 F = (double)(C - (2 * A * x1) - (2 * B * x2));
733 G = (double)((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1);
734 H = (double)((y3 - y2) / (x3 - x2));
735 K = (double)((F * F) - (4 * E * G));
736
737 if (K >= 0)
738 // In this case the line intersects the ellipse, so calculate intersection
739 {
740 if(x2 >= x1)
741 {
742 ellipse1_x = (double)(((F * -1) + sqrt(K)) / (2 * E));
743 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
744 }
745 else
746 {
747 ellipse1_x = (double)(((F * -1) - sqrt(K)) / (2 * E));
748 ellipse1_y = (double)((H * (ellipse1_x - x2)) + y2);
749 }
750 }
751 else
752 // in this case, arc does not intersect ellipse, so just draw arc
753 {
754 ellipse1_x = x3;
755 ellipse1_y = y3;
756 }
757 *x4 = ellipse1_x;
758 *y4 = ellipse1_y;
759
760 /*
761 // Draw a little circle (radius = 2) at the end of the arc where it hits
762 // the ellipse .
763
764 double circle_x = ellipse1_x - 2.0;
765 double circle_y = ellipse1_y - 2.0;
766 m_canvas->DrawEllipse(circle_x, circle_y, 4.0, 4.0);
767 */
768 }
769
770 // Update a list item from a list of strings
771 void UpdateListBox(wxListBox *item, wxList *list)
772 {
773 item->Clear();
774 if (!list)
775 return;
776
777 wxNode *node = list->GetFirst();
778 while (node)
779 {
780 wxChar *s = (wxChar *)node->GetData();
781 item->Append(s);
782 node = node->GetNext();
783 }
784 }
785
786 bool oglRoughlyEqual(double val1, double val2, double tol)
787 {
788 return ( (val1 < (val2 + tol)) && (val1 > (val2 - tol)) &&
789 (val2 < (val1 + tol)) && (val2 > (val1 - tol)));
790 }
791
792 /*
793 * Hex<->Dec conversion
794 */
795
796 // Array used in DecToHex conversion routine.
797 static wxChar sg_HexArray[] = { wxT('0'), wxT('1'), wxT('2'), wxT('3'),
798 wxT('4'), wxT('5'), wxT('6'), wxT('7'),
799 wxT('8'), wxT('9'), wxT('A'), wxT('B'),
800 wxT('C'), wxT('D'), wxT('E'), wxT('F')
801 };
802
803 // Convert 2-digit hex number to decimal
804 unsigned int oglHexToDec(wxChar* buf)
805 {
806 int firstDigit, secondDigit;
807
808 if (buf[0] >= wxT('A'))
809 firstDigit = buf[0] - wxT('A') + 10;
810 else
811 firstDigit = buf[0] - wxT('0');
812
813 if (buf[1] >= wxT('A'))
814 secondDigit = buf[1] - wxT('A') + 10;
815 else
816 secondDigit = buf[1] - wxT('0');
817
818 return firstDigit * 16 + secondDigit;
819 }
820
821 // Convert decimal integer to 2-character hex string
822 void oglDecToHex(unsigned int dec, wxChar *buf)
823 {
824 int firstDigit = (int)(dec/16.0);
825 int secondDigit = (int)(dec - (firstDigit*16.0));
826 buf[0] = sg_HexArray[firstDigit];
827 buf[1] = sg_HexArray[secondDigit];
828 buf[2] = 0;
829 }
830
831 // 3-digit hex to wxColour
832 wxColour oglHexToColour(const wxString& hex)
833 {
834 if (hex.Length() == 6)
835 {
836 long r, g, b;
837 r = g = b = 0;
838 hex.Mid(0,2).ToLong(&r, 16);
839 hex.Mid(2,2).ToLong(&g, 16);
840 hex.Mid(4,2).ToLong(&b, 16);
841 return wxColour(r, g, b);
842 }
843 else
844 return wxColour(0,0,0);
845 }
846
847 // RGB to 3-digit hex
848 wxString oglColourToHex(const wxColour& colour)
849 {
850 wxChar buf[7];
851 unsigned int red = colour.Red();
852 unsigned int green = colour.Green();
853 unsigned int blue = colour.Blue();
854
855 oglDecToHex(red, buf);
856 oglDecToHex(green, buf+2);
857 oglDecToHex(blue, buf+4);
858
859 return wxString(buf);
860 }
861
862