PageRenderTime 90ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/win/scaffold/graphics.d

http://github.com/wilkie/djehuty
D | 481 lines | 325 code | 100 blank | 56 comment | 27 complexity | b68a4a2cfc54d7c4a4fca50c2a443975 MD5 | raw file
  1. /*
  2. * graphics.d
  3. *
  4. * This file implements the Scaffold for platform specific Graphics
  5. * operations in Windows.
  6. *
  7. * Author: Dave Wilkinson
  8. *
  9. */
  10. module scaffold.graphics;
  11. pragma(lib, "gdi32.lib");
  12. import graphics.view;
  13. import platform.vars.view;
  14. import platform.vars.brush;
  15. import platform.vars.font;
  16. import platform.vars.pen;
  17. import platform.vars.region;
  18. import Gdiplus = binding.win32.gdiplus;
  19. import core.string;
  20. import core.color;
  21. import core.main;
  22. import core.definitions;
  23. import core.unicode;
  24. import graphics.region;
  25. import platform.win.main;
  26. import platform.win.common;
  27. import io.console;
  28. import math.common;
  29. // Shapes
  30. // Draw a line
  31. void drawLine(ViewPlatformVars* viewVars, int x, int y, int x2, int y2) {
  32. //MoveToEx(viewVars.dc, x, y, null);
  33. //LineTo(viewVars.dc, x2, y2);
  34. Gdiplus.GdipDrawLineI(viewVars.g, viewVars.curPen, x, y, x2, y2);
  35. }
  36. void fillRect(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  37. //width--;
  38. //height--;
  39. Gdiplus.GdipFillRectangleI(viewVars.g, viewVars.curBrush, x, y, width, height);
  40. }
  41. void strokeRect(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  42. width--;
  43. height--;
  44. Gdiplus.GdipDrawRectangleI(viewVars.g, viewVars.curPen, x, y, width, height);
  45. }
  46. // Draw a rectangle (filled with the current brush, outlined with current pen)
  47. void drawRect(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  48. width--;
  49. height--;
  50. Gdiplus.GdipFillRectangleI(viewVars.g, viewVars.curBrush, x, y, width, height);
  51. Gdiplus.GdipDrawRectangleI(viewVars.g, viewVars.curPen, x, y, width, height);
  52. }
  53. void fillOval(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  54. width--;
  55. height--;
  56. Gdiplus.GdipFillEllipseI(viewVars.g, viewVars.curBrush, x, y, width, height);
  57. }
  58. void strokeOval(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  59. width--;
  60. height--;
  61. Gdiplus.GdipDrawEllipseI(viewVars.g, viewVars.curPen, x, y, width, height);
  62. }
  63. // Draw an ellipse (filled with current brush, outlined with current pen)
  64. void drawOval(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  65. width--;
  66. height--;
  67. Gdiplus.GdipFillEllipseI(viewVars.g, viewVars.curBrush, x, y, width, height);
  68. Gdiplus.GdipDrawEllipseI(viewVars.g, viewVars.curPen, x, y, width, height);
  69. }
  70. void drawPie(ViewPlatformVars* viewVars, int x, int y, int width, int height, double startAngle, double sweepAngle) {
  71. width--;
  72. height--;
  73. Gdiplus.GdipFillPieI(viewVars.g, viewVars.curBrush, x, y, width, height, startAngle, sweepAngle);
  74. Gdiplus.GdipDrawPieI(viewVars.g, viewVars.curPen, x, y, width, height, startAngle, sweepAngle);
  75. }
  76. void fillPie(ViewPlatformVars* viewVars, int x, int y, int width, int height, double startAngle, double sweepAngle) {
  77. width--;
  78. height--;
  79. Gdiplus.GdipFillPieI(viewVars.g, viewVars.curBrush, x, y, width, height, startAngle, sweepAngle);
  80. }
  81. void strokePie(ViewPlatformVars* viewVars, int x, int y, int width, int height, double startAngle, double sweepAngle) {
  82. width--;
  83. height--;
  84. Gdiplus.GdipDrawPieI(viewVars.g, viewVars.curPen, x, y, width, height, startAngle, sweepAngle);
  85. }
  86. // Text
  87. void drawText(ViewPlatformVars* viewVars, int x, int y, string str) {
  88. wstring utf16 = Unicode.toUtf16(str ~ '\0');
  89. Gdiplus.RectF rect = Gdiplus.RectF(x, y, 0.0f, 0.0f);
  90. Gdiplus.GdipDrawString(viewVars.g, utf16.ptr, utf16.length-1, viewVars.curFont, &rect, null, viewVars.curTextBrush);
  91. //TextOutW(viewVars.dc, x, y, utf16.ptr, utf16.length-1);
  92. }
  93. void drawText(ViewPlatformVars* viewVars, int x, int y, string str, uint length) {
  94. wstring utf16 = Unicode.toUtf16(str ~ '\0');
  95. Gdiplus.RectF rect = Gdiplus.RectF(x, y, 0.0f, 0.0f);
  96. Gdiplus.GdipDrawString(viewVars.g, utf16.ptr, length, viewVars.curFont, &rect, null, viewVars.curTextBrush);
  97. //TextOutW(viewVars.dc, x, y, utf16.ptr, length);
  98. }
  99. // Clipped Text
  100. void drawClippedText(ViewPlatformVars* viewVars, int x, int y, Rect region, string str) {
  101. wstring utf16 = Unicode.toUtf16(str);
  102. ExtTextOutW(viewVars.dc, x,y, ETO_CLIPPED, cast(RECT*)&region, utf16.ptr, utf16.length, null);
  103. }
  104. void drawClippedText(ViewPlatformVars* viewVars, int x, int y, Rect region, string str, uint length) {
  105. wstring utf16 = Unicode.toUtf16(str);
  106. ExtTextOutW(viewVars.dc, x,y, ETO_CLIPPED, cast(RECT*)&region, utf16.ptr, length, null);
  107. }
  108. // Text Measurement
  109. void measureText(ViewPlatformVars* viewVars, string str, out Size sz) {
  110. wstring utf16 = Unicode.toUtf16(str) ~ cast(wchar)'\0';
  111. //GetTextExtentPoint32W(viewVars.dc, utf16.ptr, utf16.length, cast(SIZE*)&sz) ;
  112. Gdiplus.RectF rect = Gdiplus.RectF(0.0f, 0.0f, 0.0f, 0.0f);
  113. Gdiplus.RectF result;
  114. Gdiplus.GdipMeasureString(viewVars.g, utf16.ptr, utf16.length-1,
  115. viewVars.curFont, &rect, null, &result, null, null);
  116. sz.x = cast(uint)result.Width;
  117. sz.y = cast(uint)result.Height;
  118. }
  119. void measureText(ViewPlatformVars* viewVars, string str, uint length, out Size sz) {
  120. wstring utf16 = Unicode.toUtf16(str) ~ cast(wchar)'\0';
  121. //GetTextExtentPoint32W(viewVars.dc, utf16.ptr, length, cast(SIZE*)&sz);
  122. Gdiplus.RectF rect = Gdiplus.RectF(0.0f, 0.0f, 0.0f, 0.0f);
  123. Gdiplus.RectF result;
  124. Gdiplus.GdipMeasureString(viewVars.g, utf16.ptr, length,
  125. viewVars.curFont, &rect, null, &result, null, null);
  126. sz.x = cast(uint)result.Width;
  127. sz.y = cast(uint)result.Height;
  128. }
  129. // Text Colors
  130. void setTextBackgroundColor(ViewPlatformVars* viewVars, in Color textColor) {
  131. SetBkColor(viewVars.dc, textColor.value);
  132. }
  133. void setTextColor(ViewPlatformVars* viewVars, in Color textColor) {
  134. //platform.win.common.SetTextColor(viewVars.dc, ColorGetValue(textColor));
  135. Gdiplus.GdipCreateSolidFill(textColor.value, &viewVars.curTextBrush);
  136. }
  137. // Text States
  138. void setTextModeTransparent(ViewPlatformVars* viewVars) {
  139. SetBkMode(viewVars.dc, TRANSPARENT);
  140. }
  141. void setTextModeOpaque(ViewPlatformVars* viewVars) {
  142. SetBkMode(viewVars.dc, OPAQUE);
  143. }
  144. // Graphics States
  145. void setAntialias(ViewPlatformVars* viewVars, bool value) {
  146. viewVars.aa = value;
  147. if (viewVars.aa) {
  148. Gdiplus.GdipSetSmoothingMode(viewVars.g, Gdiplus.SmoothingMode.SmoothingModeAntiAlias);
  149. }
  150. else {
  151. Gdiplus.GdipSetSmoothingMode(viewVars.g, Gdiplus.SmoothingMode.SmoothingModeDefault);
  152. }
  153. }
  154. // Fonts
  155. void createFont(FontPlatformVars* font, string fontname, int fontsize, int weight, bool italic, bool underline, bool strikethru) {
  156. // Create family
  157. wstring utf16 = Unicode.toUtf16(fontname) ~ cast(wchar)'\0';
  158. Gdiplus.GdipCreateFontFamilyFromName(utf16.ptr, null, &font.family);
  159. Gdiplus.FontStyle style;
  160. bool bold = false;
  161. if (weight > 600) {
  162. bold = true;
  163. }
  164. if (bold) {
  165. style |= Gdiplus.FontStyle.FontStyleBold;
  166. }
  167. if (italic) {
  168. style |= Gdiplus.FontStyle.FontStyleItalic;
  169. }
  170. if (underline) {
  171. style |= Gdiplus.FontStyle.FontStyleUnderline;
  172. }
  173. if (strikethru) {
  174. style |= Gdiplus.FontStyle.FontStyleStrikeout;
  175. }
  176. // Create font
  177. Gdiplus.GdipCreateFont(font.family, fontsize, style, Gdiplus.Unit.UnitPoint, &font.handle);
  178. }
  179. void setFont(ViewPlatformVars* viewVars, FontPlatformVars* font) {
  180. viewVars.curFont = font.handle;
  181. //SelectObject(viewVars.dc, font.fontHandle);
  182. }
  183. void destroyFont(FontPlatformVars* font) {
  184. Gdiplus.GdipDeleteFontFamily(font.family);
  185. Gdiplus.GdipDeleteFont(font.handle);
  186. //DeleteObject(font.fontHandle);
  187. }
  188. // Brushes
  189. void createBrush(BrushPlatformVars* brush, in Color clr) {
  190. //brush.brushHandle = CreateSolidBrush(clr.value);
  191. Gdiplus.GdipCreateSolidFill(clr.value, &brush.handle);
  192. }
  193. void setBrush(ViewPlatformVars* viewVars, BrushPlatformVars* brush) {
  194. viewVars.curBrush = brush.handle;
  195. //SelectObject(viewVars.dc, brush.brushHandle);
  196. }
  197. void destroyBrush(BrushPlatformVars* brush) {
  198. //DeleteObject(brush.brushHandle);
  199. Gdiplus.GdipDeleteBrush(brush.handle);
  200. }
  201. // BitmapBrush
  202. void createBitmapBrush(BrushPlatformVars* brush, ref ViewPlatformVars viewVarsSrc) {
  203. Gdiplus.GdipCreateTexture(viewVarsSrc.image, Gdiplus.WrapMode.WrapModeTile, &brush.handle);
  204. }
  205. // PathBrush
  206. void createGradientBrush(BrushPlatformVars* brush, double origx, double origy, double[] points, Color[] clrs, double angle, double width) {
  207. Gdiplus.PointF pt1 = {origx + 0.0, origy + 0.0};
  208. Gdiplus.PointF pt2 = {origx + width, origy + 0.0};
  209. INT clr1 = 0xFF808080;
  210. INT clr2 = 0xFFFFFFFF;
  211. if (points.length == 1) {
  212. clr1 = clrs[0].value;
  213. clr2 = clrs[0].value;
  214. }
  215. else if (points.length > 1) {
  216. clr1 = clrs[0].value;
  217. clr2 = clrs[$-1].value;
  218. //
  219. // use these 1d points and the angle to
  220. // get the 2d point...
  221. // it is not magic, it is trig.
  222. //
  223. pt2.X = origx + (cos(angle) * width);
  224. pt2.Y = origy + (sin(angle) * width);
  225. }
  226. Gdiplus.GdipCreateLineBrush(&pt1, &pt2, clr1, clr2, Gdiplus.WrapMode.WrapModeTile, &brush.handle);
  227. if (points.length > 2) {
  228. // Interpolate MORE colors!!!
  229. Gdiplus.ARGB[] argbs = new Gdiplus.ARGB[points.length];
  230. Gdiplus.REAL[] blendPositions = new Gdiplus.REAL[points.length];
  231. INT count = clrs.length;
  232. for (size_t i = 0; i < count; i++) {
  233. argbs[i] = clrs[i].value;
  234. blendPositions[i] = points[i];
  235. }
  236. Gdiplus.GdipSetLinePresetBlend(brush.handle, argbs.ptr, blendPositions.ptr, count);
  237. }
  238. }
  239. // Pens
  240. void createPen(PenPlatformVars* pen, in Color clr, double width) {
  241. Gdiplus.GdipCreatePen1(clr.value, width, Gdiplus.Unit.UnitWorld, &pen.handle);
  242. //pen.penHandle = platform.win.common.CreatePen(0,1,pen.clr);
  243. }
  244. void createPenWithBrush(PenPlatformVars* pen, ref BrushPlatformVars brushVars, double width) {
  245. Gdiplus.GdipCreatePen2(brushVars.handle, width, Gdiplus.Unit.UnitWorld, &pen.handle);
  246. }
  247. void setPen(ViewPlatformVars* viewVars, PenPlatformVars* pen) {
  248. viewVars.curPen = pen.handle;
  249. viewVars.penClr = pen.clr;
  250. //SelectObject(viewVars.dc, pen.penHandle);
  251. }
  252. void destroyPen(PenPlatformVars* pen) {
  253. //DeleteObject(pen.penHandle);
  254. Gdiplus.GdipDeletePen(pen.handle);
  255. pen.handle = null;
  256. }
  257. // View Interfacing
  258. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView) {
  259. if (viewVars.image !is null) {
  260. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  261. }
  262. Gdiplus.GdipDrawImageI(viewVars.g, viewVarsSrc.image , x, y);
  263. }
  264. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView, int viewX, int viewY) {
  265. if (viewVars.image !is null) {
  266. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  267. }
  268. Gdiplus.GdipDrawImagePointRectI(viewVars.g, viewVarsSrc.image, x, y, viewX, viewY, srcView.width(), srcView.height(), Gdiplus.Unit.UnitPixel);
  269. }
  270. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView, int viewX, int viewY, int viewWidth, int viewHeight) {
  271. if (viewVars.image !is null) {
  272. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  273. }
  274. Gdiplus.GdipDrawImagePointRectI(viewVars.g, viewVarsSrc.image, x, y, viewX, viewY, viewWidth, viewHeight, Gdiplus.Unit.UnitPixel);
  275. }
  276. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView, double opacity) {
  277. if (viewVars.image !is null) {
  278. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  279. }
  280. static Gdiplus.ColorMatrix cm;
  281. cm.m[3][3] = cast(Gdiplus.REAL)opacity;
  282. Gdiplus.GpImageAttributes* ia;
  283. Gdiplus.GdipCreateImageAttributes(&ia);
  284. Gdiplus.GdipSetImageAttributesColorMatrix(ia, Gdiplus.ColorAdjustType.ColorAdjustTypeBitmap,
  285. TRUE, &cm, null, Gdiplus.ColorMatrixFlags.ColorMatrixFlagsDefault);
  286. Gdiplus.GdipDrawImageRectRectI(viewVars.g, viewVarsSrc.image, x, y, srcView.width, srcView.height,
  287. 0, 0, srcView.width, srcView.height, Gdiplus.Unit.UnitPixel, ia, null, null);
  288. Gdiplus.GdipDisposeImageAttributes(ia);
  289. }
  290. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView, int viewX, int viewY, double opacity) {
  291. if (viewVars.image !is null) {
  292. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  293. }
  294. static Gdiplus.ColorMatrix cm;
  295. cm.m[3][3] = cast(Gdiplus.REAL)opacity;
  296. Gdiplus.GpImageAttributes* ia;
  297. Gdiplus.GdipCreateImageAttributes(&ia);
  298. Gdiplus.GdipSetImageAttributesColorMatrix(ia, Gdiplus.ColorAdjustType.ColorAdjustTypeBitmap,
  299. TRUE, &cm, null, Gdiplus.ColorMatrixFlags.ColorMatrixFlagsDefault);
  300. Gdiplus.GdipDrawImageRectRectI(viewVars.g, viewVarsSrc.image, x, y, srcView.width, srcView.height,
  301. viewX, viewY, srcView.width, srcView.height, Gdiplus.Unit.UnitPixel, ia, null, null);
  302. Gdiplus.GdipDisposeImageAttributes(ia);
  303. }
  304. void drawView(ref ViewPlatformVars* viewVars, ref View view, int x, int y, ref ViewPlatformVars* viewVarsSrc, ref View srcView, int viewX, int viewY, int viewWidth, int viewHeight, double opacity) {
  305. if (viewVars.image !is null) {
  306. Gdiplus.GdipGetImageGraphicsContext(viewVars.image, &viewVars.g);
  307. }
  308. static Gdiplus.ColorMatrix cm;
  309. cm.m[3][3] = cast(Gdiplus.REAL)opacity;
  310. Gdiplus.GpImageAttributes* ia;
  311. Gdiplus.GdipCreateImageAttributes(&ia);
  312. Gdiplus.GdipSetImageAttributesColorMatrix(ia, Gdiplus.ColorAdjustType.ColorAdjustTypeBitmap,
  313. TRUE, &cm, null, Gdiplus.ColorMatrixFlags.ColorMatrixFlagsDefault);
  314. Gdiplus.GdipDrawImageRectRectI(viewVars.g, viewVarsSrc.image, x, y, viewWidth, viewHeight,
  315. viewX, viewY, viewWidth, viewHeight, Gdiplus.Unit.UnitPixel, ia, null, null);
  316. Gdiplus.GdipDisposeImageAttributes(ia);
  317. }
  318. void _createRegion(RegionPlatformVars* rgnVars, Region rgn, int x, int y) {
  319. // destroy old region data
  320. if (rgnVars.regionHandle !is null) {
  321. DeleteObject(rgnVars.regionHandle);
  322. }
  323. // compute a platform graphics api version of the region
  324. POINT[] pts = new POINT[](rgn.length);
  325. foreach(i, pt; rgn) {
  326. pts[i].x = pt.x + x;
  327. pts[i].y = pt.y + y;
  328. }
  329. // call the platform to create a region object from the points
  330. rgnVars.regionHandle = CreatePolygonRgn(pts.ptr, rgn.length, ALTERNATE);
  331. }
  332. void fillRegion(ViewPlatformVars* viewVars, RegionPlatformVars* rgnVars, bool rgnPlatformDirty, Region rgn, int x, int y) {
  333. if (rgnPlatformDirty) {
  334. _createRegion(rgnVars, rgn, x, y);
  335. }
  336. // paint the region
  337. PaintRgn(viewVars.dc, rgnVars.regionHandle);
  338. }
  339. void strokeRegion(ViewPlatformVars* viewVars, RegionPlatformVars* rgnVars, bool rgnPlatformDirty, Region rgn, int x, int y) {
  340. if (rgnPlatformDirty) {
  341. _createRegion(rgnVars, rgn, x, y);
  342. }
  343. // frame the region
  344. HBRUSH brsh = CreateSolidBrush(viewVars.penClr);
  345. FrameRgn(viewVars.dc, rgnVars.regionHandle, brsh, 1, 1);
  346. DeleteObject(brsh);
  347. }
  348. void drawRegion(ViewPlatformVars* viewVars, RegionPlatformVars* rgnVars, bool rgnPlatformDirty, Region rgn, int x, int y) {
  349. if (rgnPlatformDirty) {
  350. _createRegion(rgnVars, rgn, x, y);
  351. }
  352. // paint and frame the region
  353. PaintRgn(viewVars.dc, rgnVars.regionHandle);
  354. HBRUSH brsh = CreateSolidBrush(viewVars.penClr);
  355. FrameRgn(viewVars.dc, rgnVars.regionHandle, brsh, 1, 1);
  356. DeleteObject(brsh);
  357. }
  358. void clipSave(ViewPlatformVars* viewVars) {
  359. if (viewVars.clipRegions.length == 0) {
  360. viewVars.clipRegions.addItem(null);
  361. }
  362. else {
  363. HRGN rgn = CreateRectRgn(0,0,0,0);
  364. GetClipRgn(viewVars.dc, rgn);
  365. viewVars.clipRegions.addItem(rgn);
  366. }
  367. }
  368. void clipRestore(ViewPlatformVars* viewVars) {
  369. HRGN rgn;
  370. if (viewVars.clipRegions.remove(rgn)) {
  371. SelectClipRgn(viewVars.dc, rgn);
  372. DeleteObject(rgn);
  373. }
  374. }
  375. void clipRect(ViewPlatformVars* viewVars, int x, int y, int width, int height) {
  376. HRGN rgn = CreateRectRgn(x,y,width,height);
  377. ExtSelectClipRgn(viewVars.dc, rgn, RGN_AND);
  378. DeleteObject(rgn);
  379. }
  380. void clipRegion(ViewPlatformVars* viewVars, Region region) {
  381. }