4 // Modifications: PLOTNIKOV Eugeny at July 1998 (BUC60286)
5 // Copyright: Matra Datavision 1998
12 #define ROUNDL( d ) ( LONG )( ( d ) + 0.5 )
13 #define Y( y ) ( mySize.cy - ( y ) )
15 typedef struct _fpoint {
22 typedef struct _ddap {
29 static void WINAPI _XFORMultiply ( PXFORM, PXFORM, PXFORM );
30 static void WINAPI _XFORMApply ( PPOINT, int, PXFORM );
31 static void WINAPI _XFORMApplyf ( PFPOINT, int, PXFORM );
33 static void WINAPI _RenderPath ( HDC, LPPOINT, PBYTE, int );
34 static int WINAPI _TextPath ( HDC, int, int, void*, LPPOINT, PBYTE, int, PSIZE, BOOL );
36 EHDC :: EHDC ( HDC hdc, PSIZE szClient ) {
40 SetDC ( hdc, szClient );
42 } // end EHDC constructor ( 1 )
48 } // end EHDC constructor ( 2 )
52 HANDLE hHeap = GetProcessHeap ();
54 if ( myHDC != NULL ) {
56 SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
57 SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
61 if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
62 if ( myTextPen != NULL ) DeletePen( myTextPen );
64 if ( myTextPath != NULL ) HeapFree (
68 if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) )
70 HeapFree ( hHeap, 0, ( LPVOID )myPStyle );
72 if ( myPBrush != NULL ) DeleteBrush( myPBrush );
73 if ( myPPen != NULL ) DeletePen( myPPen );
75 if ( myFlags & EHDCF_PPUSH ) {
77 if ( myPPenPush != NULL ) DeletePen( myPPenPush );
78 if ( myPBrushPush != NULL ) DeleteBrush( myPBrushPush );
82 HeapFree ( hHeap, 0, ( LPVOID )myDDA1 );
83 HeapFree ( hHeap, 0, ( LPVOID )myDDA2 );
85 } // end EHDC destructor
87 void EHDC :: SetDC ( HDC hdc, PSIZE szClient ) {
95 SelectPen( myHDC, myPPen );
96 SelectBrush( myHDC, myPBrush );
98 MoveToEx ( 0, 0, NULL );
101 } // end EHDC :: SetDC
103 HBRUSH EHDC :: SelectEPen (
105 CONST LOGBRUSH* lplb,
111 DWORD dwLen = dwStyleCount * sizeof ( DWORD );
113 if ( dwStyleCount ) {
117 if ( myPStyle == NULL ) {
119 myPStyle = ( PDWORD )HeapAlloc (
121 HEAP_GENERATE_EXCEPTIONS,
125 myPBS = dwStyleCount;
127 } else if ( myPBS < dwStyleCount ) {
129 myPStyle = ( PDWORD )HeapReAlloc (
131 HEAP_GENERATE_EXCEPTIONS,
139 CopyMemory ( myPStyle, lpStyle, dwLen );
140 myFlags |= EHDCF_SFREE;
142 } else if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) ) {
144 HeapFree ( GetProcessHeap (), 0, ( LPVOID )myPStyle );
153 myPNS = dwStyleCount;
155 if ( myPBrush != NULL ) {
159 GetObject ( myPBrush, sizeof ( LOGBRUSH ), &lb );
161 if ( lb.lbStyle != lplb -> lbStyle ||
162 lb.lbColor != lplb -> lbColor ||
163 lb.lbHatch != lplb -> lbHatch
166 SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
167 DeleteBrush( myPBrush );
169 myPBrush = CreateBrushIndirect ( lplb );
175 myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
176 myFlags &= ~EHDCF_JOIN;
178 } else myFlags &= ~EHDCF_EPEN;
180 } else goto newBrush;
182 if ( myPPen != NULL ) {
186 GetObject ( myPPen, sizeof ( LOGPEN ), &lp );
188 if ( lp.lopnColor != lplb -> lbColor ||
192 SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
195 myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor );
201 SelectPen( myHDC, myPPen );
203 return SelectBrush( myHDC, myPBrush );
205 } // end EHDC :: SelectEPen
207 void EHDC :: SelectEPen (
212 if ( dwWidth == 0xFFFFFFFF && ( myFlags & EHDCF_PPUSH ) ) {
214 SelectPen( myHDC, myPPenPush );
215 SelectBrush( myHDC, myPBrushPush );
217 DeleteBrush( myPBrush );
219 myFlags &= ~EHDCF_PPUSH;
221 myPBrush = myPBrushPush;
223 myFlags |= ( myfXpenPush ? EHDCF_EPEN : 0 );
225 } else if ( !( myFlags & EHDCF_PPUSH ) ){
227 myFlags |= EHDCF_PPUSH;
228 myfXpenPush = ( myFlags & EHDCF_EPEN );
230 myPBrushPush = myPBrush;
234 SelectBrush( myHDC, myPBrush = CreateBrushIndirect ( lplb ) );
235 SelectPen( myHDC, myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor ) );
239 myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
240 myFlags &= ~EHDCF_JOIN;
242 } else myFlags &= ~EHDCF_EPEN;
246 } // end EHDC :: SelectEPen
248 HPEN EHDC :: SelectEPen ( HPEN hPen ) {
252 if ( myHDC != NULL ) retVal = SelectPen( myHDC, hPen );
254 myFlags &= ~EHDCF_EPEN;
258 } // end EHDC :: SelectEPen
260 void EHDC :: SelectEBrush ( PLOGBRUSH lplb, PLOGBRUSH lplbo ) {
262 if ( lplb == NULL ) {
264 DeleteBrush( myBrush );
267 } else if ( myBrush != NULL ) {
271 GetObject ( myBrush, sizeof ( LOGBRUSH ), &lb );
273 if ( lplbo != NULL ) *lplbo = lb;
275 if ( lb.lbStyle != lplb -> lbStyle ||
276 lb.lbColor != lplb -> lbColor ||
277 lb.lbHatch != lplb -> lbHatch
280 DeleteBrush( myBrush );
282 myBrush = CreateBrushIndirect ( lplb );
286 } else goto newBrush;
288 } // end EHDC :: SelectEBrush
290 void EHDC :: SetMiter ( BOOL fMiter ) {
294 myFlags &= ~EHDCF_JBEVL;
298 myFlags |= EHDCF_JBEVL;
300 } // end EHDC :: SetMiter
302 void EHDC :: MoveToEx ( int x, int y, LPPOINT lpPoint ) {
304 if ( lpPoint != NULL ) *lpPoint = myStart;
309 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &myStart, 1, &myXform );
311 myStart.y = Y( myStart.y );
312 Register ( &myStart, 1 );
314 ::MoveToEx ( myHDC, myStart.x, myStart.y, NULL );
318 myFlags &= ~EHDCF_JOIN;
319 myFlags |= ( EHDCF_PDRAW | EHDCF_DDAF );
323 } // end EHDC :: MoveToEx
325 BOOL EHDC :: LineTo ( int x, int y ) {
329 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
333 if ( myFlags & EHDCF_EPEN ) {
339 else if ( !_DrawToEx ( &p ) ) return FALSE;
341 if ( myFlags & EHDCF_CJOIN ) {
343 myFlags &= ~EHDCF_CJOIN;
348 if ( myFlags & EHDCF_JOIN )
356 if ( myFlags & EHDCF_PDRAW && !( myFlags & EHDCF_NJOIN ) )
358 myFlags |= EHDCF_JOIN;
362 myFlags &= ~( EHDCF_JOIN | EHDCF_NJOIN );
364 } else if ( myPNS == 0 ) {
368 ::LineTo ( myHDC, p.x, p.y );
372 } else _LineTo ( &p );
376 } // end EHDC :: LineTo
378 void EHDC :: ClosePath ( void ) {
383 DWORD dw = ( myFlags & EHDCF_XFORM );
385 myFlags &= ~EHDCF_XFORM;
387 if ( myStart.x != myClose.x ||
388 myStart.y != myClose.y
391 ltf = LineTo ( myClose.x, Y( myClose.y ) );
395 if ( ltf && ( myFlags & EHDCF_PDRAW ) && ( myFlags & EHDCF_EPEN ) ) {
405 } else myFlags |= dw;
407 myFlags &= ~EHDCF_JOIN;
409 myFlags |= ( EHDCF_PDRAW | EHDCF_CJOIN );
412 } // end EHDC :: ClosePath
414 void EHDC :: Polyline ( CONST POINT* lpPts, int nPts, BOOL fClose ) {
416 DWORD dwPIndex = myPIndex;
417 DWORD dwPRlen = myPRlen;
418 DWORD dwFlags = myFlags;
421 POINT pClose = myClose;
422 POINT pJoin = myJoin;
423 POINT pCJoin = myCJoin;
426 myFlags |= EHDCF_CJOIN;
428 MoveToEx ( lpPts -> x, lpPts -> y, &pStart );
430 for ( int i = 1; i < nPts; ++i )
432 LineTo ( lpPts[ i ].x, lpPts[ i ].y );
434 if ( fClose ) ClosePath ();
446 } // end EHDC :: Polyline
448 void EHDC :: Polygon ( CONST POINT* lpPts, int nPts, DWORD dwFlags ) {
451 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
452 HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
459 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
461 ::MoveToEx ( myHDC, p.x, Y( p.y ), NULL );
463 for ( int i = 1; i < nPts; ++i ) {
468 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
470 ::LineTo ( myHDC, p.x, Y( p.y ) );
474 CloseFigure ( myHDC );
480 SelectBrush( myHDC, hbo );
481 SelectPen( myHDC, hpo );
483 if ( dwFlags & POLYF_NOCLOSEDGE )
485 Polyline ( lpPts, nPts, FALSE );
487 else if ( !( dwFlags & POLYF_NOEDGE ) )
489 Polyline ( lpPts, nPts, TRUE );
491 } // end EHDC :: Polygon
494 int x, int y, int xr, int yr, double sa, double oa, DWORD dwAFlags
500 BOOL fXform = ( myFlags & EHDCF_XFORM );
501 DWORD dwPIndex = myPIndex;
502 DWORD dwPRlen = myPRlen;
503 DWORD dwFlags = myFlags;
506 POINT pClose = myClose;
507 POINT pJoin = myJoin;
508 POINT pCJoin = myCJoin;
509 POINT pStart = myStart;
511 myFlags &= ~EHDCF_XFORM;
517 else if ( oa < -6.28318 )
521 n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
524 fp[ i ].x = ( FLOAT )x;
525 fp[ i++ ].y = ( FLOAT )y;
528 for ( ; i < n; ++i, sa += delta ) {
530 fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
531 fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
535 if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
539 if ( dwAFlags & ARCF_PIE ) {
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 ) );
547 if ( i >= n ) goto end;
549 LineTo ( ROUNDL( fp[ i ].x ), ROUNDL( fp[ i ].y ) );
555 MoveToEx ( ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y ), NULL );
560 myFlags |= EHDCF_JBEVL;
562 for ( j = i - 1; i < n; ++i ) {
564 x = ROUNDL( fp[ i ].x );
565 y = ROUNDL( fp[ i ].y );
567 if ( x == ROUNDL( fp[ j ].x ) && y == ROUNDL( fp[ j ].y ) ) continue;
574 if ( dwAFlags & ( ARCF_PIE | ARCF_CHORD ) || fabs ( oa ) == 6.28318 ) {
576 myFlags &= ~EHDCF_JBEVL;
593 void EHDC :: Polyarc (
594 int x, int y, int xr, int yr, double sa, double oa, BOOL fChord
598 double ssa = sa, delta;
600 BOOL fXform = ( myFlags & EHDCF_XFORM );
606 else if ( oa < -6.28318 )
610 n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
613 fp[ i ].x = ( FLOAT )x;
614 fp[ i++ ].y = ( FLOAT )y;
617 for ( ; i < n; ++i, sa += delta ) {
619 fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
620 fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
624 if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
628 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
629 HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
637 ROUNDL( fp[ 0 ].x ), Y( ROUNDL( fp[ 0 ].y ) ), NULL
641 ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) )
646 if ( i >= n ) goto end;
650 ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
657 ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) ), NULL
663 for ( ; i < n; ++i ) ::LineTo (
665 ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
668 CloseFigure ( myHDC );
674 SelectBrush( myHDC, hbo );
675 SelectPen( myHDC, hpo );
677 Arc ( x, y, xr, yr, ssa, oa, fChord ? ARCF_CHORD : ARCF_PIE );
679 } // end EHDC :: Polyarc
681 void EHDC :: SetPixel ( int x, int y, COLORREF c ) {
685 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
689 ::SetPixel ( myHDC, p.x, p.y, c );
691 } // end EHDC :: SetPixel
693 void EHDC :: SetTextColor ( COLORREF c ) {
697 GetObject ( myTextPen, sizeof ( LOGPEN ), &lp );
699 if ( lp.lopnColor != c ) {
701 LOGBRUSH lb = { BS_SOLID, c, 0 };
703 if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
704 if ( myTextPen != NULL ) DeletePen( myTextPen );
706 myTextPen = CreatePen ( PS_SOLID, 0, c );
707 myTextBrush = CreateBrushIndirect ( &lb );
711 } // end EHDC :: SetTextColor
713 void EHDC :: SetTextAttrib ( COLORREF c, HFONT f, double slant, double hs, double vs ) {
722 } // end EHDC :: SetTextAttrib
724 void EHDC :: ETextOut ( int x, int y, char* str, double angle, BOOL fOutline ) {
726 _ETextOut ( x, y, str, angle, fOutline );
728 } // end EHDC :: TextOut
730 void EHDC :: ETextOut ( int x, int y, wchar_t* str, double angle, BOOL fOutline ) {
732 _ETextOut ( x, y, str, angle, fOutline, TRUE );
734 } // end EHDC :: TextOut
736 void EHDC :: PolyTextOut (
737 int x, int y, char* str, double angle,
738 double margin, BOOL fOutline, BOOL fNofill, BOOL fNoframe
741 _PolyTextOut ( x, y, str, angle, margin, fOutline, FALSE, fNofill, fNoframe );
743 } // end EHDC :: PolyTextOut
745 void EHDC :: PolyTextOut (
746 int x, int y, wchar_t* str, double angle, double margin,
747 BOOL fOutline, BOOL fNofill, BOOL fNoframe
750 _PolyTextOut ( x, y, str, angle, margin, fOutline, TRUE, fNofill, fNoframe );
752 } // end EHDC :: PolyTextOut
754 void EHDC :: SetWorldTransform ( XFORM* xf ) {
758 myFlags &= ~EHDCF_XFORM;
763 myFlags |= EHDCF_XFORM;
767 } // end EHDC :: SetWorldTransform
769 void EHDC :: ModifyWorldTransform ( XFORM* xf, DWORD iMode ) {
775 if ( iMode == MWT_RIGHTMULTIPLY ) {
780 } else if ( iMode == MWT_LEFTMULTIPLY ) {
785 } else if ( iMode == MWT_IDENTITY ) {
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;
791 myFlags &= ~EHDCF_XFORM;
797 _XFORMultiply ( &rxf, pxfLeft, pxfRight );
800 myFlags |= EHDCF_XFORM;
802 } // end EHDC :: ModifyWorldTransform
804 void EHDC :: Transform ( LPPOINT p, int n ) {
806 _XFORMApply ( p, n, &myXform );
810 void EHDC :: ResetURect ( void ) {
812 myURect.left = LONG_MAX;
813 myURect.top = LONG_MAX;
814 myURect.right = LONG_MIN;
815 myURect.bottom = LONG_MIN;
817 } // end EHDC :: ResetURect
819 void EHDC :: GetURect ( LPRECT lpRect ) {
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;
828 } // end EHDC :: GetURect
830 void EHDC :: _Init ( void ) {
832 myTextPen = ( HPEN )GetStockObject ( WHITE_PEN );
833 myTextBrush = ( HBRUSH )GetStockObject ( WHITE_BRUSH );
838 myBrush = myTextBrush;
848 myDDA1 = ( PPOINT )HeapAlloc (
849 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
850 sizeof ( POINT ) * myNDDA
852 myDDA2 = ( PPOINT )HeapAlloc (
853 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
854 sizeof ( POINT ) * myNDDA
858 ModifyWorldTransform ( NULL, MWT_IDENTITY );
859 myFlags &= ~EHDCF_XFORM;
861 } // end EHDC :: _Init
863 void EHDC :: _DrawTo ( PPOINT p ) {
866 double dx, dy, dxhw, dyhw, factor;
868 dx = ( double )( p -> x - myStart.x );
869 dy = ( double )( p -> y - myStart.y );
871 if ( dx == 0.0 && dy == 0.0 ) return;
873 factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
877 ip[ 0 ].x = ROUNDL( myStart.x + dxhw );
878 ip[ 0 ].y = ROUNDL( myStart.y - dyhw );
880 ip[ 1 ].x = ROUNDL( p -> x + dxhw );
881 ip[ 1 ].y = ROUNDL( p -> y - dyhw );
883 ip[ 2 ].x = ROUNDL( p -> x - dxhw );
884 ip[ 2 ].y = ROUNDL( p -> y + dyhw );
886 ip[ 3 ].x = ROUNDL( myStart.x - dxhw );
887 ip[ 3 ].y = ROUNDL( myStart.y + dyhw );
891 ::Polygon ( myHDC, ip, 4 );
897 } // end EHDC :: _DrawTo
899 void EHDC :: _Join ( void ) {
903 double r, ba, bc, dxba, dyba, dxbc, dybc,
904 s, sa, fc, xd, yd, xe, ye,
906 n2, rm1, rm2, rn1, rn2;
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 );
914 if ( ba == 0.0 || bc == 0.0 ) return;
916 n1 = -dxba / ba; n2 = dyba / ba;
917 m1 = -dxbc / bc; m2 = dybc / bc;
918 s = m1 * n2 - n1 * m2;
920 if ( ( sa = fabs ( s ) ) < 0.001 ) return;
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;
930 xe = myB.x - rm2; ye = myB.y - rm1;
931 xf = myB.x + rn2; yf = myB.y + rn1;
933 } else if ( s < 0.0 ) {
935 xe = myB.x + rm2; ye = myB.y + rm1;
936 xf = myB.x - rn2; yf = myB.y - rn1;
941 p[ 1 ].x = ROUNDL( xf ); p[ 1 ].y = ROUNDL( yf );
943 if ( !( myFlags & EHDCF_JBEVL ) ) {
945 p[ 2 ].x = ROUNDL( xd ); p[ 2 ].y = ROUNDL( yd );
946 p[ 3 ].x = ROUNDL( xe ); p[ 3 ].y = ROUNDL( ye );
951 p[ 2 ].x = ROUNDL( xe ); p[ 2 ].y = ROUNDL( ye );
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 ) );
963 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
964 ::Polygon ( myHDC, p, np );
965 SelectPen( myHDC, hpo );
967 } // end EHDC :: _Join
969 BOOL EHDC :: _DrawToEx ( PPOINT p ) {
972 DDAP ddap = { this };
974 double dx, dy, dxhw, dyhw, factor;
976 dx = ( double )( p -> x - myStart.x );
977 dy = ( double )( p -> y - myStart.y );
979 if ( dx == 0.0 && dy == 0.0 ) return FALSE;
981 factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
985 pp[ 0 ].x = ROUNDL( myStart.x + dxhw );
986 pp[ 0 ].y = ROUNDL( myStart.y - dyhw );
988 pp[ 1 ].x = ROUNDL( myStart.x - dxhw );
989 pp[ 1 ].y = ROUNDL( myStart.y + dyhw );
991 pp[ 2 ].x = ROUNDL( p -> x - dxhw );
992 pp[ 2 ].y = ROUNDL( p -> y + dyhw );
994 pp[ 3 ].x = ROUNDL( p -> x + dxhw );
995 pp[ 3 ].y = ROUNDL( p -> y - dyhw );
998 myFlags &= ~EHDCF_DDAF;
1000 LineDDA ( pp[ 0 ].x, pp[ 0 ].y, pp[ 3 ].x, pp[ 3 ].y, &___auxDDAF, ( LPARAM )&ddap );
1003 myFlags &= ~EHDCF_DDAF;
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 ) );
1011 if ( myPRlen == 0 ) {
1013 myPRlen = myPStyle[ myPIndex++ ];
1015 if ( myPIndex == myPNS ) myPIndex = 0;
1021 while ( myPRlen != 0 && j < myIDDA ) ++j, --myPRlen;
1023 if ( j == myIDDA ) {
1025 myDDA1[ j ] = pp[ 3 ];
1026 myDDA2[ j ] = pp[ 2 ];
1030 if ( myFlags & EHDCF_PDRAW ) {
1034 p[ 0 ] = myDDA1[ i ];
1035 p[ 1 ] = myDDA1[ j ];
1036 p[ 2 ] = myDDA2[ j ];
1037 p[ 3 ] = myDDA2[ i ];
1040 ::Polygon ( myHDC, p, 4 );
1046 myFlags ^= EHDCF_PDRAW;
1052 if ( j >= myIDDA ) break;
1056 SelectPen( myHDC, hpo );
1058 if ( myPRlen == 0 ) myFlags |= EHDCF_NJOIN;
1066 } // end EHDC :: _DrawToEx
1068 void EHDC :: _LineTo ( PPOINT p ) {
1071 DDAP ddap = { this };
1077 LineDDA ( myStart.x, myStart.y, p -> x, p -> y, &___auxDDAF, ( LPARAM )&ddap );
1081 if ( myPRlen == 0 ) {
1083 myPRlen = myPStyle[ myPIndex++ ];
1085 if ( myPIndex == myPNS ) myPIndex = 0;
1089 if ( myFlags & EHDCF_PDRAW ) ::MoveToEx ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y, NULL );
1091 while ( myPRlen != 0 && i < myIDDA ) ++i, --myPRlen;
1093 if ( i == myIDDA ) myDDA1[ i ] = *p;
1095 if ( myFlags & EHDCF_PDRAW )
1097 ::LineTo ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y );
1101 myFlags ^= EHDCF_PDRAW;
1109 } // end EHDC :: _LineTo
1111 void EHDC :: _ETextOut ( int x, int y, void* str, double angle, BOOL fOutline, BOOL fWide ) {
1118 XFORM lXfm, rXfm, xfm;
1127 tanVal = tan ( myTextSlant ) * myTextVScale;
1128 sinVal = sin ( angle );
1129 cosVal = cos ( angle );
1131 if ( !( myFlags & EHDCF_TPATH ) ) {
1133 hfo = SelectFont( myHDC, myTextFont );
1135 i = myTextNP = _TextPath (
1136 myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1139 SelectFont( myHDC, hfo );
1141 if ( i <= 0 ) return;
1143 if ( myTextBS < myTextNP ) {
1145 dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1147 if ( myTextPath == NULL )
1149 myTextPath = ( LPPOINT )HeapAlloc (
1151 HEAP_GENERATE_EXCEPTIONS, dwLen
1156 myTextPath = ( LPPOINT )HeapReAlloc (
1158 HEAP_GENERATE_EXCEPTIONS,
1162 myTextBS = myTextNP;
1166 myTextType = ( PBYTE )( myTextPath + myTextNP );
1168 _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1181 lXfm.eM11 = ( FLOAT )myTextHScale; lXfm.eM21 = ( FLOAT )-tanVal;
1182 lXfm.eM12 = 0.0F; lXfm.eM22 = ( FLOAT )myTextVScale;
1186 rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1187 rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1190 _XFORMultiply ( &xfm, &lXfm, &rXfm );
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 );
1198 if ( myFlags & EHDCF_XFORM ) {
1200 _XFORMultiply ( &xfm, &lXfm, &myXform );
1203 } else pXfm = &lXfm;
1205 _XFORMApply ( myTextPath, myTextNP, pXfm );
1210 while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1212 hpo = SelectPen( myHDC, myTextPen );
1214 if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1216 if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
1218 BeginPath ( myHDC );
1219 _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1225 SelectBrush( myHDC, hbo );
1227 } else StrokePath ( myHDC );
1229 SelectPen( myHDC, hpo );
1236 XFORM lXfm, rXfm, xfm;
1246 tanVal = tan ( myTextSlant );
1247 sinVal = sin ( angle );
1248 cosVal = cos ( angle );
1250 if ( !( myFlags & EHDCF_TPATH ) ) {
1252 hfo = SelectFont( myHDC, myTextFont );
1254 if ( myTextVScale != 1.0 || myTextHScale != 1.0 ) {
1259 GetObject ( myTextFont, sizeof ( LOGFONT ), &lf );
1260 GetTextMetrics ( myHDC, &tm );
1262 lf.lfHeight = ROUNDL( lf.lfHeight * myTextVScale );
1263 lf.lfWidth = ROUNDL( lf.lfWidth * myTextHScale );
1265 lf.lfQuality = DRAFT_QUALITY;
1267 if ( lf.lfWidth == 0 )
1269 lf.lfWidth = ROUNDL( tm.tmAveCharWidth * myTextHScale );
1271 SelectFont( myHDC, hfo );
1273 hfo = SelectFont( myHDC, CreateFontIndirect ( &lf ) );
1278 i = myTextNP = _TextPath (
1279 myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1282 hfo = SelectFont( myHDC, hfo );
1284 if ( fNew ) DeleteFont( hfo );
1286 if ( i <= 0 ) return;
1288 if ( myTextBS < myTextNP ) {
1290 dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1292 if ( myTextPath == NULL )
1294 myTextPath = ( LPPOINT )HeapAlloc (
1296 HEAP_GENERATE_EXCEPTIONS, dwLen
1301 myTextPath = ( LPPOINT )HeapReAlloc (
1303 HEAP_GENERATE_EXCEPTIONS,
1307 myTextBS = myTextNP;
1311 myTextType = ( PBYTE )( myTextPath + myTextNP );
1313 _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1326 lXfm.eM11 = 1.0F; lXfm.eM21 = ( FLOAT )-tanVal;
1327 lXfm.eM12 = 0.0F; lXfm.eM22 = 1.0F;
1331 rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1332 rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1335 _XFORMultiply ( &xfm, &lXfm, &rXfm );
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 );
1343 if ( myFlags & EHDCF_XFORM ) {
1345 _XFORMultiply ( &xfm, &lXfm, &myXform );
1348 } else pXfm = &lXfm;
1350 _XFORMApply ( myTextPath, myTextNP, pXfm );
1355 while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1357 hpo = SelectPen( myHDC, myTextPen );
1359 if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1361 if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
1363 BeginPath ( myHDC );
1364 _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1370 SelectBrush( myHDC, hbo );
1372 } else StrokePath ( myHDC );
1374 SelectPen( myHDC, hpo );
1376 } // end EHDC :: _ETextOut
1378 void EHDC :: _PolyTextOut (
1379 int x, int y, void* str, double angle, double margin,
1380 BOOL fOutline, BOOL fWide, BOOL fNofill, BOOL fNoframe
1390 double sinVal = sin ( angle );
1391 double cosVal = cos ( angle );
1392 double tanVal = -tan ( myTextSlant );
1395 hfo = SelectFont( myHDC, myTextFont );
1399 GetTextExtentPoint32A (
1400 myHDC, ( char* )str, lstrlenA ( ( char* )str ), &sz
1405 GetTextExtentPoint32W (
1406 myHDC, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), &sz
1409 GetTextMetrics ( myHDC, &tm );
1410 SelectFont( myHDC, hfo );
1412 sz.cy -= tm.tmInternalLeading;
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;
1425 if ( myTextSlant < 0.0F ) {
1427 p[ 0 ].x -= ( LONG )tanVal;
1428 p[ 3 ].x -= ( LONG )tanVal;
1432 p[ 1 ].x -= ( LONG )tanVal;
1433 p[ 2 ].x -= ( LONG )tanVal;
1437 height = ROUNDL( p[ 0 ].y * margin / 2.0 );
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 );
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;
1453 if ( myFlags & EHDCF_XFORM ) {
1455 _XFORMultiply ( &xfm, &lXfm, &myXform );
1458 } else pXfm = &lXfm;
1460 _XFORMApply ( p, 4, pXfm );
1462 dwFlags = ( myFlags & EHDCF_XFORM );
1463 myFlags &= ~EHDCF_XFORM;
1467 Polyline ( p, 4, TRUE );
1471 Polygon ( p, 4, fNoframe ? POLYF_NOEDGE : 0 );
1475 _ETextOut ( x, y, str, angle, fOutline, fWide );
1477 } // end EHDC :: _PolyTextOut
1479 void EHDC :: Register ( LPPOINT lpPts, int nPts ) {
1483 if ( lpPts -> x < myURect.left )
1485 myURect.left = lpPts -> x - 1;
1487 else if ( lpPts -> x > myURect.right )
1489 myURect.right = lpPts -> x + 2;
1491 if ( lpPts -> y < myURect.top )
1493 myURect.top = lpPts -> y - 1;
1495 else if ( lpPts -> y > myURect.bottom )
1497 myURect.bottom = lpPts -> y + 2;
1503 } // end EHDC :: _Register
1505 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1507 static void WINAPI _XFORMultiply ( PXFORM res, PXFORM left, PXFORM right ) {
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;
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;
1517 } /* end _XFORMultiply */
1519 static void WINAPI _XFORMApply ( PPOINT pp, int n, PXFORM xf ) {
1524 for ( i = 0; i < n; ++i ) {
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;
1529 pp[ i ].x = ROUNDL( dx );
1530 pp[ i ].y = ROUNDL( dy );
1534 } /* end _XFORMApply */
1536 static void WINAPI _XFORMApplyf ( PFPOINT pp, int n, PXFORM xf ) {
1541 for ( i = 0; i < n; ++i ) {
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;
1546 pp[ i ].x = ( FLOAT )dx;
1547 pp[ i ].y = ( FLOAT )dy;
1551 } /* end _XFORMApply */
1553 static void WINAPI _RenderPath ( HDC hdc, LPPOINT lpPts, PBYTE lpType, int nPts ) {
1557 for ( int i = 0; i < nPts; ++i ) {
1559 switch ( lpType[ i ] ) {
1563 MoveToEx ( hdc, lpPts[ i ].x, lpPts[ i ].y, NULL );
1569 case PT_LINETO | PT_CLOSEFIGURE:
1571 LineTo ( hdc, lpPts[ i ].x, lpPts[ i ].y );
1575 case PT_BEZIERTO | PT_CLOSEFIGURE:
1577 PolyBezierTo ( hdc, &lpPts[ i ], 3 );
1581 if ( lpType[ i ] & PT_CLOSEFIGURE ) LineTo ( hdc, pp -> x, pp -> y );
1587 } /* end _RenderPath */
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
1596 if ( lpPts == NULL ) {
1598 int bmo = SetBkMode ( hdc, TRANSPARENT );
1604 TextOutA ( hdc, x, y, ( char* )str, lstrlenA ( ( char* )str ) );
1608 TextOutW ( hdc, x, y, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ) );
1612 SetBkMode ( hdc, bmo );
1616 retVal = GetPath ( hdc, lpPts, lpType, nPts );
1622 GetTextExtentPoint32A ( hdc, ( char* )str, lstrlenA ( ( char* )str ), pSz );
1626 GetTextExtentPoint32W ( hdc, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), pSz );
1630 } /* end _TextPath */
1632 VOID CALLBACK ___auxDDAF ( int x, int y, LPARAM lpParam ) {
1634 PDDAP p = ( PDDAP )lpParam;
1636 p -> pp[ p -> _this -> myIDDA ].x = x;
1637 p -> pp[ p -> _this -> myIDDA++ ].y = y;
1639 if ( p -> _this -> myIDDA >= p -> _this -> myNDDA ) {
1641 p -> _this -> myDDA1 = ( PPOINT )HeapReAlloc (
1642 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1643 p -> _this -> myDDA1, p -> _this -> myNDDA <<= 1
1645 p -> _this -> myDDA2 = ( PPOINT )HeapReAlloc (
1646 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1647 p -> _this -> myDDA2, p -> _this -> myNDDA <<= 1
1654 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//