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.

387 lines
11 KiB

  1. //// DspDraws.CPP - Display plaintext using DrawString API
  2. //
  3. //
  4. #include "precomp.hxx"
  5. #include "global.h"
  6. #include "gdiplus.h"
  7. /*
  8. REAL GetEmHeightInPoints(
  9. const Font *font,
  10. const Graphics *graphics
  11. )
  12. {
  13. FontFamily family;
  14. font->GetFamily(&family);
  15. INT style = font->GetStyle();
  16. REAL pixelsPerPoint = REAL(graphics->GetDpiY() / 72.0);
  17. REAL lineSpacingInPixels = font->GetHeight(graphics);
  18. REAL emHeightInPixels = lineSpacingInPixels * family.GetEmHeight(style)
  19. / family.GetLineSpacing(style);
  20. REAL emHeightInPoints = emHeightInPixels / pixelsPerPoint;
  21. return emHeightInPoints;
  22. }
  23. */
  24. void PaintDrawString(
  25. HDC hdc,
  26. int *piY,
  27. RECT *prc,
  28. int iLineHeight) {
  29. int icpLineStart; // First character of line
  30. int icpLineEnd; // End of line (end of buffer or index of CR character)
  31. // Establish available width and height in device coordinates
  32. int plainTextWidth = prc->right - prc->left;
  33. int plainTextHeight = prc->bottom - *piY;
  34. // Draw a simple figure in the world coordinate system
  35. Graphics *g = NULL;
  36. Metafile *metafile = NULL;
  37. if (g_testMetafile)
  38. {
  39. metafile = new Metafile(L"c:\\texttest.emf", hdc);
  40. g = new Graphics(metafile);
  41. }
  42. else
  43. {
  44. g = new Graphics(hdc);
  45. }
  46. Matrix matrix;
  47. g->ResetTransform();
  48. g->SetPageUnit(UnitPixel);
  49. g->TranslateTransform(REAL(prc->left), REAL(*piY));
  50. g->SetSmoothingMode(g_SmoothingMode);
  51. g->SetTextContrast(g_GammaValue);
  52. g->SetTextRenderingHint(g_TextMode);
  53. SolidBrush whiteBrush(Color(0xff, 0xff, 0xff));
  54. Color grayColor(0xc0, 0xc0, 0xc0);
  55. SolidBrush grayBrush(grayColor);
  56. Pen grayPen(&grayBrush, 1.0);
  57. Color blackColor(0, 0, 0);
  58. SolidBrush blackBrush(blackColor);
  59. Pen blackPen(&blackBrush, 1.0);
  60. // Clear the background
  61. RectF rEntire(0, 0, REAL(plainTextWidth), REAL(plainTextHeight));
  62. g->FillRectangle(g_textBackBrush, rEntire);
  63. // Apply selected world transform, adjusted to middle of the plain text
  64. // area.
  65. g->SetTransform(&g_WorldTransform);
  66. g->TranslateTransform(
  67. REAL(prc->left + plainTextWidth/2),
  68. REAL(*piY + plainTextHeight/2),
  69. MatrixOrderAppend);
  70. Font font(
  71. &FontFamily(g_style[0].faceName),
  72. REAL(g_style[0].emSize),
  73. g_style[0].style,
  74. g_fontUnit
  75. );
  76. // Put some text in the middle
  77. RectF textRect(REAL(-25*plainTextWidth/100), REAL(-25*plainTextHeight/100),
  78. REAL( 50*plainTextWidth/100), REAL( 50*plainTextHeight/100));
  79. StringFormat format(g_typographic ? StringFormat::GenericTypographic() : StringFormat::GenericDefault());
  80. format.SetFormatFlags(g_formatFlags);
  81. format.SetTrimming(g_lineTrim);
  82. format.SetAlignment(g_align);
  83. format.SetLineAlignment(g_lineAlign);
  84. format.SetHotkeyPrefix(g_hotkey);
  85. format.SetDigitSubstitution(g_Language, g_DigitSubstituteMode);
  86. REAL tab[3] = {textRect.Width/4,
  87. textRect.Width*3/16,
  88. textRect.Width*1/8};
  89. format.SetTabStops(0.0, sizeof(tab)/sizeof(REAL), tab);
  90. if (!g_AutoDrive)
  91. {
  92. // Display selection region if any
  93. if (g_iFrom || g_iTo)
  94. {
  95. if (g_RangeCount > 0)
  96. {
  97. Region regions[MAX_RANGE_COUNT];
  98. format.SetMeasurableCharacterRanges(g_RangeCount, g_Ranges);
  99. Status status = g->MeasureCharacterRanges(g_wcBuf, g_iTextLen, &font, textRect, &format, g_RangeCount, regions);
  100. if (status == Ok)
  101. {
  102. Pen lightGrayPen(&SolidBrush(Color(0x80,0x80,0x80)), 1.0);
  103. INT rangeCount = g_RangeCount;
  104. Matrix identity;
  105. while (rangeCount > 0)
  106. {
  107. /*INT scanCount = regions[rangeCount - 1].GetRegionScansCount(&identity);
  108. RectF *boxes = new RectF[scanCount];
  109. regions[rangeCount - 1].GetRegionScans(&identity, boxes, &scanCount);
  110. for (INT i = 0; i < scanCount; i++)
  111. {
  112. g->DrawRectangle(&lightGrayPen, boxes[i]);
  113. }
  114. delete [] boxes;
  115. rangeCount--;
  116. */
  117. g->FillRegion(&SolidBrush(Color(0xc0,0xc0,0xc0)), &regions[--rangeCount]);
  118. }
  119. }
  120. }
  121. }
  122. }
  123. if (!g_AutoDrive)
  124. {
  125. // Outline the layout rectangle
  126. g->DrawRectangle(&grayPen, textRect);
  127. // Measure and outline the text
  128. RectF boundingBox;
  129. INT codepointsFitted;
  130. INT linesFilled;
  131. g->MeasureString(
  132. g_wcBuf, g_iTextLen, &font, textRect, &format, // In
  133. &boundingBox, &codepointsFitted, &linesFilled); // Out
  134. Pen lightGrayPen(&SolidBrush(Color(0x80,0x80,0x80)), 1.0);
  135. g->DrawRectangle(&lightGrayPen, boundingBox);
  136. // Also draw horizontal and vertical lines away from the rectangle
  137. // corners - this is to check that line and rectangle drawing coordinates
  138. // work consistently in a negative x scale (they didn't in GDI: the
  139. // rectangle and lines differed by one pixel).
  140. g->DrawLine(
  141. &lightGrayPen,
  142. boundingBox.X, boundingBox.Y,
  143. boundingBox.X-plainTextWidth/20, boundingBox.Y);
  144. g->DrawLine(
  145. &lightGrayPen,
  146. boundingBox.X, boundingBox.Y,
  147. boundingBox.X, boundingBox.Y-plainTextHeight/20);
  148. g->DrawLine(
  149. &lightGrayPen,
  150. boundingBox.X+boundingBox.Width, boundingBox.Y,
  151. boundingBox.X+boundingBox.Width+plainTextWidth/20, boundingBox.Y);
  152. g->DrawLine(
  153. &lightGrayPen,
  154. boundingBox.X+boundingBox.Width, boundingBox.Y,
  155. boundingBox.X+boundingBox.Width, boundingBox.Y-plainTextHeight/20);
  156. g->DrawLine(
  157. &lightGrayPen,
  158. boundingBox.X, boundingBox.Y+boundingBox.Height,
  159. boundingBox.X-plainTextWidth/20, boundingBox.Y+boundingBox.Height);
  160. g->DrawLine(
  161. &lightGrayPen,
  162. boundingBox.X, boundingBox.Y+boundingBox.Height,
  163. boundingBox.X, boundingBox.Y+boundingBox.Height+plainTextHeight/20);
  164. g->DrawLine(
  165. &lightGrayPen,
  166. boundingBox.X+boundingBox.Width, boundingBox.Y+boundingBox.Height,
  167. boundingBox.X+boundingBox.Width+plainTextWidth/20, boundingBox.Y+boundingBox.Height);
  168. g->DrawLine(
  169. &lightGrayPen,
  170. boundingBox.X+boundingBox.Width, boundingBox.Y+boundingBox.Height,
  171. boundingBox.X+boundingBox.Width, boundingBox.Y+boundingBox.Height+plainTextHeight/20);
  172. WCHAR metricString[100];
  173. wsprintfW(metricString, L"Codepoints fitted %d\r\nLines filled %d\r\nRanges %d.", codepointsFitted, linesFilled, g_RangeCount);
  174. REAL x, y;
  175. if (g_formatFlags & StringFormatFlagsDirectionVertical)
  176. {
  177. if (g_formatFlags & StringFormatFlagsDirectionRightToLeft)
  178. {
  179. x = textRect.X;
  180. y = textRect.Y + textRect.Height/2;
  181. }
  182. else
  183. {
  184. x = textRect.X + textRect.Width;
  185. y = textRect.Y + textRect.Height/2;
  186. }
  187. }
  188. else
  189. {
  190. x = textRect.X + textRect.Width/2;
  191. y = textRect.Y + textRect.Height;
  192. }
  193. g->DrawString(
  194. metricString,-1,
  195. &Font(&FontFamily(L"Tahoma"), 12, NULL, UnitPoint),
  196. PointF(x, y),
  197. &format,
  198. &SolidBrush(Color(0x80,0x80,0x80))
  199. );
  200. g->MeasureString(
  201. metricString,-1,
  202. &Font(&FontFamily(L"Tahoma"), 12, NULL, UnitPoint),
  203. PointF(x, y),
  204. &format,
  205. &boundingBox
  206. );
  207. g->DrawRectangle(&lightGrayPen, boundingBox);
  208. }
  209. // Actually draw the text string. We do this last so it appears on top of
  210. // the construction and measurement lines we have just drawn.
  211. for(int iRender=0;iRender<g_iNumRenders;iRender++)
  212. {
  213. g->DrawString(g_wcBuf, g_iTextLen, &font, textRect, &format, g_textBrush);
  214. }
  215. /*
  216. // Test Font from Logfont, and generic layout
  217. HDC derivedDc = g->GetHDC();
  218. HFONT hFont = CreateFontW(
  219. iLineHeight/2, // height of font
  220. 0, // average character width
  221. 0, // angle of escapement
  222. 0, // base-line orientation angle
  223. 0, // font weight
  224. 0, // italic attribute option
  225. 1, // underline attribute option
  226. 0, // strikeout attribute option
  227. 1, // character set identifier
  228. 0, // output precision
  229. 0, // clipping precision
  230. 0, // output quality
  231. 0, // pitch and family
  232. g_style[0].faceName // typeface name
  233. );
  234. HFONT hOldFont = (HFONT) SelectObject(hdc, hFont);
  235. Font fontFromDc(hdc);
  236. ExtTextOutW(hdc, prc->left, prc->bottom-iLineHeight, 0, NULL, L"By ExtTextOut - AaBbCcDdEeFfGgQq", 32, NULL);
  237. DeleteObject(SelectObject(hdc, hOldFont));
  238. g->ReleaseHDC(derivedDc);
  239. REAL emHeightInPoints = GetEmHeightInPoints(&fontFromDc, &g);
  240. // Test the easy layout string format
  241. g->DrawString(
  242. L"AaBbCcDdEeFfGgQq - DrawString default layout", -1,
  243. &fontFromDc, // Font(*FontFamily::GenericMonospace(), 18.0, 0, UnitPoint),
  244. PointF(0.0, REAL(plainTextHeight/2 - iLineHeight)),
  245. StringFormat::GenericDefault(),
  246. &blackBrush
  247. );
  248. // Test typographic string format
  249. g->DrawString(
  250. L"Typographic layout", -1,
  251. &Font(FontFamily::GenericSansSerif(), 10),
  252. PointF(0.0, REAL(plainTextHeight/2 - 2*iLineHeight)),
  253. StringFormat::GenericTypographic(),
  254. &blackBrush
  255. );
  256. */
  257. delete g;
  258. if (metafile)
  259. {
  260. delete metafile;
  261. }
  262. if (g_testMetafile)
  263. {
  264. // Playback metafile to screen
  265. Metafile emfplus(L"c:\\texttest.emf");
  266. Graphics graphPlayback(hdc);
  267. graphPlayback.ResetTransform();
  268. graphPlayback.TranslateTransform(REAL(prc->left), REAL(*piY));
  269. graphPlayback.DrawImage(
  270. &emfplus,
  271. REAL(0),
  272. REAL(0),
  273. REAL(plainTextWidth),
  274. REAL(plainTextHeight)
  275. );
  276. graphPlayback.Flush();
  277. }
  278. *piY += plainTextHeight;
  279. }