0022922: Clean up warnings on uninitialized / unused variables
[occt.git] / src / WNT / EHDC.cxx
1 // File:          EHDC.cxx
2 // Created:     
3 // Author:      
4 // Modifications: PLOTNIKOV Eugeny at July 1998 (BUC60286)
5 // Copyright:     Matra Datavision 1998
6
7 #include "EHDC.hxx"
8
9 #include <math.h>
10 #include <limits>
11
12 #define ROUNDL( d ) ( LONG )(  ( d ) + 0.5  )
13 #define Y( y )      (  mySize.cy - ( y )  )
14
15 typedef struct _fpoint {
16
17                 FLOAT x;
18                 FLOAT y;
19
20                } FPOINT, *PFPOINT;
21
22 typedef struct _ddap {
23
24                 EHDC*  _this;
25                 PPOINT pp;
26
27                } DDAP, *PDDAP;
28
29 static void WINAPI _XFORMultiply ( PXFORM,  PXFORM, PXFORM );
30 static void WINAPI _XFORMApply   ( PPOINT,  int, PXFORM    );
31 static void WINAPI _XFORMApplyf  ( PFPOINT, int, PXFORM    );
32
33 static void WINAPI _RenderPath ( HDC, LPPOINT, PBYTE, int );
34 static int  WINAPI _TextPath   ( HDC, int, int, void*, LPPOINT, PBYTE, int, PSIZE, BOOL );
35
36 EHDC :: EHDC ( HDC hdc, PSIZE szClient ) {
37
38  _Init ();
39
40  SetDC ( hdc, szClient );
41
42 }  // end EHDC constructor ( 1 )
43
44 EHDC :: EHDC () {
45
46  _Init ();
47
48 }  // end EHDC constructor ( 2 )
49
50 EHDC :: ~EHDC () {
51
52  HANDLE hHeap = GetProcessHeap ();
53
54  if ( myHDC != NULL ) {
55  
56   SelectPen(    myHDC, GetStockObject ( NULL_PEN   )  );
57   SelectBrush(  myHDC, GetStockObject ( NULL_BRUSH )  );
58  
59  }  // end if
60
61  if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
62  if ( myTextPen   != NULL ) DeletePen(   myTextPen   );
63
64  if ( myTextPath != NULL ) HeapFree (
65                             hHeap, 0,
66                             ( LPVOID )myTextPath
67                            );
68  if (  myPStyle != NULL && ( myFlags & EHDCF_SFREE )  )
69   
70   HeapFree (  hHeap, 0, ( LPVOID )myPStyle  );
71
72  if ( myPBrush != NULL ) DeleteBrush( myPBrush ); 
73  if ( myPPen   != NULL ) DeletePen(     myPPen );
74  
75  if ( myFlags & EHDCF_PPUSH ) {
76  
77   if ( myPPenPush   != NULL ) DeletePen( myPPenPush );
78   if ( myPBrushPush != NULL ) DeleteBrush( myPBrushPush );
79  
80  }  // end if
81
82  HeapFree (  hHeap, 0, ( LPVOID )myDDA1  );
83  HeapFree (  hHeap, 0, ( LPVOID )myDDA2  );
84
85 }  // end EHDC destructor
86
87 void EHDC :: SetDC ( HDC hdc, PSIZE szClient ) {
88
89  myHDC        = hdc;
90  myTextHScale =
91  myTextVScale = 1.0;
92  myTextSlant  = 0.0;
93  mySize       = *szClient;
94
95  SelectPen( myHDC, myPPen );
96  SelectBrush( myHDC, myPBrush );
97
98  MoveToEx   ( 0, 0, NULL );
99  ResetURect ();
100
101 }  // end EHDC :: SetDC
102
103 HBRUSH EHDC :: SelectEPen (
104                 DWORD           dwWidth,
105                 CONST LOGBRUSH* lplb,
106                 DWORD           dwStyleCount,
107                 DWORD*          lpStyle,
108                 BOOL            fNoAlloc
109                ) {
110
111  DWORD dwLen = dwStyleCount * sizeof ( DWORD );
112         
113  if ( dwStyleCount ) {
114  
115   if ( !fNoAlloc ) {
116
117    if ( myPStyle == NULL ) {
118
119     myPStyle = ( PDWORD )HeapAlloc (
120                           GetProcessHeap (),
121                           HEAP_GENERATE_EXCEPTIONS,
122                           dwLen
123                          );
124 setPBS:
125     myPBS = dwStyleCount;
126    
127    } else if ( myPBS < dwStyleCount ) {
128
129     myPStyle = ( PDWORD )HeapReAlloc (
130                           GetProcessHeap (),
131                           HEAP_GENERATE_EXCEPTIONS,
132                           myPStyle, dwLen
133                          );
134
135     goto setPBS;
136
137    }  // end if
138
139    CopyMemory ( myPStyle, lpStyle, dwLen );
140    myFlags |= EHDCF_SFREE;
141
142   } else if (  myPStyle != NULL && ( myFlags & EHDCF_SFREE )  ) {
143   
144    HeapFree (  GetProcessHeap (), 0, ( LPVOID )myPStyle  );
145    myPStyle = lpStyle;
146
147   }  // end if
148
149  }  // end if
150
151  myPIndex = 0;
152  myPWidth = dwWidth;
153  myPNS    = dwStyleCount;
154  
155  if ( myPBrush != NULL ) {
156  
157   LOGBRUSH lb;
158  
159   GetObject (  myPBrush, sizeof ( LOGBRUSH ), &lb  );
160
161   if ( lb.lbStyle != lplb -> lbStyle ||
162        lb.lbColor != lplb -> lbColor ||
163        lb.lbHatch != lplb -> lbHatch
164   ) {
165
166    SelectBrush(  myHDC, GetStockObject ( NULL_BRUSH )  );
167    DeleteBrush( myPBrush );
168 newBrush: 
169    myPBrush  = CreateBrushIndirect ( lplb );
170
171   }  // end if
172
173   if ( dwWidth > 1 ) {
174
175    myFlags  |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
176    myFlags  &= ~EHDCF_JOIN;
177
178   } else myFlags &= ~EHDCF_EPEN;
179
180  } else goto newBrush;
181
182  if ( myPPen != NULL ) {
183  
184   LOGPEN lp;
185
186   GetObject (  myPPen, sizeof ( LOGPEN ), &lp  );
187  
188   if ( lp.lopnColor   != lplb -> lbColor ||
189        lp.lopnWidth.x != 0
190   ) {
191   
192    SelectPen(  myHDC, GetStockObject ( NULL_PEN )  );
193    DeletePen( myPPen );
194 newPen:
195    myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor );
196
197   }  // end if
198
199  } else goto newPen;
200
201  SelectPen( myHDC, myPPen );
202  
203  return SelectBrush( myHDC, myPBrush );
204
205 }  // end EHDC :: SelectEPen
206
207 void EHDC :: SelectEPen (
208               DWORD           dwWidth,
209               CONST LOGBRUSH* lplb
210              ) {
211                
212  if (  dwWidth == 0xFFFFFFFF && ( myFlags & EHDCF_PPUSH )  ) {
213  
214   SelectPen( myHDC, myPPenPush );
215   SelectBrush( myHDC, myPBrushPush );
216   DeletePen( myPPen );
217   DeleteBrush( myPBrush );
218
219   myFlags  &= ~EHDCF_PPUSH;
220   myPPen    = myPPenPush;
221   myPBrush  = myPBrushPush;
222   myPWidth  = myPWPush;
223   myFlags  |= ( myfXpenPush ? EHDCF_EPEN : 0 );
224  
225  } else if (  !( myFlags & EHDCF_PPUSH )  ){
226  
227   myFlags     |= EHDCF_PPUSH;
228   myfXpenPush  = ( myFlags & EHDCF_EPEN );
229   myPPenPush   = myPPen;
230   myPBrushPush = myPBrush;
231   myPWPush     = myPWidth;
232
233   myPWidth = dwWidth;
234   SelectBrush(  myHDC, myPBrush = CreateBrushIndirect ( lplb )                );
235   SelectPen(    myHDC, myPPen   = CreatePen ( PS_SOLID, 0, lplb -> lbColor )  );
236
237   if ( dwWidth > 1 ) {
238
239    myFlags  |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
240    myFlags  &= ~EHDCF_JOIN;
241
242   } else myFlags &= ~EHDCF_EPEN;
243
244  }  // end if
245                
246 }  // end EHDC :: SelectEPen
247
248 HPEN EHDC :: SelectEPen ( HPEN hPen ) {
249
250  HPEN retVal = NULL;
251
252  if ( myHDC != NULL ) retVal = SelectPen( myHDC, hPen );
253
254  myFlags &= ~EHDCF_EPEN;
255  
256  return hPen;
257
258 }  // end EHDC :: SelectEPen
259
260 void EHDC :: SelectEBrush ( PLOGBRUSH lplb, PLOGBRUSH lplbo ) {
261
262  if ( lplb == NULL ) {
263
264   DeleteBrush( myBrush );
265   myBrush = NULL;
266
267  } else if ( myBrush != NULL ) {
268  
269   LOGBRUSH lb;
270  
271   GetObject (  myBrush, sizeof ( LOGBRUSH ), &lb  );
272
273   if ( lplbo != NULL ) *lplbo = lb;
274
275   if ( lb.lbStyle != lplb -> lbStyle ||
276        lb.lbColor != lplb -> lbColor ||
277        lb.lbHatch != lplb -> lbHatch
278   ) {
279   
280    DeleteBrush( myBrush );
281 newBrush: 
282    myBrush  = CreateBrushIndirect ( lplb );
283
284   }  // end if
285
286  } else goto newBrush; 
287
288 }  // end EHDC :: SelectEBrush
289
290 void EHDC :: SetMiter ( BOOL fMiter ) {
291
292  if ( fMiter )
293
294   myFlags &= ~EHDCF_JBEVL;
295
296  else
297
298   myFlags |= EHDCF_JBEVL;
299
300 }  // end EHDC :: SetMiter
301
302 void EHDC :: MoveToEx ( int x, int y, LPPOINT lpPoint ) {
303
304  if ( lpPoint != NULL ) *lpPoint = myStart;
305
306  myStart.x = x;
307  myStart.y = y;
308
309  if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &myStart, 1, &myXform );
310
311  myStart.y = Y( myStart.y );
312  Register ( &myStart, 1 );
313
314  ::MoveToEx ( myHDC, myStart.x, myStart.y, NULL );
315
316  myClose  = myStart;
317  myPIndex = 0;
318  myFlags &= ~EHDCF_JOIN;
319  myFlags |= ( EHDCF_PDRAW | EHDCF_DDAF );
320  myPIndex = 0;
321  myPRlen  = 0;
322
323 }  // end EHDC :: MoveToEx
324
325 BOOL EHDC :: LineTo ( int x, int y ) {
326
327  POINT p = { x, y };
328
329  if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
330
331  p.y = Y( p.y );
332
333  if ( myFlags & EHDCF_EPEN ) {
334
335   if ( myPNS == 0 )
336   
337    _DrawTo ( &p );
338
339   else if (  !_DrawToEx ( &p )  ) return FALSE;
340
341   if ( myFlags & EHDCF_CJOIN ) {
342   
343    myFlags &= ~EHDCF_CJOIN;
344    myCJoin  = p;
345   
346   }  // end if
347
348   if ( myFlags & EHDCF_JOIN )
349   
350    _Join ();
351
352   else
353
354    myJoin = p;
355    
356   if (  myFlags & EHDCF_PDRAW && !( myFlags & EHDCF_NJOIN )  )
357   
358    myFlags |= EHDCF_JOIN;
359
360   else
361
362    myFlags &= ~( EHDCF_JOIN | EHDCF_NJOIN );
363  
364  } else if ( myPNS == 0 ) {
365  
366   Register ( &p, 1 );
367
368   ::LineTo ( myHDC, p.x, p.y );
369
370   myStart = p;
371
372  } else _LineTo ( &p );
373
374  return TRUE;
375
376 }  // end EHDC :: LineTo
377
378 void EHDC :: ClosePath ( void ) {
379
380  BOOL  ltf;
381  POINT pa = myStart;
382  POINT pb = myClose;
383  DWORD dw = ( myFlags & EHDCF_XFORM );
384
385  myFlags &= ~EHDCF_XFORM;
386
387  if ( myStart.x != myClose.x ||
388       myStart.y != myClose.y
389  ) {
390  
391   ltf = LineTo (  myClose.x, Y( myClose.y )  );
392
393   myFlags |= dw;
394
395   if (  ltf && ( myFlags & EHDCF_PDRAW ) && ( myFlags & EHDCF_EPEN )  ) {
396
397    myA     = pa;
398    myB     = pb;
399    myStart = myCJoin;
400
401    _Join ();
402
403   }  // end if
404
405  } else myFlags |= dw;
406
407  myFlags  &= ~EHDCF_JOIN;
408  myPIndex  = 0;
409  myFlags  |= ( EHDCF_PDRAW | EHDCF_CJOIN );
410  myPRlen   = 0;
411
412 }  // end EHDC :: ClosePath
413
414 void EHDC :: Polyline ( CONST POINT* lpPts, int nPts, BOOL fClose ) {
415
416  DWORD dwPIndex = myPIndex;
417  DWORD dwPRlen  = myPRlen;
418  DWORD dwFlags  = myFlags;
419  POINT pA       = myA;
420  POINT pB       = myB;
421  POINT pClose   = myClose;
422  POINT pJoin    = myJoin;
423  POINT pCJoin   = myCJoin;
424  POINT pStart;
425
426  myFlags |= EHDCF_CJOIN;
427
428  MoveToEx ( lpPts -> x, lpPts -> y, &pStart );
429
430  for ( int i = 1; i < nPts; ++i )
431
432   LineTo ( lpPts[ i ].x, lpPts[ i ].y );
433
434  if ( fClose ) ClosePath ();
435
436  myFlags  = dwFlags;
437  myA      = pA;
438  myB      = pB;
439  myClose  = pClose;
440  myJoin   = pJoin;
441  myCJoin  = pCJoin;
442  myStart  = pStart;
443  myPRlen  = dwPRlen;
444  myPIndex = dwPIndex;
445
446 }  // end EHDC :: Polyline
447
448 void EHDC :: Polygon ( CONST POINT* lpPts, int nPts, DWORD dwFlags ) {
449
450  POINT  p;
451  HPEN   hpo = SelectPen(  myHDC, GetStockObject ( NULL_PEN )  );
452  HBRUSH hbo = SelectBrush(  myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH )  );
453
454  BeginPath ( myHDC );
455   
456   p.x = lpPts -> x;
457   p.y = lpPts -> y;
458
459   if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
460
461   ::MoveToEx (  myHDC, p.x, Y( p.y ), NULL  );
462
463   for ( int i = 1; i < nPts; ++i ) {
464   
465    p.x = lpPts[ i ].x;
466    p.y = lpPts[ i ].y;
467
468    if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
469    
470    ::LineTo (  myHDC, p.x, Y( p.y )  );
471   
472   }  // end for
473
474   CloseFigure ( myHDC );
475
476  EndPath ( myHDC );
477
478  FillPath ( myHDC );
479
480  SelectBrush( myHDC, hbo );
481  SelectPen( myHDC, hpo );
482
483  if ( dwFlags & POLYF_NOCLOSEDGE )
484  
485   Polyline ( lpPts, nPts, FALSE );
486
487  else if (  !( dwFlags & POLYF_NOEDGE )  )
488
489   Polyline ( lpPts, nPts, TRUE );
490
491 }  // end EHDC :: Polygon
492
493 void EHDC :: Arc (
494               int x, int y, int xr, int yr, double sa, double oa, DWORD dwAFlags
495              ) {
496
497  int    i = 0, j, n;
498  double delta;
499  FPOINT fp[ 362 ];
500  BOOL   fXform = ( myFlags & EHDCF_XFORM );
501  DWORD  dwPIndex = myPIndex;
502  DWORD  dwPRlen  = myPRlen;
503  DWORD  dwFlags  = myFlags;
504  POINT  pA       = myA;
505  POINT  pB       = myB;
506  POINT  pClose   = myClose;
507  POINT  pJoin    = myJoin;
508  POINT  pCJoin   = myCJoin;
509  POINT  pStart   = myStart;
510
511  myFlags &= ~EHDCF_XFORM;
512
513  if ( oa > 6.28318 )
514
515   oa = 6.28318;
516
517  else if ( oa < -6.28318 )
518
519   oa = -6.28318;
520
521  n = abs (  ROUNDL( oa * 180.0 / 3.14159 )  );
522  delta = oa / n;
523
524  fp[ i   ].x = ( FLOAT )x;
525  fp[ i++ ].y = ( FLOAT )y;
526  n += 2;
527
528  for ( ; i < n; ++i, sa += delta ) {
529  
530   fp[ i ].x = FLOAT(  x + xr * cos ( sa )  );
531   fp[ i ].y = FLOAT(  y + yr * sin ( sa )  );
532
533  }  // end for
534
535  if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
536
537  i = 0;
538
539  if ( dwAFlags & ARCF_PIE ) {
540  
541   myFlags &= ~EHDCF_JBEVL;
542   MoveToEx (  ROUNDL( fp[ 0 ].x ), ROUNDL( fp[ 0 ].y ), NULL  );
543   LineTo   (  ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y )  );
544   
545   ++i;
546
547   if ( i >= n ) goto end;
548
549   LineTo (  ROUNDL( fp[ i ].x ), ROUNDL( fp[ i ].y )  );
550
551   ++i;
552
553  } else {
554  
555   MoveToEx (  ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y ), NULL  );
556   ++i;
557
558  }  // end else
559
560  myFlags |= EHDCF_JBEVL;
561  
562  for ( j = i - 1; i < n; ++i ) {
563  
564   x = ROUNDL( fp[ i ].x );
565   y = ROUNDL( fp[ i ].y );
566
567   if (  x == ROUNDL( fp[ j ].x ) && y == ROUNDL( fp[ j ].y )  ) continue;
568
569   LineTo ( x, y );
570   j = i;
571
572  }  // end for
573 end:
574  if (  dwAFlags & ( ARCF_PIE | ARCF_CHORD ) || fabs ( oa ) == 6.28318  ) {
575  
576   myFlags &= ~EHDCF_JBEVL;
577   ClosePath (); 
578  
579  }  // end if
580
581  myFlags  = dwFlags;
582  myA      = pA;
583  myB      = pB;
584  myClose  = pClose;
585  myJoin   = pJoin;
586  myCJoin  = pCJoin;
587  myStart  = pStart;
588  myPRlen  = dwPRlen;
589  myPIndex = dwPIndex;
590
591 }  // end EHDC :: Arc
592
593 void EHDC :: Polyarc (
594               int x, int y, int xr, int yr, double sa, double oa, BOOL fChord
595              ) {
596
597  int       i = 0, n;
598  double    ssa = sa, delta;
599  FPOINT    fp[ 362 ];
600  BOOL      fXform = ( myFlags & EHDCF_XFORM );
601
602  if ( oa > 6.28318 )
603
604   oa = 6.28318;
605
606  else if ( oa < -6.28318 )
607
608   oa = -6.28318;
609
610  n = abs (  ROUNDL( oa * 180.0 / 3.14159 )  );
611  delta = oa / n;
612
613  fp[ i   ].x = ( FLOAT )x;
614  fp[ i++ ].y = ( FLOAT )y;
615  n += 2;
616
617  for ( ; i < n; ++i, sa += delta ) {
618  
619   fp[ i ].x = FLOAT(  x + xr * cos ( sa )  );
620   fp[ i ].y = FLOAT(  y + yr * sin ( sa )  );
621
622  }  // end for
623
624  if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
625
626  i = 0;
627
628  HPEN hpo = SelectPen(  myHDC, GetStockObject ( NULL_PEN )  );
629  HBRUSH hbo = SelectBrush(  myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH )  );
630
631   BeginPath ( myHDC );
632
633    if ( !fChord ) {
634  
635     ::MoveToEx (
636        myHDC,
637        ROUNDL( fp[ 0 ].x ), Y(  ROUNDL( fp[ 0 ].y )  ), NULL
638       );
639     ::LineTo (
640        myHDC,
641        ROUNDL( fp[ 1 ].x ), Y(  ROUNDL( fp[ 1 ].y )  )
642       );
643   
644     ++i;
645
646     if ( i >= n ) goto end;
647
648     ::LineTo (
649        myHDC,
650        ROUNDL( fp[ i ].x ), Y(  ROUNDL( fp[ i ].y )  )
651       );
652
653    } else {
654  
655     ::MoveToEx (
656        myHDC,
657        ROUNDL( fp[ 1 ].x ), Y(  ROUNDL( fp[ 1 ].y )  ), NULL
658       );
659     ++i;
660
661    }  // end else
662
663    for ( ; i < n; ++i ) ::LineTo (
664                            myHDC,
665                            ROUNDL( fp[ i ].x ), Y(  ROUNDL( fp[ i ].y )  )
666                           );
667 end:
668    CloseFigure ( myHDC ); 
669
670   EndPath ( myHDC );
671  
672   FillPath ( myHDC );
673
674  SelectBrush( myHDC, hbo );
675  SelectPen( myHDC, hpo );
676
677  Arc ( x, y, xr, yr, ssa, oa, fChord ? ARCF_CHORD : ARCF_PIE );
678
679 }  // end EHDC :: Polyarc
680
681 void EHDC :: SetPixel ( int x, int y, COLORREF c ) {
682
683  POINT p = { x, y };
684
685  if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
686
687  p.y = Y( p.y );
688
689  ::SetPixel ( myHDC, p.x, p.y, c );
690
691 }  // end EHDC :: SetPixel
692
693 void EHDC :: SetTextColor ( COLORREF c ) {
694
695  LOGPEN lp;
696
697  GetObject (  myTextPen, sizeof ( LOGPEN ), &lp  );
698
699  if ( lp.lopnColor != c ) {
700
701   LOGBRUSH lb = { BS_SOLID, c, 0 };
702  
703   if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
704   if ( myTextPen   != NULL ) DeletePen( myTextPen     );
705
706   myTextPen   = CreatePen ( PS_SOLID, 0, c );
707   myTextBrush = CreateBrushIndirect ( &lb );
708  
709  }  // end if
710
711 }  // end EHDC :: SetTextColor
712
713 void EHDC :: SetTextAttrib ( COLORREF c, HFONT f, double slant, double hs, double vs ) {
714
715  SetTextColor ( c );
716
717  myTextFont   = f;
718  myTextSlant  = slant;
719  myTextHScale = hs;
720  myTextVScale = vs;
721
722 }  // end EHDC :: SetTextAttrib
723
724 void EHDC :: ETextOut ( int x, int y, char* str, double angle, BOOL fOutline ) {
725
726  _ETextOut ( x, y, str, angle, fOutline );
727
728 }  // end EHDC :: TextOut
729
730 void EHDC :: ETextOut ( int x, int y, wchar_t* str, double angle, BOOL fOutline ) {
731
732  _ETextOut ( x, y, str, angle, fOutline, TRUE );
733
734 }  // end EHDC :: TextOut
735
736 void EHDC :: PolyTextOut (
737       int x, int y, char* str, double angle,
738       double margin, BOOL fOutline, BOOL fNofill, BOOL fNoframe
739      ) {
740
741  _PolyTextOut ( x, y, str, angle, margin, fOutline, FALSE, fNofill, fNoframe );
742
743 }  // end EHDC :: PolyTextOut
744
745 void EHDC :: PolyTextOut (
746       int x, int y, wchar_t* str, double angle, double margin,
747       BOOL fOutline, BOOL fNofill, BOOL fNoframe
748      ) {
749
750  _PolyTextOut ( x, y, str, angle, margin, fOutline, TRUE, fNofill, fNoframe );
751
752 }  // end EHDC :: PolyTextOut
753
754 void EHDC :: SetWorldTransform ( XFORM* xf ) {
755
756  if ( xf == NULL )
757
758   myFlags &= ~EHDCF_XFORM;
759
760  else {
761
762   myXform = *xf;
763   myFlags |= EHDCF_XFORM;
764
765  }  // end else
766
767 }  // end EHDC :: SetWorldTransform
768
769 void EHDC :: ModifyWorldTransform ( XFORM* xf, DWORD iMode ) {
770
771  XFORM  rxf;
772  PXFORM pxfLeft;
773  PXFORM pxfRight;
774
775  if ( iMode == MWT_RIGHTMULTIPLY ) {
776  
777   pxfLeft  = &myXform;
778   pxfRight = xf;
779  
780  } else if ( iMode == MWT_LEFTMULTIPLY ) {
781  
782   pxfLeft  = xf;
783   pxfRight = &myXform;
784   
785  } else if ( iMode == MWT_IDENTITY ) {
786  
787   myXform.eM11 = 1.0F; myXform.eM12 = 0.0F;
788   myXform.eM21 = 0.0F; myXform.eM22 = 1.0F;
789   myXform.eDx  = 0.0F; myXform.eDy  = 0.0F;
790
791   myFlags &= ~EHDCF_XFORM;
792  
793   return;
794  
795  } else return;
796
797  _XFORMultiply ( &rxf, pxfLeft, pxfRight );
798
799  myXform  = rxf;
800  myFlags |= EHDCF_XFORM;
801
802 }  // end EHDC :: ModifyWorldTransform
803
804 void EHDC :: Transform ( LPPOINT p, int n ) {
805
806  _XFORMApply ( p, n, &myXform );
807
808 }  // end TransformXY
809
810 void EHDC :: ResetURect ( void ) {
811
812  myURect.left   = LONG_MAX;
813  myURect.top    = LONG_MAX;
814  myURect.right  = LONG_MIN;
815  myURect.bottom = LONG_MIN;
816
817 }  // end EHDC :: ResetURect
818
819 void EHDC :: GetURect ( LPRECT lpRect ) {
820
821  *lpRect = myURect;
822
823  if ( lpRect -> top    < 0         ) lpRect -> top    = 0;
824  if ( lpRect -> left   < 0         ) lpRect -> left   = 0;
825  if ( lpRect -> bottom > mySize.cy ) lpRect -> bottom = mySize.cy;
826  if ( lpRect -> right  > mySize.cx ) lpRect -> right  = mySize.cx;
827
828 }  // end EHDC :: GetURect
829
830 void EHDC :: _Init ( void ) {
831
832  myTextPen    = ( HPEN   )GetStockObject ( WHITE_PEN   );
833  myTextBrush  = ( HBRUSH )GetStockObject ( WHITE_BRUSH );
834  myTextFont   = NULL;
835  myTextPath   = NULL;
836  myPPen       = myTextPen;
837  myPBrush     = 
838  myBrush      = myTextBrush;
839  myPStyle     = NULL;
840  myTextBS     =
841  myPBS        =
842  myPNS        = 0;
843  myFlags      = 0;
844  myTextSlant  = 0.0;
845  myTextHScale =
846  myTextVScale = 1.0;
847  myNDDA       = 1024;
848  myDDA1       = ( PPOINT )HeapAlloc (
849                            GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
850                            sizeof ( POINT ) * myNDDA
851                           );
852  myDDA2       = ( PPOINT )HeapAlloc (
853                            GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
854                            sizeof ( POINT ) * myNDDA
855                           );
856  myIDDA       = 0;
857
858  ModifyWorldTransform ( NULL, MWT_IDENTITY );
859  myFlags &= ~EHDCF_XFORM;
860
861 }  // end EHDC :: _Init
862
863 void EHDC :: _DrawTo ( PPOINT p ) {
864
865  POINT  ip[ 4 ];
866  double dx, dy, dxhw, dyhw, factor;
867
868  dx = ( double )(  p -> x - myStart.x  );
869  dy = ( double )(  p -> y - myStart.y  );
870
871  if ( dx == 0.0 && dy == 0.0 ) return;
872
873  factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
874  dxhw   = dy * factor;
875  dyhw   = dx * factor;
876
877  ip[ 0 ].x = ROUNDL( myStart.x + dxhw );
878  ip[ 0 ].y = ROUNDL( myStart.y - dyhw );
879
880  ip[ 1 ].x = ROUNDL( p -> x + dxhw );
881  ip[ 1 ].y = ROUNDL( p -> y - dyhw );
882
883  ip[ 2 ].x = ROUNDL( p -> x - dxhw );
884  ip[ 2 ].y = ROUNDL( p -> y + dyhw );
885
886  ip[ 3 ].x = ROUNDL( myStart.x - dxhw );
887  ip[ 3 ].y = ROUNDL( myStart.y + dyhw );
888
889  Register ( ip, 4 );
890
891  ::Polygon ( myHDC, ip, 4 );
892
893  myA     = myB;
894  myB     = myStart;
895  myStart = *p;
896
897 }  // end EHDC :: _DrawTo
898
899 void EHDC :: _Join ( void ) {
900
901  int   np;
902  POINT p[ 4 ];
903  double r, ba, bc, dxba, dyba, dxbc, dybc,
904         s, sa, fc,   xd,   yd,   xe,   ye,
905                xf,   yf,   m1,   m2,   n1,
906                n2,  rm1,  rm2,  rn1,  rn2;
907               
908  r    = myPWidth / 2.0;
909  dxba = ( double )(  myA.x     - myB.x  ); dyba = ( FLOAT )(  myA.y     - myB.y  );
910  dxbc = ( double )(  myStart.x - myB.x  ); dybc = ( FLOAT )(  myStart.y - myB.y  );
911  ba   = sqrt ( dxba * dxba + dyba * dyba );
912  bc   = sqrt ( dxbc * dxbc + dybc * dybc );
913
914  if ( ba == 0.0 || bc == 0.0 ) return;
915
916  n1 = -dxba / ba; n2 = dyba / ba;
917  m1 = -dxbc / bc; m2 = dybc / bc;
918  s  = m1 * n2 - n1 * m2;
919
920  if (   (  sa = fabs ( s )  ) < 0.001   ) return;
921
922  fc   = r / sa;
923  xd   = myB.x + fc * ( m1 + n1 );
924  yd   = myB.y - fc * ( m2 + n2 );
925  rm1  = r * m1; rm2 = r * m2;
926  rn1  = r * n1; rn2 = r * n2;
927
928  if ( s > 0.0 ) {
929  
930   xe = myB.x - rm2; ye = myB.y - rm1;
931   xf = myB.x + rn2; yf = myB.y + rn1;
932  
933  } else if ( s < 0.0 ) {
934  
935   xe = myB.x + rm2; ye = myB.y + rm1;
936   xf = myB.x - rn2; yf = myB.y - rn1;
937  
938  } else return;
939
940  p[ 0 ] = myB;
941  p[ 1 ].x = ROUNDL( xf ); p[ 1 ].y = ROUNDL( yf );
942  
943  if (  !( myFlags & EHDCF_JBEVL )  ) {
944  
945   p[ 2 ].x = ROUNDL( xd ); p[ 2 ].y = ROUNDL( yd );
946   p[ 3 ].x = ROUNDL( xe ); p[ 3 ].y = ROUNDL( ye );
947   np = 4;
948
949  } else {
950  
951   p[ 2 ].x = ROUNDL( xe ); p[ 2 ].y = ROUNDL( ye );
952   np = 3;
953
954  }  // end else
955
956  Register ( p, np );
957 #if 0
958   ::SetPixel (  myHDC, p[ 0 ].x, p[ 0 ].y, RGB( 255, 255, 255 )  );
959   ::SetPixel (  myHDC, p[ 1 ].x, p[ 1 ].y, RGB( 255, 255, 255 )  );
960   ::SetPixel (  myHDC, p[ 2 ].x, p[ 2 ].y, RGB( 255, 255, 255 )  );
961   ::SetPixel (  myHDC, p[ 3 ].x, p[ 3 ].y, RGB( 255, 255, 255 )  );
962 #endif
963  HPEN hpo = SelectPen(  myHDC, GetStockObject ( NULL_PEN )  );
964   ::Polygon ( myHDC, p, np );
965  SelectPen( myHDC, hpo );
966
967 }  // end EHDC :: _Join
968
969 BOOL EHDC :: _DrawToEx ( PPOINT p ) {
970
971  DWORD  i = 0, j, k;
972  DDAP   ddap = { this };
973  POINT  pp[ 4 ];
974  double dx, dy, dxhw, dyhw, factor;
975
976  dx = ( double )( p -> x - myStart.x );
977  dy = ( double )( p -> y - myStart.y );
978
979  if ( dx == 0.0 && dy == 0.0 ) return FALSE;
980
981  factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
982  dxhw   = dy * factor;
983  dyhw   = dx * factor;
984
985  pp[ 0 ].x = ROUNDL( myStart.x + dxhw );
986  pp[ 0 ].y = ROUNDL( myStart.y - dyhw );
987
988  pp[ 1 ].x = ROUNDL( myStart.x - dxhw );
989  pp[ 1 ].y = ROUNDL( myStart.y + dyhw );
990
991  pp[ 2 ].x = ROUNDL( p -> x - dxhw );
992  pp[ 2 ].y = ROUNDL( p -> y + dyhw );
993
994  pp[ 3 ].x = ROUNDL( p -> x + dxhw );
995  pp[ 3 ].y = ROUNDL( p -> y - dyhw );
996
997  myIDDA = 0;
998  myFlags &= ~EHDCF_DDAF;
999  ddap.pp = myDDA1;
1000  LineDDA (  pp[ 0 ].x, pp[ 0 ].y, pp[ 3 ].x, pp[ 3 ].y, &___auxDDAF, ( LPARAM )&ddap  );
1001  k = myIDDA;
1002  myIDDA = 0;
1003  myFlags &= ~EHDCF_DDAF;
1004  ddap.pp = myDDA2;
1005  LineDDA (  pp[ 1 ].x, pp[ 1 ].y, pp[ 2 ].x, pp[ 2 ].y, &___auxDDAF, ( LPARAM )&ddap  );
1006  myIDDA = min( k, myIDDA );
1007  HPEN hpo = SelectPen(  myHDC, GetStockObject ( NULL_PEN )  );
1008
1009  while ( TRUE ) {
1010  
1011   if ( myPRlen == 0 ) {
1012  
1013    myPRlen = myPStyle[ myPIndex++ ];
1014
1015    if ( myPIndex == myPNS ) myPIndex = 0;
1016  
1017   }  // end if
1018  
1019   j = i;
1020
1021   while ( myPRlen != 0 && j < myIDDA ) ++j, --myPRlen;
1022
1023   if ( j == myIDDA ) {
1024   
1025    myDDA1[ j ] = pp[ 3 ];
1026    myDDA2[ j ] = pp[ 2 ];
1027
1028   }  // end if
1029
1030   if ( myFlags & EHDCF_PDRAW ) {
1031
1032    POINT p[ 4 ];
1033
1034    p[ 0 ] = myDDA1[ i ];
1035    p[ 1 ] = myDDA1[ j ];
1036    p[ 2 ] = myDDA2[ j ];
1037    p[ 3 ] = myDDA2[ i ];
1038
1039    Register ( p, 4 );
1040    ::Polygon ( myHDC, p, 4 );
1041   
1042   }  // end if
1043  
1044   if ( myPRlen == 0 )
1045   
1046    myFlags ^= EHDCF_PDRAW;
1047
1048   else break;
1049
1050   i = j;
1051
1052   if ( j >= myIDDA ) break;
1053
1054  }  // end while
1055
1056  SelectPen( myHDC, hpo );
1057
1058  if ( myPRlen == 0 ) myFlags |= EHDCF_NJOIN;
1059
1060  myA = myB;
1061  myB = myStart;
1062  myStart = *p;
1063
1064  return TRUE;
1065
1066 }  // end EHDC :: _DrawToEx
1067
1068 void EHDC :: _LineTo ( PPOINT p ) {
1069
1070  DWORD  i = 0;
1071  DDAP   ddap = { this };
1072
1073  Register ( p, 1 );
1074
1075  myIDDA = 0;
1076  ddap.pp = myDDA1;
1077  LineDDA (  myStart.x, myStart.y, p -> x, p -> y, &___auxDDAF, ( LPARAM )&ddap  );
1078
1079  while ( TRUE ) {
1080
1081   if ( myPRlen == 0 ) {
1082  
1083    myPRlen = myPStyle[ myPIndex++ ];
1084
1085    if ( myPIndex == myPNS ) myPIndex = 0;
1086  
1087   }  // end if
1088
1089   if ( myFlags & EHDCF_PDRAW ) ::MoveToEx ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y, NULL );
1090
1091   while ( myPRlen != 0 && i < myIDDA ) ++i, --myPRlen;
1092
1093   if ( i == myIDDA ) myDDA1[ i ] = *p;
1094
1095   if ( myFlags & EHDCF_PDRAW )
1096  
1097    ::LineTo ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y );
1098
1099   if ( myPRlen == 0 )
1100   
1101    myFlags ^= EHDCF_PDRAW;
1102
1103   else break;
1104
1105  }  // end while
1106
1107  myStart = *p;
1108
1109 }  // end EHDC :: _LineTo
1110
1111 void EHDC :: _ETextOut ( int x, int y, void* str, double angle, BOOL fOutline, BOOL fWide ) {
1112 #if 1
1113  int     i;
1114  DWORD   dwLen;
1115  HPEN    hpo;
1116  HBRUSH  hbo;
1117  HFONT   hfo;
1118  XFORM   lXfm, rXfm, xfm;
1119  PXFORM  pXfm;
1120  SIZE    sz;
1121  double  tanVal;
1122  double  sinVal;
1123  double  cosVal;
1124  LPPOINT lp;
1125
1126  angle  = -angle;
1127  tanVal = tan ( myTextSlant ) * myTextVScale;
1128  sinVal = sin ( angle       );
1129  cosVal = cos ( angle       );
1130
1131  if (  !( myFlags & EHDCF_TPATH )  ) {
1132
1133   hfo = SelectFont( myHDC, myTextFont );
1134
1135    i = myTextNP = _TextPath (
1136                    myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1137                   );
1138
1139   SelectFont( myHDC, hfo );
1140
1141   if ( i <= 0 ) return;
1142
1143   if ( myTextBS < myTextNP ) {
1144
1145    dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1146  
1147    if ( myTextPath == NULL )
1148
1149     myTextPath = ( LPPOINT )HeapAlloc (
1150                              GetProcessHeap (),
1151                              HEAP_GENERATE_EXCEPTIONS, dwLen
1152                             );
1153
1154    else
1155
1156     myTextPath = ( LPPOINT )HeapReAlloc (
1157                              GetProcessHeap (),
1158                              HEAP_GENERATE_EXCEPTIONS,
1159                              myTextPath, dwLen
1160                             );
1161
1162    myTextBS = myTextNP;
1163
1164   }  // end if
1165
1166   myTextType = ( PBYTE )( myTextPath + myTextNP );
1167
1168   _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1169
1170   lp = myTextPath;
1171
1172   while ( i-- ) {
1173    
1174    lp -> y -= sz.cy;
1175    ++lp;
1176
1177   }  // end while
1178
1179  }  // end if
1180
1181  lXfm.eM11 = ( FLOAT )myTextHScale; lXfm.eM21 = ( FLOAT )-tanVal;
1182  lXfm.eM12 = 0.0F;                  lXfm.eM22 = ( FLOAT )myTextVScale;
1183  lXfm.eDx  = 0.0F;
1184  lXfm.eDy  = 0.0F;
1185
1186  rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1187  rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1188  rXfm.eDx = 0.0F;
1189  rXfm.eDy = 0.0F;
1190  _XFORMultiply ( &xfm, &lXfm, &rXfm );
1191
1192  rXfm.eM11 = 1.0F; rXfm.eM21 =  0.0F;
1193  rXfm.eM12 = 0.0F; rXfm.eM22 = -1.0F;
1194  rXfm.eDx  = ( FLOAT )x;
1195  rXfm.eDy  = ( FLOAT )y;
1196  _XFORMultiply ( &lXfm,  &xfm, &rXfm   );
1197
1198  if ( myFlags & EHDCF_XFORM ) {
1199  
1200   _XFORMultiply ( &xfm, &lXfm, &myXform );
1201   pXfm = &xfm;
1202
1203  } else pXfm = &lXfm;
1204
1205  _XFORMApply ( myTextPath, myTextNP, pXfm );
1206
1207  i  = myTextNP;
1208  lp = myTextPath;
1209
1210  while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1211   
1212  hpo = SelectPen( myHDC, myTextPen );
1213
1214  if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1215
1216   if (  !( myFlags & EHDCF_TREG )  ) Register ( myTextPath, myTextNP );
1217
1218   BeginPath ( myHDC );
1219    _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1220   EndPath ( myHDC );
1221
1222   if ( !fOutline ) {
1223  
1224    FillPath ( myHDC );
1225    SelectBrush( myHDC, hbo );
1226  
1227   } else StrokePath ( myHDC );
1228
1229  SelectPen( myHDC, hpo );
1230 #else
1231  int     i;
1232  DWORD   dwLen;
1233  HPEN    hpo;
1234  HBRUSH  hbo;
1235  HFONT   hfo;
1236  XFORM   lXfm, rXfm, xfm;
1237  PXFORM  pXfm;
1238  SIZE    sz;
1239  double  tanVal;
1240  double  sinVal;
1241  double  cosVal;
1242  LPPOINT lp;
1243  BOOL    fNew = FALSE;
1244
1245  angle  = -angle;
1246  tanVal = tan ( myTextSlant );
1247  sinVal = sin ( angle       );
1248  cosVal = cos ( angle       );
1249
1250  if (  !( myFlags & EHDCF_TPATH )  ) {
1251
1252   hfo = SelectFont( myHDC, myTextFont );
1253
1254    if ( myTextVScale != 1.0 || myTextHScale != 1.0 ) {
1255    
1256     LOGFONT    lf;
1257     TEXTMETRIC tm;
1258
1259     GetObject (  myTextFont, sizeof ( LOGFONT ), &lf  );
1260     GetTextMetrics ( myHDC, &tm );
1261
1262     lf.lfHeight = ROUNDL( lf.lfHeight * myTextVScale );
1263     lf.lfWidth  = ROUNDL( lf.lfWidth  * myTextHScale );
1264
1265     lf.lfQuality = DRAFT_QUALITY;
1266
1267     if ( lf.lfWidth == 0 )
1268
1269      lf.lfWidth = ROUNDL( tm.tmAveCharWidth * myTextHScale );
1270
1271     SelectFont( myHDC, hfo );
1272
1273     hfo  = SelectFont(  myHDC, CreateFontIndirect ( &lf )  );
1274     fNew = TRUE;
1275    
1276    }  // end if
1277
1278    i = myTextNP = _TextPath (
1279                    myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1280                   );
1281
1282   hfo = SelectFont( myHDC, hfo );
1283
1284   if ( fNew ) DeleteFont( hfo );
1285
1286   if ( i <= 0 ) return;
1287
1288   if ( myTextBS < myTextNP ) {
1289
1290    dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1291  
1292    if ( myTextPath == NULL )
1293
1294     myTextPath = ( LPPOINT )HeapAlloc (
1295                              GetProcessHeap (),
1296                              HEAP_GENERATE_EXCEPTIONS, dwLen
1297                             );
1298
1299    else
1300
1301     myTextPath = ( LPPOINT )HeapReAlloc (
1302                              GetProcessHeap (),
1303                              HEAP_GENERATE_EXCEPTIONS,
1304                              myTextPath, dwLen
1305                             );
1306
1307    myTextBS = myTextNP;
1308
1309   }  // end if
1310
1311   myTextType = ( PBYTE )( myTextPath + myTextNP );
1312
1313   _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1314
1315   lp = myTextPath;
1316
1317   while ( i-- ) {
1318    
1319    lp -> y -= sz.cy;
1320    ++lp;
1321
1322   }  // end while
1323
1324  }  // end if
1325
1326  lXfm.eM11 = 1.0F; lXfm.eM21 = ( FLOAT )-tanVal;
1327  lXfm.eM12 = 0.0F; lXfm.eM22 = 1.0F;
1328  lXfm.eDx  = 0.0F;
1329  lXfm.eDy  = 0.0F;
1330
1331  rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1332  rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1333  rXfm.eDx = 0.0F;
1334  rXfm.eDy = 0.0F;
1335  _XFORMultiply ( &xfm, &lXfm, &rXfm );
1336
1337  rXfm.eM11 = 1.0F; rXfm.eM21 =  0.0F;
1338  rXfm.eM12 = 0.0F; rXfm.eM22 = -1.0F;
1339  rXfm.eDx  = ( FLOAT )x;
1340  rXfm.eDy  = ( FLOAT )y;
1341  _XFORMultiply ( &lXfm,  &xfm, &rXfm   );
1342
1343  if ( myFlags & EHDCF_XFORM ) {
1344  
1345   _XFORMultiply ( &xfm, &lXfm, &myXform );
1346   pXfm = &xfm;
1347
1348  } else pXfm = &lXfm;
1349
1350  _XFORMApply ( myTextPath, myTextNP, pXfm );
1351
1352  i  = myTextNP;
1353  lp = myTextPath;
1354
1355  while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1356   
1357  hpo = SelectPen( myHDC, myTextPen );
1358
1359  if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1360
1361   if (  !( myFlags & EHDCF_TREG )  ) Register ( myTextPath, myTextNP );
1362
1363   BeginPath ( myHDC );
1364    _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1365   EndPath ( myHDC );
1366
1367   if ( !fOutline ) {
1368  
1369    FillPath ( myHDC );
1370    SelectBrush( myHDC, hbo );
1371  
1372   } else StrokePath ( myHDC );
1373
1374  SelectPen( myHDC, hpo );
1375 #endif
1376 }  // end EHDC :: _ETextOut
1377
1378 void EHDC :: _PolyTextOut (
1379       int x, int y, void* str, double angle, double margin,
1380       BOOL fOutline, BOOL fWide, BOOL fNofill, BOOL fNoframe
1381      ) {
1382
1383  POINT      p[ 4 ];     
1384  XFORM      lXfm, xfm;
1385  PXFORM     pXfm;
1386  SIZE       sz;
1387  HFONT      hfo;
1388  DWORD      dwFlags;
1389  TEXTMETRIC tm;
1390  double     sinVal = sin ( angle );
1391  double     cosVal = cos ( angle );
1392  double     tanVal = -tan ( myTextSlant );
1393  double     height;
1394
1395  hfo = SelectFont( myHDC, myTextFont );
1396
1397   if ( !fWide )
1398  
1399    GetTextExtentPoint32A (
1400     myHDC, ( char* )str, lstrlenA (  ( char* )str  ), &sz
1401    );
1402  
1403   else
1404  
1405    GetTextExtentPoint32W (
1406     myHDC, ( wchar_t* )str, lstrlenW (  ( wchar_t* )str  ), &sz
1407    );
1408  
1409  GetTextMetrics ( myHDC, &tm );
1410  SelectFont( myHDC, hfo );
1411
1412  sz.cy -= tm.tmInternalLeading;
1413
1414  p[ 0 ].x = 0;
1415  p[ 0 ].y = ROUNDL( sz.cy * myTextVScale );
1416  p[ 1 ].x = ROUNDL( sz.cx * myTextHScale );
1417  p[ 1 ].y = p[ 0 ].y;
1418  p[ 2 ].x = p[ 1 ].x;
1419  p[ 2 ].y = 0;
1420  p[ 3 ].x = 0;
1421  p[ 3 ].y = 0;
1422
1423  tanVal *= p[ 1 ].y;
1424
1425  if ( myTextSlant < 0.0F ) {
1426  
1427   p[ 0 ].x -= ( LONG )tanVal;
1428   p[ 3 ].x -= ( LONG )tanVal;
1429   
1430  } else {
1431  
1432   p[ 1 ].x -= ( LONG )tanVal;
1433   p[ 2 ].x -= ( LONG )tanVal;
1434  
1435  }  /* end else */
1436
1437  height = ROUNDL( p[ 0 ].y * margin / 2.0 );
1438
1439  p[ 0 ].x = ROUNDL( p[ 0 ].x - height );
1440  p[ 0 ].y = ROUNDL( p[ 0 ].y + height );
1441  p[ 1 ].x = ROUNDL( p[ 1 ].x + height );
1442  p[ 1 ].y = ROUNDL( p[ 1 ].y + height );
1443  p[ 2 ].x = ROUNDL( p[ 2 ].x + height );
1444  p[ 2 ].y = ROUNDL( p[ 2 ].y - height );
1445  p[ 3 ].x = ROUNDL( p[ 3 ].x - height );
1446  p[ 3 ].y = ROUNDL( p[ 3 ].y - height );
1447
1448  lXfm.eM11 = ( FLOAT ) cosVal; lXfm.eM12 = ( FLOAT )sinVal;
1449  lXfm.eM21 = ( FLOAT )-sinVal; lXfm.eM22 = ( FLOAT )cosVal;
1450  lXfm.eDx  = ( FLOAT )x;
1451  lXfm.eDy  = ( FLOAT )y;
1452
1453  if ( myFlags & EHDCF_XFORM ) {
1454  
1455   _XFORMultiply ( &xfm, &lXfm, &myXform );
1456   pXfm = &xfm;
1457
1458  } else pXfm = &lXfm;
1459
1460  _XFORMApply ( p, 4, pXfm );
1461  
1462  dwFlags = ( myFlags & EHDCF_XFORM );
1463  myFlags &= ~EHDCF_XFORM;
1464
1465  if ( fNofill )
1466  
1467   Polyline ( p, 4, TRUE );
1468
1469  else
1470
1471   Polygon ( p, 4, fNoframe ? POLYF_NOEDGE : 0 );
1472
1473  myFlags |= dwFlags;
1474
1475  _ETextOut ( x, y, str, angle, fOutline, fWide );
1476      
1477 }  // end EHDC :: _PolyTextOut
1478
1479 void EHDC :: Register ( LPPOINT lpPts, int nPts ) {
1480
1481  while ( nPts-- ) {
1482
1483   if ( lpPts -> x < myURect.left )
1484
1485    myURect.left = lpPts -> x - 1;
1486
1487   else if ( lpPts -> x > myURect.right )
1488
1489    myURect.right = lpPts -> x + 2;
1490
1491   if ( lpPts -> y < myURect.top )
1492
1493    myURect.top = lpPts -> y - 1;
1494
1495   else if ( lpPts -> y > myURect.bottom )
1496
1497    myURect.bottom = lpPts -> y + 2;
1498   
1499   ++lpPts;
1500
1501  }  // end while
1502
1503 }  // end EHDC :: _Register
1504 //+++//
1505 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1506 //+++//
1507 static void WINAPI _XFORMultiply ( PXFORM res, PXFORM left, PXFORM right ) {
1508
1509  res -> eM11 = left -> eM11 * right -> eM11 + left -> eM12 * right -> eM21;
1510  res -> eM12 = left -> eM11 * right -> eM12 + left -> eM12 * right -> eM22;
1511  res -> eDx  = left -> eDx  * right -> eM11 + left -> eDy  * right -> eM21 + right -> eDx;
1512
1513  res -> eM21 = left -> eM21 * right -> eM11 + left -> eM22 * right -> eM21;
1514  res -> eM22 = left -> eM21 * right -> eM12 + left -> eM22 * right -> eM22;
1515  res -> eDy  = left -> eDx  * right -> eM12 + left -> eDy  * right -> eM22 + right -> eDy;
1516
1517 }  /* end _XFORMultiply */
1518
1519 static void WINAPI _XFORMApply ( PPOINT pp, int n, PXFORM xf ) {
1520
1521  int    i;
1522  double dx, dy;
1523
1524  for ( i = 0; i < n; ++i ) {
1525
1526   dx = pp[ i ].x * xf -> eM11 + pp[ i ].y * xf -> eM21 + xf -> eDx;
1527   dy = pp[ i ].x * xf -> eM12 + pp[ i ].y * xf -> eM22 + xf -> eDy;
1528
1529   pp[ i ].x = ROUNDL( dx );
1530   pp[ i ].y = ROUNDL( dy );
1531
1532  }  /* end for */
1533
1534 }  /* end _XFORMApply */
1535
1536 static void WINAPI _XFORMApplyf ( PFPOINT pp, int n, PXFORM xf ) {
1537
1538  int    i;
1539  double dx, dy;
1540
1541  for ( i = 0; i < n; ++i ) {
1542
1543   dx = pp[ i ].x * xf -> eM11 + pp[ i ].y * xf -> eM21 + xf -> eDx;
1544   dy = pp[ i ].x * xf -> eM12 + pp[ i ].y * xf -> eM22 + xf -> eDy;
1545
1546   pp[ i ].x = ( FLOAT )dx;
1547   pp[ i ].y = ( FLOAT )dy;
1548
1549  }  /* end for */
1550
1551 }  /* end _XFORMApply */
1552
1553 static void WINAPI _RenderPath ( HDC hdc, LPPOINT lpPts, PBYTE lpType, int nPts ) {
1554
1555  LPPOINT pp;
1556
1557  for ( int i = 0; i < nPts; ++i ) {
1558
1559   switch ( lpType[ i ] ) {
1560
1561    case PT_MOVETO:
1562
1563     MoveToEx ( hdc, lpPts[ i ].x, lpPts[ i ].y, NULL );
1564     pp = &lpPts[ i ];
1565          
1566    continue;
1567       
1568    case PT_LINETO:
1569    case PT_LINETO | PT_CLOSEFIGURE:
1570
1571     LineTo ( hdc, lpPts[ i ].x, lpPts[ i ].y );
1572     goto testClose;
1573          
1574    case PT_BEZIERTO:
1575    case PT_BEZIERTO | PT_CLOSEFIGURE:
1576
1577     PolyBezierTo ( hdc, &lpPts[ i ], 3 );
1578                  
1579     i += 2;
1580 testClose:
1581     if ( lpType[ i ] & PT_CLOSEFIGURE ) LineTo ( hdc, pp -> x, pp -> y );
1582          
1583   }  /* end switch */
1584
1585  }  /* end for */
1586
1587 }  /* end _RenderPath */
1588
1589 static int WINAPI _TextPath (
1590                    HDC hdc, int x, int y, void* str, LPPOINT lpPts, PBYTE lpType,
1591                    int nPts, PSIZE pSz, BOOL fWide
1592                   ) {
1593
1594  int retVal;
1595
1596  if ( lpPts == NULL ) {
1597
1598   int bmo = SetBkMode ( hdc, TRANSPARENT );
1599
1600    BeginPath ( hdc );
1601
1602     if ( !fWide )
1603
1604      TextOutA (   hdc,  x, y, ( char* )str, lstrlenA (  ( char* )str  )   );
1605
1606     else
1607
1608      TextOutW (   hdc,  x, y, ( wchar_t* )str, lstrlenW (  ( wchar_t* )str  )   );
1609
1610    EndPath ( hdc );
1611
1612   SetBkMode ( hdc, bmo );
1613
1614  }  /* end if */
1615
1616  retVal = GetPath ( hdc, lpPts, lpType, nPts );
1617
1618  if ( pSz != NULL )
1619
1620   if ( !fWide )
1621
1622    GetTextExtentPoint32A (   hdc, ( char* )str, lstrlenA (  ( char* )str  ), pSz   );
1623
1624   else
1625
1626    GetTextExtentPoint32W (   hdc, ( wchar_t* )str, lstrlenW (  ( wchar_t* )str  ), pSz   );
1627
1628  return retVal;
1629
1630 }  /* end _TextPath */
1631
1632 VOID CALLBACK ___auxDDAF ( int x, int y, LPARAM lpParam ) {
1633
1634  PDDAP p = ( PDDAP )lpParam;
1635
1636  p -> pp[ p -> _this -> myIDDA   ].x = x;
1637  p -> pp[ p -> _this -> myIDDA++ ].y = y;
1638
1639  if ( p -> _this -> myIDDA >= p -> _this -> myNDDA ) {
1640  
1641   p -> _this -> myDDA1 = ( PPOINT )HeapReAlloc (
1642                                GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1643                                p -> _this -> myDDA1, p -> _this -> myNDDA <<= 1
1644                               );
1645   p -> _this -> myDDA2 = ( PPOINT )HeapReAlloc (
1646                                     GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1647                                     p -> _this -> myDDA2, p -> _this -> myNDDA <<= 1
1648                                    );
1649
1650  }  // end if
1651
1652 }  // end ___auxDDAF
1653 //+++//
1654 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//