1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
19 // Modifications: PLOTNIKOV Eugeny at July 1998 (BUC60286)
26 #define ROUNDL( d ) ( LONG )( ( d ) + 0.5 )
27 #define Y( y ) ( mySize.cy - ( y ) )
29 typedef struct _fpoint {
36 typedef struct _ddap {
43 static void WINAPI _XFORMultiply ( PXFORM, PXFORM, PXFORM );
44 static void WINAPI _XFORMApply ( PPOINT, int, PXFORM );
45 static void WINAPI _XFORMApplyf ( PFPOINT, int, PXFORM );
47 static void WINAPI _RenderPath ( HDC, LPPOINT, PBYTE, int );
48 static int WINAPI _TextPath ( HDC, int, int, void*, LPPOINT, PBYTE, int, PSIZE, BOOL );
50 EHDC :: EHDC ( HDC hdc, PSIZE szClient ) {
54 SetDC ( hdc, szClient );
56 } // end EHDC constructor ( 1 )
62 } // end EHDC constructor ( 2 )
66 HANDLE hHeap = GetProcessHeap ();
68 if ( myHDC != NULL ) {
70 SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
71 SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
75 if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
76 if ( myTextPen != NULL ) DeletePen( myTextPen );
78 if ( myTextPath != NULL ) HeapFree (
82 if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) )
84 HeapFree ( hHeap, 0, ( LPVOID )myPStyle );
86 if ( myPBrush != NULL ) DeleteBrush( myPBrush );
87 if ( myPPen != NULL ) DeletePen( myPPen );
89 if ( myFlags & EHDCF_PPUSH ) {
91 if ( myPPenPush != NULL ) DeletePen( myPPenPush );
92 if ( myPBrushPush != NULL ) DeleteBrush( myPBrushPush );
96 HeapFree ( hHeap, 0, ( LPVOID )myDDA1 );
97 HeapFree ( hHeap, 0, ( LPVOID )myDDA2 );
99 } // end EHDC destructor
101 void EHDC :: SetDC ( HDC hdc, PSIZE szClient ) {
109 SelectPen( myHDC, myPPen );
110 SelectBrush( myHDC, myPBrush );
112 MoveToEx ( 0, 0, NULL );
115 } // end EHDC :: SetDC
117 HBRUSH EHDC :: SelectEPen (
119 CONST LOGBRUSH* lplb,
125 DWORD dwLen = dwStyleCount * sizeof ( DWORD );
127 if ( dwStyleCount ) {
131 if ( myPStyle == NULL ) {
133 myPStyle = ( PDWORD )HeapAlloc (
135 HEAP_GENERATE_EXCEPTIONS,
139 myPBS = dwStyleCount;
141 } else if ( myPBS < dwStyleCount ) {
143 myPStyle = ( PDWORD )HeapReAlloc (
145 HEAP_GENERATE_EXCEPTIONS,
153 CopyMemory ( myPStyle, lpStyle, dwLen );
154 myFlags |= EHDCF_SFREE;
156 } else if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) ) {
158 HeapFree ( GetProcessHeap (), 0, ( LPVOID )myPStyle );
167 myPNS = dwStyleCount;
169 if ( myPBrush != NULL ) {
173 GetObject ( myPBrush, sizeof ( LOGBRUSH ), &lb );
175 if ( lb.lbStyle != lplb -> lbStyle ||
176 lb.lbColor != lplb -> lbColor ||
177 lb.lbHatch != lplb -> lbHatch
180 SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
181 DeleteBrush( myPBrush );
183 myPBrush = CreateBrushIndirect ( lplb );
189 myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
190 myFlags &= ~EHDCF_JOIN;
192 } else myFlags &= ~EHDCF_EPEN;
194 } else goto newBrush;
196 if ( myPPen != NULL ) {
200 GetObject ( myPPen, sizeof ( LOGPEN ), &lp );
202 if ( lp.lopnColor != lplb -> lbColor ||
206 SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
209 myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor );
215 SelectPen( myHDC, myPPen );
217 return SelectBrush( myHDC, myPBrush );
219 } // end EHDC :: SelectEPen
221 void EHDC :: SelectEPen (
226 if ( dwWidth == 0xFFFFFFFF && ( myFlags & EHDCF_PPUSH ) ) {
228 SelectPen( myHDC, myPPenPush );
229 SelectBrush( myHDC, myPBrushPush );
231 DeleteBrush( myPBrush );
233 myFlags &= ~EHDCF_PPUSH;
235 myPBrush = myPBrushPush;
237 myFlags |= ( myfXpenPush ? EHDCF_EPEN : 0 );
239 } else if ( !( myFlags & EHDCF_PPUSH ) ){
241 myFlags |= EHDCF_PPUSH;
242 myfXpenPush = ( myFlags & EHDCF_EPEN );
244 myPBrushPush = myPBrush;
248 SelectBrush( myHDC, myPBrush = CreateBrushIndirect ( lplb ) );
249 SelectPen( myHDC, myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor ) );
253 myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
254 myFlags &= ~EHDCF_JOIN;
256 } else myFlags &= ~EHDCF_EPEN;
260 } // end EHDC :: SelectEPen
262 HPEN EHDC :: SelectEPen ( HPEN hPen ) {
266 if ( myHDC != NULL ) retVal = SelectPen( myHDC, hPen );
268 myFlags &= ~EHDCF_EPEN;
272 } // end EHDC :: SelectEPen
274 void EHDC :: SelectEBrush ( PLOGBRUSH lplb, PLOGBRUSH lplbo ) {
276 if ( lplb == NULL ) {
278 DeleteBrush( myBrush );
281 } else if ( myBrush != NULL ) {
285 GetObject ( myBrush, sizeof ( LOGBRUSH ), &lb );
287 if ( lplbo != NULL ) *lplbo = lb;
289 if ( lb.lbStyle != lplb -> lbStyle ||
290 lb.lbColor != lplb -> lbColor ||
291 lb.lbHatch != lplb -> lbHatch
294 DeleteBrush( myBrush );
296 myBrush = CreateBrushIndirect ( lplb );
300 } else goto newBrush;
302 } // end EHDC :: SelectEBrush
304 void EHDC :: SetMiter ( BOOL fMiter ) {
308 myFlags &= ~EHDCF_JBEVL;
312 myFlags |= EHDCF_JBEVL;
314 } // end EHDC :: SetMiter
316 void EHDC :: MoveToEx ( int x, int y, LPPOINT lpPoint ) {
318 if ( lpPoint != NULL ) *lpPoint = myStart;
323 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &myStart, 1, &myXform );
325 myStart.y = Y( myStart.y );
326 Register ( &myStart, 1 );
328 ::MoveToEx ( myHDC, myStart.x, myStart.y, NULL );
332 myFlags &= ~EHDCF_JOIN;
333 myFlags |= ( EHDCF_PDRAW | EHDCF_DDAF );
337 } // end EHDC :: MoveToEx
339 BOOL EHDC :: LineTo ( int x, int y ) {
343 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
347 if ( myFlags & EHDCF_EPEN ) {
353 else if ( !_DrawToEx ( &p ) ) return FALSE;
355 if ( myFlags & EHDCF_CJOIN ) {
357 myFlags &= ~EHDCF_CJOIN;
362 if ( myFlags & EHDCF_JOIN )
370 if ( myFlags & EHDCF_PDRAW && !( myFlags & EHDCF_NJOIN ) )
372 myFlags |= EHDCF_JOIN;
376 myFlags &= ~( EHDCF_JOIN | EHDCF_NJOIN );
378 } else if ( myPNS == 0 ) {
382 ::LineTo ( myHDC, p.x, p.y );
386 } else _LineTo ( &p );
390 } // end EHDC :: LineTo
392 void EHDC :: ClosePath ( void ) {
397 DWORD dw = ( myFlags & EHDCF_XFORM );
399 myFlags &= ~EHDCF_XFORM;
401 if ( myStart.x != myClose.x ||
402 myStart.y != myClose.y
405 ltf = LineTo ( myClose.x, Y( myClose.y ) );
409 if ( ltf && ( myFlags & EHDCF_PDRAW ) && ( myFlags & EHDCF_EPEN ) ) {
419 } else myFlags |= dw;
421 myFlags &= ~EHDCF_JOIN;
423 myFlags |= ( EHDCF_PDRAW | EHDCF_CJOIN );
426 } // end EHDC :: ClosePath
428 void EHDC :: Polyline ( CONST POINT* lpPts, int nPts, BOOL fClose ) {
430 DWORD dwPIndex = myPIndex;
431 DWORD dwPRlen = myPRlen;
432 DWORD dwFlags = myFlags;
435 POINT pClose = myClose;
436 POINT pJoin = myJoin;
437 POINT pCJoin = myCJoin;
440 myFlags |= EHDCF_CJOIN;
442 MoveToEx ( lpPts -> x, lpPts -> y, &pStart );
444 for ( int i = 1; i < nPts; ++i )
446 LineTo ( lpPts[ i ].x, lpPts[ i ].y );
448 if ( fClose ) ClosePath ();
460 } // end EHDC :: Polyline
462 void EHDC :: Polygon ( CONST POINT* lpPts, int nPts, DWORD dwFlags ) {
465 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
466 HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
473 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
475 ::MoveToEx ( myHDC, p.x, Y( p.y ), NULL );
477 for ( int i = 1; i < nPts; ++i ) {
482 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
484 ::LineTo ( myHDC, p.x, Y( p.y ) );
488 CloseFigure ( myHDC );
494 SelectBrush( myHDC, hbo );
495 SelectPen( myHDC, hpo );
497 if ( dwFlags & POLYF_NOCLOSEDGE )
499 Polyline ( lpPts, nPts, FALSE );
501 else if ( !( dwFlags & POLYF_NOEDGE ) )
503 Polyline ( lpPts, nPts, TRUE );
505 } // end EHDC :: Polygon
508 int x, int y, int xr, int yr, double sa, double oa, DWORD dwAFlags
514 BOOL fXform = ( myFlags & EHDCF_XFORM );
515 DWORD dwPIndex = myPIndex;
516 DWORD dwPRlen = myPRlen;
517 DWORD dwFlags = myFlags;
520 POINT pClose = myClose;
521 POINT pJoin = myJoin;
522 POINT pCJoin = myCJoin;
523 POINT pStart = myStart;
525 myFlags &= ~EHDCF_XFORM;
531 else if ( oa < -6.28318 )
535 n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
538 fp[ i ].x = ( FLOAT )x;
539 fp[ i++ ].y = ( FLOAT )y;
542 for ( ; i < n; ++i, sa += delta ) {
544 fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
545 fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
549 if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
553 if ( dwAFlags & ARCF_PIE ) {
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 ) );
561 if ( i >= n ) goto end;
563 LineTo ( ROUNDL( fp[ i ].x ), ROUNDL( fp[ i ].y ) );
569 MoveToEx ( ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y ), NULL );
574 myFlags |= EHDCF_JBEVL;
576 for ( j = i - 1; i < n; ++i ) {
578 x = ROUNDL( fp[ i ].x );
579 y = ROUNDL( fp[ i ].y );
581 if ( x == ROUNDL( fp[ j ].x ) && y == ROUNDL( fp[ j ].y ) ) continue;
588 if ( dwAFlags & ( ARCF_PIE | ARCF_CHORD ) || fabs ( oa ) == 6.28318 ) {
590 myFlags &= ~EHDCF_JBEVL;
607 void EHDC :: Polyarc (
608 int x, int y, int xr, int yr, double sa, double oa, BOOL fChord
612 double ssa = sa, delta;
614 BOOL fXform = ( myFlags & EHDCF_XFORM );
620 else if ( oa < -6.28318 )
624 n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
627 fp[ i ].x = ( FLOAT )x;
628 fp[ i++ ].y = ( FLOAT )y;
631 for ( ; i < n; ++i, sa += delta ) {
633 fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
634 fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
638 if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
642 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
643 HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
651 ROUNDL( fp[ 0 ].x ), Y( ROUNDL( fp[ 0 ].y ) ), NULL
655 ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) )
660 if ( i >= n ) goto end;
664 ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
671 ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) ), NULL
677 for ( ; i < n; ++i ) ::LineTo (
679 ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
682 CloseFigure ( myHDC );
688 SelectBrush( myHDC, hbo );
689 SelectPen( myHDC, hpo );
691 Arc ( x, y, xr, yr, ssa, oa, fChord ? ARCF_CHORD : ARCF_PIE );
693 } // end EHDC :: Polyarc
695 void EHDC :: SetPixel ( int x, int y, COLORREF c ) {
699 if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
703 ::SetPixel ( myHDC, p.x, p.y, c );
705 } // end EHDC :: SetPixel
707 void EHDC :: SetTextColor ( COLORREF c ) {
711 GetObject ( myTextPen, sizeof ( LOGPEN ), &lp );
713 if ( lp.lopnColor != c ) {
715 LOGBRUSH lb = { BS_SOLID, c, 0 };
717 if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
718 if ( myTextPen != NULL ) DeletePen( myTextPen );
720 myTextPen = CreatePen ( PS_SOLID, 0, c );
721 myTextBrush = CreateBrushIndirect ( &lb );
725 } // end EHDC :: SetTextColor
727 void EHDC :: SetTextAttrib ( COLORREF c, HFONT f, double slant, double hs, double vs ) {
736 } // end EHDC :: SetTextAttrib
738 void EHDC :: ETextOut ( int x, int y, char* str, double angle, BOOL fOutline ) {
740 _ETextOut ( x, y, str, angle, fOutline );
742 } // end EHDC :: TextOut
744 void EHDC :: ETextOut ( int x, int y, wchar_t* str, double angle, BOOL fOutline ) {
746 _ETextOut ( x, y, str, angle, fOutline, TRUE );
748 } // end EHDC :: TextOut
750 void EHDC :: PolyTextOut (
751 int x, int y, char* str, double angle,
752 double margin, BOOL fOutline, BOOL fNofill, BOOL fNoframe
755 _PolyTextOut ( x, y, str, angle, margin, fOutline, FALSE, fNofill, fNoframe );
757 } // end EHDC :: PolyTextOut
759 void EHDC :: PolyTextOut (
760 int x, int y, wchar_t* str, double angle, double margin,
761 BOOL fOutline, BOOL fNofill, BOOL fNoframe
764 _PolyTextOut ( x, y, str, angle, margin, fOutline, TRUE, fNofill, fNoframe );
766 } // end EHDC :: PolyTextOut
768 void EHDC :: SetWorldTransform ( XFORM* xf ) {
772 myFlags &= ~EHDCF_XFORM;
777 myFlags |= EHDCF_XFORM;
781 } // end EHDC :: SetWorldTransform
783 void EHDC :: ModifyWorldTransform ( XFORM* xf, DWORD iMode ) {
789 if ( iMode == MWT_RIGHTMULTIPLY ) {
794 } else if ( iMode == MWT_LEFTMULTIPLY ) {
799 } else if ( iMode == MWT_IDENTITY ) {
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;
805 myFlags &= ~EHDCF_XFORM;
811 _XFORMultiply ( &rxf, pxfLeft, pxfRight );
814 myFlags |= EHDCF_XFORM;
816 } // end EHDC :: ModifyWorldTransform
818 void EHDC :: Transform ( LPPOINT p, int n ) {
820 _XFORMApply ( p, n, &myXform );
824 void EHDC :: ResetURect ( void ) {
826 myURect.left = LONG_MAX;
827 myURect.top = LONG_MAX;
828 myURect.right = LONG_MIN;
829 myURect.bottom = LONG_MIN;
831 } // end EHDC :: ResetURect
833 void EHDC :: GetURect ( LPRECT lpRect ) {
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;
842 } // end EHDC :: GetURect
844 void EHDC :: _Init ( void ) {
846 myTextPen = ( HPEN )GetStockObject ( WHITE_PEN );
847 myTextBrush = ( HBRUSH )GetStockObject ( WHITE_BRUSH );
852 myBrush = myTextBrush;
862 myDDA1 = ( PPOINT )HeapAlloc (
863 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
864 sizeof ( POINT ) * myNDDA
866 myDDA2 = ( PPOINT )HeapAlloc (
867 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
868 sizeof ( POINT ) * myNDDA
872 ModifyWorldTransform ( NULL, MWT_IDENTITY );
873 myFlags &= ~EHDCF_XFORM;
875 } // end EHDC :: _Init
877 void EHDC :: _DrawTo ( PPOINT p ) {
880 double dx, dy, dxhw, dyhw, factor;
882 dx = ( double )( p -> x - myStart.x );
883 dy = ( double )( p -> y - myStart.y );
885 if ( dx == 0.0 && dy == 0.0 ) return;
887 factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
891 ip[ 0 ].x = ROUNDL( myStart.x + dxhw );
892 ip[ 0 ].y = ROUNDL( myStart.y - dyhw );
894 ip[ 1 ].x = ROUNDL( p -> x + dxhw );
895 ip[ 1 ].y = ROUNDL( p -> y - dyhw );
897 ip[ 2 ].x = ROUNDL( p -> x - dxhw );
898 ip[ 2 ].y = ROUNDL( p -> y + dyhw );
900 ip[ 3 ].x = ROUNDL( myStart.x - dxhw );
901 ip[ 3 ].y = ROUNDL( myStart.y + dyhw );
905 ::Polygon ( myHDC, ip, 4 );
911 } // end EHDC :: _DrawTo
913 void EHDC :: _Join ( void ) {
917 double r, ba, bc, dxba, dyba, dxbc, dybc,
918 s, sa, fc, xd, yd, xe, ye,
920 n2, rm1, rm2, rn1, rn2;
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 );
928 if ( ba == 0.0 || bc == 0.0 ) return;
930 n1 = -dxba / ba; n2 = dyba / ba;
931 m1 = -dxbc / bc; m2 = dybc / bc;
932 s = m1 * n2 - n1 * m2;
934 if ( ( sa = fabs ( s ) ) < 0.001 ) return;
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;
944 xe = myB.x - rm2; ye = myB.y - rm1;
945 xf = myB.x + rn2; yf = myB.y + rn1;
947 } else if ( s < 0.0 ) {
949 xe = myB.x + rm2; ye = myB.y + rm1;
950 xf = myB.x - rn2; yf = myB.y - rn1;
955 p[ 1 ].x = ROUNDL( xf ); p[ 1 ].y = ROUNDL( yf );
957 if ( !( myFlags & EHDCF_JBEVL ) ) {
959 p[ 2 ].x = ROUNDL( xd ); p[ 2 ].y = ROUNDL( yd );
960 p[ 3 ].x = ROUNDL( xe ); p[ 3 ].y = ROUNDL( ye );
965 p[ 2 ].x = ROUNDL( xe ); p[ 2 ].y = ROUNDL( ye );
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 ) );
977 HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
978 ::Polygon ( myHDC, p, np );
979 SelectPen( myHDC, hpo );
981 } // end EHDC :: _Join
983 BOOL EHDC :: _DrawToEx ( PPOINT p ) {
986 DDAP ddap = { this };
988 double dx, dy, dxhw, dyhw, factor;
990 dx = ( double )( p -> x - myStart.x );
991 dy = ( double )( p -> y - myStart.y );
993 if ( dx == 0.0 && dy == 0.0 ) return FALSE;
995 factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
999 pp[ 0 ].x = ROUNDL( myStart.x + dxhw );
1000 pp[ 0 ].y = ROUNDL( myStart.y - dyhw );
1002 pp[ 1 ].x = ROUNDL( myStart.x - dxhw );
1003 pp[ 1 ].y = ROUNDL( myStart.y + dyhw );
1005 pp[ 2 ].x = ROUNDL( p -> x - dxhw );
1006 pp[ 2 ].y = ROUNDL( p -> y + dyhw );
1008 pp[ 3 ].x = ROUNDL( p -> x + dxhw );
1009 pp[ 3 ].y = ROUNDL( p -> y - dyhw );
1012 myFlags &= ~EHDCF_DDAF;
1014 LineDDA ( pp[ 0 ].x, pp[ 0 ].y, pp[ 3 ].x, pp[ 3 ].y, &___auxDDAF, ( LPARAM )&ddap );
1017 myFlags &= ~EHDCF_DDAF;
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 ) );
1025 if ( myPRlen == 0 ) {
1027 myPRlen = myPStyle[ myPIndex++ ];
1029 if ( myPIndex == myPNS ) myPIndex = 0;
1035 while ( myPRlen != 0 && j < myIDDA ) ++j, --myPRlen;
1037 if ( j == myIDDA ) {
1039 myDDA1[ j ] = pp[ 3 ];
1040 myDDA2[ j ] = pp[ 2 ];
1044 if ( myFlags & EHDCF_PDRAW ) {
1048 p[ 0 ] = myDDA1[ i ];
1049 p[ 1 ] = myDDA1[ j ];
1050 p[ 2 ] = myDDA2[ j ];
1051 p[ 3 ] = myDDA2[ i ];
1054 ::Polygon ( myHDC, p, 4 );
1060 myFlags ^= EHDCF_PDRAW;
1066 if ( j >= myIDDA ) break;
1070 SelectPen( myHDC, hpo );
1072 if ( myPRlen == 0 ) myFlags |= EHDCF_NJOIN;
1080 } // end EHDC :: _DrawToEx
1082 void EHDC :: _LineTo ( PPOINT p ) {
1085 DDAP ddap = { this };
1091 LineDDA ( myStart.x, myStart.y, p -> x, p -> y, &___auxDDAF, ( LPARAM )&ddap );
1095 if ( myPRlen == 0 ) {
1097 myPRlen = myPStyle[ myPIndex++ ];
1099 if ( myPIndex == myPNS ) myPIndex = 0;
1103 if ( myFlags & EHDCF_PDRAW ) ::MoveToEx ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y, NULL );
1105 while ( myPRlen != 0 && i < myIDDA ) ++i, --myPRlen;
1107 if ( i == myIDDA ) myDDA1[ i ] = *p;
1109 if ( myFlags & EHDCF_PDRAW )
1111 ::LineTo ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y );
1115 myFlags ^= EHDCF_PDRAW;
1123 } // end EHDC :: _LineTo
1125 void EHDC :: _ETextOut ( int x, int y, void* str, double angle, BOOL fOutline, BOOL fWide ) {
1132 XFORM lXfm, rXfm, xfm;
1141 tanVal = tan ( myTextSlant ) * myTextVScale;
1142 sinVal = sin ( angle );
1143 cosVal = cos ( angle );
1145 if ( !( myFlags & EHDCF_TPATH ) ) {
1147 hfo = SelectFont( myHDC, myTextFont );
1149 i = myTextNP = _TextPath (
1150 myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1153 SelectFont( myHDC, hfo );
1155 if ( i <= 0 ) return;
1157 if ( myTextBS < myTextNP ) {
1159 dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1161 if ( myTextPath == NULL )
1163 myTextPath = ( LPPOINT )HeapAlloc (
1165 HEAP_GENERATE_EXCEPTIONS, dwLen
1170 myTextPath = ( LPPOINT )HeapReAlloc (
1172 HEAP_GENERATE_EXCEPTIONS,
1176 myTextBS = myTextNP;
1180 myTextType = ( PBYTE )( myTextPath + myTextNP );
1182 _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1195 lXfm.eM11 = ( FLOAT )myTextHScale; lXfm.eM21 = ( FLOAT )-tanVal;
1196 lXfm.eM12 = 0.0F; lXfm.eM22 = ( FLOAT )myTextVScale;
1200 rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1201 rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1204 _XFORMultiply ( &xfm, &lXfm, &rXfm );
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 );
1212 if ( myFlags & EHDCF_XFORM ) {
1214 _XFORMultiply ( &xfm, &lXfm, &myXform );
1217 } else pXfm = &lXfm;
1219 _XFORMApply ( myTextPath, myTextNP, pXfm );
1224 while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1226 hpo = SelectPen( myHDC, myTextPen );
1228 if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1230 if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
1232 BeginPath ( myHDC );
1233 _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1239 SelectBrush( myHDC, hbo );
1241 } else StrokePath ( myHDC );
1243 SelectPen( myHDC, hpo );
1250 XFORM lXfm, rXfm, xfm;
1260 tanVal = tan ( myTextSlant );
1261 sinVal = sin ( angle );
1262 cosVal = cos ( angle );
1264 if ( !( myFlags & EHDCF_TPATH ) ) {
1266 hfo = SelectFont( myHDC, myTextFont );
1268 if ( myTextVScale != 1.0 || myTextHScale != 1.0 ) {
1273 GetObject ( myTextFont, sizeof ( LOGFONT ), &lf );
1274 GetTextMetrics ( myHDC, &tm );
1276 lf.lfHeight = ROUNDL( lf.lfHeight * myTextVScale );
1277 lf.lfWidth = ROUNDL( lf.lfWidth * myTextHScale );
1279 lf.lfQuality = DRAFT_QUALITY;
1281 if ( lf.lfWidth == 0 )
1283 lf.lfWidth = ROUNDL( tm.tmAveCharWidth * myTextHScale );
1285 SelectFont( myHDC, hfo );
1287 hfo = SelectFont( myHDC, CreateFontIndirect ( &lf ) );
1292 i = myTextNP = _TextPath (
1293 myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
1296 hfo = SelectFont( myHDC, hfo );
1298 if ( fNew ) DeleteFont( hfo );
1300 if ( i <= 0 ) return;
1302 if ( myTextBS < myTextNP ) {
1304 dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
1306 if ( myTextPath == NULL )
1308 myTextPath = ( LPPOINT )HeapAlloc (
1310 HEAP_GENERATE_EXCEPTIONS, dwLen
1315 myTextPath = ( LPPOINT )HeapReAlloc (
1317 HEAP_GENERATE_EXCEPTIONS,
1321 myTextBS = myTextNP;
1325 myTextType = ( PBYTE )( myTextPath + myTextNP );
1327 _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
1340 lXfm.eM11 = 1.0F; lXfm.eM21 = ( FLOAT )-tanVal;
1341 lXfm.eM12 = 0.0F; lXfm.eM22 = 1.0F;
1345 rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
1346 rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
1349 _XFORMultiply ( &xfm, &lXfm, &rXfm );
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 );
1357 if ( myFlags & EHDCF_XFORM ) {
1359 _XFORMultiply ( &xfm, &lXfm, &myXform );
1362 } else pXfm = &lXfm;
1364 _XFORMApply ( myTextPath, myTextNP, pXfm );
1369 while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
1371 hpo = SelectPen( myHDC, myTextPen );
1373 if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
1375 if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
1377 BeginPath ( myHDC );
1378 _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
1384 SelectBrush( myHDC, hbo );
1386 } else StrokePath ( myHDC );
1388 SelectPen( myHDC, hpo );
1390 } // end EHDC :: _ETextOut
1392 void EHDC :: _PolyTextOut (
1393 int x, int y, void* str, double angle, double margin,
1394 BOOL fOutline, BOOL fWide, BOOL fNofill, BOOL fNoframe
1404 double sinVal = sin ( angle );
1405 double cosVal = cos ( angle );
1406 double tanVal = -tan ( myTextSlant );
1409 hfo = SelectFont( myHDC, myTextFont );
1413 GetTextExtentPoint32A (
1414 myHDC, ( char* )str, lstrlenA ( ( char* )str ), &sz
1419 GetTextExtentPoint32W (
1420 myHDC, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), &sz
1423 GetTextMetrics ( myHDC, &tm );
1424 SelectFont( myHDC, hfo );
1426 sz.cy -= tm.tmInternalLeading;
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;
1439 if ( myTextSlant < 0.0F ) {
1441 p[ 0 ].x -= ( LONG )tanVal;
1442 p[ 3 ].x -= ( LONG )tanVal;
1446 p[ 1 ].x -= ( LONG )tanVal;
1447 p[ 2 ].x -= ( LONG )tanVal;
1451 height = ROUNDL( p[ 0 ].y * margin / 2.0 );
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 );
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;
1467 if ( myFlags & EHDCF_XFORM ) {
1469 _XFORMultiply ( &xfm, &lXfm, &myXform );
1472 } else pXfm = &lXfm;
1474 _XFORMApply ( p, 4, pXfm );
1476 dwFlags = ( myFlags & EHDCF_XFORM );
1477 myFlags &= ~EHDCF_XFORM;
1481 Polyline ( p, 4, TRUE );
1485 Polygon ( p, 4, fNoframe ? POLYF_NOEDGE : 0 );
1489 _ETextOut ( x, y, str, angle, fOutline, fWide );
1491 } // end EHDC :: _PolyTextOut
1493 void EHDC :: Register ( LPPOINT lpPts, int nPts ) {
1497 if ( lpPts -> x < myURect.left )
1499 myURect.left = lpPts -> x - 1;
1501 else if ( lpPts -> x > myURect.right )
1503 myURect.right = lpPts -> x + 2;
1505 if ( lpPts -> y < myURect.top )
1507 myURect.top = lpPts -> y - 1;
1509 else if ( lpPts -> y > myURect.bottom )
1511 myURect.bottom = lpPts -> y + 2;
1517 } // end EHDC :: _Register
1519 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1521 static void WINAPI _XFORMultiply ( PXFORM res, PXFORM left, PXFORM right ) {
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;
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;
1531 } /* end _XFORMultiply */
1533 static void WINAPI _XFORMApply ( PPOINT pp, int n, PXFORM xf ) {
1538 for ( i = 0; i < n; ++i ) {
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;
1543 pp[ i ].x = ROUNDL( dx );
1544 pp[ i ].y = ROUNDL( dy );
1548 } /* end _XFORMApply */
1550 static void WINAPI _XFORMApplyf ( PFPOINT pp, int n, PXFORM xf ) {
1555 for ( i = 0; i < n; ++i ) {
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;
1560 pp[ i ].x = ( FLOAT )dx;
1561 pp[ i ].y = ( FLOAT )dy;
1565 } /* end _XFORMApply */
1567 static void WINAPI _RenderPath ( HDC hdc, LPPOINT lpPts, PBYTE lpType, int nPts ) {
1571 for ( int i = 0; i < nPts; ++i ) {
1573 switch ( lpType[ i ] ) {
1577 MoveToEx ( hdc, lpPts[ i ].x, lpPts[ i ].y, NULL );
1583 case PT_LINETO | PT_CLOSEFIGURE:
1585 LineTo ( hdc, lpPts[ i ].x, lpPts[ i ].y );
1589 case PT_BEZIERTO | PT_CLOSEFIGURE:
1591 PolyBezierTo ( hdc, &lpPts[ i ], 3 );
1595 if ( lpType[ i ] & PT_CLOSEFIGURE ) LineTo ( hdc, pp -> x, pp -> y );
1601 } /* end _RenderPath */
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
1610 if ( lpPts == NULL ) {
1612 int bmo = SetBkMode ( hdc, TRANSPARENT );
1618 TextOutA ( hdc, x, y, ( char* )str, lstrlenA ( ( char* )str ) );
1622 TextOutW ( hdc, x, y, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ) );
1626 SetBkMode ( hdc, bmo );
1630 retVal = GetPath ( hdc, lpPts, lpType, nPts );
1636 GetTextExtentPoint32A ( hdc, ( char* )str, lstrlenA ( ( char* )str ), pSz );
1640 GetTextExtentPoint32W ( hdc, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), pSz );
1644 } /* end _TextPath */
1646 VOID CALLBACK ___auxDDAF ( int x, int y, LPARAM lpParam ) {
1648 PDDAP p = ( PDDAP )lpParam;
1650 p -> pp[ p -> _this -> myIDDA ].x = x;
1651 p -> pp[ p -> _this -> myIDDA++ ].y = y;
1653 if ( p -> _this -> myIDDA >= p -> _this -> myNDDA ) {
1655 p -> _this -> myDDA1 = ( PPOINT )HeapReAlloc (
1656 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1657 p -> _this -> myDDA1, p -> _this -> myNDDA <<= 1
1659 p -> _this -> myDDA2 = ( PPOINT )HeapReAlloc (
1660 GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
1661 p -> _this -> myDDA2, p -> _this -> myNDDA <<= 1
1668 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//