2
// ContextBackendHandler.cs
5
// Eric Maupin <ermau@xamarin.com>
6
// Hywel Thomas <hywel.w.thomas@gmail.com>
7
// Lytico (http://limada.sourceforge.net)
8
// LuĆs Reis <luiscubal@gmail.com>
10
// Copyright (c) 2012 Xamarin, Inc.
12
// Permission is hereby granted, free of charge, to any person obtaining a copy
13
// of this software and associated documentation files (the "Software"), to deal
14
// in the Software without restriction, including without limitation the rights
15
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
// copies of the Software, and to permit persons to whom the Software is
17
// furnished to do so, subject to the following conditions:
19
// The above copyright notice and this permission notice shall be included in
20
// all copies or substantial portions of the Software.
22
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
using System.Drawing.Drawing2D;
33
using System.Drawing.Imaging;
36
using System.Windows.Media.Imaging;
40
using Color = Xwt.Drawing.Color;
41
using Font = Xwt.Drawing.Font;
43
namespace Xwt.WPFBackend
45
public class ContextBackendHandler
46
: Backend, IContextBackendHandler
48
public void Save (object backend)
50
var c = (DrawingContext) backend;
54
public void Restore (object backend)
56
var c = (DrawingContext) backend;
60
public void SetGlobalAlpha (object backend, double alpha)
65
public void Arc (object backend, double xc, double yc, double radius, double angle1, double angle2)
67
// ensure sweep angle is always positive
69
angle2 = 360 + angle2;
70
ArcInternal (backend, xc, yc, radius, angle1, angle2);
73
public void ArcNegative (object backend, double xc, double yc, double radius, double angle1, double angle2)
75
// ensure sweep angle is always negative
77
angle1 = 360 + angle1;
78
ArcInternal (backend, xc, yc, radius, angle1, angle2);
81
void ArcInternal (object backend, double xc, double yc, double radius, double angle1, double angle2)
83
var c = (DrawingContext)backend;
84
c.Path.AddArc ((float)(xc - radius), (float)(yc - radius), (float)radius * 2, (float)radius * 2, (float)angle1,
85
(float)(angle2 - angle1));
87
var current = c.Path.GetLastPoint ();
88
c.CurrentX = current.X;
89
c.CurrentY = current.Y;
92
public void Clip (object backend)
94
var c = (DrawingContext) backend;
95
c.Graphics.SetClip (c.Path);
99
public void ClipPreserve (object backend)
101
var c = (DrawingContext) backend;
102
c.Graphics.SetClip (c.Path);
105
public void ClosePath (object backend)
107
var c = (DrawingContext) backend;
108
c.Path.CloseFigure();
111
public void CurveTo (object backend, double x1, double y1, double x2, double y2, double x3, double y3)
113
var c = (DrawingContext)backend;
114
c.Path.AddBezier (c.CurrentX, c.CurrentY,
115
(float)x1, (float)y1,
116
(float)x2, (float)y2,
117
(float)x3, (float)y3);
118
c.CurrentX = (float)x3;
119
c.CurrentY = (float)y3;
122
public void Fill (object backend)
124
var c = (DrawingContext) backend;
125
c.Graphics.FillPath (c.Brush, c.Path);
131
public void FillPreserve (object backend)
133
var c = (DrawingContext) backend;
134
c.Graphics.FillPath (c.Brush, c.Path);
137
public void LineTo (object backend, double x, double y)
139
var c = (DrawingContext) backend;
141
c.Path.AddLine (c.CurrentX, c.CurrentY, (float) x, (float) y);
142
c.CurrentX = (float) x;
143
c.CurrentY = (float) y;
146
public void MoveTo (object backend, double x, double y)
148
var c = (DrawingContext) backend;
149
if (c.CurrentX != x || c.CurrentY != y) {
150
c.Path.StartFigure ();
151
c.CurrentX = (float)x;
152
c.CurrentY = (float)y;
156
public void NewPath (object backend)
158
var c = (DrawingContext) backend;
164
public void Rectangle (object backend, double x, double y, double width, double height)
166
var c = (DrawingContext) backend;
167
if (c.CurrentX != x || c.CurrentY != y)
168
c.Path.StartFigure ();
169
c.Path.AddRectangle (new RectangleF ((float)x, (float)y, (float)width, (float)height));
170
c.CurrentX = (float)x;
171
c.CurrentY = (float)y;
174
public void RelCurveTo (object backend, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
176
var c = (DrawingContext)backend;
177
c.Path.AddBezier (c.CurrentX, c.CurrentY,
178
(float)(c.CurrentX + dx1), (float)(c.CurrentY + dy1),
179
(float)(c.CurrentX + dx2), (float)(c.CurrentY + dy2),
180
(float)(c.CurrentX + dx3), (float)(c.CurrentY + dy3));
181
c.CurrentX = (float)(c.CurrentX + dx3);
182
c.CurrentY = (float)(c.CurrentX + dy3);
185
public void RelLineTo (object backend, double dx, double dy)
187
var c = (DrawingContext) backend;
189
float x = c.CurrentX;
190
float y = c.CurrentY;
191
c.CurrentX += (float)dx;
192
c.CurrentY += (float)dy;
194
c.Path.AddLine (x, y, c.CurrentX, c.CurrentY);
197
public void RelMoveTo (object backend, double dx, double dy)
199
var c = (DrawingContext) backend;
200
c.Path.StartFigure ();
201
c.CurrentX += (float)dx;
202
c.CurrentY += (float)dy;
205
public void Stroke (object backend)
207
var c = (DrawingContext) backend;
208
c.Graphics.DrawPath (c.Pen, c.Path);
214
public void StrokePreserve (object backend)
216
var c = (DrawingContext) backend;
217
c.Graphics.DrawPath (c.Pen, c.Path);
220
public void SetColor (object backend, Color color)
222
var c = (DrawingContext) backend;
224
var dc = color.ToDrawingColor ();
228
public void SetLineWidth (object backend, double width)
230
var c = (DrawingContext) backend;
231
c.SetWidth ((float) width);
234
public void SetLineDash (object backend, double offset, params double[] pattern)
236
var c = (DrawingContext) backend;
238
if (pattern.Length != 0) {
239
c.Pen.DashOffset = (float) (offset / c.Pen.Width);
240
float[] fp = new float [pattern.Length];
241
for (int i = 0; i < fp.Length; ++i)
242
fp [i] = (float) (pattern [i] / c.Pen.Width);
244
c.Pen.DashStyle = DashStyle.Custom;
245
c.Pen.DashPattern = fp;
247
c.Pen.DashStyle = DashStyle.Solid;
250
public void SetPattern (object backend, object p)
252
var c = (DrawingContext) backend;
254
if (p is LinearGradient) {
255
c.Brush = ((LinearGradient) p).CreateBrush ();
256
} else if (p is RadialGradient) {
257
c.Brush = ((RadialGradient) p).CreateBrush ();
258
} else if (p is Brush)
262
public void SetFont (object backend, Font font)
264
var c = (DrawingContext) backend;
266
c.Font = font.ToDrawingFont ();
269
public void DrawTextLayout (object backend, TextLayout layout, double x, double y)
271
var c = (DrawingContext)backend;
272
System.Drawing.StringFormat stringFormat = TextLayoutContext.StringFormat;
273
StringTrimming trimming = layout.Trimming.ToDrawingStringTrimming ();
275
if (layout.Height > 0 && stringFormat.Trimming != trimming) {
276
stringFormat = (System.Drawing.StringFormat)stringFormat.Clone ();
277
stringFormat.Trimming = trimming;
280
var font = layout.Font.ToDrawingFont ();
282
if (layout.Width == -1 && layout.Height == -1) {
283
c.Graphics.DrawString (layout.Text, font, c.Brush, (float)x, (float)y, stringFormat);
285
Size measure = layout.GetSize ();
286
float h = layout.Height > 0 ? (float)layout.Height : (float)measure.Height;
287
c.Graphics.DrawString (layout.Text, font, c.Brush,
288
new RectangleF ((float)x, (float)y, (float)measure.Width, h),
293
public void DrawImage (object backend, object img, double x, double y, double alpha)
295
var c = (DrawingContext) backend;
297
Bitmap bmp = DataConverter.AsBitmap (img);
298
DrawImageCore (c.Graphics, bmp, (float) x, (float) y, bmp.Width, bmp.Height, (float)alpha);
301
public void DrawImage (object backend, object img, double x, double y, double width, double height, double alpha)
303
var c = (DrawingContext) backend;
305
Bitmap bmp = DataConverter.AsBitmap (img);
306
DrawImageCore (c.Graphics, bmp, (float) x, (float) y, (float) width, (float) height, (float) alpha);
309
public void DrawImage (object backend, object img, Rectangle srcRect, Rectangle destRect, double alpha)
311
var c = (DrawingContext) backend;
313
Bitmap bmp = DataConverter.AsBitmap (img);
315
DrawImageCore (c.Graphics, bmp, srcRect, destRect, (float) alpha);
318
public void Rotate (object backend, double angle)
320
var c = (DrawingContext)backend;
321
c.Graphics.RotateTransform ((float)angle);
324
public void Scale (object backend, double scaleX, double scaleY)
326
var c = (DrawingContext)backend;
327
c.Graphics.ScaleTransform ((float)scaleX, (float)scaleY);
330
public void Translate (object backend, double tx, double ty)
332
var c = (DrawingContext)backend;
333
c.Graphics.TranslateTransform ((float)tx, (float)ty);
336
public void TransformPoint (object backend, ref double x, ref double y)
338
var m = ((DrawingContext)backend).Graphics.Transform;
339
PointF p = new PointF ((float)x, (float)y);
340
PointF[] pts = new PointF[] { p };
341
m.TransformPoints (pts);
346
public void TransformDistance (object backend, ref double dx, ref double dy)
348
var m = ((DrawingContext)backend).Graphics.Transform;
349
PointF p = new PointF ((float)dx, (float)dy);
350
PointF[] pts = new PointF[] {p};
351
m.TransformVectors (pts);
356
public void TransformPoints (object backend, Point[] points)
358
var m = ((DrawingContext)backend).Graphics.Transform;
359
PointF[] pts = new PointF[points.Length];
360
for (int i = 0; i < points.Length; ++i) {
361
pts[i].X = (float)points[i].X;
362
pts[i].Y = (float)points[i].Y;
364
m.TransformPoints (pts);
365
for (int i = 0; i < points.Length; ++i) {
366
points[i].X = pts[i].X;
367
points[i].Y = pts[i].Y;
371
public void TransformDistances (object backend, Distance[] vectors)
373
var m = ((DrawingContext)backend).Graphics.Transform;
374
PointF[] pts = new PointF[vectors.Length];
375
for (int i = 0; i < vectors.Length; ++i) {
376
pts[i].X = (float)vectors[i].Dx;
377
pts[i].Y = (float)vectors[i].Dy;
379
m.TransformVectors (pts);
380
for (int i = 0; i < vectors.Length; ++i) {
381
vectors[i].Dx = pts[i].X;
382
vectors[i].Dy = pts[i].Y;
386
public void Dispose (object backend)
388
((DrawingContext)backend).Dispose();
391
internal static void DrawImageCore (Graphics g, Bitmap bmp, float x, float y, float width, float height, float alpha)
394
throw new ArgumentException();
397
var attr = new ImageAttributes ();
399
float[][] matrixItems = new[] {
400
new float[] { 1, 0, 0, 0, 0 },
401
new float[] { 0, 1, 0, 0, 0 },
402
new float[] { 0, 0, 1, 0, 0 },
403
new float[] { 0, 0, 0, alpha, 0 },
404
new float[] { 0, 0, 0, 0, 1 },
407
attr.SetColorMatrix (new ColorMatrix (matrixItems), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
409
PointF[] points = new PointF[3];
410
points [0] = new PointF (x, y);
411
points [1] = new PointF (x + width, y);
412
points [2] = new PointF (x, y + height);
414
g.DrawImage (bmp, points, new RectangleF (0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel, attr);
417
g.DrawImage (bmp, x, y, width, height);
420
internal void DrawImageCore (Graphics g, Bitmap bmp, Rectangle srcRect, Rectangle destRect, float alpha)
424
var attr = new ImageAttributes ();
426
float[][] matrixItems = new[] {
427
new float[] { 1, 0, 0, 0, 0 },
428
new float[] { 0, 1, 0, 0, 0 },
429
new float[] { 0, 0, 1, 0, 0 },
430
new float[] { 0, 0, 0, alpha, 0 },
431
new float[] { 0, 0, 0, 0, 1 },
434
attr.SetColorMatrix (new ColorMatrix (matrixItems), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
436
PointF[] points = new PointF[3];
437
points[0] = new PointF ((float) destRect.X, (float) destRect.Y);
438
points[1] = new PointF ((float) (destRect.X + destRect.Width), (float) destRect.Y);
439
points[2] = new PointF ((float) destRect.X, (float) (destRect.Y + destRect.Height));
441
g.DrawImage (bmp, points, srcRect.ToSDRectF (), GraphicsUnit.Pixel, attr);
444
g.DrawImage (bmp, destRect.ToSDRectF (), srcRect.ToSDRectF (), GraphicsUnit.Pixel);