]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dc.cpp
fixed incorrect GetTextExtent for wxTELETYPE font
[wxWidgets.git] / src / os2 / dc.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dc.cpp
3// Purpose: wxDC class
fb46a9a6 4// Author: David Webster
0e320a79 5// Modified by:
fb46a9a6 6// Created: 10/14/99
0e320a79 7// RCS-ID: $Id$
fb46a9a6
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
fb46a9a6
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/utils.h"
19 #include "wx/dialog.h"
20 #include "wx/app.h"
21 #include "wx/bitmap.h"
22 #include "wx/dcmemory.h"
23 #include "wx/log.h"
24 #include "wx/icon.h"
0e320a79
DW
25#endif
26
fb46a9a6
DW
27#include "wx/dcprint.h"
28
29#include <string.h>
30#include <math.h>
31
32#include "wx/os2/private.h"
0e320a79 33
fb46a9a6 34 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
0e320a79 35
fb46a9a6 36// ---------------------------------------------------------------------------
0e320a79 37// constants
fb46a9a6 38// ---------------------------------------------------------------------------
1408104d 39
fb46a9a6 40static const int VIEWPORT_EXTENT = 1000;
1408104d 41
fb46a9a6
DW
42static const int MM_POINTS = 9;
43static const int MM_METRIC = 10;
1408104d 44
f6bcfd97
BP
45// usually this is defined in math.h
46#ifndef M_PI
47 static const double M_PI = 3.14159265358979323846;
48#endif // M_PI
49
50// ---------------------------------------------------------------------------
51// private functions
52// ---------------------------------------------------------------------------
53
54// convert degrees to radians
55static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
56
7e99520b
DW
57int SetTextColor(
58 HPS hPS
59, int nForegroundColour
60)
61{
62 CHARBUNDLE vCbnd;
63
64 vCbnd.lColor = nForegroundColour;
65 ::GpiSetAttrs( hPS // presentation-space handle
66 ,PRIM_CHAR // Char primitive.
67 ,CBB_COLOR // sets color.
68 ,0 //
69 ,&vCbnd // buffer for attributes.
70 );
71 return 0;
72}
73
74int QueryTextBkColor(
75 HPS hPS
76)
77{
78 CHARBUNDLE vCbnd;
79
f44fdfb0
DW
80 ::GpiQueryAttrs( hPS // presentation-space handle
81 ,PRIM_CHAR // Char primitive.
82 ,CBB_BACK_COLOR // Background color.
83 ,&vCbnd // buffer for attributes.
84 );
7e99520b
DW
85 return vCbnd.lBackColor;
86}
87
88
89int SetTextBkColor(
90 HPS hPS
91, int nBackgroundColour
92)
93{
94 CHARBUNDLE vCbnd;
95 int rc;
96
97 rc = QueryTextBkColor(hPS);
98
99 vCbnd.lBackColor = nBackgroundColour;
100 ::GpiSetAttrs(hPS, // presentation-space handle
101 PRIM_CHAR, // Char primitive.
102 CBB_BACK_COLOR, // sets color.
103 0,
104 &vCbnd // buffer for attributes.
105 );
106 return rc;
107}
108
109int SetBkMode(
110 HPS hPS
111, int nBackgroundMode
112)
113{
114 if(nBackgroundMode == wxTRANSPARENT)
115 ::GpiSetBackMix( hPS
116 ,BM_LEAVEALONE
117 );
118 else
119 // the background of the primitive takes over whatever is underneath.
120 ::GpiSetBackMix( hPS
121 ,BM_OVERPAINT
122 );
123 return 0;
124}
125
fb46a9a6
DW
126// ===========================================================================
127// implementation
128// ===========================================================================
1408104d 129
fb46a9a6 130// ---------------------------------------------------------------------------
0e320a79 131// wxDC
fb46a9a6 132// ---------------------------------------------------------------------------
0e320a79
DW
133
134wxDC::wxDC(void)
135{
7e99520b 136 m_pCanvas = NULL;
c3d43472 137
7e99520b
DW
138 m_hOldBitmap = 0;
139 m_hOldPen = 0;
140 m_hOldBrush = 0;
141 m_hOldFont = 0;
142 m_hOldPalette = 0;
ce44c50e 143
7e99520b
DW
144 m_bOwnsDC = FALSE;
145 m_hDC = 0;
146 m_nDCCount = 0;
147 m_hOldPS = NULL;
148 m_hPS = NULL;
149 m_bIsPaintTime = FALSE;// True at Paint Time
0e320a79
DW
150};
151
152wxDC::~wxDC(void)
153{
c3d43472 154 // TODO:
0e320a79
DW
155};
156
fb46a9a6
DW
157// This will select current objects out of the DC,
158// which is what you have to do before deleting the
159// DC.
160void wxDC::SelectOldObjects(WXHDC dc)
0e320a79 161{
fb46a9a6
DW
162 if (dc)
163 {
f6bcfd97 164 if (m_hOldBitmap)
fb46a9a6
DW
165 {
166// ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
f6bcfd97 167 if (m_vSelectedBitmap.Ok())
fb46a9a6 168 {
f6bcfd97 169 m_vSelectedBitmap.SetSelectedInto(NULL);
fb46a9a6
DW
170 }
171 }
f6bcfd97
BP
172 m_hOldBitmap = 0;
173 if (m_hOldPen)
fb46a9a6
DW
174 {
175// ::SelectObject((HDC) dc, (HPEN) m_oldPen);
176 }
f6bcfd97
BP
177 m_hOldPen = 0;
178 if (m_hOldBrush)
fb46a9a6
DW
179 {
180// ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
181 }
f6bcfd97
BP
182 m_hOldBrush = 0;
183 if (m_hOldFont)
fb46a9a6
DW
184 {
185// ::SelectObject((HDC) dc, (HFONT) m_oldFont);
186 }
f6bcfd97
BP
187 m_hOldFont = 0;
188 if (m_hOldPalette)
fb46a9a6
DW
189 {
190// ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
191 }
f6bcfd97 192 m_hOldPalette = 0;
fb46a9a6 193 }
0e320a79 194
f6bcfd97
BP
195 m_brush = wxNullBrush;
196 m_pen = wxNullPen;
197 m_palette = wxNullPalette;
198 m_font = wxNullFont;
fb46a9a6 199 m_backgroundBrush = wxNullBrush;
f6bcfd97 200 m_vSelectedBitmap = wxNullBitmap;
fb46a9a6 201}
0e320a79 202
fb46a9a6
DW
203// ---------------------------------------------------------------------------
204// clipping
205// ---------------------------------------------------------------------------
0e320a79 206
f6bcfd97
BP
207#define DO_SET_CLIPPING_BOX() \
208{ \
209 RECT rect; \
210 \
211 GetClipBox(GetHdc(), &rect); \
212 \
213 m_clipX1 = (wxCoord) XDEV2LOG(rect.left); \
214 m_clipY1 = (wxCoord) YDEV2LOG(rect.top); \
215 m_clipX2 = (wxCoord) XDEV2LOG(rect.right); \
216 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \
fb46a9a6 217}
0e320a79 218
7cdc2f1e
DW
219void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y
220 ,wxCoord width, wxCoord height
fb46a9a6 221 )
0e320a79 222{
fb46a9a6
DW
223 // TODO
224}
0e320a79 225
f6bcfd97 226void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
0e320a79 227{
f6bcfd97 228 // TODO
fb46a9a6 229}
0e320a79 230
fb46a9a6 231void wxDC::DestroyClippingRegion(void)
0e320a79 232{
c3d43472 233 // TODO:
0e320a79
DW
234};
235
fb46a9a6
DW
236// ---------------------------------------------------------------------------
237// query capabilities
238// ---------------------------------------------------------------------------
0e320a79 239
fb46a9a6 240bool wxDC::CanDrawBitmap() const
0e320a79 241{
fb46a9a6
DW
242 return TRUE;
243}
0e320a79 244
fb46a9a6 245bool wxDC::CanGetTextExtent() const
0e320a79 246{
fb46a9a6
DW
247 // What sort of display is it?
248 int technology = 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
0e320a79 249
fb46a9a6
DW
250 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
251 return FALSE;
252}
1408104d
DW
253
254int wxDC::GetDepth() const
0e320a79 255{
1408104d
DW
256 // TODO:
257 return (1);
258}
0e320a79 259
fb46a9a6
DW
260// ---------------------------------------------------------------------------
261// drawing
262// ---------------------------------------------------------------------------
0e320a79 263
1408104d 264void wxDC::Clear()
0e320a79 265{
1408104d
DW
266 // TODO
267}
0e320a79 268
7cdc2f1e
DW
269void wxDC::DoFloodFill( wxCoord x
270 ,wxCoord y
fb46a9a6
DW
271 ,const wxColour& col
272 ,int style
273 )
0e320a79 274{
1408104d
DW
275 // TODO
276}
0e320a79 277
7cdc2f1e 278bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
1408104d
DW
279{
280 // TODO
fb46a9a6 281 return(TRUE);
1408104d 282}
0e320a79 283
7cdc2f1e 284void wxDC::DoCrossHair(wxCoord x, wxCoord y)
0e320a79 285{
1408104d
DW
286 // TODO
287}
288
7e99520b
DW
289void wxDC::DoDrawLine(
290 wxCoord vX1
291, wxCoord vY1
292, wxCoord vX2
293, wxCoord vY2
294)
0e320a79 295{
7e99520b
DW
296 POINTL vPoint[2];
297
298 vPoint[0].x = vX1;
299 vPoint[0].y = vY1;
300 vPoint[1].x = vX2;
301 vPoint[1].y = vY2;
302 // ::GpiSetColor(m_hPS,CLR_RED); //DEbug
303 ::GpiMove(m_hPS, &vPoint[0]);
304 ::GpiLine(m_hPS, &vPoint[1]);
1408104d
DW
305}
306
7cdc2f1e
DW
307void wxDC::DoDrawArc( wxCoord x1, wxCoord y1
308 ,wxCoord x2, wxCoord y2
309 ,wxCoord xc, wxCoord yc
fb46a9a6 310 )
1408104d
DW
311{
312 // TODO
313}
314
f6bcfd97
BP
315void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
316 wxCoord width, wxCoord height)
317{
318 // TODO
319}
320
7cdc2f1e 321void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
1408104d
DW
322{
323 // TODO
324}
325
fb46a9a6 326void wxDC::DoDrawPolygon(int n, wxPoint points[]
7cdc2f1e 327 ,wxCoord xoffset, wxCoord yoffset
fb46a9a6
DW
328 ,int fillStyle
329 )
1408104d
DW
330{
331 // TODO
332}
333
fb46a9a6 334void wxDC::DoDrawLines( int n, wxPoint points[]
7cdc2f1e 335 ,wxCoord xoffset, wxCoord yoffset
fb46a9a6 336 )
1408104d
DW
337{
338 // TODO
1408104d
DW
339}
340
7e99520b 341void wxDC::DoDrawRectangle(
f44fdfb0 342 wxCoord vX
7e99520b
DW
343, wxCoord vY
344, wxCoord vWidth
345, wxCoord vHeight
346)
1408104d 347{
7e99520b
DW
348 POINTL vPoint[2];
349
350 vPoint[0].x = vX;
351 vPoint[0].y = vY;
f44fdfb0
DW
352 vPoint[1].x = vX + vWidth;
353 vPoint[1].y = vY - vHeight; //mustdie !!! ??
7e99520b
DW
354
355 ::GpiMove(m_hPS, &vPoint[0]);
356 ::GpiBox( m_hPS // handle to a presentation space
357 ,DRO_OUTLINE // draw the box outline ? or ?
358 ,&vPoint[1] // address of the corner
359 ,0L // horizontal corner radius
360 ,0L // vertical corner radius
361 );
1408104d
DW
362}
363
7e99520b
DW
364void wxDC::DoDrawRoundedRectangle(
365 wxCoord vX
366, wxCoord vY
367, wxCoord vWidth
368, wxCoord vHeight
369, double dRadius
370)
1408104d 371{
7e99520b
DW
372 POINTL vPoint[2];
373
374 vPoint[0].x = vX;
375 vPoint[0].y = vY;
376 vPoint[1].x = vX + vWidth;
377 vPoint[1].y = vY + vHeight; //or -height aka mustdie !!! ??
378
379 ::GpiMove(m_hPS, &vPoint[0]);
f44fdfb0
DW
380 ::GpiBox( m_hPS // handle to a presentation space
381 ,DRO_OUTLINE // draw the box outline ? or ?
382 ,&vPoint[1] // address of the corner
383 ,(LONG)dRadius // horizontal corner radius
384 ,(LONG)dRadius // vertical corner radius
7e99520b 385 );
1408104d
DW
386}
387
7cdc2f1e 388void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1408104d
DW
389{
390 // TODO
391}
392
7cdc2f1e
DW
393void wxDC::DoDrawEllipticArc( wxCoord x
394 ,wxCoord y
395 ,wxCoord w
396 ,wxCoord h
1408104d
DW
397 ,double sa
398 ,double ea
399 )
400{
401 // TODO
402}
403
7cdc2f1e 404void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y)
1408104d
DW
405{
406 // TODO
407}
408
fb46a9a6 409void wxDC::DoDrawBitmap( const wxBitmap &bmp
7cdc2f1e 410 ,wxCoord x, wxCoord y
fb46a9a6
DW
411 ,bool useMask
412 )
1408104d
DW
413{
414 // TODO
415}
416
7e99520b
DW
417void wxDC::DoDrawText(
418 const wxString& rsText
419, wxCoord vX
420, wxCoord vY
421)
1408104d 422{
7e99520b
DW
423 DrawAnyText( rsText
424 ,vX
425 ,vY
426 );
1408104d
DW
427}
428
7e99520b
DW
429void wxDC::DrawAnyText(
430 const wxString& rsText
431, wxCoord vX
432, wxCoord vY
433)
f6bcfd97 434{
7e99520b
DW
435 int nOldBackground = 0;
436 POINTL vPtlStart;
437 LONG lHits;
f6bcfd97 438
7e99520b
DW
439 //
440 // prepare for drawing the text
441 //
442
443 //
444 // Set text color attributes
445 //
446 if (m_textForegroundColour.Ok())
447 {
448 SetTextColor( m_hPS
449 ,(int)m_textForegroundColour.GetPixel()
450 );
451 }
452
453 if (m_textBackgroundColour.Ok())
454 {
455 nOldBackground = SetTextBkColor( m_hPS
456 ,(int)m_textBackgroundColour.GetPixel()
457 );
458 }
459 SetBkMode( m_hPS
460 ,m_backgroundMode
461 );
462 vPtlStart.x = vX;
463 vPtlStart.y = vY;
464
465 lHits = ::GpiCharStringAt( m_hPS
466 ,&vPtlStart
467 ,rsText.length()
468 ,(PCH)rsText.c_str()
469 );
470 if (lHits != GPI_OK)
471 {
472 wxLogLastError(wxT("TextOut"));
473 }
474
475 //
476 // Restore the old parameters (text foreground colour may be left because
477 // it never is set to anything else, but background should remain
478 // transparent even if we just drew an opaque string)
479 //
480 if (m_textBackgroundColour.Ok())
481 SetTextBkColor( m_hPS
482 ,nOldBackground
483 );
484 SetBkMode( m_hPS
485 ,wxTRANSPARENT
486 );
487}
488
489void wxDC::DoDrawRotatedText(
490 const wxString& rsText
491, wxCoord vX
492, wxCoord vY
493, double dAngle
494)
c8ce6bcc 495{
7e99520b
DW
496 if (dAngle == 0.0)
497 {
498 DoDrawText( rsText
499 ,vX
500 ,vY
501 );
502 }
503
c8ce6bcc
DW
504 // TODO:
505 /*
506 if ( angle == 0.0 )
507 {
508 DoDrawText(text, x, y);
509 }
510 else
511 {
512 LOGFONT lf;
513 wxFillLogFont(&lf, &m_font);
514
515 // GDI wants the angle in tenth of degree
516 long angle10 = (long)(angle * 10);
517 lf.lfEscapement = angle10;
518 lf. lfOrientation = angle10;
519
520 HFONT hfont = ::CreateFontIndirect(&lf);
521 if ( !hfont )
522 {
523 wxLogLastError("CreateFont");
524 }
525 else
526 {
527 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
528
529 DrawAnyText(text, x, y);
530
531 (void)::SelectObject(GetHdc(), hfontOld);
532 }
533
534 // call the bounding box by adding all four vertices of the rectangle
535 // containing the text to it (simpler and probably not slower than
536 // determining which of them is really topmost/leftmost/...)
537 wxCoord w, h;
538 GetTextExtent(text, &w, &h);
539
540 double rad = DegToRad(angle);
541
542 // "upper left" and "upper right"
543 CalcBoundingBox(x, y);
544 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
545 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
546
547 // "bottom left" and "bottom right"
548 x += (wxCoord)(h*sin(rad));
549 y += (wxCoord)(h*cos(rad));
550 CalcBoundingBox(x, y);
551 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
552 }
553*/
554}
555
fb46a9a6
DW
556// ---------------------------------------------------------------------------
557// set GDI objects
558// ---------------------------------------------------------------------------
1408104d 559
fb46a9a6 560void wxDC::SetPalette(const wxPalette& palette)
1408104d
DW
561{
562 // TODO
563}
564
f6bcfd97
BP
565void wxDC::SetFont(
566 const wxFont& rFont
567)
1408104d 568{
f6bcfd97
BP
569 //
570 // Set the old object temporarily, in case the assignment deletes an object
571 // that's not yet selected out.
572 //
573 if (m_hOldFont)
574 {
575// ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
576 m_hOldFont = 0;
577 }
578
579 m_font = rFont;
580
581 if (!rFont.Ok())
582 {
583 if (m_hOldFont)
584// ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
585 m_hOldFont = 0;
586 }
587
588 if (m_font.Ok() && m_font.GetResourceHandle())
589 {
590 HFONT hFont = (HFONT)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle());
591 if (hFont == (HFONT) NULL)
592 {
593 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
594 }
595 if (!m_hOldFont)
596 m_hOldFont = (WXHFONT) hFont;
597 }
1408104d
DW
598}
599
7e99520b
DW
600void wxDC::SetPen(
601 const wxPen& rPen
602)
1408104d 603{
7e99520b
DW
604 wxCHECK_RET( Ok(), wxT("invalid window dc") );
605
606 if (m_pen == rPen)
607 return;
608 m_pen = rPen;
609 if (!m_pen.Ok())
610 return;
611
612 int nWidth = m_pen.GetWidth();
613
614 if (nWidth <= 0)
615 {
616 nWidth = 1;
617 }
618 else
619 {
620 double dW = 0.5 +
f44fdfb0
DW
621 ( fabs((double) XLOG2DEVREL(nWidth)) +
622 fabs((double) YLOG2DEVREL(nWidth))
7e99520b
DW
623 ) / 2.0;
624 nWidth = (int)dW;
625 }
626 wxColour vColor = m_pen.GetColour();
627
628 ::GpiSetColor( m_hPS
629 ,vColor.GetPixel()
630 ); //DEbug ??
1408104d 631}
7e99520b 632
fb46a9a6 633void wxDC::SetBrush(const wxBrush& brush)
1408104d
DW
634{
635 // TODO
636}
637
fb46a9a6 638void wxDC::SetBackground(const wxBrush& brush)
1408104d
DW
639{
640 // TODO
641}
642
7e99520b
DW
643void wxDC::SetBackgroundMode(
644 int nMode
645)
1408104d 646{
7e99520b 647 m_backgroundMode = nMode;
1408104d
DW
648}
649
fb46a9a6 650void wxDC::SetLogicalFunction(int function)
1408104d
DW
651{
652 // TODO
653}
1408104d 654
ce44c50e
DW
655void wxDC::SetRop(WXHDC dc)
656{
657 if (!dc || m_logicalFunction < 0)
658 return;
659
660 int c_rop;
661 // These may be wrong
662 switch (m_logicalFunction)
663 {
664// TODO: Figure this stuff out
665 // case wxXOR: c_rop = R2_XORPEN; break;
666// case wxXOR: c_rop = R2_NOTXORPEN; break;
667// case wxINVERT: c_rop = R2_NOT; break;
668// case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
669// case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
670// case wxCLEAR: c_rop = R2_WHITE; break;
671// case wxSET: c_rop = R2_BLACK; break;
672// case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
673// case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
674// case wxAND: c_rop = R2_MASKPEN; break;
675// case wxOR: c_rop = R2_MERGEPEN; break;
676// case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
677// case wxEQUIV:
678// case wxNAND:
679// case wxCOPY:
680 default:
681// c_rop = R2_COPYPEN;
682 break;
683 }
684// SetROP2((HDC) dc, c_rop);
685}
686
fb46a9a6 687bool wxDC::StartDoc(const wxString& message)
ce44c50e 688{
fb46a9a6
DW
689 // We might be previewing, so return TRUE to let it continue.
690 return TRUE;
691}
692
693void wxDC::EndDoc()
694{
695}
696
697void wxDC::StartPage()
698{
699}
700
701void wxDC::EndPage()
702{
703}
704
705// ---------------------------------------------------------------------------
706// text metrics
707// ---------------------------------------------------------------------------
708
7cdc2f1e 709wxCoord wxDC::GetCharHeight() const
fb46a9a6
DW
710{
711 // TODO
7e99520b 712 return(8);
fb46a9a6
DW
713}
714
7cdc2f1e 715wxCoord wxDC::GetCharWidth() const
fb46a9a6
DW
716{
717 // TODO
7e99520b
DW
718 return(8);
719}
720
721void wxDC::DoGetTextExtent(
722 const wxString& rsString
723, wxCoord* pvX
724, wxCoord* pvY
f44fdfb0 725, wxCoord* pvDescent
7e99520b
DW
726, wxCoord* pvExternalLeading
727, wxFont* pTheFont
728) const
729{
730 POINTL avPoint[TXTBOX_COUNT];
731 POINTL vPtMin;
732 POINTL vPtMax;
733 int i;
734 int l;
735 FONTMETRICS vFM; // metrics structure
736 BOOL bRc;
737 char* pStr;
738 ERRORID vErrorCode; // last error id code
739 wxFont* pFontToUse = (wxFont*)pTheFont;
740
741 if (!pFontToUse)
742 pFontToUse = (wxFont*)&m_font;
743 l = rsString.length();
744 pStr = (PCH) rsString.c_str();
fb46a9a6 745
7e99520b
DW
746 //
747 // In world coordinates.
748 //
749 bRc = ::GpiQueryTextBox( m_hPS
750 ,l
751 ,pStr
752 ,TXTBOX_COUNT // return maximum information
753 ,avPoint // array of coordinates points
f44fdfb0 754 );
7e99520b
DW
755 if(!bRc)
756 {
757 vErrorCode = ::WinGetLastError(wxGetInstance());
758 }
759
760 vPtMin.x = avPoint[0].x;
761 vPtMax.x = avPoint[0].x;
762 vPtMin.y = avPoint[0].y;
763 vPtMax.y = avPoint[0].y;
764 for (i = 1; i < 4; i++)
765 {
766 if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
767 if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
768 if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
769 if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
770 }
771 ::GpiQueryFontMetrics( m_hPS
772 ,sizeof(FONTMETRICS)
773 ,&vFM
774 );
775
776 if (pvX)
777 *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1);
778 if (pvY)
779 *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1);
780 if (pvDescent)
781 *pvDescent = vFM.lMaxDescender;
f44fdfb0 782 if (pvExternalLeading)
7e99520b 783 *pvExternalLeading = vFM.lExternalLeading;
fb46a9a6
DW
784}
785
786void wxDC::SetMapMode( int mode )
787{
788 // TODO:
789};
790
791void wxDC::SetUserScale(double x, double y)
792{
793 m_userScaleX = x;
794 m_userScaleY = y;
795
796 SetMapMode(m_mappingMode);
797}
798
799void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
800{
801 m_signX = xLeftRight ? 1 : -1;
802 m_signY = yBottomUp ? -1 : 1;
803
804 SetMapMode(m_mappingMode);
805}
806
807void wxDC::SetSystemScale(double x, double y)
808{
809 m_scaleX = x;
810 m_scaleY = y;
811
812 SetMapMode(m_mappingMode);
813}
814
7cdc2f1e 815void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
fb46a9a6
DW
816{
817 // TODO:
818};
819
7cdc2f1e 820void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
fb46a9a6
DW
821{
822 // TODO:
823};
824
825// ---------------------------------------------------------------------------
826// coordinates transformations
827// ---------------------------------------------------------------------------
828
7cdc2f1e 829wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
fb46a9a6 830{
f6bcfd97
BP
831 return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX);
832}
fb46a9a6 833
7cdc2f1e 834wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
fb46a9a6 835{
f6bcfd97
BP
836 return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX));
837}
fb46a9a6 838
7cdc2f1e 839wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
fb46a9a6 840{
f6bcfd97
BP
841 return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
842}
fb46a9a6 843
7cdc2f1e 844wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
fb46a9a6 845{
f6bcfd97
BP
846 return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY));
847}
fb46a9a6 848
7cdc2f1e 849wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
fb46a9a6 850{
f6bcfd97
BP
851 return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
852}
fb46a9a6 853
7cdc2f1e 854wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
fb46a9a6 855{
f6bcfd97
BP
856 return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX);
857}
fb46a9a6 858
7cdc2f1e 859wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
fb46a9a6 860{
f6bcfd97
BP
861 return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
862}
fb46a9a6 863
7cdc2f1e 864wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
fb46a9a6 865{
f6bcfd97
BP
866 return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY);
867}
fb46a9a6
DW
868
869// ---------------------------------------------------------------------------
870// bit blit
871// ---------------------------------------------------------------------------
872
7cdc2f1e
DW
873bool wxDC::DoBlit( wxCoord xdest
874 ,wxCoord ydest
875 ,wxCoord width
876 ,wxCoord height
fb46a9a6 877 ,wxDC *source
7cdc2f1e
DW
878 ,wxCoord xsrc
879 ,wxCoord ysrc
fb46a9a6
DW
880 ,int rop
881 ,bool useMask
882 )
883{
884 // TODO
885 return(TRUE);
886}
887
888void wxDC::DoGetSize( int* width, int* height ) const
889{
890 // TODO:
891};
892
893void wxDC::DoGetSizeMM( int* width, int* height ) const
894{
895 // TODO:
896};
897
898wxSize wxDC::GetPPI() const
899{
900 int x = 1;
901 int y = 1;
902 // TODO:
903 return (wxSize(x,y));
904}
905
906void wxDC::SetLogicalScale( double x, double y )
907{
908 // TODO:
909};
910
911#if WXWIN_COMPATIBILITY
912void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
913 float *descent, float *externalLeading,
914 wxFont *theFont, bool use16bit) const
915{
7cdc2f1e 916 wxCoord x1, y1, descent1, externalLeading1;
fb46a9a6
DW
917 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
918 *x = x1; *y = y1;
919 if (descent)
920 *descent = descent1;
921 if (externalLeading)
922 *externalLeading = externalLeading1;
923}
924#endif
925
926// ---------------------------------------------------------------------------
927// spline drawing code
928// ---------------------------------------------------------------------------
929
930#if wxUSE_SPLINES
931
932class wxSpline: public wxObject
933{
934public:
935 int type;
936 wxList *points;
937
938 wxSpline(wxList *list);
939 void DeletePoints();
940
941 // Doesn't delete points
942 ~wxSpline();
943};
944
945void wx_draw_open_spline(wxDC *dc, wxSpline *spline);
946
947void wx_quadratic_spline(double a1, double b1, double a2, double b2,
948 double a3, double b3, double a4, double b4);
949void wx_clear_stack();
950int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
951 double *y3, double *x4, double *y4);
952void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
953 double x4, double y4);
954static bool wx_spline_add_point(double x, double y);
955static void wx_spline_draw_point_array(wxDC *dc);
956wxSpline *wx_make_spline(int x1, int y1, int x2, int y2, int x3, int y3);
957
958void wxDC::DoDrawSpline(wxList *list)
959{
960 wxSpline spline(list);
961
962 wx_draw_open_spline(this, &spline);
963}
964
965wxList wx_spline_point_list;
966
967void wx_draw_open_spline(wxDC *dc, wxSpline *spline)
968{
969 wxPoint *p;
970 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
971 double x1, y1, x2, y2;
972
973 wxNode *node = spline->points->First();
974 p = (wxPoint *)node->Data();
975
976 x1 = p->x;
977 y1 = p->y;
978
979 node = node->Next();
980 p = (wxPoint *)node->Data();
981
982 x2 = p->x;
983 y2 = p->y;
984 cx1 = (double)((x1 + x2) / 2);
985 cy1 = (double)((y1 + y2) / 2);
986 cx2 = (double)((cx1 + x2) / 2);
987 cy2 = (double)((cy1 + y2) / 2);
988
989 wx_spline_add_point(x1, y1);
990
991 while ((node = node->Next()) != NULL)
ce44c50e 992 {
fb46a9a6
DW
993 p = (wxPoint *)node->Data();
994 x1 = x2;
995 y1 = y2;
996 x2 = p->x;
997 y2 = p->y;
998 cx4 = (double)(x1 + x2) / 2;
999 cy4 = (double)(y1 + y2) / 2;
1000 cx3 = (double)(x1 + cx4) / 2;
1001 cy3 = (double)(y1 + cy4) / 2;
1002
1003 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
1004
1005 cx1 = cx4;
1006 cy1 = cy4;
1007 cx2 = (double)(cx1 + x2) / 2;
1008 cy2 = (double)(cy1 + y2) / 2;
ce44c50e 1009 }
fb46a9a6
DW
1010
1011 wx_spline_add_point((double)wx_round(cx1), (double)wx_round(cy1));
1012 wx_spline_add_point(x2, y2);
1013
1014 wx_spline_draw_point_array(dc);
1015
ce44c50e
DW
1016}
1017
fb46a9a6
DW
1018/********************* CURVES FOR SPLINES *****************************
1019
1020 The following spline drawing routine is from
1021
1022 "An Algorithm for High-Speed Curve Generation"
1023 by George Merrill Chaikin,
1024 Computer Graphics and Image Processing, 3, Academic Press,
1025 1974, 346-349.
1026
1027 and
1028
1029 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1030 Computer Graphics and Image Processing, 4, Academic Press,
1031 1975, 304-310.
1032
1033***********************************************************************/
1034
1035#define half(z1, z2) ((z1+z2)/2.0)
1036#define THRESHOLD 5
1037
1038/* iterative version */
1039
1040void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
1041 double b4)
ce44c50e 1042{
fb46a9a6
DW
1043 register double xmid, ymid;
1044 double x1, y1, x2, y2, x3, y3, x4, y4;
1045
1046 wx_clear_stack();
1047 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
1048
1049 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
1050 xmid = (double)half(x2, x3);
1051 ymid = (double)half(y2, y3);
1052 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
1053 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
1054 wx_spline_add_point((double)wx_round(x1), (double)wx_round(y1));
1055 wx_spline_add_point((double)wx_round(xmid), (double)wx_round(ymid));
1056 } else {
1057 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
1058 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
1059 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
1060 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
ce44c50e 1061 }
ce44c50e 1062 }
fb46a9a6 1063}
ce44c50e 1064
fb46a9a6
DW
1065
1066/* utilities used by spline drawing routines */
1067
1068
1069typedef struct wx_spline_stack_struct {
1070 double x1, y1, x2, y2, x3, y3, x4, y4;
1071}
1072Stack;
1073
1074#define SPLINE_STACK_DEPTH 20
1075static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
1076static Stack *wx_stack_top;
1077static int wx_stack_count;
1078
1079void wx_clear_stack()
1080{
1081 wx_stack_top = wx_spline_stack;
1082 wx_stack_count = 0;
1083}
1084
1085void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
1086{
1087 wx_stack_top->x1 = x1;
1088 wx_stack_top->y1 = y1;
1089 wx_stack_top->x2 = x2;
1090 wx_stack_top->y2 = y2;
1091 wx_stack_top->x3 = x3;
1092 wx_stack_top->y3 = y3;
1093 wx_stack_top->x4 = x4;
1094 wx_stack_top->y4 = y4;
1095 wx_stack_top++;
1096 wx_stack_count++;
1097}
1098
1099int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
1100 double *x3, double *y3, double *x4, double *y4)
1101{
1102 if (wx_stack_count == 0)
1103 return (0);
1104 wx_stack_top--;
1105 wx_stack_count--;
1106 *x1 = wx_stack_top->x1;
1107 *y1 = wx_stack_top->y1;
1108 *x2 = wx_stack_top->x2;
1109 *y2 = wx_stack_top->y2;
1110 *x3 = wx_stack_top->x3;
1111 *y3 = wx_stack_top->y3;
1112 *x4 = wx_stack_top->x4;
1113 *y4 = wx_stack_top->y4;
1114 return (1);
1115}
1116
1117static bool wx_spline_add_point(double x, double y)
1118{
1119 wxPoint *point = new wxPoint;
1120 point->x = (int) x;
1121 point->y = (int) y;
1122 wx_spline_point_list.Append((wxObject*)point);
1123 return TRUE;
1124}
1125
1126static void wx_spline_draw_point_array(wxDC *dc)
1127{
1128 dc->DrawLines(&wx_spline_point_list, 0, 0);
1129 wxNode *node = wx_spline_point_list.First();
1130 while (node)
1131 {
1132 wxPoint *point = (wxPoint *)node->Data();
1133 delete point;
1134 delete node;
1135 node = wx_spline_point_list.First();
1136 }
1137}
1138
1139wxSpline::wxSpline(wxList *list)
1140{
1141 points = list;
1142}
1143
1144wxSpline::~wxSpline()
1145{
1146}
1147
1148void wxSpline::DeletePoints()
1149{
1150 for(wxNode *node = points->First(); node; node = points->First())
1151 {
1152 wxPoint *point = (wxPoint *)node->Data();
1153 delete point;
1154 delete node;
1155 }
1156 delete points;
ce44c50e
DW
1157}
1158
0e320a79 1159
fb46a9a6 1160#endif // wxUSE_SPLINES
0e320a79 1161