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