Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

641 lines
19 KiB

  1. /*****************************************************************************
  2. *
  3. * text - Entry points for Win32 to Win 16 converter
  4. *
  5. * Date: 7/1/91
  6. * Author: Jeffrey Newman (c-jeffn)
  7. *
  8. * Copyright 1991 Microsoft Corp
  9. *****************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. // GillesK, We don't have access to RtlUnicodeToMultiByteN so this call
  13. // has been converted to a MultiByteToWideChar... We don't need to import
  14. // anymore
  15. /*
  16. __declspec(dllimport)
  17. ULONG
  18. __stdcall
  19. RtlUnicodeToMultiByteN(
  20. PCHAR MultiByteString,
  21. ULONG MaxBytesInMultiByteString,
  22. PULONG BytesInMultiByteString,
  23. PWSTR UnicodeString,
  24. ULONG BytesInUnicodeString
  25. );
  26. ULONG
  27. __stdcall
  28. RtlUnicodeToMultiByteSize(
  29. PULONG BytesInMultiByteString,
  30. PWSTR UnicodeString,
  31. ULONG BytesInUnicodeString
  32. );
  33. */
  34. extern fnSetVirtualResolution pfnSetVirtualResolution;
  35. DWORD GetCodePage(HDC hdc)
  36. {
  37. DWORD FAR *lpSrc = (DWORD FAR *)UIntToPtr(GetTextCharsetInfo(hdc, 0, 0));
  38. CHARSETINFO csi;
  39. TranslateCharsetInfo(lpSrc, &csi, TCI_SRCCHARSET);
  40. return csi.ciACP;
  41. }
  42. /***************************************************************************
  43. * ExtTextOut - Win32 to Win16 Metafile Converter Entry Point
  44. **************************************************************************/
  45. BOOL WINAPI DoExtTextOut
  46. (
  47. PLOCALDC pLocalDC,
  48. INT x, // Initial x position
  49. INT y, // Initial y position
  50. DWORD flOpts, // Options
  51. PRECTL prcl, // Clipping rectangle
  52. PWCH pwch, // Character array
  53. DWORD cch, // Character count
  54. PLONG pDx, // Inter-Character spacing
  55. DWORD iGraphicsMode, // Graphics mode
  56. INT mrType // Either EMR_EXTTEXTOUTW (Unicode)
  57. // or EMR_EXTTEXTOUTA (Ansi)
  58. )
  59. {
  60. INT i;
  61. BOOL b;
  62. RECTS rcs;
  63. POINTL ptlRef;
  64. UINT fTextAlign;
  65. WORD fsOpts;
  66. PCHAR pch, pchAlloc;
  67. PPOINTL pptl;
  68. POINTL ptlAdjust;
  69. BOOL bAdjustAlignment;
  70. ULONG nANSIChars;
  71. PCHAR pDBCSBuffer = NULL;
  72. POINTL p = {x, y};
  73. pptl = (PPOINTL) NULL;
  74. fsOpts = (WORD) flOpts;
  75. pchAlloc = (PCHAR) NULL;
  76. bAdjustAlignment = FALSE;
  77. b = FALSE; // assume failure
  78. ASSERTGDI(mrType == EMR_EXTTEXTOUTA || mrType == EMR_EXTTEXTOUTW,
  79. "MF3216: DoExtTextOut: bad record type");
  80. // We do not handle the advanced graphics mode here except when
  81. // we are in a path!
  82. // If we're recording the drawing orders for a path
  83. // then just pass the drawing order to the helper DC.
  84. // Do not emit any Win16 drawing orders.
  85. if (pLocalDC->flags & RECORDING_PATH)
  86. {
  87. // The helper DC is in the advanced graphics mode. We need to set
  88. // it to the compatible graphics mode temporarily if necessary.
  89. if (iGraphicsMode != GM_ADVANCED)
  90. SetGraphicsMode(pLocalDC->hdcHelper, iGraphicsMode);
  91. if (pfnSetVirtualResolution == NULL)
  92. {
  93. if (!bXformRWorldToRDev(pLocalDC, &p, 1))
  94. {
  95. return FALSE;
  96. }
  97. }
  98. if (mrType == EMR_EXTTEXTOUTA)
  99. b = ExtTextOutA
  100. (
  101. pLocalDC->hdcHelper,
  102. (int) p.x,
  103. (int) p.y,
  104. (UINT) flOpts,
  105. (LPRECT) prcl,
  106. (LPSTR) pwch,
  107. (int) cch,
  108. (LPINT) pDx
  109. );
  110. else
  111. b = ExtTextOutW
  112. (
  113. pLocalDC->hdcHelper,
  114. (int) p.x,
  115. (int) p.y,
  116. (UINT) flOpts,
  117. (LPRECT) prcl,
  118. (LPWSTR) pwch,
  119. (int) cch,
  120. (LPINT) pDx
  121. );
  122. // Restore the graphics mode.
  123. if (iGraphicsMode != GM_ADVANCED)
  124. SetGraphicsMode(pLocalDC->hdcHelper, GM_ADVANCED);
  125. return(b);
  126. }
  127. // If the string uses the current position, make sure that the metafile
  128. // has the same current position as that of the helper DC.
  129. fTextAlign = GetTextAlign(pLocalDC->hdcHelper);
  130. if (fTextAlign & TA_UPDATECP)
  131. {
  132. POINT ptCP;
  133. // Update the current position in the converted metafile if
  134. // it is different from that of the helper DC. See notes
  135. // in DoMoveTo().
  136. if (!GetCurrentPositionEx(pLocalDC->hdcHelper, &ptCP))
  137. goto exit_DoExtTextOut;
  138. // We don't need to update to change the clip region on the helper
  139. // DC in Win9x anymore because we are using a bitmap and not the
  140. // screen anymore. What we do need to do, is get the current position
  141. // of the cursor and convert it back to Logical Units... Make the
  142. // call on the helper DC and the convert the position back to
  143. // device units and save it.
  144. if (pfnSetVirtualResolution == NULL)
  145. {
  146. if (!bXformRDevToRWorld(pLocalDC, (PPOINTL) &ptCP, 1))
  147. return(b);
  148. }
  149. // Make sure that the converted metafile has the same CP as the
  150. // helper DC.
  151. if (!bValidateMetaFileCP(pLocalDC, ptCP.x, ptCP.y))
  152. goto exit_DoExtTextOut;
  153. // Initialize the XY start position.
  154. x = ptCP.x;
  155. y = ptCP.y;
  156. }
  157. // Transform the XY start position.
  158. ptlRef.x = x;
  159. ptlRef.y = y;
  160. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) &ptlRef, 1))
  161. goto exit_DoExtTextOut;
  162. // If we have an opaque/clipping rectangle, transform it.
  163. // If we have a strange transform, we will do the rectangle at this time.
  164. if (fsOpts & (ETO_OPAQUE | ETO_CLIPPED))
  165. {
  166. RECTL rcl;
  167. rcl = *prcl ;
  168. if (!(pLocalDC->flags & STRANGE_XFORM))
  169. {
  170. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) &rcl, 2))
  171. goto exit_DoExtTextOut;
  172. // The overflow test has been done in the xform.
  173. rcs.left = (SHORT) rcl.left;
  174. rcs.top = (SHORT) rcl.top;
  175. rcs.right = (SHORT) rcl.right;
  176. rcs.bottom = (SHORT) rcl.bottom;
  177. }
  178. else
  179. {
  180. if (fsOpts & ETO_OPAQUE)
  181. {
  182. LONG lhpn32;
  183. LONG lhbr32;
  184. INT ihW32Br;
  185. LOGBRUSH lbBkColor;
  186. // Remember the previous pen and brush
  187. lhpn32 = pLocalDC->lhpn32;
  188. lhbr32 = pLocalDC->lhbr32;
  189. if (DoSelectObject(pLocalDC, ENHMETA_STOCK_OBJECT | NULL_PEN))
  190. {
  191. lbBkColor.lbStyle = BS_SOLID;
  192. lbBkColor.lbColor = pLocalDC->crBkColor;
  193. lbBkColor.lbHatch = 0;
  194. // Get an unused W32 object index.
  195. ihW32Br = pLocalDC->cW32ToW16ObjectMap - (STOCK_LAST + 1) - 1;
  196. if (DoCreateBrushIndirect(pLocalDC, ihW32Br, &lbBkColor))
  197. {
  198. if (DoSelectObject(pLocalDC, ihW32Br))
  199. {
  200. if (DoRectangle(pLocalDC, rcl.left, rcl.top, rcl.right, rcl.bottom))
  201. fsOpts &= ~ETO_OPAQUE;
  202. // Restore the previous brush.
  203. if (!DoSelectObject(pLocalDC, lhbr32))
  204. ASSERTGDI(FALSE,
  205. "MF3216: DoExtTextOut, DoSelectObject failed");
  206. }
  207. if (!DoDeleteObject(pLocalDC, ihW32Br))
  208. ASSERTGDI(FALSE,
  209. "MF3216: DoExtTextOut, DoDeleteObject failed");
  210. }
  211. // Restore the previous pen.
  212. if (!DoSelectObject(pLocalDC, lhpn32))
  213. ASSERTGDI(FALSE,
  214. "MF3216: DoExtTextOut, DoSelectObject failed");
  215. }
  216. // Check if the rectangle is drawn.
  217. if (fsOpts & ETO_OPAQUE)
  218. goto exit_DoExtTextOut;
  219. }
  220. if (fsOpts & ETO_CLIPPED)
  221. {
  222. // Save the DC so that we can restore it when we are done
  223. if (!DoSaveDC(pLocalDC))
  224. goto exit_DoExtTextOut;
  225. fsOpts &= ~ETO_CLIPPED; // need to restore dc
  226. if (!DoClipRect(pLocalDC, rcl.left, rcl.top,
  227. rcl.right, rcl.bottom, EMR_INTERSECTCLIPRECT))
  228. goto exit_DoExtTextOut;
  229. }
  230. }
  231. }
  232. // Convert the Unicode to Ansi.
  233. if (mrType == EMR_EXTTEXTOUTW)
  234. {
  235. // Get the codepage from the helperDC since the proper font and code page should have been selected.
  236. DWORD dwCP = GetCodePage(pLocalDC->hdcHelper);
  237. nANSIChars = WideCharToMultiByte(dwCP, 0, pwch, cch, NULL, 0, NULL, NULL);
  238. if (nANSIChars == cch)
  239. {
  240. pch = pchAlloc = (PCHAR) LocalAlloc(LMEM_FIXED, cch * sizeof(BYTE)) ;
  241. if (pch == (PCHAR) NULL)
  242. {
  243. RIPS("MF3216: ExtTextOut, pch LocalAlloc failed\n") ;
  244. goto exit_DoExtTextOut;
  245. }
  246. WideCharToMultiByte(dwCP, 0, pwch, cch, pch, cch, NULL, NULL);
  247. }
  248. else
  249. {
  250. // DBCS char string
  251. UINT cjBufferSize;
  252. // we want DX array on a DWORD boundary
  253. cjBufferSize = ((nANSIChars+3)/4) * 4 * (sizeof(char) + sizeof(LONG));
  254. pchAlloc = pDBCSBuffer = LocalAlloc(LMEM_FIXED, cjBufferSize);
  255. if (pDBCSBuffer)
  256. {
  257. // start munging passed in parameters
  258. mrType = EMR_EXTTEXTOUTA;
  259. WideCharToMultiByte(dwCP, 0, pwch, cch, pDBCSBuffer, nANSIChars, NULL, NULL);
  260. pwch = (PWCH) pDBCSBuffer;
  261. pch = (PCHAR) pwch;
  262. cch = nANSIChars;
  263. if (pDx)
  264. {
  265. ULONG ii, jj;
  266. PULONG pDxTmp = (PLONG) &pDBCSBuffer[((nANSIChars+3)/4)*4];
  267. for(ii=jj=0; ii < nANSIChars; ii++, jj++)
  268. {
  269. pDxTmp[ii] = pDx[jj];
  270. // Use IsDBCSLeadByteEx to be able to specify the codepage
  271. if(IsDBCSLeadByteEx(dwCP, pDBCSBuffer[ii]))
  272. {
  273. pDxTmp[++ii] = 0;
  274. }
  275. }
  276. pDx = pDxTmp;
  277. }
  278. }
  279. else
  280. {
  281. goto exit_DoExtTextOut;
  282. }
  283. }
  284. }
  285. else
  286. {
  287. pch = (PCHAR) pwch ;
  288. }
  289. // Transform the intercharacter spacing information.
  290. // Allocate an array of (cch + 1) points to transform the points in,
  291. // and copy the points to the array.
  292. // ATTENTION: The following will not work if the current font has a vertical default
  293. // baseline
  294. pptl = (PPOINTL) LocalAlloc(LMEM_FIXED, (cch + 1) * sizeof(POINTL));
  295. if (pptl == (PPOINTL) NULL)
  296. {
  297. RIPS("MF3216: ExtTextOut, pptl LocalAlloc failed\n") ;
  298. goto exit_DoExtTextOut;
  299. }
  300. pptl[0].x = x;
  301. pptl[0].y = y;
  302. for (i = 1; i < (INT) cch + 1; i++)
  303. {
  304. pptl[i].x = pptl[i-1].x + pDx[i-1];
  305. pptl[i].y = y;
  306. }
  307. // If there is no rotation or shear then we can
  308. // output the characters as a string.
  309. // On the other hand, if there is rotation or shear then we
  310. // have to output each character independently.
  311. if (!(pLocalDC->flags & STRANGE_XFORM))
  312. {
  313. // Win31 does not do text alignment correctly in some transforms.
  314. // It performs alignment in device space but win32 does it in the
  315. // notional space. As a result, a win32 TextOut call may produce
  316. // different output than a similar call in win31. We cannot
  317. // convert this correctly since if we make it works on win31,
  318. // it will not work on wow!
  319. PSHORT pDx16;
  320. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) pptl, (INT) cch + 1))
  321. goto exit_DoExtTextOut;
  322. // Convert it to the Dx array. We do not need to compute it
  323. // as a vector since we have a scaling transform here.
  324. pDx16 = (PSHORT) pptl;
  325. for (i = 0; i < (INT) cch; i++)
  326. pDx16[i] = (SHORT) (pptl[i+1].x - pptl[i].x);
  327. // Emit the Win16 ExtTextOut metafile record.
  328. if (!bEmitWin16ExtTextOut(pLocalDC,
  329. (SHORT) ptlRef.x, (SHORT) ptlRef.y,
  330. fsOpts, &rcs, (PSTR) pch, (SHORT) cch,
  331. (PWORD) pDx16))
  332. goto exit_DoExtTextOut;
  333. }
  334. else
  335. {
  336. // Deal with alignment in the world space. We should really
  337. // do it in the notional space but with escapement and angles,
  338. // things gets complicated pretty easily. We will try
  339. // our best to make it work in the common case. We will not
  340. // worry about escapement and angles.
  341. ptlAdjust.x = 0;
  342. ptlAdjust.y = 0;
  343. switch (fTextAlign & (TA_LEFT | TA_RIGHT | TA_CENTER))
  344. {
  345. case TA_LEFT: // default, no need to adjust x's
  346. break;
  347. case TA_RIGHT: // shift the string by the string length
  348. bAdjustAlignment = TRUE;
  349. ptlAdjust.x = pptl[0].x - pptl[cch+1].x;
  350. break;
  351. case TA_CENTER: // shift the string to the center
  352. bAdjustAlignment = TRUE;
  353. ptlAdjust.x = (pptl[0].x - pptl[cch+1].x) / 2;
  354. break;
  355. }
  356. // We will not adjust for the vertical alignment in the strange
  357. // transform case. We cannot rotate the glyphs in any case.
  358. #if 0
  359. switch (fTextAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE))
  360. {
  361. case TA_TOP: // default, no need to adjust y's
  362. break;
  363. case TA_BOTTOM:
  364. ptlAdjust.y = -logfont.height;
  365. break;
  366. case TA_BASELINE:
  367. ptlAdjust.y = -(logfont.height - logfont.baseline);
  368. break;
  369. }
  370. #endif // 0
  371. // Adjust the character positions taking into account the alignment.
  372. for (i = 0; i < (INT) cch + 1; i++)
  373. {
  374. pptl[i].x += ptlAdjust.x;
  375. pptl[i].y += ptlAdjust.y;
  376. }
  377. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) pptl, (INT) cch + 1))
  378. goto exit_DoExtTextOut;
  379. // Reset the alignment since it has been accounted for.
  380. if (bAdjustAlignment)
  381. if (!bEmitWin16SetTextAlign(pLocalDC,
  382. (WORD) ((fTextAlign & ~(TA_LEFT | TA_RIGHT | TA_CENTER)) | TA_LEFT)))
  383. goto exit_DoExtTextOut;
  384. // Output the characters one at a time.
  385. for (i = 0 ; i < (INT) cch ; i++)
  386. {
  387. ASSERTGDI(!(fsOpts & (ETO_OPAQUE | ETO_CLIPPED)),
  388. "mf3216: DoExtTextOut: rectangle not expected");
  389. if (!bEmitWin16ExtTextOut(pLocalDC,
  390. (SHORT) pptl[i].x, (SHORT) pptl[i].y,
  391. fsOpts, (PRECTS) NULL,
  392. (PSTR) &pch[i], 1, (PWORD) NULL))
  393. goto exit_DoExtTextOut;
  394. }
  395. }
  396. // Everything is golden.
  397. b = TRUE;
  398. // Cleanup and return.
  399. exit_DoExtTextOut:
  400. // Restore the alignment.
  401. if (bAdjustAlignment)
  402. (void) bEmitWin16SetTextAlign(pLocalDC, (WORD) fTextAlign);
  403. if ((flOpts & ETO_CLIPPED) && !(fsOpts & ETO_CLIPPED))
  404. (void) DoRestoreDC(pLocalDC, -1);
  405. if (pchAlloc)
  406. LocalFree((HANDLE) pchAlloc);
  407. if (pptl)
  408. LocalFree((HANDLE) pptl);
  409. // Update the current position if the call succeeds.
  410. if (b)
  411. {
  412. if (fTextAlign & TA_UPDATECP)
  413. {
  414. // Update the helper DC.
  415. INT iRet;
  416. POINTL pos;
  417. // We don't need to update to change the clip region on the helper
  418. // DC in Win9x anymore because we are using a bitmap and not the
  419. // screen anymore. What we do need to do, is get the current position
  420. // of the cursor and convert it back to Logical Units... Make the
  421. // call on the helper DC and the convert the position back to
  422. // device units and save it.
  423. if (pfnSetVirtualResolution == NULL)
  424. {
  425. if (GetCurrentPositionEx(pLocalDC->hdcHelper, (LPPOINT) &pos))
  426. {
  427. b = bXformRDevToRWorld(pLocalDC, &pos, 1);
  428. if (!b)
  429. {
  430. return(b);
  431. }
  432. MoveToEx(pLocalDC->hdcHelper, pos.x, pos.y, NULL);
  433. }
  434. }
  435. // Finally, update the CP.
  436. if (mrType == EMR_EXTTEXTOUTA)
  437. ExtTextOutA
  438. (
  439. pLocalDC->hdcHelper,
  440. (int) x,
  441. (int) y,
  442. (UINT) flOpts,
  443. (LPRECT) prcl,
  444. (LPSTR) pwch,
  445. (int) cch,
  446. (LPINT) pDx
  447. );
  448. else
  449. ExtTextOutW
  450. (
  451. pLocalDC->hdcHelper,
  452. (int) x,
  453. (int) y,
  454. (UINT) flOpts,
  455. (LPRECT) prcl,
  456. (LPWSTR) pwch,
  457. (int) cch,
  458. (LPINT) pDx
  459. );
  460. // Make the metafile CP invalid to force update
  461. // when it is used next time
  462. pLocalDC->ptCP.x = MAXLONG ;
  463. pLocalDC->ptCP.y = MAXLONG ;
  464. // Set the position in the helperDC back to Device units
  465. if (pfnSetVirtualResolution == NULL)
  466. {
  467. if (GetCurrentPositionEx(pLocalDC->hdcHelper, (LPPOINT) &pos))
  468. {
  469. b = bXformRWorldToRDev(pLocalDC, &pos, 1);
  470. if (!b)
  471. {
  472. return(b);
  473. }
  474. MoveToEx(pLocalDC->hdcHelper, pos.x, pos.y, NULL);
  475. }
  476. }
  477. }
  478. }
  479. return(b);
  480. }
  481. /***************************************************************************
  482. * SetTextAlign - Win32 to Win16 Metafile Converter Entry Point
  483. **************************************************************************/
  484. BOOL WINAPI DoSetTextAlign
  485. (
  486. PLOCALDC pLocalDC,
  487. DWORD fMode
  488. )
  489. {
  490. BOOL b ;
  491. // Do it to the helper DC. It needs this in a path bracket
  492. // and to update current position correctly.
  493. SetTextAlign(pLocalDC->hdcHelper, (UINT) fMode);
  494. // Emit the Win16 metafile drawing order.
  495. b = bEmitWin16SetTextAlign(pLocalDC, LOWORD(fMode)) ;
  496. return(b) ;
  497. }
  498. /***************************************************************************
  499. * SetTextColor - Win32 to Win16 Metafile Converter Entry Point
  500. **************************************************************************/
  501. BOOL WINAPI DoSetTextColor
  502. (
  503. PLOCALDC pLocalDC,
  504. COLORREF crColor
  505. )
  506. {
  507. BOOL b ;
  508. pLocalDC->crTextColor = crColor ; // used by ExtCreatePen
  509. // Emit the Win16 metafile drawing order.
  510. b = bEmitWin16SetTextColor(pLocalDC, crColor) ;
  511. return(b) ;
  512. }