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