/opencascade-6.5.1/ros/src/WNT/EHDC.cxx

https://github.com/jehc/MondocosmOS · C++ · 1654 lines · 1051 code · 593 blank · 10 comment · 256 complexity · 8d5126be8e7395104104245d06c863fe MD5 · raw file

  1. // File: EHDC.cxx
  2. // Created:
  3. // Author:
  4. // Modifications: PLOTNIKOV Eugeny at July 1998 (BUC60286)
  5. // Copyright: Matra Datavision 1998
  6. #include "EHDC.hxx"
  7. #include <math.h>
  8. #include <limits>
  9. #define ROUNDL( d ) ( LONG )( ( d ) + 0.5 )
  10. #define Y( y ) ( mySize.cy - ( y ) )
  11. typedef struct _fpoint {
  12. FLOAT x;
  13. FLOAT y;
  14. } FPOINT, *PFPOINT;
  15. typedef struct _ddap {
  16. EHDC* _this;
  17. PPOINT pp;
  18. } DDAP, *PDDAP;
  19. static void WINAPI _XFORMultiply ( PXFORM, PXFORM, PXFORM );
  20. static void WINAPI _XFORMApply ( PPOINT, int, PXFORM );
  21. static void WINAPI _XFORMApplyf ( PFPOINT, int, PXFORM );
  22. static void WINAPI _RenderPath ( HDC, LPPOINT, PBYTE, int );
  23. static int WINAPI _TextPath ( HDC, int, int, void*, LPPOINT, PBYTE, int, PSIZE, BOOL );
  24. EHDC :: EHDC ( HDC hdc, PSIZE szClient ) {
  25. _Init ();
  26. SetDC ( hdc, szClient );
  27. } // end EHDC constructor ( 1 )
  28. EHDC :: EHDC () {
  29. _Init ();
  30. } // end EHDC constructor ( 2 )
  31. EHDC :: ~EHDC () {
  32. HANDLE hHeap = GetProcessHeap ();
  33. if ( myHDC != NULL ) {
  34. SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  35. SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
  36. } // end if
  37. if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
  38. if ( myTextPen != NULL ) DeletePen( myTextPen );
  39. if ( myTextPath != NULL ) HeapFree (
  40. hHeap, 0,
  41. ( LPVOID )myTextPath
  42. );
  43. if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) )
  44. HeapFree ( hHeap, 0, ( LPVOID )myPStyle );
  45. if ( myPBrush != NULL ) DeleteBrush( myPBrush );
  46. if ( myPPen != NULL ) DeletePen( myPPen );
  47. if ( myFlags & EHDCF_PPUSH ) {
  48. if ( myPPenPush != NULL ) DeletePen( myPPenPush );
  49. if ( myPBrushPush != NULL ) DeleteBrush( myPBrushPush );
  50. } // end if
  51. HeapFree ( hHeap, 0, ( LPVOID )myDDA1 );
  52. HeapFree ( hHeap, 0, ( LPVOID )myDDA2 );
  53. } // end EHDC destructor
  54. void EHDC :: SetDC ( HDC hdc, PSIZE szClient ) {
  55. myHDC = hdc;
  56. myTextHScale =
  57. myTextVScale = 1.0;
  58. myTextSlant = 0.0;
  59. mySize = *szClient;
  60. SelectPen( myHDC, myPPen );
  61. SelectBrush( myHDC, myPBrush );
  62. MoveToEx ( 0, 0, NULL );
  63. ResetURect ();
  64. } // end EHDC :: SetDC
  65. HBRUSH EHDC :: SelectEPen (
  66. DWORD dwWidth,
  67. CONST LOGBRUSH* lplb,
  68. DWORD dwStyleCount,
  69. DWORD* lpStyle,
  70. BOOL fNoAlloc
  71. ) {
  72. DWORD dwLen = dwStyleCount * sizeof ( DWORD );
  73. if ( dwStyleCount ) {
  74. if ( !fNoAlloc ) {
  75. if ( myPStyle == NULL ) {
  76. myPStyle = ( PDWORD )HeapAlloc (
  77. GetProcessHeap (),
  78. HEAP_GENERATE_EXCEPTIONS,
  79. dwLen
  80. );
  81. setPBS:
  82. myPBS = dwStyleCount;
  83. } else if ( myPBS < dwStyleCount ) {
  84. myPStyle = ( PDWORD )HeapReAlloc (
  85. GetProcessHeap (),
  86. HEAP_GENERATE_EXCEPTIONS,
  87. myPStyle, dwLen
  88. );
  89. goto setPBS;
  90. } // end if
  91. CopyMemory ( myPStyle, lpStyle, dwLen );
  92. myFlags |= EHDCF_SFREE;
  93. } else if ( myPStyle != NULL && ( myFlags & EHDCF_SFREE ) ) {
  94. HeapFree ( GetProcessHeap (), 0, ( LPVOID )myPStyle );
  95. myPStyle = lpStyle;
  96. } // end if
  97. } // end if
  98. myPIndex = 0;
  99. myPWidth = dwWidth;
  100. myPNS = dwStyleCount;
  101. if ( myPBrush != NULL ) {
  102. LOGBRUSH lb;
  103. GetObject ( myPBrush, sizeof ( LOGBRUSH ), &lb );
  104. if ( lb.lbStyle != lplb -> lbStyle ||
  105. lb.lbColor != lplb -> lbColor ||
  106. lb.lbHatch != lplb -> lbHatch
  107. ) {
  108. SelectBrush( myHDC, GetStockObject ( NULL_BRUSH ) );
  109. DeleteBrush( myPBrush );
  110. newBrush:
  111. myPBrush = CreateBrushIndirect ( lplb );
  112. } // end if
  113. if ( dwWidth > 1 ) {
  114. myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
  115. myFlags &= ~EHDCF_JOIN;
  116. } else myFlags &= ~EHDCF_EPEN;
  117. } else goto newBrush;
  118. if ( myPPen != NULL ) {
  119. LOGPEN lp;
  120. GetObject ( myPPen, sizeof ( LOGPEN ), &lp );
  121. if ( lp.lopnColor != lplb -> lbColor ||
  122. lp.lopnWidth.x != 0
  123. ) {
  124. SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  125. DeletePen( myPPen );
  126. newPen:
  127. myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor );
  128. } // end if
  129. } else goto newPen;
  130. SelectPen( myHDC, myPPen );
  131. return SelectBrush( myHDC, myPBrush );
  132. } // end EHDC :: SelectEPen
  133. void EHDC :: SelectEPen (
  134. DWORD dwWidth,
  135. CONST LOGBRUSH* lplb
  136. ) {
  137. if ( dwWidth == 0xFFFFFFFF && ( myFlags & EHDCF_PPUSH ) ) {
  138. SelectPen( myHDC, myPPenPush );
  139. SelectBrush( myHDC, myPBrushPush );
  140. DeletePen( myPPen );
  141. DeleteBrush( myPBrush );
  142. myFlags &= ~EHDCF_PPUSH;
  143. myPPen = myPPenPush;
  144. myPBrush = myPBrushPush;
  145. myPWidth = myPWPush;
  146. myFlags |= ( myfXpenPush ? EHDCF_EPEN : 0 );
  147. } else if ( !( myFlags & EHDCF_PPUSH ) ){
  148. myFlags |= EHDCF_PPUSH;
  149. myfXpenPush = ( myFlags & EHDCF_EPEN );
  150. myPPenPush = myPPen;
  151. myPBrushPush = myPBrush;
  152. myPWPush = myPWidth;
  153. myPWidth = dwWidth;
  154. SelectBrush( myHDC, myPBrush = CreateBrushIndirect ( lplb ) );
  155. SelectPen( myHDC, myPPen = CreatePen ( PS_SOLID, 0, lplb -> lbColor ) );
  156. if ( dwWidth > 1 ) {
  157. myFlags |= ( EHDCF_EPEN | EHDCF_PDRAW | EHDCF_CJOIN );
  158. myFlags &= ~EHDCF_JOIN;
  159. } else myFlags &= ~EHDCF_EPEN;
  160. } // end if
  161. } // end EHDC :: SelectEPen
  162. HPEN EHDC :: SelectEPen ( HPEN hPen ) {
  163. HPEN retVal = NULL;
  164. if ( myHDC != NULL ) retVal = SelectPen( myHDC, hPen );
  165. myFlags &= ~EHDCF_EPEN;
  166. return hPen;
  167. } // end EHDC :: SelectEPen
  168. void EHDC :: SelectEBrush ( PLOGBRUSH lplb, PLOGBRUSH lplbo ) {
  169. if ( lplb == NULL ) {
  170. DeleteBrush( myBrush );
  171. myBrush = NULL;
  172. } else if ( myBrush != NULL ) {
  173. LOGBRUSH lb;
  174. GetObject ( myBrush, sizeof ( LOGBRUSH ), &lb );
  175. if ( lplbo != NULL ) *lplbo = lb;
  176. if ( lb.lbStyle != lplb -> lbStyle ||
  177. lb.lbColor != lplb -> lbColor ||
  178. lb.lbHatch != lplb -> lbHatch
  179. ) {
  180. DeleteBrush( myBrush );
  181. newBrush:
  182. myBrush = CreateBrushIndirect ( lplb );
  183. } // end if
  184. } else goto newBrush;
  185. } // end EHDC :: SelectEBrush
  186. void EHDC :: SetMiter ( BOOL fMiter ) {
  187. if ( fMiter )
  188. myFlags &= ~EHDCF_JBEVL;
  189. else
  190. myFlags |= EHDCF_JBEVL;
  191. } // end EHDC :: SetMiter
  192. void EHDC :: MoveToEx ( int x, int y, LPPOINT lpPoint ) {
  193. if ( lpPoint != NULL ) *lpPoint = myStart;
  194. myStart.x = x;
  195. myStart.y = y;
  196. if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &myStart, 1, &myXform );
  197. myStart.y = Y( myStart.y );
  198. Register ( &myStart, 1 );
  199. ::MoveToEx ( myHDC, myStart.x, myStart.y, NULL );
  200. myClose = myStart;
  201. myPIndex = 0;
  202. myFlags &= ~EHDCF_JOIN;
  203. myFlags |= ( EHDCF_PDRAW | EHDCF_DDAF );
  204. myPIndex = 0;
  205. myPRlen = 0;
  206. } // end EHDC :: MoveToEx
  207. BOOL EHDC :: LineTo ( int x, int y ) {
  208. POINT p = { x, y };
  209. if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
  210. p.y = Y( p.y );
  211. if ( myFlags & EHDCF_EPEN ) {
  212. if ( myPNS == 0 )
  213. _DrawTo ( &p );
  214. else if ( !_DrawToEx ( &p ) ) return FALSE;
  215. if ( myFlags & EHDCF_CJOIN ) {
  216. myFlags &= ~EHDCF_CJOIN;
  217. myCJoin = p;
  218. } // end if
  219. if ( myFlags & EHDCF_JOIN )
  220. _Join ();
  221. else
  222. myJoin = p;
  223. if ( myFlags & EHDCF_PDRAW && !( myFlags & EHDCF_NJOIN ) )
  224. myFlags |= EHDCF_JOIN;
  225. else
  226. myFlags &= ~( EHDCF_JOIN | EHDCF_NJOIN );
  227. } else if ( myPNS == 0 ) {
  228. Register ( &p, 1 );
  229. ::LineTo ( myHDC, p.x, p.y );
  230. myStart = p;
  231. } else _LineTo ( &p );
  232. return TRUE;
  233. } // end EHDC :: LineTo
  234. void EHDC :: ClosePath ( void ) {
  235. BOOL ltf;
  236. POINT pa = myStart;
  237. POINT pb = myClose;
  238. DWORD dw = ( myFlags & EHDCF_XFORM );
  239. myFlags &= ~EHDCF_XFORM;
  240. if ( myStart.x != myClose.x ||
  241. myStart.y != myClose.y
  242. ) {
  243. ltf = LineTo ( myClose.x, Y( myClose.y ) );
  244. myFlags |= dw;
  245. if ( ltf && ( myFlags & EHDCF_PDRAW ) && ( myFlags & EHDCF_EPEN ) ) {
  246. myA = pa;
  247. myB = pb;
  248. myStart = myCJoin;
  249. _Join ();
  250. } // end if
  251. } else myFlags |= dw;
  252. myFlags &= ~EHDCF_JOIN;
  253. myPIndex = 0;
  254. myFlags |= ( EHDCF_PDRAW | EHDCF_CJOIN );
  255. myPRlen = 0;
  256. } // end EHDC :: ClosePath
  257. void EHDC :: Polyline ( CONST POINT* lpPts, int nPts, BOOL fClose ) {
  258. DWORD dwPIndex = myPIndex;
  259. DWORD dwPRlen = myPRlen;
  260. DWORD dwFlags = myFlags;
  261. POINT pA = myA;
  262. POINT pB = myB;
  263. POINT pClose = myClose;
  264. POINT pJoin = myJoin;
  265. POINT pCJoin = myCJoin;
  266. POINT pStart;
  267. myFlags |= EHDCF_CJOIN;
  268. MoveToEx ( lpPts -> x, lpPts -> y, &pStart );
  269. for ( int i = 1; i < nPts; ++i )
  270. LineTo ( lpPts[ i ].x, lpPts[ i ].y );
  271. if ( fClose ) ClosePath ();
  272. myFlags = dwFlags;
  273. myA = pA;
  274. myB = pB;
  275. myClose = pClose;
  276. myJoin = pJoin;
  277. myCJoin = pCJoin;
  278. myStart = pStart;
  279. myPRlen = dwPRlen;
  280. myPIndex = dwPIndex;
  281. } // end EHDC :: Polyline
  282. void EHDC :: Polygon ( CONST POINT* lpPts, int nPts, DWORD dwFlags ) {
  283. POINT p;
  284. HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  285. HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
  286. BeginPath ( myHDC );
  287. p.x = lpPts -> x;
  288. p.y = lpPts -> y;
  289. if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
  290. ::MoveToEx ( myHDC, p.x, Y( p.y ), NULL );
  291. for ( int i = 1; i < nPts; ++i ) {
  292. p.x = lpPts[ i ].x;
  293. p.y = lpPts[ i ].y;
  294. if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
  295. ::LineTo ( myHDC, p.x, Y( p.y ) );
  296. } // end for
  297. CloseFigure ( myHDC );
  298. EndPath ( myHDC );
  299. FillPath ( myHDC );
  300. SelectBrush( myHDC, hbo );
  301. SelectPen( myHDC, hpo );
  302. if ( dwFlags & POLYF_NOCLOSEDGE )
  303. Polyline ( lpPts, nPts, FALSE );
  304. else if ( !( dwFlags & POLYF_NOEDGE ) )
  305. Polyline ( lpPts, nPts, TRUE );
  306. } // end EHDC :: Polygon
  307. void EHDC :: Arc (
  308. int x, int y, int xr, int yr, double sa, double oa, DWORD dwAFlags
  309. ) {
  310. int i = 0, j, n;
  311. double delta;
  312. FPOINT fp[ 362 ];
  313. BOOL fXform = ( myFlags & EHDCF_XFORM );
  314. DWORD dwPIndex = myPIndex;
  315. DWORD dwPRlen = myPRlen;
  316. DWORD dwFlags = myFlags;
  317. POINT pA = myA;
  318. POINT pB = myB;
  319. POINT pClose = myClose;
  320. POINT pJoin = myJoin;
  321. POINT pCJoin = myCJoin;
  322. POINT pStart = myStart;
  323. myFlags &= ~EHDCF_XFORM;
  324. if ( oa > 6.28318 )
  325. oa = 6.28318;
  326. else if ( oa < -6.28318 )
  327. oa = -6.28318;
  328. n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
  329. delta = oa / n;
  330. fp[ i ].x = ( FLOAT )x;
  331. fp[ i++ ].y = ( FLOAT )y;
  332. n += 2;
  333. for ( ; i < n; ++i, sa += delta ) {
  334. fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
  335. fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
  336. } // end for
  337. if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
  338. i = 0;
  339. if ( dwAFlags & ARCF_PIE ) {
  340. myFlags &= ~EHDCF_JBEVL;
  341. MoveToEx ( ROUNDL( fp[ 0 ].x ), ROUNDL( fp[ 0 ].y ), NULL );
  342. LineTo ( ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y ) );
  343. ++i;
  344. if ( i >= n ) goto end;
  345. LineTo ( ROUNDL( fp[ i ].x ), ROUNDL( fp[ i ].y ) );
  346. ++i;
  347. } else {
  348. MoveToEx ( ROUNDL( fp[ 1 ].x ), ROUNDL( fp[ 1 ].y ), NULL );
  349. ++i;
  350. } // end else
  351. myFlags |= EHDCF_JBEVL;
  352. for ( j = i - 1; i < n; ++i ) {
  353. x = ROUNDL( fp[ i ].x );
  354. y = ROUNDL( fp[ i ].y );
  355. if ( x == ROUNDL( fp[ j ].x ) && y == ROUNDL( fp[ j ].y ) ) continue;
  356. LineTo ( x, y );
  357. j = i;
  358. } // end for
  359. end:
  360. if ( dwAFlags & ( ARCF_PIE | ARCF_CHORD ) || fabs ( oa ) == 6.28318 ) {
  361. myFlags &= ~EHDCF_JBEVL;
  362. ClosePath ();
  363. } // end if
  364. myFlags = dwFlags;
  365. myA = pA;
  366. myB = pB;
  367. myClose = pClose;
  368. myJoin = pJoin;
  369. myCJoin = pCJoin;
  370. myStart = pStart;
  371. myPRlen = dwPRlen;
  372. myPIndex = dwPIndex;
  373. } // end EHDC :: Arc
  374. void EHDC :: Polyarc (
  375. int x, int y, int xr, int yr, double sa, double oa, BOOL fChord
  376. ) {
  377. int i = 0, n;
  378. double ssa = sa, delta;
  379. FPOINT fp[ 362 ];
  380. BOOL fXform = ( myFlags & EHDCF_XFORM );
  381. if ( oa > 6.28318 )
  382. oa = 6.28318;
  383. else if ( oa < -6.28318 )
  384. oa = -6.28318;
  385. n = abs ( ROUNDL( oa * 180.0 / 3.14159 ) );
  386. delta = oa / n;
  387. fp[ i ].x = ( FLOAT )x;
  388. fp[ i++ ].y = ( FLOAT )y;
  389. n += 2;
  390. for ( ; i < n; ++i, sa += delta ) {
  391. fp[ i ].x = FLOAT( x + xr * cos ( sa ) );
  392. fp[ i ].y = FLOAT( y + yr * sin ( sa ) );
  393. } // end for
  394. if ( fXform ) _XFORMApplyf ( fp, n, &myXform );
  395. i = 0;
  396. HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  397. HBRUSH hbo = SelectBrush( myHDC, myBrush ? myBrush : GetStockObject ( NULL_BRUSH ) );
  398. BeginPath ( myHDC );
  399. if ( !fChord ) {
  400. ::MoveToEx (
  401. myHDC,
  402. ROUNDL( fp[ 0 ].x ), Y( ROUNDL( fp[ 0 ].y ) ), NULL
  403. );
  404. ::LineTo (
  405. myHDC,
  406. ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) )
  407. );
  408. ++i;
  409. if ( i >= n ) goto end;
  410. ::LineTo (
  411. myHDC,
  412. ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
  413. );
  414. } else {
  415. ::MoveToEx (
  416. myHDC,
  417. ROUNDL( fp[ 1 ].x ), Y( ROUNDL( fp[ 1 ].y ) ), NULL
  418. );
  419. ++i;
  420. } // end else
  421. for ( ; i < n; ++i ) ::LineTo (
  422. myHDC,
  423. ROUNDL( fp[ i ].x ), Y( ROUNDL( fp[ i ].y ) )
  424. );
  425. end:
  426. CloseFigure ( myHDC );
  427. EndPath ( myHDC );
  428. FillPath ( myHDC );
  429. SelectBrush( myHDC, hbo );
  430. SelectPen( myHDC, hpo );
  431. Arc ( x, y, xr, yr, ssa, oa, fChord ? ARCF_CHORD : ARCF_PIE );
  432. } // end EHDC :: Polyarc
  433. void EHDC :: SetPixel ( int x, int y, COLORREF c ) {
  434. POINT p = { x, y };
  435. if ( myFlags & EHDCF_XFORM ) _XFORMApply ( &p, 1, &myXform );
  436. p.y = Y( p.y );
  437. ::SetPixel ( myHDC, p.x, p.y, c );
  438. } // end EHDC :: SetPixel
  439. void EHDC :: SetTextColor ( COLORREF c ) {
  440. LOGPEN lp;
  441. GetObject ( myTextPen, sizeof ( LOGPEN ), &lp );
  442. if ( lp.lopnColor != c ) {
  443. LOGBRUSH lb = { BS_SOLID, c, 0 };
  444. if ( myTextBrush != NULL ) DeleteBrush( myTextBrush );
  445. if ( myTextPen != NULL ) DeletePen( myTextPen );
  446. myTextPen = CreatePen ( PS_SOLID, 0, c );
  447. myTextBrush = CreateBrushIndirect ( &lb );
  448. } // end if
  449. } // end EHDC :: SetTextColor
  450. void EHDC :: SetTextAttrib ( COLORREF c, HFONT f, double slant, double hs, double vs ) {
  451. SetTextColor ( c );
  452. myTextFont = f;
  453. myTextSlant = slant;
  454. myTextHScale = hs;
  455. myTextVScale = vs;
  456. } // end EHDC :: SetTextAttrib
  457. void EHDC :: ETextOut ( int x, int y, char* str, double angle, BOOL fOutline ) {
  458. _ETextOut ( x, y, str, angle, fOutline );
  459. } // end EHDC :: TextOut
  460. void EHDC :: ETextOut ( int x, int y, wchar_t* str, double angle, BOOL fOutline ) {
  461. _ETextOut ( x, y, str, angle, fOutline, TRUE );
  462. } // end EHDC :: TextOut
  463. void EHDC :: PolyTextOut (
  464. int x, int y, char* str, double angle,
  465. double margin, BOOL fOutline, BOOL fNofill, BOOL fNoframe
  466. ) {
  467. _PolyTextOut ( x, y, str, angle, margin, fOutline, FALSE, fNofill, fNoframe );
  468. } // end EHDC :: PolyTextOut
  469. void EHDC :: PolyTextOut (
  470. int x, int y, wchar_t* str, double angle, double margin,
  471. BOOL fOutline, BOOL fNofill, BOOL fNoframe
  472. ) {
  473. _PolyTextOut ( x, y, str, angle, margin, fOutline, TRUE, fNofill, fNoframe );
  474. } // end EHDC :: PolyTextOut
  475. void EHDC :: SetWorldTransform ( XFORM* xf ) {
  476. if ( xf == NULL )
  477. myFlags &= ~EHDCF_XFORM;
  478. else {
  479. myXform = *xf;
  480. myFlags |= EHDCF_XFORM;
  481. } // end else
  482. } // end EHDC :: SetWorldTransform
  483. void EHDC :: ModifyWorldTransform ( XFORM* xf, DWORD iMode ) {
  484. XFORM rxf;
  485. PXFORM pxfLeft;
  486. PXFORM pxfRight;
  487. if ( iMode == MWT_RIGHTMULTIPLY ) {
  488. pxfLeft = &myXform;
  489. pxfRight = xf;
  490. } else if ( iMode == MWT_LEFTMULTIPLY ) {
  491. pxfLeft = xf;
  492. pxfRight = &myXform;
  493. } else if ( iMode == MWT_IDENTITY ) {
  494. myXform.eM11 = 1.0F; myXform.eM12 = 0.0F;
  495. myXform.eM21 = 0.0F; myXform.eM22 = 1.0F;
  496. myXform.eDx = 0.0F; myXform.eDy = 0.0F;
  497. myFlags &= ~EHDCF_XFORM;
  498. return;
  499. } else return;
  500. _XFORMultiply ( &rxf, pxfLeft, pxfRight );
  501. myXform = rxf;
  502. myFlags |= EHDCF_XFORM;
  503. } // end EHDC :: ModifyWorldTransform
  504. void EHDC :: Transform ( LPPOINT p, int n ) {
  505. _XFORMApply ( p, n, &myXform );
  506. } // end TransformXY
  507. void EHDC :: ResetURect ( void ) {
  508. myURect.left = LONG_MAX;
  509. myURect.top = LONG_MAX;
  510. myURect.right = LONG_MIN;
  511. myURect.bottom = LONG_MIN;
  512. } // end EHDC :: ResetURect
  513. void EHDC :: GetURect ( LPRECT lpRect ) {
  514. *lpRect = myURect;
  515. if ( lpRect -> top < 0 ) lpRect -> top = 0;
  516. if ( lpRect -> left < 0 ) lpRect -> left = 0;
  517. if ( lpRect -> bottom > mySize.cy ) lpRect -> bottom = mySize.cy;
  518. if ( lpRect -> right > mySize.cx ) lpRect -> right = mySize.cx;
  519. } // end EHDC :: GetURect
  520. void EHDC :: _Init ( void ) {
  521. myTextPen = ( HPEN )GetStockObject ( WHITE_PEN );
  522. myTextBrush = ( HBRUSH )GetStockObject ( WHITE_BRUSH );
  523. myTextFont = NULL;
  524. myTextPath = NULL;
  525. myPPen = myTextPen;
  526. myPBrush =
  527. myBrush = myTextBrush;
  528. myPStyle = NULL;
  529. myTextBS =
  530. myPBS =
  531. myPNS = 0;
  532. myFlags = 0;
  533. myTextSlant = 0.0;
  534. myTextHScale =
  535. myTextVScale = 1.0;
  536. myNDDA = 1024;
  537. myDDA1 = ( PPOINT )HeapAlloc (
  538. GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
  539. sizeof ( POINT ) * myNDDA
  540. );
  541. myDDA2 = ( PPOINT )HeapAlloc (
  542. GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
  543. sizeof ( POINT ) * myNDDA
  544. );
  545. myIDDA = 0;
  546. ModifyWorldTransform ( NULL, MWT_IDENTITY );
  547. myFlags &= ~EHDCF_XFORM;
  548. } // end EHDC :: _Init
  549. void EHDC :: _DrawTo ( PPOINT p ) {
  550. POINT ip[ 4 ];
  551. double dx, dy, dxhw, dyhw, factor;
  552. dx = ( double )( p -> x - myStart.x );
  553. dy = ( double )( p -> y - myStart.y );
  554. if ( dx == 0.0 && dy == 0.0 ) return;
  555. factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
  556. dxhw = dy * factor;
  557. dyhw = dx * factor;
  558. ip[ 0 ].x = ROUNDL( myStart.x + dxhw );
  559. ip[ 0 ].y = ROUNDL( myStart.y - dyhw );
  560. ip[ 1 ].x = ROUNDL( p -> x + dxhw );
  561. ip[ 1 ].y = ROUNDL( p -> y - dyhw );
  562. ip[ 2 ].x = ROUNDL( p -> x - dxhw );
  563. ip[ 2 ].y = ROUNDL( p -> y + dyhw );
  564. ip[ 3 ].x = ROUNDL( myStart.x - dxhw );
  565. ip[ 3 ].y = ROUNDL( myStart.y + dyhw );
  566. Register ( ip, 4 );
  567. ::Polygon ( myHDC, ip, 4 );
  568. myA = myB;
  569. myB = myStart;
  570. myStart = *p;
  571. } // end EHDC :: _DrawTo
  572. void EHDC :: _Join ( void ) {
  573. int np;
  574. POINT p[ 4 ];
  575. double r, ba, bc, dxba, dyba, dxbc, dybc,
  576. s, sa, fc, xd, yd, xe, ye,
  577. xf, yf, m1, m2, n1,
  578. n2, rm1, rm2, rn1, rn2;
  579. r = myPWidth / 2.0;
  580. dxba = ( double )( myA.x - myB.x ); dyba = ( FLOAT )( myA.y - myB.y );
  581. dxbc = ( double )( myStart.x - myB.x ); dybc = ( FLOAT )( myStart.y - myB.y );
  582. ba = sqrt ( dxba * dxba + dyba * dyba );
  583. bc = sqrt ( dxbc * dxbc + dybc * dybc );
  584. if ( ba == 0.0 || bc == 0.0 ) return;
  585. n1 = -dxba / ba; n2 = dyba / ba;
  586. m1 = -dxbc / bc; m2 = dybc / bc;
  587. s = m1 * n2 - n1 * m2;
  588. if ( ( sa = fabs ( s ) ) < 0.001 ) return;
  589. fc = r / sa;
  590. xd = myB.x + fc * ( m1 + n1 );
  591. yd = myB.y - fc * ( m2 + n2 );
  592. rm1 = r * m1; rm2 = r * m2;
  593. rn1 = r * n1; rn2 = r * n2;
  594. if ( s > 0.0 ) {
  595. xe = myB.x - rm2; ye = myB.y - rm1;
  596. xf = myB.x + rn2; yf = myB.y + rn1;
  597. } else if ( s < 0.0 ) {
  598. xe = myB.x + rm2; ye = myB.y + rm1;
  599. xf = myB.x - rn2; yf = myB.y - rn1;
  600. } else return;
  601. p[ 0 ] = myB;
  602. p[ 1 ].x = ROUNDL( xf ); p[ 1 ].y = ROUNDL( yf );
  603. if ( !( myFlags & EHDCF_JBEVL ) ) {
  604. p[ 2 ].x = ROUNDL( xd ); p[ 2 ].y = ROUNDL( yd );
  605. p[ 3 ].x = ROUNDL( xe ); p[ 3 ].y = ROUNDL( ye );
  606. np = 4;
  607. } else {
  608. p[ 2 ].x = ROUNDL( xe ); p[ 2 ].y = ROUNDL( ye );
  609. np = 3;
  610. } // end else
  611. Register ( p, np );
  612. #if 0
  613. ::SetPixel ( myHDC, p[ 0 ].x, p[ 0 ].y, RGB( 255, 255, 255 ) );
  614. ::SetPixel ( myHDC, p[ 1 ].x, p[ 1 ].y, RGB( 255, 255, 255 ) );
  615. ::SetPixel ( myHDC, p[ 2 ].x, p[ 2 ].y, RGB( 255, 255, 255 ) );
  616. ::SetPixel ( myHDC, p[ 3 ].x, p[ 3 ].y, RGB( 255, 255, 255 ) );
  617. #endif
  618. HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  619. ::Polygon ( myHDC, p, np );
  620. SelectPen( myHDC, hpo );
  621. } // end EHDC :: _Join
  622. BOOL EHDC :: _DrawToEx ( PPOINT p ) {
  623. DWORD i = 0, j, k;
  624. DDAP ddap = { this };
  625. POINT pp[ 4 ];
  626. double dx, dy, dxhw, dyhw, factor;
  627. dx = ( double )( p -> x - myStart.x );
  628. dy = ( double )( p -> y - myStart.y );
  629. if ( dx == 0.0 && dy == 0.0 ) return FALSE;
  630. factor = myPWidth / 2.0 / sqrt ( dx * dx + dy * dy );
  631. dxhw = dy * factor;
  632. dyhw = dx * factor;
  633. pp[ 0 ].x = ROUNDL( myStart.x + dxhw );
  634. pp[ 0 ].y = ROUNDL( myStart.y - dyhw );
  635. pp[ 1 ].x = ROUNDL( myStart.x - dxhw );
  636. pp[ 1 ].y = ROUNDL( myStart.y + dyhw );
  637. pp[ 2 ].x = ROUNDL( p -> x - dxhw );
  638. pp[ 2 ].y = ROUNDL( p -> y + dyhw );
  639. pp[ 3 ].x = ROUNDL( p -> x + dxhw );
  640. pp[ 3 ].y = ROUNDL( p -> y - dyhw );
  641. myIDDA = 0;
  642. myFlags &= ~EHDCF_DDAF;
  643. ddap.pp = myDDA1;
  644. LineDDA ( pp[ 0 ].x, pp[ 0 ].y, pp[ 3 ].x, pp[ 3 ].y, &___auxDDAF, ( LPARAM )&ddap );
  645. k = myIDDA;
  646. myIDDA = 0;
  647. myFlags &= ~EHDCF_DDAF;
  648. ddap.pp = myDDA2;
  649. LineDDA ( pp[ 1 ].x, pp[ 1 ].y, pp[ 2 ].x, pp[ 2 ].y, &___auxDDAF, ( LPARAM )&ddap );
  650. myIDDA = min( k, myIDDA );
  651. HPEN hpo = SelectPen( myHDC, GetStockObject ( NULL_PEN ) );
  652. while ( TRUE ) {
  653. if ( myPRlen == 0 ) {
  654. myPRlen = myPStyle[ myPIndex++ ];
  655. if ( myPIndex == myPNS ) myPIndex = 0;
  656. } // end if
  657. j = i;
  658. while ( myPRlen != 0 && j < myIDDA ) ++j, --myPRlen;
  659. if ( j == myIDDA ) {
  660. myDDA1[ j ] = pp[ 3 ];
  661. myDDA2[ j ] = pp[ 2 ];
  662. } // end if
  663. if ( myFlags & EHDCF_PDRAW ) {
  664. POINT p[ 4 ];
  665. p[ 0 ] = myDDA1[ i ];
  666. p[ 1 ] = myDDA1[ j ];
  667. p[ 2 ] = myDDA2[ j ];
  668. p[ 3 ] = myDDA2[ i ];
  669. Register ( p, 4 );
  670. ::Polygon ( myHDC, p, 4 );
  671. } // end if
  672. if ( myPRlen == 0 )
  673. myFlags ^= EHDCF_PDRAW;
  674. else break;
  675. i = j;
  676. if ( j >= myIDDA ) break;
  677. } // end while
  678. SelectPen( myHDC, hpo );
  679. if ( myPRlen == 0 ) myFlags |= EHDCF_NJOIN;
  680. myA = myB;
  681. myB = myStart;
  682. myStart = *p;
  683. return TRUE;
  684. } // end EHDC :: _DrawToEx
  685. void EHDC :: _LineTo ( PPOINT p ) {
  686. DWORD i = 0;
  687. DDAP ddap = { this };
  688. Register ( p, 1 );
  689. myIDDA = 0;
  690. ddap.pp = myDDA1;
  691. LineDDA ( myStart.x, myStart.y, p -> x, p -> y, &___auxDDAF, ( LPARAM )&ddap );
  692. while ( TRUE ) {
  693. if ( myPRlen == 0 ) {
  694. myPRlen = myPStyle[ myPIndex++ ];
  695. if ( myPIndex == myPNS ) myPIndex = 0;
  696. } // end if
  697. if ( myFlags & EHDCF_PDRAW ) ::MoveToEx ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y, NULL );
  698. while ( myPRlen != 0 && i < myIDDA ) ++i, --myPRlen;
  699. if ( i == myIDDA ) myDDA1[ i ] = *p;
  700. if ( myFlags & EHDCF_PDRAW )
  701. ::LineTo ( myHDC, myDDA1[ i ].x, myDDA1[ i ].y );
  702. if ( myPRlen == 0 )
  703. myFlags ^= EHDCF_PDRAW;
  704. else break;
  705. } // end while
  706. myStart = *p;
  707. } // end EHDC :: _LineTo
  708. void EHDC :: _ETextOut ( int x, int y, void* str, double angle, BOOL fOutline, BOOL fWide ) {
  709. #if 1
  710. int i;
  711. DWORD dwLen;
  712. HPEN hpo;
  713. HBRUSH hbo;
  714. HFONT hfo;
  715. XFORM lXfm, rXfm, xfm;
  716. PXFORM pXfm;
  717. SIZE sz;
  718. double tanVal;
  719. double sinVal;
  720. double cosVal;
  721. LPPOINT lp;
  722. angle = -angle;
  723. tanVal = tan ( myTextSlant ) * myTextVScale;
  724. sinVal = sin ( angle );
  725. cosVal = cos ( angle );
  726. if ( !( myFlags & EHDCF_TPATH ) ) {
  727. hfo = SelectFont( myHDC, myTextFont );
  728. i = myTextNP = _TextPath (
  729. myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
  730. );
  731. SelectFont( myHDC, hfo );
  732. if ( i <= 0 ) return;
  733. if ( myTextBS < myTextNP ) {
  734. dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
  735. if ( myTextPath == NULL )
  736. myTextPath = ( LPPOINT )HeapAlloc (
  737. GetProcessHeap (),
  738. HEAP_GENERATE_EXCEPTIONS, dwLen
  739. );
  740. else
  741. myTextPath = ( LPPOINT )HeapReAlloc (
  742. GetProcessHeap (),
  743. HEAP_GENERATE_EXCEPTIONS,
  744. myTextPath, dwLen
  745. );
  746. myTextBS = myTextNP;
  747. } // end if
  748. myTextType = ( PBYTE )( myTextPath + myTextNP );
  749. _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
  750. lp = myTextPath;
  751. while ( i-- ) {
  752. lp -> y -= sz.cy;
  753. ++lp;
  754. } // end while
  755. } // end if
  756. lXfm.eM11 = ( FLOAT )myTextHScale; lXfm.eM21 = ( FLOAT )-tanVal;
  757. lXfm.eM12 = 0.0F; lXfm.eM22 = ( FLOAT )myTextVScale;
  758. lXfm.eDx = 0.0F;
  759. lXfm.eDy = 0.0F;
  760. rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
  761. rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
  762. rXfm.eDx = 0.0F;
  763. rXfm.eDy = 0.0F;
  764. _XFORMultiply ( &xfm, &lXfm, &rXfm );
  765. rXfm.eM11 = 1.0F; rXfm.eM21 = 0.0F;
  766. rXfm.eM12 = 0.0F; rXfm.eM22 = -1.0F;
  767. rXfm.eDx = ( FLOAT )x;
  768. rXfm.eDy = ( FLOAT )y;
  769. _XFORMultiply ( &lXfm, &xfm, &rXfm );
  770. if ( myFlags & EHDCF_XFORM ) {
  771. _XFORMultiply ( &xfm, &lXfm, &myXform );
  772. pXfm = &xfm;
  773. } else pXfm = &lXfm;
  774. _XFORMApply ( myTextPath, myTextNP, pXfm );
  775. i = myTextNP;
  776. lp = myTextPath;
  777. while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
  778. hpo = SelectPen( myHDC, myTextPen );
  779. if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
  780. if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
  781. BeginPath ( myHDC );
  782. _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
  783. EndPath ( myHDC );
  784. if ( !fOutline ) {
  785. FillPath ( myHDC );
  786. SelectBrush( myHDC, hbo );
  787. } else StrokePath ( myHDC );
  788. SelectPen( myHDC, hpo );
  789. #else
  790. int i;
  791. DWORD dwLen;
  792. HPEN hpo;
  793. HBRUSH hbo;
  794. HFONT hfo;
  795. XFORM lXfm, rXfm, xfm;
  796. PXFORM pXfm;
  797. SIZE sz;
  798. double tanVal;
  799. double sinVal;
  800. double cosVal;
  801. LPPOINT lp;
  802. BOOL fNew = FALSE;
  803. angle = -angle;
  804. tanVal = tan ( myTextSlant );
  805. sinVal = sin ( angle );
  806. cosVal = cos ( angle );
  807. if ( !( myFlags & EHDCF_TPATH ) ) {
  808. hfo = SelectFont( myHDC, myTextFont );
  809. if ( myTextVScale != 1.0 || myTextHScale != 1.0 ) {
  810. LOGFONT lf;
  811. TEXTMETRIC tm;
  812. GetObject ( myTextFont, sizeof ( LOGFONT ), &lf );
  813. GetTextMetrics ( myHDC, &tm );
  814. lf.lfHeight = ROUNDL( lf.lfHeight * myTextVScale );
  815. lf.lfWidth = ROUNDL( lf.lfWidth * myTextHScale );
  816. lf.lfQuality = DRAFT_QUALITY;
  817. if ( lf.lfWidth == 0 )
  818. lf.lfWidth = ROUNDL( tm.tmAveCharWidth * myTextHScale );
  819. SelectFont( myHDC, hfo );
  820. hfo = SelectFont( myHDC, CreateFontIndirect ( &lf ) );
  821. fNew = TRUE;
  822. } // end if
  823. i = myTextNP = _TextPath (
  824. myHDC, 0, 0, str, NULL, NULL, 0, &sz, fWide
  825. );
  826. hfo = SelectFont( myHDC, hfo );
  827. if ( fNew ) DeleteFont( hfo );
  828. if ( i <= 0 ) return;
  829. if ( myTextBS < myTextNP ) {
  830. dwLen = sizeof ( POINT ) * myTextNP + sizeof ( BYTE ) * myTextNP;
  831. if ( myTextPath == NULL )
  832. myTextPath = ( LPPOINT )HeapAlloc (
  833. GetProcessHeap (),
  834. HEAP_GENERATE_EXCEPTIONS, dwLen
  835. );
  836. else
  837. myTextPath = ( LPPOINT )HeapReAlloc (
  838. GetProcessHeap (),
  839. HEAP_GENERATE_EXCEPTIONS,
  840. myTextPath, dwLen
  841. );
  842. myTextBS = myTextNP;
  843. } // end if
  844. myTextType = ( PBYTE )( myTextPath + myTextNP );
  845. _TextPath ( myHDC, 0, 0, str, myTextPath, myTextType, myTextNP, NULL, fWide );
  846. lp = myTextPath;
  847. while ( i-- ) {
  848. lp -> y -= sz.cy;
  849. ++lp;
  850. } // end while
  851. } // end if
  852. lXfm.eM11 = 1.0F; lXfm.eM21 = ( FLOAT )-tanVal;
  853. lXfm.eM12 = 0.0F; lXfm.eM22 = 1.0F;
  854. lXfm.eDx = 0.0F;
  855. lXfm.eDy = 0.0F;
  856. rXfm.eM11 = ( FLOAT ) cosVal; rXfm.eM12 = ( FLOAT )sinVal;
  857. rXfm.eM21 = ( FLOAT )-sinVal; rXfm.eM22 = ( FLOAT )cosVal;
  858. rXfm.eDx = 0.0F;
  859. rXfm.eDy = 0.0F;
  860. _XFORMultiply ( &xfm, &lXfm, &rXfm );
  861. rXfm.eM11 = 1.0F; rXfm.eM21 = 0.0F;
  862. rXfm.eM12 = 0.0F; rXfm.eM22 = -1.0F;
  863. rXfm.eDx = ( FLOAT )x;
  864. rXfm.eDy = ( FLOAT )y;
  865. _XFORMultiply ( &lXfm, &xfm, &rXfm );
  866. if ( myFlags & EHDCF_XFORM ) {
  867. _XFORMultiply ( &xfm, &lXfm, &myXform );
  868. pXfm = &xfm;
  869. } else pXfm = &lXfm;
  870. _XFORMApply ( myTextPath, myTextNP, pXfm );
  871. i = myTextNP;
  872. lp = myTextPath;
  873. while ( i-- ) lp -> y = Y( lp -> y ), ++lp;
  874. hpo = SelectPen( myHDC, myTextPen );
  875. if ( !fOutline ) hbo = SelectBrush( myHDC, myTextBrush );
  876. if ( !( myFlags & EHDCF_TREG ) ) Register ( myTextPath, myTextNP );
  877. BeginPath ( myHDC );
  878. _RenderPath ( myHDC, myTextPath, myTextType, myTextNP );
  879. EndPath ( myHDC );
  880. if ( !fOutline ) {
  881. FillPath ( myHDC );
  882. SelectBrush( myHDC, hbo );
  883. } else StrokePath ( myHDC );
  884. SelectPen( myHDC, hpo );
  885. #endif
  886. } // end EHDC :: _ETextOut
  887. void EHDC :: _PolyTextOut (
  888. int x, int y, void* str, double angle, double margin,
  889. BOOL fOutline, BOOL fWide, BOOL fNofill, BOOL fNoframe
  890. ) {
  891. POINT p[ 4 ];
  892. XFORM lXfm, xfm;
  893. PXFORM pXfm;
  894. SIZE sz;
  895. HFONT hfo;
  896. DWORD dwFlags;
  897. TEXTMETRIC tm;
  898. double sinVal = sin ( angle );
  899. double cosVal = cos ( angle );
  900. double tanVal = -tan ( myTextSlant );
  901. double height;
  902. hfo = SelectFont( myHDC, myTextFont );
  903. if ( !fWide )
  904. GetTextExtentPoint32A (
  905. myHDC, ( char* )str, lstrlenA ( ( char* )str ), &sz
  906. );
  907. else
  908. GetTextExtentPoint32W (
  909. myHDC, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), &sz
  910. );
  911. GetTextMetrics ( myHDC, &tm );
  912. SelectFont( myHDC, hfo );
  913. sz.cy -= tm.tmInternalLeading;
  914. p[ 0 ].x = 0;
  915. p[ 0 ].y = ROUNDL( sz.cy * myTextVScale );
  916. p[ 1 ].x = ROUNDL( sz.cx * myTextHScale );
  917. p[ 1 ].y = p[ 0 ].y;
  918. p[ 2 ].x = p[ 1 ].x;
  919. p[ 2 ].y = 0;
  920. p[ 3 ].x = 0;
  921. p[ 3 ].y = 0;
  922. tanVal *= p[ 1 ].y;
  923. if ( myTextSlant < 0.0F ) {
  924. p[ 0 ].x -= ( LONG )tanVal;
  925. p[ 3 ].x -= ( LONG )tanVal;
  926. } else {
  927. p[ 1 ].x -= ( LONG )tanVal;
  928. p[ 2 ].x -= ( LONG )tanVal;
  929. } /* end else */
  930. height = ROUNDL( p[ 0 ].y * margin / 2.0 );
  931. p[ 0 ].x = ROUNDL( p[ 0 ].x - height );
  932. p[ 0 ].y = ROUNDL( p[ 0 ].y + height );
  933. p[ 1 ].x = ROUNDL( p[ 1 ].x + height );
  934. p[ 1 ].y = ROUNDL( p[ 1 ].y + height );
  935. p[ 2 ].x = ROUNDL( p[ 2 ].x + height );
  936. p[ 2 ].y = ROUNDL( p[ 2 ].y - height );
  937. p[ 3 ].x = ROUNDL( p[ 3 ].x - height );
  938. p[ 3 ].y = ROUNDL( p[ 3 ].y - height );
  939. lXfm.eM11 = ( FLOAT ) cosVal; lXfm.eM12 = ( FLOAT )sinVal;
  940. lXfm.eM21 = ( FLOAT )-sinVal; lXfm.eM22 = ( FLOAT )cosVal;
  941. lXfm.eDx = ( FLOAT )x;
  942. lXfm.eDy = ( FLOAT )y;
  943. if ( myFlags & EHDCF_XFORM ) {
  944. _XFORMultiply ( &xfm, &lXfm, &myXform );
  945. pXfm = &xfm;
  946. } else pXfm = &lXfm;
  947. _XFORMApply ( p, 4, pXfm );
  948. dwFlags = ( myFlags & EHDCF_XFORM );
  949. myFlags &= ~EHDCF_XFORM;
  950. if ( fNofill )
  951. Polyline ( p, 4, TRUE );
  952. else
  953. Polygon ( p, 4, fNoframe ? POLYF_NOEDGE : 0 );
  954. myFlags |= dwFlags;
  955. _ETextOut ( x, y, str, angle, fOutline, fWide );
  956. } // end EHDC :: _PolyTextOut
  957. void EHDC :: Register ( LPPOINT lpPts, int nPts ) {
  958. while ( nPts-- ) {
  959. if ( lpPts -> x < myURect.left )
  960. myURect.left = lpPts -> x - 1;
  961. else if ( lpPts -> x > myURect.right )
  962. myURect.right = lpPts -> x + 2;
  963. if ( lpPts -> y < myURect.top )
  964. myURect.top = lpPts -> y - 1;
  965. else if ( lpPts -> y > myURect.bottom )
  966. myURect.bottom = lpPts -> y + 2;
  967. ++lpPts;
  968. } // end while
  969. } // end EHDC :: _Register
  970. //+++//
  971. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
  972. //+++//
  973. static void WINAPI _XFORMultiply ( PXFORM res, PXFORM left, PXFORM right ) {
  974. res -> eM11 = left -> eM11 * right -> eM11 + left -> eM12 * right -> eM21;
  975. res -> eM12 = left -> eM11 * right -> eM12 + left -> eM12 * right -> eM22;
  976. res -> eDx = left -> eDx * right -> eM11 + left -> eDy * right -> eM21 + right -> eDx;
  977. res -> eM21 = left -> eM21 * right -> eM11 + left -> eM22 * right -> eM21;
  978. res -> eM22 = left -> eM21 * right -> eM12 + left -> eM22 * right -> eM22;
  979. res -> eDy = left -> eDx * right -> eM12 + left -> eDy * right -> eM22 + right -> eDy;
  980. } /* end _XFORMultiply */
  981. static void WINAPI _XFORMApply ( PPOINT pp, int n, PXFORM xf ) {
  982. int i;
  983. double dx, dy;
  984. for ( i = 0; i < n; ++i ) {
  985. dx = pp[ i ].x * xf -> eM11 + pp[ i ].y * xf -> eM21 + xf -> eDx;
  986. dy = pp[ i ].x * xf -> eM12 + pp[ i ].y * xf -> eM22 + xf -> eDy;
  987. pp[ i ].x = ROUNDL( dx );
  988. pp[ i ].y = ROUNDL( dy );
  989. } /* end for */
  990. } /* end _XFORMApply */
  991. static void WINAPI _XFORMApplyf ( PFPOINT pp, int n, PXFORM xf ) {
  992. int i;
  993. double dx, dy;
  994. for ( i = 0; i < n; ++i ) {
  995. dx = pp[ i ].x * xf -> eM11 + pp[ i ].y * xf -> eM21 + xf -> eDx;
  996. dy = pp[ i ].x * xf -> eM12 + pp[ i ].y * xf -> eM22 + xf -> eDy;
  997. pp[ i ].x = ( FLOAT )dx;
  998. pp[ i ].y = ( FLOAT )dy;
  999. } /* end for */
  1000. } /* end _XFORMApply */
  1001. static void WINAPI _RenderPath ( HDC hdc, LPPOINT lpPts, PBYTE lpType, int nPts ) {
  1002. LPPOINT pp;
  1003. for ( int i = 0; i < nPts; ++i ) {
  1004. switch ( lpType[ i ] ) {
  1005. case PT_MOVETO:
  1006. MoveToEx ( hdc, lpPts[ i ].x, lpPts[ i ].y, NULL );
  1007. pp = &lpPts[ i ];
  1008. continue;
  1009. case PT_LINETO:
  1010. case PT_LINETO | PT_CLOSEFIGURE:
  1011. LineTo ( hdc, lpPts[ i ].x, lpPts[ i ].y );
  1012. goto testClose;
  1013. case PT_BEZIERTO:
  1014. case PT_BEZIERTO | PT_CLOSEFIGURE:
  1015. PolyBezierTo ( hdc, &lpPts[ i ], 3 );
  1016. i += 2;
  1017. testClose:
  1018. if ( lpType[ i ] & PT_CLOSEFIGURE ) LineTo ( hdc, pp -> x, pp -> y );
  1019. } /* end switch */
  1020. } /* end for */
  1021. } /* end _RenderPath */
  1022. static int WINAPI _TextPath (
  1023. HDC hdc, int x, int y, void* str, LPPOINT lpPts, PBYTE lpType,
  1024. int nPts, PSIZE pSz, BOOL fWide
  1025. ) {
  1026. int retVal;
  1027. if ( lpPts == NULL ) {
  1028. int bmo = SetBkMode ( hdc, TRANSPARENT );
  1029. BeginPath ( hdc );
  1030. if ( !fWide )
  1031. TextOutA ( hdc, x, y, ( char* )str, lstrlenA ( ( char* )str ) );
  1032. else
  1033. TextOutW ( hdc, x, y, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ) );
  1034. EndPath ( hdc );
  1035. SetBkMode ( hdc, bmo );
  1036. } /* end if */
  1037. retVal = GetPath ( hdc, lpPts, lpType, nPts );
  1038. if ( pSz != NULL )
  1039. if ( !fWide )
  1040. GetTextExtentPoint32A ( hdc, ( char* )str, lstrlenA ( ( char* )str ), pSz );
  1041. else
  1042. GetTextExtentPoint32W ( hdc, ( wchar_t* )str, lstrlenW ( ( wchar_t* )str ), pSz );
  1043. return retVal;
  1044. } /* end _TextPath */
  1045. VOID CALLBACK ___auxDDAF ( int x, int y, LPARAM lpParam ) {
  1046. PDDAP p = ( PDDAP )lpParam;
  1047. p -> pp[ p -> _this -> myIDDA ].x = x;
  1048. p -> pp[ p -> _this -> myIDDA++ ].y = y;
  1049. if ( p -> _this -> myIDDA >= p -> _this -> myNDDA ) {
  1050. p -> _this -> myDDA1 = ( PPOINT )HeapReAlloc (
  1051. GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
  1052. p -> _this -> myDDA1, p -> _this -> myNDDA <<= 1
  1053. );
  1054. p -> _this -> myDDA2 = ( PPOINT )HeapReAlloc (
  1055. GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
  1056. p -> _this -> myDDA2, p -> _this -> myNDDA <<= 1
  1057. );
  1058. } // end if
  1059. } // end ___auxDDAF
  1060. //+++//
  1061. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//