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.

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