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