1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.Windows.API;
9
10 namespace System.Windows
11 {
12 public class Point
13 {
14 public Point() : x(0), y(0)
15 {
16 }
17 public Point(int x_, int y_) : x(x_), y(y_)
18 {
19 }
20 public default Point(const Point&);
21 public default void operator=(const Point&);
22 public static Point Default()
23 {
24 return Point(CW_USEDEFAULT, CW_USEDEFAULT);
25 }
26 public string ToString() const
27 {
28 return "(" + ToString(x) + ", " + ToString(y) + ")";
29 }
30 public inline void Offset(int dx, int dy)
31 {
32 x = x + dx;
33 y = y + dy;
34 }
35 public int x;
36 public int y;
37 }
38
39 public inline bool operator==(const Point& left, const Point& right)
40 {
41 return left.x == right.x && left.y == right.y;
42 }
43
44 public class Size
45 {
46 public Size() : h(0), w(0)
47 {
48 }
49 public Size(int w_, int h_) : w(w_), h(h_)
50 {
51 }
52 public default Size(const Size&);
53 public default void operator=(const Size&);
54 public static Size Default()
55 {
56 return Size(CW_USEDEFAULT, CW_USEDEFAULT);
57 }
58 public string ToString() const
59 {
60 return "(" + ToString(w) + ", " + ToString(h) + ")";
61 }
62 public int w;
63 public int h;
64 }
65
66 public inline bool operator==(const Size& left, const Size& right)
67 {
68 return left.w == right.w && left.h == right.h;
69 }
70
71 public class PointF
72 {
73 public PointF() : x(0.000000f), y(0.000000f)
74 {
75 }
76 public PointF(float x_, float y_) : x(x_), y(y_)
77 {
78 }
79 public string ToString() const
80 {
81 return "(" + ToString(x) + ", " + ToString(y) + ")";
82 }
83 public inline void Offset(float dx, float dy)
84 {
85 x = x + dx;
86 y = y + dy;
87 }
88 public float x;
89 public float y;
90 }
91
92 public inline bool operator==(const PointF& left, const PointF& right)
93 {
94 return left.x == right.x && left.y == right.y;
95 }
96
97 public float Distance(const PointF& start, const PointF& end)
98 {
99 float dx = Abs(start.x - end.x);
100 float dy = Abs(start.y - end.y);
101 float distance = cast<float>(Sqrt(dx * dx + dy * dy));
102 return distance;
103 }
104
105 public class Vector
106 {
107 public Vector() : x(0), y(0)
108 {
109 }
110 public Vector(float x_, float y_) : x(x_), y(y_)
111 {
112 }
113 public explicit Vector(const PointF& point) : x(point.x), y(point.y)
114 {
115 }
116 public float Length() const
117 {
118 return cast<float>(Sqrt(x * x + y * y));
119 }
120 public PointF ToPoint() const
121 {
122 return PointF(x, y);
123 }
124 public string ToString() const
125 {
126 return "[" + ToString(x) + ", " + ToString(y) + "]";
127 }
128 public float x;
129 public float y;
130 }
131
132 public inline bool operator==(const Vector& v, const Vector& u)
133 {
134 return v.x == u.x && v.y == u.y;
135 }
136
137 public Vector operator*(const Vector& v, float a)
138 {
139 return Vector(v.x * a, v.y * a);
140 }
141
142 public Vector operator*(float a, const Vector& v)
143 {
144 return Vector(v.x * a, v.y * a);
145 }
146
147 public Vector operator+(const Vector& left, const Vector& right)
148 {
149 return Vector(left.x + right.x, left.y + right.y);
150 }
151
152 public Vector operator-(const Vector& left, const Vector& right)
153 {
154 return Vector(left.x - right.x, left.y - right.y);
155 }
156
157 public Vector UnitVector(const Vector& v)
158 {
159 float length = v.Length();
160 return v * (1.000000f / length);
161 }
162
163
164
165 public float Dot(const Vector& u, const Vector& v)
166 {
167 return u.x * v.x + u.y * v.y;
168 }
169
170 public float ProjectionFactor(const Vector& a, const Vector& b)
171 {
172 return Dot(a, b * (1 / b.Length()));
173 }
174
175
176
177 public Vector Projection(const Vector& a, const Vector& b)
178 {
179 return UnitVector(b) * ProjectionFactor(a, b);
180 }
181
182
183
184
185
186
187
188
189 public int MainDirection(const Vector& v)
190 {
191 if (v.x >= 0)
192 {
193 if (v.y >= 0)
194 {
195 Vector u(1, -1);
196 if (Dot(v, u) >= 0)
197 {
198 return 0;
199 }
200 else
201 {
202 return 90;
203 }
204 }
205 else
206 {
207 Vector u(-1, -1);
208 if (Dot(v, u) >= 0)
209 {
210 return 270;
211 }
212 else
213 {
214 return 0;
215 }
216 }
217 }
218 else
219 {
220 if (v.y >= 0)
221 {
222 Vector u(1, 1);
223 if (Dot(v, u) >= 0)
224 {
225 return 90;
226 }
227 else
228 {
229 return 180u;
230 }
231 }
232 else
233 {
234 Vector u(-1, 1);
235 if (Dot(v, u) >= 0)
236 {
237 return 180u;
238 }
239 else
240 {
241 return 270;
242 }
243 }
244 }
245 }
246
247 public Vector Rotate(const Vector& v, double angleRad)
248 {
249 float cosTheta = cast<float>(Cos(angleRad));
250 float sinTheta = cast<float>(Sin(angleRad));
251 Vector r(v.x * cosTheta - v.y * sinTheta, v.x * sinTheta + v.y * cosTheta);
252 return r;
253 }
254
255 public class Line
256 {
257 public Line() : start(), end()
258 {
259 }
260 public Line(const PointF& start_, const PointF& end_) : start(start_), end(end_)
261 {
262 }
263 public Line(const PointF& start_, const Vector& v) : start(start_), end(Vector(Vector(start) + v).ToPoint())
264 {
265 }
266 public float Length() const
267 {
268 return Distance(start, end);
269 }
270 public Vector ToVector() const
271 {
272 return Vector(end.x - start.x, end.y - start.y);
273 }
274 public string ToString() const
275 {
276 return "[" + start.ToString() + ", " + end.ToString() + "]";
277 }
278 public PointF start;
279 public PointF end;
280 }
281
282 public inline bool operator==(const Line& left, const Line& right)
283 {
284 return left.start == right.start && left.end == right.end;
285 }
286
287 public Line Rotate(const Line& line, double angleDeg)
288 {
289 double angleRad = PI() / 180.000000 * angleDeg;
290 Vector v = line.ToVector();
291 Vector r = Rotate(v, angleRad);
292 Line result(line.start, r);
293 return result;
294 }
295
296 public class SizeF
297 {
298 public SizeF() : w(0.000000f), h(0.000000f)
299 {
300 }
301 public SizeF(float w_, float h_) : w(w_), h(h_)
302 {
303 }
304 public string ToString() const
305 {
306 return "(" + ToString(w) + ", " + ToString(h) + ")";
307 }
308 public float w;
309 public float h;
310 }
311
312 public inline bool operator==(const SizeF& left, const SizeF& right)
313 {
314 return left.w == right.w && left.h == right.h;
315 }
316
317 public class Rect
318 {
319 public Rect() : location(), size()
320 {
321 }
322 public Rect(const Point& location_, const Size& size_) : location(location_), size(size_)
323 {
324 }
325 public Rect(const WinRect& winRect) : location(winRect.left, winRect.top), size(winRect.right - winRect.left, winRect.bottom - winRect.top)
326 {
327 }
328 public WinRect ToWinRect() const
329 {
330 return WinRect(location.x, location.y, location.x + size.w, location.y + size.h);
331 }
332 public inline bool IsEmpty() const
333 {
334 return size.w == 0 && size.h == 0;
335 }
336 public inline int Left() const
337 {
338 return location.x;
339 }
340 public inline int Right() const
341 {
342 return location.x + size.w;
343 }
344 public inline int Top() const
345 {
346 return location.y;
347 }
348 public inline int Bottom() const
349 {
350 return location.y + size.h;
351 }
352 public inline bool Contains(const Point& p)
353 {
354 return p.x >= location.x && p.x < location.x + size.w && p.y >= location.y && p.y < location.y + size.h;
355 }
356 public inline void Inflate(int dx, int dy)
357 {
358 location.x = location.x - dx;
359 location.y = location.y - dy;
360 size.w = size.w + 2 * dx;
361 size.h = size.h + 2 * dy;
362 }
363 public inline void Offset(int dx, int dy)
364 {
365 location.Offset(dx, dy);
366 }
367 public bool IntersectsWith(const Rect& that) const
368 {
369 return Left() < that.Right() && Top() < that.Bottom() && Right() > that.Left() && Bottom() > that.Top();
370 }
371 public static Rect Union(const Rect& a, const Rect& b)
372 {
373 int right = Max(a.Right(), b.Right());
374 int bottom = Max(a.Bottom(), b.Bottom());
375 int left = Min(a.Left(), b.Left());
376 int top = Min(a.Top(), b.Top());
377 return Rect(Point(left, top), Size(right - left, bottom - top));
378 }
379 public string ToString() const
380 {
381 return "(" + ToString(location.x) + ", " + ToString(location.y) + ", " + ToString(size.w) + ", " + ToString(size.h) + ")";
382 }
383 public Point location;
384 public Size size;
385 }
386
387 public inline bool operator==(const Rect& left, const Rect& right)
388 {
389 return left.location == right.location && left.size == right.size;
390 }
391
392 public class RectF
393 {
394 public RectF() : location(), size()
395 {
396 }
397 public RectF(const PointF& location_, const SizeF& size_) : location(location_), size(size_)
398 {
399 }
400 public inline float Left() const
401 {
402 return location.x;
403 }
404 public inline float Right() const
405 {
406 return location.x + size.w;
407 }
408 public inline float Top() const
409 {
410 return location.y;
411 }
412 public inline float Bottom() const
413 {
414 return location.y + size.h;
415 }
416 public string ToString() const
417 {
418 return "(" + ToString(location.x) + ", " + ToString(location.y) + ", " + ToString(size.w) + ", " + ToString(size.h) + ")";
419 }
420 public inline bool IsEmpty() const
421 {
422 return size.w == 0 && size.h == 0;
423 }
424 public inline bool Contains(const PointF& p)
425 {
426 return p.x >= location.x && p.x < location.x + size.w && p.y >= location.y && p.y < location.y + size.h;
427 }
428 public inline void Inflate(float dx, float dy)
429 {
430 location.x = location.x - dx;
431 location.y = location.y - dy;
432 size.w = size.w + 2 * dx;
433 size.h = size.h + 2 * dy;
434 }
435 public inline void Offset(float dx, float dy)
436 {
437 location.Offset(dx, dy);
438 }
439 public bool IntersectsWith(const RectF& that) const
440 {
441 return Left() < that.Right() && Top() < that.Bottom() && Right() > that.Left() && Bottom() > that.Top();
442 }
443 public static RectF Union(const RectF& a, const RectF& b)
444 {
445 float right = Max(a.Right(), b.Right());
446 float bottom = Max(a.Bottom(), b.Bottom());
447 float left = Min(a.Left(), b.Left());
448 float top = Min(a.Top(), b.Top());
449 return RectF(PointF(left, top), SizeF(right - left, bottom - top));
450 }
451 public PointF location;
452 public SizeF size;
453 }
454
455 public enum LineCap : int
456 {
457 flat = 0,
458 square = 1,
459 round = 2,
460 triangle = 3,
461 noAnchor = 16,
462 squareAnchor = 17,
463 roundAnchopr = 18,
464 diamondAnchor = 19,
465 arrowAnchor = 20,
466 custom = 255u,
467 anchorMask = 240u
468 }
469
470 public enum LineJoin : int
471 {
472 miter = 0,
473 bevel = 1,
474 round = 2,
475 miterClipped = 3
476 }
477
478 public enum DashCap : int
479 {
480 flat = 0,
481 round = 2,
482 triangle = 3
483 }
484
485 public enum DashStyle : int
486 {
487 solid = 0,
488 dash = 1,
489 dot = 2,
490 dashDot = 3,
491 dashDotDot = 4,
492 custom = 5
493 }
494
495 public string ToString(DashStyle dashStyle)
496 {
497 switch (dashStyle)
498 {
499 case DashStyle.solid: return "solid";
500 case DashStyle.dash: return "dash";
501 case DashStyle.dot: return "dot";
502 case DashStyle.dashDot: return "dashDot";
503 case DashStyle.dashDotDot: return "dashDotDot";
504 case DashStyle.custom: return "custom";
505 }
506 return string();
507 }
508
509 public class Pen : GraphicsObject
510 {
511 public enum Alignment : int
512 {
513 center = 0, inset = 1
514 }
515 public Pen(const Color& color, float width) : base(), nativePen(WinGraphicsCreatePen(color.alpha, color.red, color.green, color.blue, width))
516 {
517 int status = WinGraphicsPenGetLastStatus(nativePen);
518 if (status != 0)
519 {
520 SetErrorId(WinAllocateGdiPlusError("Pen constructor failed", status));
521 return;
522 }
523 }
524 public Pen(const Color& color) : this(color, 1.000000f)
525 {
526 }
527 public Pen(const Pen& that) : nativePen(WinGraphicsClonePen(that.nativePen))
528 {
529 int status = WinGraphicsPenGetLastStatus(nativePen);
530 if (status != 0)
531 {
532 SetErrorId(WinAllocateGdiPlusError("Pen copy constructor failed", status));
533 return;
534 }
535 }
536 public Pen(Pen&& that) : nativePen(that.nativePen)
537 {
538 that.nativePen = null;
539 }
540 public void operator=(const Pen& that)
541 {
542 if (nativePen != that.nativePen)
543 {
544 if (nativePen != null)
545 {
546 WinGraphicsDeletePen(nativePen);
547 }
548 nativePen = WinGraphicsClonePen(that.nativePen);
549 int status = WinGraphicsPenGetLastStatus(nativePen);
550 if (status != 0)
551 {
552 SetErrorId(WinAllocateGdiPlusError("Pen copy assignment failed", status));
553 return;
554 }
555 }
556 }
557 public default void operator=(Pen&& that);
558 public ~Pen()
559 {
560 if (nativePen != null)
561 {
562 WinGraphicsDeletePen(nativePen);
563 }
564 }
565 public Alignment GetAlignment() const
566 {
567 return cast<Alignment>(WinGraphicsPenGetAlignment(nativePen));
568 }
569 [nodiscard]
570 public Result<bool> SetAlignment(Alignment alignment)
571 {
572 int status = WinGraphicsPenSetAlignment(nativePen, cast<int>(alignment));
573 if (status != 0)
574 {
575 int errorId = WinAllocateGdiPlusError("Pen.SetAlignment failed", status);
576 return Result<bool>(ErrorId(errorId));
577 }
578 return Result<bool>(true);
579 }
580 public Brush GetBrush() const
581 {
582 Brush brush;
583 brush.SetNativeBrush(WinGraphicsPenGetBrush(nativePen));
584 return brush;
585 }
586 [nodiscard]
587 public Result<bool> SetBrush(const Brush& brush)
588 {
589 int status = WinGraphicsPenSetBrush(nativePen, brush.NativeBrush());
590 if (status != 0)
591 {
592 int errorId = WinAllocateGdiPlusError("Pen.SetBrush failed", status);
593 return Result<bool>(ErrorId(errorId));
594 }
595 return Result<bool>(true);
596 }
597 [nodiscard]
598 public Result<Color> GetColor() const
599 {
600 Color color;
601 int status = WinGraphicsPenGetColor(nativePen, color.alpha, color.red, color.green, color.blue);
602 if (status != 0)
603 {
604 int errorId = WinAllocateGdiPlusError("Pen.GetColor failed", status);
605 return Result<Color>(ErrorId(errorId));
606 }
607 return Result<Color>(color);
608 }
609 [nodiscard]
610 public Result<bool> SetColor(const Color& color)
611 {
612 return WinGraphicsPenSetColor(nativePen, color.alpha, color.red, color.green, color.blue);
613 }
614 public LineCap GetStartCap() const
615 {
616 return cast<LineCap>(WinGraphicsPenGetStartCap(nativePen));
617 }
618 [nodiscard]
619 public Result<bool> SetStartCap(LineCap startCap)
620 {
621 int status = WinGraphicsPenSetStartCap(nativePen, cast<int>(startCap));
622 if (status != 0)
623 {
624 int errorId = WinAllocateGdiPlusError("Pen.SetStartCap failed", status);
625 return Result<bool>(ErrorId(errorId));
626 }
627 return Result<bool>(true);
628 }
629 public LineCap GetEndCap() const
630 {
631 return cast<LineCap>(WinGraphicsPenGetEndCap(nativePen));
632 }
633 [nodiscard]
634 public Result<bool> SetEndCap(LineCap endCap)
635 {
636 int status = WinGraphicsPenSetEndCap(nativePen, cast<int>(endCap));
637 if (status != 0)
638 {
639 int errorId = WinAllocateGdiPlusError("Pen.SetEndCap failed", status);
640 return Result<bool>(ErrorId(errorId));
641 }
642 return Result<bool>(true);
643 }
644 public DashCap GetDashCap() const
645 {
646 return cast<DashCap>(WinGraphicsPenGetDashCap(nativePen));
647 }
648 [nodiscard]
649 public Result<bool> SetDashCap(DashCap dashCap)
650 {
651 int status = WinGraphicsPenSetDashCap(nativePen, cast<int>(dashCap));
652 if (status != 0)
653 {
654 int errorId = WinAllocateGdiPlusError("Pen.SetDashCap failed", status);
655 return Result<bool>(ErrorId(errorId));
656 }
657 return Result<bool>(true);
658 }
659 public float GetDashOffset() const
660 {
661 return WinGraphicsPenGetDashOffset(nativePen);
662 }
663 [nodiscard]
664 public Result<bool> SetDashOffset(float dashOffset)
665 {
666 int status = WinGraphicsPenSetDashOffset(nativePen, dashOffset);
667 if (status != 0)
668 {
669 int errorId = WinAllocateGdiPlusError("Pen.SetDashOffset failed", status);
670 return Result<bool>(ErrorId(errorId));
671 }
672 return Result<bool>(true);
673 }
674 public DashStyle GetDashStyle() const
675 {
676 return cast<DashStyle>(WinGraphicsPenGetDashStyle(nativePen));
677 }
678 [nodiscard]
679 public Result<bool> SetDashStyle(DashStyle dashStyle)
680 {
681 int status = WinGraphicsPenSetDashStyle(nativePen, cast<int>(dashStyle));
682 if (status != 0)
683 {
684 int errorId = WinAllocateGdiPlusError("Pen.SetDashStyle failed", status);
685 return Result<bool>(ErrorId(errorId));
686 }
687 return Result<bool>(true);
688 }
689 public LineJoin GetLineJoin() const
690 {
691 return cast<LineJoin>(WinGraphicsPenGetLineJoin(nativePen));
692 }
693 [nodiscard]
694 public Result<bool> SetLineJoin(LineJoin lineJoin)
695 {
696 int status = WinGraphicsPenSetLineJoin(nativePen, cast<int>(lineJoin));
697 if (status != 0)
698 {
699 int errorId = WinAllocateGdiPlusError("Pen.SetLineJoin failed", status);
700 return Result<bool>(ErrorId(errorId));
701 }
702 return Result<bool>(true);
703 }
704 public inline void* NativePen() const
705 {
706 return nativePen;
707 }
708 private void* nativePen;
709 }
710
711 public class PenKey
712 {
713 public PenKey(const Color& color_, float width_, DashStyle dashStyle_) : color(color_), width(width_), dashStyle(dashStyle_)
714 {
715 }
716 public string ToString() const
717 {
718 return color.ToString() + ":" + System.ToString(width) + ":" + ToString(dashStyle);
719 }
720 public Color color;
721 public float width;
722 public DashStyle dashStyle;
723 }
724
725 public bool operator==(const PenKey& left, const PenKey& right)
726 {
727 return left.color == right.color && left.width == right.width && left.dashStyle == right.dashStyle;
728 }
729
730 public ulong GetHashCode(const PenKey& penKey)
731 {
732 return GetHashCode(penKey.ToString());
733 }
734
735 public abstract class Brush : GraphicsObject
736 {
737 public Brush() : base(), nativeBrush(null)
738 {
739 }
740 public void SetNativeBrush(const void* nativeBrush_)
741 {
742 nativeBrush = nativeBrush_;
743 }
744 public virtual ~Brush()
745 {
746 }
747 public virtual const void* NativeBrush() const
748 {
749 return nativeBrush;
750 }
751 private const void* nativeBrush;
752 }
753
754 public class SolidBrush : Brush
755 {
756 public SolidBrush(const Color& color) : nativeSolidBrush(WinGraphicsCreateSolidBrush(color.alpha, color.red, color.green, color.blue))
757 {
758 int status = WinGraphicsBrushGetLastStatus(nativeSolidBrush);
759 if (status != 0)
760 {
761 int errorId = WinAllocateGdiPlusError("SolidBrush constructor failed", status);
762 SetErrorId(errorId);
763 return;
764 }
765 SetNativeBrush(nativeSolidBrush);
766 }
767 public SolidBrush(const SolidBrush& that) : nativeSolidBrush(WinGraphicsCloneSolidBrush(that.nativeSolidBrush))
768 {
769 int status = WinGraphicsBrushGetLastStatus(nativeSolidBrush);
770 if (status != 0)
771 {
772 int errorId = WinAllocateGdiPlusError("SolidBrush copy constructor failed", status);
773 SetErrorId(errorId);
774 return;
775 }
776 SetNativeBrush(nativeSolidBrush);
777 }
778 public SolidBrush(SolidBrush&& that) : nativeSolidBrush(that.nativeSolidBrush)
779 {
780 that.SetNativeBrush(null);
781 that.nativeSolidBrush = null;
782 }
783 public void operator=(const SolidBrush& that)
784 {
785 if (nativeSolidBrush != that.nativeSolidBrush)
786 {
787 if (nativeSolidBrush != null)
788 {
789 WinGraphicsDeleteSolidBrush(nativeSolidBrush);
790 }
791 nativeSolidBrush = WinGraphicsCloneSolidBrush(that.nativeSolidBrush);
792 int status = WinGraphicsBrushGetLastStatus(nativeSolidBrush);
793 if (status != 0)
794 {
795 int errorId = WinAllocateGdiPlusError("SolidBrush copy assignment failed", status);
796 SetErrorId(errorId);
797 return;
798 }
799 SetNativeBrush(nativeSolidBrush);
800 }
801 }
802 public void operator=(SolidBrush&& that)
803 {
804 const void* thatNativeBrush = that.NativeBrush();
805 const void* nativeBrush = NativeBrush();
806 Swap(thatNativeBrush, nativeBrush);
807 that.SetNativeBrush(thatNativeBrush);
808 SetNativeBrush(nativeBrush);
809 Swap(nativeSolidBrush, that.nativeSolidBrush);
810 }
811 public ~SolidBrush()
812 {
813 if (nativeSolidBrush != null)
814 {
815 WinGraphicsDeleteSolidBrush(nativeSolidBrush);
816 }
817 }
818 public override const void* NativeBrush() const
819 {
820 return nativeSolidBrush;
821 }
822 private void* nativeSolidBrush;
823 }
824
825 public class NativeHandle
826 {
827 public explicit NativeHandle(const void* handle_) : handle(handle_)
828 {
829 }
830 public void* handle;
831 }
832
833 public class FontFamily : GraphicsObject
834 {
835 public FontFamily() : base(), nativeFontFamily(WinGraphicsCreateEmptyFontFamily()), owned(true)
836 {
837 int status = WinGraphicsFontFamilyGetLastStatus(nativeFontFamily);
838 if (status != 0)
839 {
840 int errorId = WinAllocateGdiPlusError("FontFamily constructor failed", status);
841 SetErrorId(errorId);
842 return;
843 }
844 }
845 public FontFamily(const string& familyName) : nativeFontFamily(WinGraphicsCreateFontFamily(familyName.Chars())), owned(true)
846 {
847 int status = WinGraphicsFontFamilyGetLastStatus(nativeFontFamily);
848 if (status != 0)
849 {
850 int errorId = WinAllocateGdiPlusError("FontFamily string constructor failed", status);
851 SetErrorId(errorId);
852 return;
853 }
854 }
855 public explicit FontFamily(const NativeHandle& nativeHandle_) : nativeFontFamily(nativeHandle_.handle), owned(false)
856 {
857 }
858 public FontFamily(const FontFamily& that) : nativeFontFamily(null), owned(that.owned)
859 {
860 if (owned)
861 {
862 nativeFontFamily = WinGraphicsCloneFontFamily(that.nativeFontFamily);
863 int status = WinGraphicsFontFamilyGetLastStatus(nativeFontFamily);
864 if (status != 0)
865 {
866 int errorId = WinAllocateGdiPlusError("FontFamily copy constructor failed", status);
867 SetErrorId(errorId);
868 return;
869 }
870 }
871 else
872 {
873 nativeFontFamily = that.nativeFontFamily;
874 }
875 }
876 public FontFamily(FontFamily&& that) : nativeFontFamily(that.nativeFontFamily), owned(that.owned)
877 {
878 that.nativeFontFamily = null;
879 that.owned = false;
880 }
881 public void operator=(const FontFamily& that)
882 {
883 if (nativeFontFamily != that.nativeFontFamily)
884 {
885 if (nativeFontFamily != null && owned)
886 {
887 WinGraphicsDeleteFontFamily(nativeFontFamily);
888 }
889 if (that.owned)
890 {
891 nativeFontFamily = WinGraphicsCloneFontFamily(that.nativeFontFamily);
892 int status = WinGraphicsFontFamilyGetLastStatus(nativeFontFamily);
893 if (status != 0)
894 {
895 int errorId = WinAllocateGdiPlusError("FontFamily copy assignment failed", status);
896 SetErrorId(errorId);
897 return;
898 }
899 else
900 {
901 owned = true;
902 }
903 }
904 else
905 {
906 nativeFontFamily = that.nativeFontFamily;
907 owned = false;
908 }
909 }
910 }
911 public default void operator=(FontFamily&&);
912 public ~FontFamily()
913 {
914 if (nativeFontFamily != null && owned)
915 {
916 WinGraphicsDeleteFontFamily(nativeFontFamily);
917 }
918 }
919 [nodiscard]
920 public Result<string> GetFamilyName() const
921 {
922 void* str = null;
923 int status = WinGraphicsGetFontFamilyName(nativeFontFamily, str);
924 if (status != 0)
925 {
926 int errorId = WinAllocateGdiPlusError("FontFamily.GetFamilyName failed", status);
927 return Result<string>(ErrorId(errorId));
928 }
929 auto familyNameResult = ToUtf8(cast<wchar*>(str));
930 if (familyNameResult.Error())
931 {
932 return Result<string>(ErrorId(familyNameResult.GetErrorId()));
933 }
934 return Result<string>(familyNameResult.Value());
935 }
936 public static FontFamily GenericMonospace()
937 {
938 NativeHandle nativeHandle(WinGraphicsGetGenericMonospaceFontFamily());
939 return FontFamily(nativeHandle);
940 }
941 public static FontFamily GenericSansSerif()
942 {
943 NativeHandle nativeHandle(WinGraphicsGetGenericSansSerifFontFamily());
944 return FontFamily(nativeHandle);
945 }
946 public static FontFamily GenericSerif()
947 {
948 NativeHandle nativeHandle(WinGraphicsGetGenericSerifFontFamily());
949 return FontFamily(nativeHandle);
950 }
951 public inline void* NativeFontFamily() const
952 {
953 return nativeFontFamily;
954 }
955 private void* nativeFontFamily;
956 private bool owned;
957 }
958
959 public enum FontStyle : int
960 {
961 regular = 0,
962 bold = 1 << 0,
963 italic = 1 << 1,
964 boldItalic = bold | italic,
965 underline = 1 << 2,
966 strikeOut = 1 << 3
967 }
968
969 public ulong GetHashCode(FontStyle fontStyle)
970 {
971 return cast<ulong>(cast<int>(fontStyle));
972 }
973
974 public enum Unit : int
975 {
976 world = 0,
977 display = 1,
978 pixel = 2,
979 point = 3,
980 inch = 4,
981 document = 5,
982 millimeter = 6
983 }
984
985 public class FontHandle
986 {
987 public FontHandle(void* hfont_) : hfont(hfont_)
988 {
989 }
990 suppress FontHandle(const FontHandle&);
991 suppress void operator=(const FontHandle&);
992 public FontHandle(FontHandle&& that) : hfont(that.hfont)
993 {
994 that.hfont = null;
995 }
996 public default void operator=(FontHandle&&);
997 public ~FontHandle()
998 {
999 if (hfont != null)
1000 {
1001 WinDeleteObject(hfont);
1002 }
1003 }
1004 public inline bool IsNull() const
1005 {
1006 return hfont == null;
1007 }
1008 public inline void* HFont() const
1009 {
1010 return hfont;
1011 }
1012 private void* hfont;
1013 }
1014
1015 public class Font : GraphicsObject
1016 {
1017 public Font(const FontFamily& family, float emSize, FontStyle style, Unit unit) :
1018 base(), nativeFont(WinGraphicsCreateFont(family.NativeFontFamily(), emSize, style, unit))
1019 {
1020 int status = WinGraphicsFontGetLastStatus(nativeFont);
1021 if (status != 0)
1022 {
1023 int errorId = WinAllocateGdiPlusError("Font constructor failed", status);
1024 SetErrorId(errorId);
1025 return;
1026 }
1027 }
1028 public Font(const FontFamily& family, float emSize) : this(family, emSize, FontStyle.regular, Unit.point)
1029 {
1030 }
1031 public Font(void* nativeFont_) : nativeFont(nativeFont_)
1032 {
1033 }
1034 public Font() : this(null)
1035 {
1036 }
1037 public Font(const Font& that) : nativeFont(WinGraphicsCloneFont(that.nativeFont))
1038 {
1039 int status = WinGraphicsFontGetLastStatus(nativeFont);
1040 if (status != 0)
1041 {
1042 int errorId = WinAllocateGdiPlusError("Font copy constructor failed", status);
1043 SetErrorId(errorId);
1044 return;
1045 }
1046 }
1047 public Font(Font&& that) : nativeFont(that.nativeFont)
1048 {
1049 that.nativeFont = null;
1050 }
1051 public void operator=(const Font& that)
1052 {
1053 if (nativeFont != that.nativeFont)
1054 {
1055 if (nativeFont != null)
1056 {
1057 WinGraphicsDeleteFont(nativeFont);
1058 }
1059 nativeFont = WinGraphicsCloneFont(that.nativeFont);
1060 }
1061 }
1062 public default void operator=(Font&&);
1063 public ~Font()
1064 {
1065 if (nativeFont != null)
1066 {
1067 WinGraphicsDeleteFont(nativeFont);
1068 }
1069 }
1070 public bool IsNull() const
1071 {
1072 return nativeFont == null;
1073 }
1074 public float GetSize() const
1075 {
1076 return WinGraphicsGetFontSize(nativeFont);
1077 }
1078 public float GetHeight(const Graphics& graphics) const
1079 {
1080 return WinGraphicsGetFontHeight(nativeFont, graphics.NativeGraphics());
1081 }
1082 public FontStyle GetStyle() const
1083 {
1084 return cast<FontStyle>(WinGraphicsGetFontStyle(nativeFont));
1085 }
1086 [nodiscard]
1087 public Result<FontFamily> GetFamily()
1088 {
1089 FontFamily fontFamily;
1090 int status = WinGraphicsGetFontFamily(nativeFont, fontFamily.NativeFontFamily());
1091 if (status != 0)
1092 {
1093 int errorId = WinAllocateGdiPlusError("Font.GetFamily failed", status);
1094 return Result<FontFamily>(ErrorId(errorId));
1095 }
1096 return Result<FontFamily>(fontFamily);
1097 }
1098 [nodiscard]
1099 public static Result<Font> FromHFont(void* hdc, void* hfont)
1100 {
1101 Font font(WinGraphicsCreateFontFromHFont(hdc, hfont));
1102 int status = WinGraphicsFontGetLastStatus(font.NativeFont());
1103 if (status != 0)
1104 {
1105 int errorId = WinAllocateGdiPlusError("Font.FromHFont failed", status);
1106 return Result<Font>(ErrorId(errorId));
1107 }
1108 return Result<Font>(font);
1109 }
1110 [nodiscard]
1111 public Result<FontHandle> ToHFont(const Graphics& graphics)
1112 {
1113 void* hfont = null;
1114 int status = WinGraphicsFontToHFont(nativeFont, graphics.NativeGraphics(), hfont);
1115 if (status != 0)
1116 {
1117 int errorId = WinAllocateGdiPlusError("Font.ToHFont failed", status);
1118 return Result<FontHandle>(ErrorId(errorId));
1119 }
1120 else
1121 {
1122 FontHandle fontHandle = FontHandle(hfont);
1123 return Result<FontHandle>(Rvalue(fontHandle));
1124 }
1125 }
1126 public inline void* NativeFont() const
1127 {
1128 return nativeFont;
1129 }
1130 private void* nativeFont;
1131 }
1132
1133 public string ToString(FontStyle style)
1134 {
1135 string s;
1136 if (style == FontStyle.regular)
1137 {
1138 s.Append("regular");
1139 }
1140 else
1141 {
1142 if ((style & FontStyle.bold) != 0)
1143 {
1144 if (!s.IsEmpty())
1145 {
1146 s.Append('.');
1147 }
1148 s.Append("bold");
1149 }
1150 if ((style & FontStyle.italic) != 0)
1151 {
1152 if (!s.IsEmpty())
1153 {
1154 s.Append('.');
1155 }
1156 s.Append("italic");
1157 }
1158 if ((style & FontStyle.underline) != 0)
1159 {
1160 if (!s.IsEmpty())
1161 {
1162 s.Append('.');
1163 }
1164 s.Append("underline");
1165 }
1166 if ((style & FontStyle.strikeOut) != 0)
1167 {
1168 if (!s.IsEmpty())
1169 {
1170 s.Append('.');
1171 }
1172 s.Append("strikeOut");
1173 }
1174 }
1175 return s;
1176 }
1177
1178 public FontStyle ParseFontStyle(const string& fontStyleStr)
1179 {
1180 FontStyle fontStyle = FontStyle.regular;
1181 List<string> components = fontStyleStr.Split('.');
1182 for (const string& component : components)
1183 {
1184 if (component == "bold")
1185 {
1186 fontStyle = cast<FontStyle>(fontStyle | FontStyle.bold);
1187 }
1188 else if (component == "italic")
1189 {
1190 fontStyle = cast<FontStyle>(fontStyle | FontStyle.italic);
1191 }
1192 else if (component == "underline")
1193 {
1194 fontStyle = cast<FontStyle>(fontStyle | FontStyle.underline);
1195 }
1196 else if (component == "strikeOut")
1197 {
1198 fontStyle = cast<FontStyle>(fontStyle | FontStyle.strikeOut);
1199 }
1200 }
1201 return fontStyle;
1202 }
1203
1204 public class FontKey
1205 {
1206 public FontKey(const string& family_, float size_, FontStyle style_) : family(family_), size(size_), style(style_)
1207 {
1208 }
1209 [nodiscard]
1210 public Result<string> ToString()
1211 {
1212 auto toLowerResult = ToLower(family);
1213 if (toLowerResult.Error())
1214 {
1215 return Result<string>(ErrorId(toLowerResult.GetErrorId()));
1216 }
1217 string s = Rvalue(toLowerResult.Value());
1218 s.Append('.').Append(System.ToString(size)).Append('.').Append(ToString(style));
1219 return s;
1220 }
1221 public string family;
1222 public float size;
1223 public FontStyle style;
1224 }
1225
1226 public bool operator==(const FontKey& left, const FontKey& right)
1227 {
1228 return ToLower(left.family) == ToLower(right.family) && left.size == right.size && left.style == right.style;
1229 }
1230
1231 [nodiscard]
1232 public Result<ulong> GetHashCode(const FontKey& fontKey)
1233 {
1234 auto fontKeyResult = fontKey.ToString();
1235 if (fontKeyResult.Error())
1236 {
1237 return Result<ulong>(ErrorId(fontKeyResult.GetErrorId()));
1238 }
1239 return Result<ulong>(GetHashCode(fontKeyResult.Value()));
1240 }
1241
1242 public enum StringAlignment : int
1243 {
1244 near, center, far
1245 }
1246
1247 public enum HotKeyPrefix : int
1248 {
1249 none, show, hide
1250 }
1251
1252 public class StringFormat : GraphicsObject
1253 {
1254 public StringFormat() : nativeFormat(WinGraphicsCreateDefaultStringFormat()), owned(true)
1255 {
1256 int status = WinGraphicsStringFormatGetLastStatus(nativeFormat);
1257 if (status != 0)
1258 {
1259 int errorId = WinAllocateGdiPlusError("StringFormat constructor failed", status);
1260 SetErrorId(errorId);
1261 return;
1262 }
1263 }
1264 public StringFormat(const NativeHandle& nativeHandle_) : nativeFormat(nativeHandle_.handle), owned(false)
1265 {
1266 }
1267 public StringFormat(const StringFormat& that) : nativeFormat(null), owned(that.owned)
1268 {
1269 if (owned)
1270 {
1271 nativeFormat = WinGraphicsCloneStringFormat(that.nativeFormat);
1272 int status = WinGraphicsStringFormatGetLastStatus(nativeFormat);
1273 if (status != 0)
1274 {
1275 int errorId = WinAllocateGdiPlusError("StringFormat copy constructor failed", status);
1276 SetErrorId(errorId);
1277 return;
1278 }
1279 }
1280 else
1281 {
1282 nativeFormat = that.nativeFormat;
1283 }
1284 }
1285 public StringFormat(StringAlignment horizontalAlignment, StringAlignment verticalAlignment, HotKeyPrefix hotKeyPrefix) : this()
1286 {
1287 auto setAlignmentResult = SetAlignment(horizontalAlignment);
1288 if (setAlignmentResult.Error())
1289 {
1290 SetErrorId(setAlignmentResult.GetErrorId());
1291 return;
1292 }
1293 auto setLineAlignmentResult = SetLineAlignment(verticalAlignment);
1294 if (setLineAlignmentResult.Error())
1295 {
1296 SetErrorId(setLineAlignmentResult.GetErrorId());
1297 return;
1298 }
1299 auto setHotKeyPrefixResult = SetHotKeyPrefix(hotKeyPrefix);
1300 if (setHotKeyPrefixResult.Error())
1301 {
1302 SetErrorId(setHotKeyPrefixResult.GetErrorId());
1303 return;
1304 }
1305 }
1306 public StringFormat(StringAlignment horizontalAlignment, StringAlignment verticalAlignment) : this(horizontalAlignment, verticalAlignment, HotKeyPrefix.none)
1307 {
1308 }
1309 public StringFormat(StringFormat&& that) : nativeFormat(that.nativeFormat), owned(that.owned)
1310 {
1311 that.nativeFormat = null;
1312 that.owned = false;
1313 }
1314 public void operator=(const StringFormat& that)
1315 {
1316 if (nativeFormat != that.nativeFormat)
1317 {
1318 if (nativeFormat != null && owned)
1319 {
1320 WinGraphicsDeleteStringFormat(nativeFormat);
1321 }
1322 if (that.owned)
1323 {
1324 nativeFormat = WinGraphicsCloneStringFormat(that.nativeFormat);
1325 int status = WinGraphicsStringFormatGetLastStatus(nativeFormat);
1326 if (status != 0)
1327 {
1328 int errorId = WinAllocateGdiPlusError("StringFormat copy assignment failed", status);
1329 SetErrorId(errorId);
1330 return;
1331 }
1332 owned = true;
1333 }
1334 else
1335 {
1336 nativeFormat = that.nativeFormat;
1337 owned = false;
1338 }
1339 }
1340 }
1341 public default void operator=(StringFormat&&);
1342 public ~StringFormat()
1343 {
1344 if (nativeFormat != null && owned)
1345 {
1346 WinGraphicsDeleteStringFormat(nativeFormat);
1347 }
1348 }
1349 [nodiscard]
1350 public Result<bool> SetAlignment(StringAlignment alignment)
1351 {
1352 int status = WinGraphicsStringFormatSetAlignment(nativeFormat, alignment);
1353 if (status != 0)
1354 {
1355 int errorId = WinAllocateGdiPlusError("StringFormat.SetAlignment failed", status);
1356 return Result<bool>(ErrorId(errorId));
1357 }
1358 return Result<bool>(true);
1359 }
1360 [nodiscard]
1361 public Result<bool> SetLineAlignment(StringAlignment alignment)
1362 {
1363 int status = WinGraphicsStringFormatSetLineAlignment(nativeFormat, alignment);
1364 if (status != 0)
1365 {
1366 int errorId = WinAllocateGdiPlusError("StringFormat.SetLineAlignment failed", status);
1367 return Result<bool>(ErrorId(errorId));
1368 }
1369 return Result<bool>(true);
1370 }
1371 [nodiscard]
1372 public Result<bool> SetHotKeyPrefix(HotKeyPrefix hotKeyPrefix)
1373 {
1374 int status = WinGraphicsStringFormatSetHotKeyPrefix(nativeFormat, hotKeyPrefix);
1375 if (status != 0)
1376 {
1377 int errorId = WinAllocateGdiPlusError("StringFormat.SetHotKeyPrefix failed", status);
1378 return Result<bool>(ErrorId(errorId));
1379 }
1380 return Result<bool>(true);
1381 }
1382 public inline void* NativeFormat() const
1383 {
1384 return nativeFormat;
1385 }
1386 public static StringFormat GenericDefault()
1387 {
1388 NativeHandle nativeHandle(WinGraphicsGetGenericDefaultStringFormat());
1389 return StringFormat(nativeHandle);
1390 }
1391 public static StringFormat GenericTypographic()
1392 {
1393 NativeHandle nativeHandle(WinGraphicsGetGenericTypographicStringFormat());
1394 return StringFormat(nativeHandle);
1395 }
1396 private void* nativeFormat;
1397 private bool owned;
1398 }
1399
1400 public enum TextRenderingHint : int
1401 {
1402 systemDefault = 0,
1403 singleBitPerPixelGridFit = 1,
1404 singleBitPerPixel = 2,
1405 antiAliasGridFit = 3,
1406 antiAlias = 4,
1407 clearTypeGridFit = 5
1408 }
1409
1410 internal class PaintGuard
1411 {
1412 public PaintGuard(void* hdc_, void* paintStruct_) : hdc(hdc_), paintStruct(paintStruct_)
1413 {
1414 }
1415 public ~PaintGuard()
1416 {
1417 if (hdc != null)
1418 {
1419 EndPaint(hdc, paintStruct);
1420 }
1421 }
1422 private void* hdc;
1423 private void* paintStruct;
1424 }
1425
1426 public enum CombineMode : int
1427 {
1428 replace, intersect, union, xor, exclude, complement
1429 }
1430
1431 public class Region : GraphicsObject
1432 {
1433 public Region() : nativeRegion(WinGraphicsCreateRegion())
1434 {
1435 int status = WinGraphicsRegionGetLastStatus(nativeRegion);
1436 if (status != 0)
1437 {
1438 int errorId = WinAllocateGdiPlusError("Region constructor failed", status);
1439 SetErrorId(errorId);
1440 return;
1441 }
1442 }
1443 public Region(const Region& that) : nativeRegion(WinGraphicsCloneRegion(that.nativeRegion))
1444 {
1445 int status = WinGraphicsRegionGetLastStatus(nativeRegion);
1446 if (status != 0)
1447 {
1448 int errorId = WinAllocateGdiPlusError("Region copy constructor failed", status);
1449 SetErrorId(errorId);
1450 return;
1451 }
1452 }
1453 public Region(Region&& that) : nativeRegion(that.nativeRegion)
1454 {
1455 that.nativeRegion = null;
1456 }
1457 public void operator=(const Region& that)
1458 {
1459 if (nativeRegion != null)
1460 {
1461 WinGraphicsDeleteRegion(nativeRegion);
1462 }
1463 nativeRegion = WinGraphicsCloneRegion(that.nativeRegion);
1464 int status = WinGraphicsRegionGetLastStatus(nativeRegion);
1465 if (status != 0)
1466 {
1467 int errorId = WinAllocateGdiPlusError("Region copy assignment failed", status);
1468 SetErrorId(errorId);
1469 return;
1470 }
1471 }
1472 public default void operator=(Region&&);
1473 public ~Region()
1474 {
1475 if (nativeRegion != null)
1476 {
1477 WinGraphicsDeleteRegion(nativeRegion);
1478 }
1479 }
1480 public inline void* NativeRegion() const
1481 {
1482 return nativeRegion;
1483 }
1484 private void* nativeRegion;
1485 }
1486
1487
1488
1489 public enum ImageFormat : int
1490 {
1491 bmp, jpeg, gif, tiff, png
1492 }
1493
1494 public const char* GetImageFormat(ImageFormat format)
1495 {
1496 switch (format)
1497 {
1498 case ImageFormat.bmp: return "image/bmp";
1499 case ImageFormat.jpeg: return "image/jpeg";
1500 case ImageFormat.gif: return "image/gif";
1501 case ImageFormat.tiff: return "image/tiff";
1502 case ImageFormat.png: return "image/png";
1503 }
1504 return "";
1505 }
1506
1507 [nodiscard]
1508 public Result<Uuid> GetEncoderClsId(const char* imageFormat)
1509 {
1510 Uuid clsid;
1511 int status = WinGraphicsGetEncoderClsId(imageFormat, &clsid);
1512 if (status != 0)
1513 {
1514 int errorId = WinAllocateGdiPlusError("get encoder clsid failed", status);
1515 return Result<Uuid>(ErrorId(errorId));
1516 }
1517 return Result<Uuid>(clsid);
1518 }
1519
1520 public class Image : GraphicsObject
1521 {
1522 public Image() : base(), nativeImage(null)
1523 {
1524 }
1525 public explicit Image(void* nativeImage_) : base(), nativeImage(nativeImage_)
1526 {
1527 }
1528 public Image(const string& fileName, bool useEmbeddedColorManagement) : base(), nativeImage(WinGraphicsCreateImage(fileName.Chars(), useEmbeddedColorManagement))
1529 {
1530 int status = WinGraphicsImageGetLastStatus(nativeImage);
1531 if (status != 0)
1532 {
1533 int errorId = WinAllocateGdiPlusError("Image constructor failed", status);
1534 SetErrorId(errorId);
1535 return;
1536 }
1537 }
1538 public Image(const Image& that) : nativeImage(WinGraphicsCloneImage(that.nativeImage))
1539 {
1540 int status = WinGraphicsImageGetLastStatus(nativeImage);
1541 if (status != 0)
1542 {
1543 int errorId = WinAllocateGdiPlusError("Image copy constructor failed", status);
1544 SetErrorId(errorId);
1545 return;
1546 }
1547 }
1548 public Image(Image&& that) : nativeImage(that.nativeImage)
1549 {
1550 that.nativeImage = null;
1551 }
1552 public void operator=(const Image& that)
1553 {
1554 if (nativeImage != null)
1555 {
1556 WinGraphicsDeleteImage(nativeImage);
1557 }
1558 nativeImage = WinGraphicsCloneImage(that.nativeImage);
1559 int status = WinGraphicsImageGetLastStatus(nativeImage);
1560 if (status != 0)
1561 {
1562 int errorId = WinAllocateGdiPlusError("Image copy assignment failed", status);
1563 SetErrorId(errorId);
1564 return;
1565 }
1566 }
1567 public default void operator=(Image&&);
1568 public virtual ~Image()
1569 {
1570 if (nativeImage != null)
1571 {
1572 WinGraphicsDeleteImage(nativeImage);
1573 }
1574 }
1575 public int GetHeight() const
1576 {
1577 return WinGraphicsImageGetHeight(nativeImage);
1578 }
1579 public int GetWidth() const
1580 {
1581 return WinGraphicsImageGetWidth(nativeImage);
1582 }
1583 [nodiscard]
1584 public Result<bool> Save(const char* fileName, const Uuid& encoderClsId)
1585 {
1586 int status = WinGraphicsImageSave(nativeImage, fileName, &encoderClsId);
1587 if (status != 0)
1588 {
1589 int errorId = WinAllocateGdiPlusError("Image.Save failed", status);
1590 return Result<bool>(ErrorId(errorId));
1591 }
1592 return Result<bool>(true);
1593 }
1594 public void* NativeImage() const
1595 {
1596 return nativeImage;
1597 }
1598 private void* nativeImage;
1599 }
1600
1601 public const int pixelFormatIndexed = 65536;
1602 public const int pixelFormatGDI = 131072;
1603 public const int pixelFormatAlpha = 262144;
1604 public const int pixelFormatPAlpha = 524288;
1605 public const int pixelFormatExtended = 1048576;
1606 public const int pixelFormatCanonical = 2097152;
1607
1608 public enum PixelFormat : int
1609 {
1610 pixelFormat1bppIndexed = 1 | (1 << 8) | pixelFormatIndexed | pixelFormatGDI,
1611 pixelFormat4bppIndexed = 2 | (4 << 8) | pixelFormatIndexed | pixelFormatGDI,
1612 pixelFormat8bppIndexed = 3 | ( 8 << 8) | pixelFormatIndexed | pixelFormatGDI,
1613 pixelFormat16bppGrayScale = 4 | (16 << 8) | pixelFormatExtended,
1614 pixelFormat16bppRGB555 = 5 | (16 << 8) | pixelFormatGDI,
1615 pixelFormat16bppRGB565 = 6 | (16 << 8) | pixelFormatGDI,
1616 pixelFormat16bppARGB1555 = 7 | (16 << 8) | pixelFormatAlpha | pixelFormatGDI,
1617 pixelFormat24bppRGB = 8 | (24 << 8) | pixelFormatGDI,
1618 pixelFormat32bppRGB = 9 | (32 << 8) | pixelFormatGDI,
1619 pixelFormat32bppARGB = 10 | (32 << 8) | pixelFormatAlpha | pixelFormatGDI | pixelFormatCanonical,
1620 pixelFormat32bppPARGB = 11 | (32 << 8) | pixelFormatAlpha | pixelFormatPAlpha | pixelFormatGDI,
1621 pixelFormat48bppRGB = 12 | (48 << 8) | pixelFormatExtended,
1622 pixelFormat64bppARGB = 13 | (64 << 8) | pixelFormatAlpha | pixelFormatCanonical | pixelFormatExtended,
1623 pixelFormat64bppPARGB = 14 | (64 << 8) | pixelFormatAlpha | pixelFormatPAlpha | pixelFormatExtended,
1624 pixelFormat32bppCMYK = 15 | (32 << 8),
1625 pixelFormatMax = 16
1626 }
1627
1628 public class Bitmap : Image
1629 {
1630 public Bitmap() : base()
1631 {
1632 }
1633 public explicit Bitmap(void* nativeHandle_) : base(nativeHandle_)
1634 {
1635 }
1636 public Bitmap(const string& fileName, bool useEmbeddedColorManagement) : base(WinGraphicsCreateBitmap(fileName.Chars(), useEmbeddedColorManagement))
1637 {
1638 int status = WinGraphicsImageGetLastStatus(NativeImage());
1639 if (status != 0)
1640 {
1641 int errorId = WinAllocateGdiPlusError("Bitmap(string, bool) constructor failed", status);
1642 SetErrorId(errorId);
1643 return;
1644 }
1645 }
1646 public Bitmap(int width, int height, const Graphics& graphics) : base(WinGraphicsCreateBitmapWidthHeight(width, height, graphics.NativeGraphics()))
1647 {
1648 int status = WinGraphicsImageGetLastStatus(NativeImage());
1649 if (status != 0)
1650 {
1651 int errorId = WinAllocateGdiPlusError("Bitmap(int, int) constructor failed", status);
1652 SetErrorId(errorId);
1653 return;
1654 }
1655 }
1656 public Bitmap(const WinBitmap& winBitmap, void* palette) : base(WinGraphicsCreateBitmapWinBitmap(winBitmap.Handle(), palette))
1657 {
1658 int status = WinGraphicsImageGetLastStatus(NativeImage());
1659 if (status != 0)
1660 {
1661 int errorId = WinAllocateGdiPlusError("Bitmap(WinBitmap, void*) constructor failed", status);
1662 SetErrorId(errorId);
1663 return;
1664 }
1665 }
1666 public Bitmap(const Icon& icon) : base(WinGraphicsCreateBitmapIcon(icon.Handle()))
1667 {
1668 int status = WinGraphicsImageGetLastStatus(NativeImage());
1669 if (status != 0)
1670 {
1671 int errorId = WinAllocateGdiPlusError("Bitmap(Icon) constructor failed", status);
1672 SetErrorId(errorId);
1673 return;
1674 }
1675 }
1676 [nodiscard]
1677 public static Result<Bitmap> FromResource(const string& resourceName)
1678 {
1679 Bitmap bitmap(WinGraphicsCreateBitmapResource(resourceName.Chars()));
1680 if (bitmap.Error())
1681 {
1682 return Result<Bitmap>(ErrorId(bitmap.GetErrorId()));
1683 }
1684 int status = WinGraphicsImageGetLastStatus(bitmap.NativeImage());
1685 if (status != 0)
1686 {
1687 int errorId = WinAllocateGdiPlusError("Bitmap.FromResource failed", status);
1688 return Result<Bitmap>(ErrorId(errorId));
1689 }
1690 return Result<Bitmap>(Rvalue(bitmap));
1691 }
1692 [nodiscard]
1693 public Result<Color> GetPixel(int x, int y) const
1694 {
1695 Color color;
1696 int status = WinGraphicsBitmapGetPixel(NativeImage(), x, y, color.alpha, color.red, color.green, color.blue);
1697 if (status != 0)
1698 {
1699 int errorId = WinAllocateGdiPlusError("Bitmap.GetPixel failed", status);
1700 return Result<Color>(ErrorId(errorId));
1701 }
1702 return Result<Color>(color);
1703 }
1704 [nodiscard]
1705 public Result<bool> SetPixel(int x, int y, const Color& color)
1706 {
1707 int status = WinGraphicsBitmapSetPixel(NativeImage(), x, y, color.alpha, color.red, color.green, color.blue);
1708 if (status != 0)
1709 {
1710 int errorId = WinAllocateGdiPlusError("Bitmap.SetPixel failed", status);
1711 return Result<bool>(ErrorId(errorId));
1712 }
1713 return Result<bool>(true);
1714 }
1715 [nodiscard]
1716 public Result<Bitmap> ToGrayBitmap(PixelFormat pixelFormat, const Color& bitmapTransparentColor)
1717 {
1718 int w = cast<int>(GetWidth());
1719 int h = cast<int>(GetHeight());
1720 Bitmap grayBitmap(WinGraphicsCloneBitmap(NativeImage(), 0, 0, w, h, pixelFormat));
1721 if (grayBitmap.Error())
1722 {
1723 return Result<Bitmap>(ErrorId(grayBitmap.GetErrorId()));
1724 }
1725 for (int y = 0; y < h; ++y;)
1726 {
1727 for(int x = 0; x < w; ++x;)
1728 {
1729 Result<Color> colorResult = grayBitmap.GetPixel(x, y);
1730 if (colorResult.Error())
1731 {
1732 return Result<Bitmap>(ErrorId(colorResult.GetErrorId()));
1733 }
1734 Color color = colorResult.Value();
1735 Color gray = color.ToGray(bitmapTransparentColor);
1736 auto setPixelResult = grayBitmap.SetPixel(x, y, gray);
1737 if (setPixelResult.Error())
1738 {
1739 return Result<Bitmap>(ErrorId(setPixelResult.GetErrorId()));
1740 }
1741 }
1742 }
1743 return Result<Bitmap>(grayBitmap);
1744 }
1745 [nodiscard]
1746 public Result<Bitmap> ToGrayBitmap()
1747 {
1748 return ToGrayBitmap(PixelFormat.pixelFormat24bppRGB, Color.DefaultBitmapTransparent());
1749 }
1750 public ~Bitmap()
1751 {
1752 }
1753 }
1754
1755 public enum MatrixOrder
1756 {
1757 prepend, append
1758 }
1759
1760 public class Matrix : GraphicsObject
1761 {
1762 public Matrix() : nativeMatrix(WinGraphicsCreateMatrix())
1763 {
1764 int status = WinGraphicsMatrixGetLastStatus(nativeMatrix);
1765 if (status != 0)
1766 {
1767 int errorId = WinAllocateGdiPlusError("Matrix constructor failed", status);
1768 SetErrorId(errorId);
1769 return;
1770 }
1771 }
1772 public Matrix(const Rect& rect, const Point& pt) : nativeMatrix(WinGraphicsCreateMatrixRectPoint(rect.location.x, rect.location.y, rect.size.w, rect.size.h, pt.x, pt.y))
1773 {
1774 int status = WinGraphicsMatrixGetLastStatus(nativeMatrix);
1775 if (status != 0)
1776 {
1777 int errorId = WinAllocateGdiPlusError("Matrix(Rect, Point) constructor failed", status);
1778 SetErrorId(errorId);
1779 return;
1780 }
1781 }
1782 public Matrix(const RectF& rect, const PointF& pt) : nativeMatrix(WinGraphicsCreateMatrixRectFPointF(rect.location.x, rect.location.y, rect.size.w, rect.size.h, pt.x, pt.y))
1783 {
1784 int status = WinGraphicsMatrixGetLastStatus(nativeMatrix);
1785 if (status != 0)
1786 {
1787 int errorId = WinAllocateGdiPlusError("Matrix(RectF, PointF) constructor failed", status);
1788 SetErrorId(errorId);
1789 return;
1790 }
1791 }
1792 public Matrix(const Matrix& that) : nativeMatrix(WinGraphicsCloneMatrix(that.nativeMatrix))
1793 {
1794 int status = WinGraphicsMatrixGetLastStatus(nativeMatrix);
1795 if (status != 0)
1796 {
1797 int errorId = WinAllocateGdiPlusError("Matrix copy constructor failed", status);
1798 SetErrorId(errorId);
1799 return;
1800 }
1801 }
1802 public Matrix(Matrix&& that) : nativeMatrix(that.nativeMatrix)
1803 {
1804 that.nativeMatrix = null;
1805 }
1806 public void operator=(const Matrix& that)
1807 {
1808 if (nativeMatrix != null)
1809 {
1810 WinGraphicsDeleteMatrix(nativeMatrix);
1811 }
1812 nativeMatrix = WinGraphicsCloneMatrix(that.nativeMatrix);
1813 int status = WinGraphicsMatrixGetLastStatus(nativeMatrix);
1814 if (status != 0)
1815 {
1816 int errorId = WinAllocateGdiPlusError("Matrix copy assignment failed", status);
1817 SetErrorId(errorId);
1818 return;
1819 }
1820 }
1821 public default void operator=(Matrix&&);
1822 public ~Matrix()
1823 {
1824 if (nativeMatrix != null)
1825 {
1826 WinGraphicsDeleteMatrix(nativeMatrix);
1827 }
1828 }
1829 [nodiscard]
1830 public Result<bool> Multiply(const Matrix& that, MatrixOrder order)
1831 {
1832 int status = WinGraphicsMultiplyMatrix(nativeMatrix, that.nativeMatrix, cast<int>(order));
1833 if (status != 0)
1834 {
1835 int errorId = WinAllocateGdiPlusError("Matrix.Multiply(Matrix, MatrixOrder) failed", status);
1836 return Result<bool>(ErrorId(errorId));
1837 }
1838 return Result<bool>(true);
1839 }
1840 [nodiscard]
1841 public Result<bool> Multiply(const Matrix& that)
1842 {
1843 int status = WinGraphicsMultiplyMatrix(nativeMatrix, that.nativeMatrix, cast<int>(MatrixOrder.prepend));
1844 if (status != 0)
1845 {
1846 int errorId = WinAllocateGdiPlusError("Matrix.Multiply(Matrix) failed", status);
1847 return Result<bool>(ErrorId(errorId));
1848 }
1849 return Result<bool>(true);
1850 }
1851 [nodiscard]
1852 public Result<bool> Reset()
1853 {
1854 int status = WinGraphicsResetMatrix(nativeMatrix);
1855 if (status != 0)
1856 {
1857 int errorId = WinAllocateGdiPlusError("Matrix.Reset failed", status);
1858 return Result<bool>(ErrorId(errorId));
1859 }
1860 return Result<bool>(true);
1861 }
1862 [nodiscard]
1863 public Result<bool> Invert()
1864 {
1865 int status = WinGraphicsInvertMatrix(nativeMatrix);
1866 if (status != 0)
1867 {
1868 int errorId = WinAllocateGdiPlusError("Matrix.Invert failed", status);
1869 return Result<bool>(ErrorId(errorId));
1870 }
1871 return Result<bool>(true);
1872 }
1873 public float OffsetX() const
1874 {
1875 return WinGraphicsMatrixOffsetX(nativeMatrix);
1876 }
1877 public float OffsetY() const
1878 {
1879 return WinGraphicsMatrixOffsetY(nativeMatrix);
1880 }
1881 [nodiscard]
1882 public Result<bool> Rotate(float angle, MatrixOrder order)
1883 {
1884 int status = WinGraphicsMatrixRotate(nativeMatrix, angle, cast<int>(order));
1885 if (status != 0)
1886 {
1887 int errorId = WinAllocateGdiPlusError("Matrix.Rotate(float, MatrixOrder) failed", status);
1888 return Result<bool>(ErrorId(errorId));
1889 }
1890 return Result<bool>(true);
1891 }
1892 [nodiscard]
1893 public Result<bool> Rotate(float angle)
1894 {
1895 int status = WinGraphicsMatrixRotate(nativeMatrix, angle, cast<int>(MatrixOrder.prepend));
1896 if (status != 0)
1897 {
1898 int errorId = WinAllocateGdiPlusError("Matrix.Rotate(float) failed", status);
1899 return Result<bool>(ErrorId(errorId));
1900 }
1901 return Result<bool>(true);
1902 }
1903 [nodiscard]
1904 public Result<bool> RotateAt(float angle, const PointF& center, MatrixOrder order)
1905 {
1906 int status = WinGraphicsMatrixRotateAt(nativeMatrix, angle, center.x, center.y, cast<int>(order));
1907 if (status != 0)
1908 {
1909 int errorId = WinAllocateGdiPlusError("Matrix.RotateAt(float, PointF, MatrixOrder) failed", status);
1910 return Result<bool>(ErrorId(errorId));
1911 }
1912 return Result<bool>(true);
1913 }
1914 [nodiscard]
1915 public Result<bool> RotateAt(float angle, const PointF& center)
1916 {
1917 return RotateAt(angle, center, MatrixOrder.prepend);
1918 }
1919 [nodiscard]
1920 public Result<bool> Scale(float scaleX, float scaleY, MatrixOrder order)
1921 {
1922 int status = WinGraphicsMatrixScale(nativeMatrix, scaleX, scaleY, cast<int>(order));
1923 if (status != 0)
1924 {
1925 int errorId = WinAllocateGdiPlusError("Matrix.Scale failed", status);
1926 return Result<bool>(ErrorId(errorId));
1927 }
1928 return Result<bool>(true);
1929 }
1930 [nodiscard]
1931 public Result<bool> Scale(float scaleX, float scaleY)
1932 {
1933 return Scale(scaleX, scaleY, MatrixOrder.prepend);
1934 }
1935 [nodiscard]
1936 public Result<bool> Shear(float shearX, float shearY, MatrixOrder order)
1937 {
1938 int status = WinGraphicsMatrixShear(nativeMatrix, shearX, shearY, cast<int>(order));
1939 if (status != 0)
1940 {
1941 int errorId = WinAllocateGdiPlusError("Matrix.Shear failed", status);
1942 return Result<bool>(ErrorId(errorId));
1943 }
1944 return Result<bool>(true);
1945 }
1946 [nodiscard]
1947 public Result<bool> Shear(float shearX, float shearY)
1948 {
1949 return Shear(shearX, shearY, MatrixOrder.prepend);
1950 }
1951 [nodiscard]
1952 public Result<bool> Translate(float offsetX, float offsetY, MatrixOrder order)
1953 {
1954 int status = WinGraphicsMatrixTranslate(nativeMatrix, offsetX, offsetY, cast<int>(order));
1955 if (status != 0)
1956 {
1957 int errorId = WinAllocateGdiPlusError("Matrix.Translate failed", status);
1958 return Result<bool>(ErrorId(errorId));
1959 }
1960 return Result<bool>(true);
1961 }
1962 [nodiscard]
1963 public Result<bool> Translate(float offsetX, float offsetY)
1964 {
1965 return Translate(offsetX, offsetY, MatrixOrder.prepend);
1966 }
1967 [nodiscard]
1968 public Result<bool> SetElements(float m11, float m12, float m21, float m22, float dx, float dy)
1969 {
1970 int status = WinGraphicsMatrixSetElements(nativeMatrix, m11, m12, m21, m22, dx, dy);
1971 if (status != 0)
1972 {
1973 int errorId = WinAllocateGdiPlusError("Matrix.SetElements failed", status);
1974 return Result<bool>(ErrorId(errorId));
1975 }
1976 return Result<bool>(true);
1977 }
1978 [nodiscard]
1979 public Result<bool> TransformPoints(List<Point>& points)
1980 {
1981 int status = WinGraphicsMatrixTransformPoints(nativeMatrix, points.Begin().Ptr(), cast<int>(points.Count()));
1982 if (status != 0)
1983 {
1984 int errorId = WinAllocateGdiPlusError("Matrix.TransformPoints(List<Point>) failed", status);
1985 return Result<bool>(ErrorId(errorId));
1986 }
1987 return Result<bool>(true);
1988 }
1989 [nodiscard]
1990 public Result<bool> TransformPoints(List<PointF>& points)
1991 {
1992 int status = WinGraphicsMatrixTransformPointsF(nativeMatrix, points.Begin().Ptr(), cast<int>(points.Count()));
1993 if (status != 0)
1994 {
1995 int errorId = WinAllocateGdiPlusError("Matrix.TransformPoints(List<PointF>) failed", status);
1996 return Result<bool>(ErrorId(errorId));
1997 }
1998 return Result<bool>(true);
1999 }
2000 public inline void* NativeMatrix() const
2001 {
2002 return nativeMatrix;
2003 }
2004 private void* nativeMatrix;
2005 }
2006
2007 [nodiscard]
2008 public Result<Matrix> operator*(const Matrix& left, const Matrix& right)
2009 {
2010 Matrix product(right);
2011 if (product.Error())
2012 {
2013 return Result<Matrix>(ErrorId(product.GetErrorId()));
2014 }
2015 auto result = product.Multiply(left);
2016 if (result.Error())
2017 {
2018 return Result<Matrix>(ErrorId(result.GetErrorId()));
2019 }
2020 return Result<Matrix>(Rvalue(product));
2021 }
2022
2023 [nodiscard]
2024 public Result<Matrix> Rotate(const Matrix& m, float angle)
2025 {
2026 Matrix rm(m);
2027 if (rm.Error())
2028 {
2029 return Result<Matrix>(ErrorId(rm.GetErrorId()));
2030 }
2031 auto result = rm.Rotate(angle);
2032 if (result.Error())
2033 {
2034 return Result<Matrix>(ErrorId(result.GetErrorId()));
2035 }
2036 return Result<Matrix>(Rvalue(rm));
2037 }
2038
2039 [nodiscard]
2040 public Result<Matrix> RotateAt(const Matrix& m, float angle, const PointF& center)
2041 {
2042 Matrix rm(m);
2043 if (rm.Error())
2044 {
2045 return Result<Matrix>(ErrorId(rm.GetErrorId()));
2046 }
2047 auto result = rm.RotateAt(angle, center);
2048 if (result.Error())
2049 {
2050 return Result<Matrix>(ErrorId(result.GetErrorId()));
2051 }
2052 return Result<Matrix>(Rvalue(rm));
2053 }
2054
2055 [nodiscard]
2056 public Result<Matrix> Scale(const Matrix& m, float scaleX, float scaleY)
2057 {
2058 Matrix sm(m);
2059 if (sm.Error())
2060 {
2061 return Result<Matrix>(ErrorId(sm.GetErrorId()));
2062 }
2063 auto result = sm.Scale(scaleX, scaleY);
2064 if (result.Error())
2065 {
2066 return Result<Matrix>(ErrorId(result.GetErrorId()));
2067 }
2068 return Result<Matrix>(Rvalue(sm));
2069 }
2070
2071 [nodiscard]
2072 public Result<Matrix> Shear(const Matrix& m, float shearX, float shearY)
2073 {
2074 Matrix sm(m);
2075 if (sm.Error())
2076 {
2077 return Result<Matrix>(ErrorId(sm.GetErrorId()));
2078 }
2079 auto result = sm.Shear(shearX, shearY);
2080 if (result.Error())
2081 {
2082 return Result<Matrix>(ErrorId(result.GetErrorId()));
2083 }
2084 return Result<Matrix>(Rvalue(sm));
2085 }
2086
2087 [nodiscard]
2088 public Result<Matrix> Translate(const Matrix& m, float offsetX, float offsetY)
2089 {
2090 Matrix tm(m);
2091 if (tm.Error())
2092 {
2093 return Result<Matrix>(ErrorId(tm.GetErrorId()));
2094 }
2095 auto result = tm.Translate(offsetX, offsetY);
2096 if (result.Error())
2097 {
2098 return Result<Matrix>(ErrorId(result.GetErrorId()));
2099 }
2100 return Result<Matrix>(Rvalue(tm));
2101 }
2102
2103 [nodiscard]
2104 public Result<Matrix> Invert(const Matrix& m)
2105 {
2106 Matrix im(m);
2107 if (im.Error())
2108 {
2109 return Result<Matrix>(ErrorId(im.GetErrorId()));
2110 }
2111 auto result = im.Invert();
2112 if (result.Error())
2113 {
2114 return Result<Matrix>(ErrorId(result.GetErrorId()));
2115 }
2116 return Result<Matrix>(Rvalue(im));
2117 }
2118
2119 public enum GraphicsState : uint
2120 {
2121 state = 0u
2122 }
2123
2124 public enum SmoothingMode : int
2125 {
2126 invalid = -1,
2127 default_ = 0,
2128 highSpeed = 1,
2129 highQuality = 2,
2130 none = 3,
2131 antiAlias = 4
2132 }
2133
2134 public enum ColorAdjustType : int
2135 {
2136 default_ = 0,
2137 bitmap = 1,
2138 brush = 2,
2139 pen = 3,
2140 text = 4,
2141 count = 5,
2142 any = 6
2143 }
2144
2145 public class ImageAttributes : GraphicsObject
2146 {
2147 public ImageAttributes() : nativeImageAttributes(WinGraphicsCreateDefaultImageAttributes())
2148 {
2149 int status = WinGraphicsImageAttributesGetLastStatus(nativeImageAttributes);
2150 if (status != 0)
2151 {
2152 int errorId = WinAllocateGdiPlusError("ImageAttributes constructor failed", status);
2153 SetErrorId(errorId);
2154 return;
2155 }
2156 }
2157 public ImageAttributes(const ImageAttributes& that) : nativeImageAttributes(WinGraphicsCloneImageAttributes(that.nativeImageAttributes))
2158 {
2159 int status = WinGraphicsImageAttributesGetLastStatus(nativeImageAttributes);
2160 if (status != 0)
2161 {
2162 int errorId = WinAllocateGdiPlusError("ImageAttributes copy constructor failed", status);
2163 SetErrorId(errorId);
2164 return;
2165 }
2166 }
2167 public ImageAttributes(ImageAttributes&& that) : nativeImageAttributes(that.nativeImageAttributes)
2168 {
2169 that.nativeImageAttributes = null;
2170 }
2171 public void operator=(const ImageAttributes& that)
2172 {
2173 if (nativeImageAttributes != that.nativeImageAttributes)
2174 {
2175 if (that.nativeImageAttributes != null)
2176 {
2177 WinGraphicsDeleteImageAttributes(that.nativeImageAttributes);
2178 }
2179 nativeImageAttributes = WinGraphicsCloneImageAttributes(that.nativeImageAttributes);
2180 int status = WinGraphicsImageAttributesGetLastStatus(nativeImageAttributes);
2181 if (status != 0)
2182 {
2183 int errorId = WinAllocateGdiPlusError("ImageAttributes copy assignment failed", status);
2184 SetErrorId(errorId);
2185 return;
2186 }
2187 }
2188 }
2189 public default void operator=(ImageAttributes&&);
2190 public ~ImageAttributes()
2191 {
2192 if (nativeImageAttributes != null)
2193 {
2194 WinGraphicsDeleteImageAttributes(nativeImageAttributes);
2195 }
2196 }
2197 [nodiscard]
2198 public Result<bool> SetColorKey(const Color& colorLow, const Color& colorHigh, ColorAdjustType type)
2199 {
2200 int status = WinGraphicsImageAttributesSetColorKey(nativeImageAttributes, colorLow.alpha, colorLow.red, colorLow.green, colorLow.blue,
2201 colorHigh.alpha, colorHigh.red, colorHigh.green, colorHigh.blue, cast<int>(type));
2202 if (status != 0)
2203 {
2204 int errorId = WinAllocateGdiPlusError("ImageAttributes.SetColorKey failed", status);
2205 return Result<bool>(ErrorId(errorId));
2206 }
2207 return Result<bool>(true);
2208 }
2209 public void* NativeImageAttributes() const
2210 {
2211 return nativeImageAttributes;
2212 }
2213 private void* nativeImageAttributes;
2214 }
2215
2216 public class Graphics : GraphicsObject
2217 {
2218 public Graphics() : nativeGraphics(null)
2219 {
2220 }
2221 public Graphics(void* hdc) : nativeGraphics(WinCreateGraphics(hdc))
2222 {
2223 int status = WinGraphicsGetLastStatus(nativeGraphics);
2224 if (status != 0)
2225 {
2226 int errorId = WinAllocateGdiPlusError("Graphics constructor failed", status);
2227 SetErrorId(errorId);
2228 return;
2229 }
2230 }
2231 public Graphics(const NativeHandle& nativeHandle) : nativeGraphics(nativeHandle.handle)
2232 {
2233 int status = WinGraphicsGetLastStatus(nativeGraphics);
2234 if (status != 0)
2235 {
2236 int errorId = WinAllocateGdiPlusError("Graphics(NativeHandle) constructor failed", status);
2237 SetErrorId(errorId);
2238 return;
2239 }
2240 }
2241 [nodiscard]
2242 public static Result<Graphics> FromWindowHandle(void* windowHandle)
2243 {
2244 NativeHandle nativeHandle = WinCreateGraphicsFromWindowHandle(windowHandle);
2245 Graphics graphics(nativeHandle);
2246 if (graphics.Error())
2247 {
2248 return Result<Graphics>(ErrorId(graphics.GetErrorId()));
2249 }
2250 return Result<Graphics>(Rvalue(graphics));
2251 }
2252 [nodiscard]
2253 public static Result<Graphics> FromImage(const Image& image)
2254 {
2255 NativeHandle nativeHandle = WinCreateGraphicsFromImage(image.NativeImage());
2256 Graphics graphics(nativeHandle);
2257 if (graphics.Error())
2258 {
2259 return Result<Graphics>(ErrorId(graphics.GetErrorId()));
2260 }
2261 return Result<Graphics>(Rvalue(graphics));
2262 }
2263 suppress Graphics(const Graphics&);
2264 public Graphics(Graphics&& that) : nativeGraphics(that.nativeGraphics)
2265 {
2266 that.nativeGraphics = null;
2267 }
2268 suppress void operator=(const Graphics&);
2269 public default void operator=(Graphics&&);
2270 public ~Graphics()
2271 {
2272 if (nativeGraphics != null)
2273 {
2274 WinDeleteGraphics(nativeGraphics);
2275 }
2276 }
2277 public void* GetHDC() const
2278 {
2279 return WinGraphicsGetHDC(nativeGraphics);
2280 }
2281 [nodiscard]
2282 public Result<bool> DrawLine(const Pen& pen, const Point& start, const Point& end)
2283 {
2284 int status = WinGraphicsDrawLine(nativeGraphics, pen.NativePen(), start.x, start.y, end.x, end.y);
2285 if (status != 0)
2286 {
2287 int errorId = WinAllocateGdiPlusError("Graphics.DrawLine(Pen, Point, Point) failed", status);
2288 return Result<bool>(ErrorId(errorId));
2289 }
2290 return Result<bool>(true);
2291 }
2292 [nodiscard]
2293 public Result<bool> DrawLine(const Pen& pen, const PointF& start, const PointF& end)
2294 {
2295 int status = WinGraphicsDrawLineF(nativeGraphics, pen.NativePen(), start.x, start.y, end.x, end.y);
2296 if (status != 0)
2297 {
2298 int errorId = WinAllocateGdiPlusError("Graphics.DrawLine(Pen, PointF, PointF) failed", status);
2299 return Result<bool>(ErrorId(errorId));
2300 }
2301 return Result<bool>(true);
2302 }
2303 [nodiscard]
2304 public Result<bool> DrawLines(const Pen& pen, int numPoints, const Point* points)
2305 {
2306 int status = WinGraphicsDrawLines(nativeGraphics, pen.NativePen(), numPoints, points);
2307 if (status != 0)
2308 {
2309 int errorId = WinAllocateGdiPlusError("Graphics.DrawLines(Pen, int, Point*) failed", status);
2310 return Result<bool>(ErrorId(errorId));
2311 }
2312 return Result<bool>(true);
2313 }
2314 [nodiscard]
2315 public Result<bool> DrawLines(const Pen& pen, int numPoints, const PointF* points)
2316 {
2317 int status = WinGraphicsDrawLinesF(nativeGraphics, pen.NativePen(), numPoints, points);
2318 if (status != 0)
2319 {
2320 int errorId = WinAllocateGdiPlusError("Graphics.DrawLines(Pen, int, PointF*) failed", status);
2321 return Result<bool>(ErrorId(errorId));
2322 }
2323 return Result<bool>(true);
2324 }
2325 [nodiscard]
2326 public Result<bool> DrawString(const string& str, const Font& font, const PointF& origin, const Brush& brush)
2327 {
2328 int status = WinGraphicsDrawString(nativeGraphics, str.Chars(), font.NativeFont(), origin.x, origin.y, brush.NativeBrush());
2329 if (status != 0)
2330 {
2331 int errorId = WinAllocateGdiPlusError("Graphics.DrawString(string, Font, PointF) failed", status);
2332 return Result<bool>(ErrorId(errorId));
2333 }
2334 return Result<bool>(true);
2335 }
2336 [nodiscard]
2337 public Result<bool> DrawString(const string& str, const Font& font, const PointF& origin, const StringFormat& format, const Brush& brush)
2338 {
2339 int status = WinGraphicsDrawStringFormatPoint(nativeGraphics, str.Chars(), font.NativeFont(),
2340 origin.x, origin.y, format.NativeFormat(), brush.NativeBrush());
2341 if (status != 0)
2342 {
2343 int errorId = WinAllocateGdiPlusError("Graphics.DrawString(string, Font, PointF, StringFormat, Brush) failed", status);
2344 return Result<bool>(ErrorId(errorId));
2345 }
2346 return Result<bool>(true);
2347 }
2348 [nodiscard]
2349 public Result<bool> DrawString(const string& str, const Font& font, const RectF& rect, const StringFormat& format, const Brush& brush)
2350 {
2351 int status = WinGraphicsDrawStringFormatRect(nativeGraphics, str.Chars(), font.NativeFont(),
2352 rect.location.x, rect.location.y, rect.size.w, rect.size.h,
2353 format.NativeFormat(), brush.NativeBrush());
2354 if (status != 0)
2355 {
2356 int errorId = WinAllocateGdiPlusError("Graphics.DrawString(string, Font, RectF, StringFormat, Brush) failed", status);
2357 return Result<bool>(ErrorId(errorId));
2358 }
2359 return Result<bool>(true);
2360 }
2361 [nodiscard]
2362 public Result<SizeF> MeasureStringSizeF(const string& str, const Font& font, const SizeF& layoutRectSize, const StringFormat& format,
2363 int* codePointsFitted, int* linesFilled)
2364 {
2365 SizeF size;
2366 int status = WinGraphicsMeasureStringFormatSize(nativeGraphics, str.Chars(), font.NativeFont(),
2367 layoutRectSize.w, layoutRectSize.h, format.NativeFormat(),
2368 size.w, size.h, codePointsFitted, linesFilled);
2369 if (status != 0)
2370 {
2371 int errorId = WinAllocateGdiPlusError("Graphics.MeasureString(string, Font, SizeF, StringFormat, int*, int*) failed", status);
2372 return Result<SizeF>(ErrorId(errorId));
2373 }
2374 return Result<SizeF>(Rvalue(size));
2375 }
2376 [nodiscard]
2377 public Result<SizeF> MeasureStringSizeF(const string& str, const Font& font, const SizeF& layoutRectSize, const StringFormat& format)
2378 {
2379 SizeF size;
2380 int status = WinGraphicsMeasureStringFormatSize(nativeGraphics, str.Chars(), font.NativeFont(),
2381 layoutRectSize.w, layoutRectSize.h, format.NativeFormat(), size.w, size.h, null, null);
2382 if (status != 0)
2383 {
2384 int errorId = WinAllocateGdiPlusError("Graphics.MeasureStringSizeF(string, Font, SizeF, StringFormat) failed", status);
2385 return Result<SizeF>(ErrorId(errorId));
2386 }
2387 return Result<SizeF>(Rvalue(size));
2388 }
2389 [nodiscard]
2390 public Result<RectF> MeasureStringRectF(const string& str, const Font& font, const RectF& layoutRect, const StringFormat& format,
2391 int* codePointsFitted, int* linesFilled)
2392 {
2393 RectF boundingBox;
2394 int status = WinGraphicsMeasureStringFormatRect(nativeGraphics, str.Chars(), font.NativeFont(),
2395 layoutRect.location.x, layoutRect.location.y, layoutRect.size.w, layoutRect.size.h, format.NativeFormat(),
2396 boundingBox.location.x, boundingBox.location.y, boundingBox.size.w, boundingBox.size.h,
2397 codePointsFitted, linesFilled);
2398 if (status != 0)
2399 {
2400 int errorId = WinAllocateGdiPlusError("Graphics.MeasureStringRectF(string, Font, RectF, StringFormat, int* int*) failed", status);
2401 return Result<RectF>(ErrorId(errorId));
2402 }
2403 return Result<RectF>(Rvalue(boundingBox));
2404 }
2405 [nodiscard]
2406 public Result<RectF> MeasureStringRectF(const string& str, const Font& font, const RectF& layoutRect, const StringFormat& format)
2407 {
2408 RectF boundingBox;
2409 int status = WinGraphicsMeasureStringFormatRect(nativeGraphics, str.Chars(), font.NativeFont(),
2410 layoutRect.location.x, layoutRect.location.y, layoutRect.size.w, layoutRect.size.h, format.NativeFormat(),
2411 boundingBox.location.x, boundingBox.location.y, boundingBox.size.w, boundingBox.size.h,
2412 null, null);
2413 if (status != 0)
2414 {
2415 int errorId = WinAllocateGdiPlusError("Graphics.MeasureStringRectF(string, Font, RectF, StringFormat) failed", status);
2416 return Result<RectF>(ErrorId(errorId));
2417 }
2418 return Result<RectF>(Rvalue(boundingBox));
2419 }
2420 [nodiscard]
2421 public Result<RectF> MeasureStringRectF(const string& str, const Font& font, const PointF& origin, const StringFormat& format)
2422 {
2423 RectF boundingBox;
2424 int status = WinGraphicsMeasureStringFormatPoint(nativeGraphics, str.Chars(), font.NativeFont(), origin.x, origin.y, format.NativeFormat(),
2425 boundingBox.location.x, boundingBox.location.y, boundingBox.size.w, boundingBox.size.h);
2426 if (status != 0)
2427 {
2428 int errorId = WinAllocateGdiPlusError("Graphics.MeasureStringRectF(string, Font, PointF, StringFormat) failed", status);
2429 return Result<RectF>(ErrorId(errorId));
2430 }
2431 return Result<RectF>(Rvalue(boundingBox));
2432 }
2433 public TextRenderingHint GetTextRenderingHint()
2434 {
2435 return cast<TextRenderingHint>(WinGraphicsGetTextRenderingHint(nativeGraphics));
2436 }
2437 [nodiscard]
2438 public Result<bool> SetTextRenderingHint(TextRenderingHint textRenderingHint)
2439 {
2440 int status = WinGraphicsSetTextRenderingHint(nativeGraphics, cast<int>(textRenderingHint));
2441 if (status != 0)
2442 {
2443 int errorId = WinAllocateGdiPlusError("Graphics.SetTextRenderingHint failed", status);
2444 return Result<bool>(ErrorId(errorId));
2445 }
2446 return Result<bool>(true);
2447 }
2448 [nodiscard]
2449 public Result<bool> Clear(const Color& color)
2450 {
2451 int status = WinGraphicsClear(nativeGraphics, color.alpha, color.red, color.green, color.blue);
2452 if (status != 0)
2453 {
2454 int errorId = WinAllocateGdiPlusError("Graphics.Clear failed", status);
2455 return Result<bool>(ErrorId(errorId));
2456 }
2457 return Result<bool>(true);
2458 }
2459 [nodiscard]
2460 public Result<bool> DrawRectangle(const Pen& pen, const Rect& rect)
2461 {
2462 int status = WinGraphicsDrawRectangle(nativeGraphics, pen.NativePen(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2463 if (status != 0)
2464 {
2465 int errorId = WinAllocateGdiPlusError("Graphics.DrawRectangle(Pen, Rect) failed", status);
2466 return Result<bool>(ErrorId(errorId));
2467 }
2468 return Result<bool>(true);
2469 }
2470 [nodiscard]
2471 public Result<bool> DrawRectangle(const Pen& pen, const RectF& rect)
2472 {
2473 int status = WinGraphicsDrawRectangleF(nativeGraphics, pen.NativePen(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2474 if (status != 0)
2475 {
2476 int errorId = WinAllocateGdiPlusError("Graphics.DrawRectangle(Pen, RectF) failed", status);
2477 return Result<bool>(ErrorId(errorId));
2478 }
2479 return Result<bool>(true);
2480 }
2481 [nodiscard]
2482 public Result<bool> FillRectangle(const Brush& brush, const Rect& rect)
2483 {
2484 int status = WinGraphicsFillRectangle(nativeGraphics, brush.NativeBrush(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2485 if (status != 0)
2486 {
2487 int errorId = WinAllocateGdiPlusError("Graphics.FillRectangle(Brush, Rect) failed", status);
2488 return Result<bool>(ErrorId(errorId));
2489 }
2490 return Result<bool>(true);
2491 }
2492 [nodiscard]
2493 public Result<bool> FillRectangle(const Brush& brush, const RectF& rect)
2494 {
2495 int status = WinGraphicsFillRectangleF(nativeGraphics, brush.NativeBrush(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2496 if (status != 0)
2497 {
2498 int errorId = WinAllocateGdiPlusError("Graphics.FillRectangle(Brush, RectF) failed", status);
2499 return Result<bool>(ErrorId(errorId));
2500 }
2501 return Result<bool>(true);
2502 }
2503 [nodiscard]
2504 public Result<bool> FillPolygon(const Brush& brush, int numPoints, const Point* points)
2505 {
2506 int status = WinGraphicsFillPolygon(nativeGraphics, brush.NativeBrush(), numPoints, points);
2507 if (status != 0)
2508 {
2509 int errorId = WinAllocateGdiPlusError("Graphics.FillPolygon(Brush, int, Point*) failed", status);
2510 return Result<bool>(ErrorId(errorId));
2511 }
2512 return Result<bool>(true);
2513 }
2514 [nodiscard]
2515 public Result<bool> FillPolygon(const Brush& brush, int numPoints, const PointF* points)
2516 {
2517 int status = WinGraphicsFillPolygonF(nativeGraphics, brush.NativeBrush(), numPoints, points);
2518 if (status != 0)
2519 {
2520 int errorId = WinAllocateGdiPlusError("Graphics.FillPolygon(Brush, int, PointF*) failed", status);
2521 return Result<bool>(ErrorId(errorId));
2522 }
2523 return Result<bool>(true);
2524 }
2525 [nodiscard]
2526 public Result<bool> DrawArc(const Pen& pen, const RectF& rect, float startAngle, float sweepAngle)
2527 {
2528 int status = WinGraphicsDrawArc(nativeGraphics, pen.NativePen(), rect.location.x, rect.location.y, rect.size.w, rect.size.h, startAngle, sweepAngle);
2529 if (status != 0)
2530 {
2531 int errorId = WinAllocateGdiPlusError("Graphics.DrawArc failed", status);
2532 return Result<bool>(ErrorId(errorId));
2533 }
2534 return Result<bool>(true);
2535 }
2536 [nodiscard]
2537 public Result<bool> DrawEllipse(const Pen& pen, const RectF& rect)
2538 {
2539 int status = WinGraphicsDrawEllipse(nativeGraphics, pen.NativePen(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2540 if (status != 0)
2541 {
2542 int errorId = WinAllocateGdiPlusError("Graphics.DrawEllipse failed", status);
2543 return Result<bool>(ErrorId(errorId));
2544 }
2545 return Result<bool>(true);
2546 }
2547 [nodiscard]
2548 public Result<bool> FillEllipse(const Brush& brush, const RectF& rect)
2549 {
2550 int status = WinGraphicsFillEllipse(nativeGraphics, brush.NativeBrush(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2551 if (status != 0)
2552 {
2553 int errorId = WinAllocateGdiPlusError("Graphics.FillEllipse failed", status);
2554 return Result<bool>(ErrorId(errorId));
2555 }
2556 return Result<bool>(true);
2557 }
2558 [nodiscard]
2559 public Result<bool> DrawImage(const Image& image, const PointF& point)
2560 {
2561 int status = WinGraphicsDrawImagePoint(nativeGraphics, image.NativeImage(), point.x, point.y);
2562 if (status != 0)
2563 {
2564 int errorId = WinAllocateGdiPlusError("Graphics.DrawImage(Image, PointF) failed", status);
2565 return Result<bool>(ErrorId(errorId));
2566 }
2567 return Result<bool>(true);
2568 }
2569 [nodiscard]
2570 public Result<bool> DrawImage(const Image& image, const RectF& rect)
2571 {
2572 int status = WinGraphicsDrawImageRect(nativeGraphics, image.NativeImage(), rect.location.x, rect.location.y, rect.size.w, rect.size.h);
2573 if (status != 0)
2574 {
2575 int errorId = WinAllocateGdiPlusError("Graphics.DrawImage(Image, RectF) failed", status);
2576 return Result<bool>(ErrorId(errorId));
2577 }
2578 return Result<bool>(true);
2579 }
2580 [nodiscard]
2581 public Result<bool> DrawImage(const Image& image, const Rect& destRect, int srcX, int srcY, int srcW, int srcH, Unit srcUnit, const ImageAttributes& attributes)
2582 {
2583 int status = WinGraphicsDrawImageWithAttributes(nativeGraphics, image.NativeImage(), destRect.location.x, destRect.location.y, destRect.size.w, destRect.size.h,
2584 srcX, srcY, srcW, srcH, srcUnit, attributes.NativeImageAttributes());
2585 if (status != 0)
2586 {
2587 int errorId = WinAllocateGdiPlusError("Graphics.DrawImage(Image, Rect, int, int, int, int, Unit, ImageAttributes) failed", status);
2588 return Result<bool>(ErrorId(errorId));
2589 }
2590 return Result<bool>(true);
2591 }
2592 [nodiscard]
2593 public Result<bool> DrawImage(const Image& image, const RectF& destRect, const RectF& sourceRect, Unit srcUnit, const ImageAttributes& attributes)
2594 {
2595 int status = WinGraphicsDrawImageWithAttributesF(nativeGraphics, image.NativeImage(), destRect.location.x, destRect.location.y, destRect.size.w, destRect.size.h,
2596 sourceRect.location.x, sourceRect.location.y, sourceRect.size.w, sourceRect.size.h, srcUnit, attributes.NativeImageAttributes());
2597 if (status != 0)
2598 {
2599 int errorId = WinAllocateGdiPlusError("Graphics.DrawImage(Image, RectF, RectF, Unit, ImageAttributes) failed", status);
2600 return Result<bool>(ErrorId(errorId));
2601 }
2602 return Result<bool>(true);
2603 }
2604 [nodiscard]
2605 public Result<Region> GetClip()
2606 {
2607 Region region;
2608 int status = WinGraphicsGetClip(nativeGraphics, region.NativeRegion());
2609 if (status != 0)
2610 {
2611 int errorId = WinAllocateGdiPlusError("Graphics.GetClip failed", status);
2612 return Result<Region>(ErrorId(errorId));
2613 }
2614 return Result<Region>(Rvalue(region));
2615 }
2616 [nodiscard]
2617 public Result<bool> SetClip(const Rect& rect, CombineMode combineMode)
2618 {
2619 int status = WinGraphicsSetClipRect(nativeGraphics, rect.location.x, rect.location.y, rect.size.w, rect.size.h, combineMode);
2620 if (status != 0)
2621 {
2622 int errorId = WinAllocateGdiPlusError("Graphics.SetClip(Rect, CombineMode) failed", status);
2623 return Result<bool>(ErrorId(errorId));
2624 }
2625 return Result<bool>(true);
2626 }
2627 [nodiscard]
2628 public Result<bool> SetClip(const Rect& rect)
2629 {
2630 int status = WinGraphicsSetClipRect(nativeGraphics, rect.location.x, rect.location.y, rect.size.w, rect.size.h, CombineMode.replace);
2631 if (status != 0)
2632 {
2633 int errorId = WinAllocateGdiPlusError("Graphics.SetClip(Rect) failed", status);
2634 return Result<bool>(ErrorId(errorId));
2635 }
2636 return Result<bool>(true);
2637 }
2638 [nodiscard]
2639 public Result<bool> SetClip(const Region& region)
2640 {
2641 int status = WinGraphicsSetClipRegion(nativeGraphics, region.NativeRegion());
2642 if (status != 0)
2643 {
2644 int errorId = WinAllocateGdiPlusError("Graphics.SetClip(Region) failed", status);
2645 return Result<bool>(ErrorId(errorId));
2646 }
2647 return Result<bool>(true);
2648 }
2649 [nodiscard]
2650 public Result<GraphicsState> Save()
2651 {
2652 GraphicsState state = cast<GraphicsState>(WinGraphicsSave(nativeGraphics));
2653 int status = WinGraphicsGetLastStatus(nativeGraphics);
2654 if (status != 0)
2655 {
2656 int errorId = WinAllocateGdiPlusError("Graphics.Save failed", status);
2657 return Result<GraphicsState>(ErrorId(errorId));
2658 }
2659 return Result<GraphicsState>(state);
2660 }
2661 [nodiscard]
2662 public Result<bool> Restore(GraphicsState graphicsState)
2663 {
2664 int status = WinGraphicsRestore(nativeGraphics, cast<uint>(graphicsState));
2665 if (status != 0)
2666 {
2667 int errorId = WinAllocateGdiPlusError("Graphics.Restore failed", status);
2668 return Result<bool>(ErrorId(errorId));
2669 }
2670 return Result<bool>(true);
2671 }
2672 [nodiscard]
2673 public Result<bool> GetTransform(Matrix& m)
2674 {
2675 int status = WinGraphicsGetTransform(nativeGraphics, m.NativeMatrix());
2676 if (status != 0)
2677 {
2678 int errorId = WinAllocateGdiPlusError("Graphics.GetTransform failed", status);
2679 return Result<bool>(ErrorId(errorId));
2680 }
2681 return Result<bool>(true);
2682 }
2683 [nodiscard]
2684 public Result<bool> SetTransform(Matrix& m)
2685 {
2686 int status = WinGraphicsSetTransform(nativeGraphics, m.NativeMatrix());
2687 if (status != 0)
2688 {
2689 int errorId = WinAllocateGdiPlusError("Graphics.SetTransform failed", status);
2690 return Result<bool>(ErrorId(errorId));
2691 }
2692 return Result<bool>(true);
2693 }
2694 [nodiscard]
2695 public Result<bool> MultiplyTransform(const Matrix& matrix, MatrixOrder order)
2696 {
2697 int status = WinGraphicsMultiplyTransform(nativeGraphics, matrix.NativeMatrix(), cast<int>(order));
2698 if (status != 0)
2699 {
2700 int errorId = WinAllocateGdiPlusError("Graphics.MultiplyTransform(Matrix, MatrixOrder) failed", status);
2701 return Result<bool>(ErrorId(errorId));
2702 }
2703 return Result<bool>(true);
2704 }
2705 [nodiscard]
2706 public Result<bool> MultiplyTransform(const Matrix& matrix)
2707 {
2708 return MultiplyTransform(matrix, MatrixOrder.prepend);
2709 }
2710 [nodiscard]
2711 public Result<bool> ResetTransform()
2712 {
2713 int status = WinGraphicsResetTransform(nativeGraphics);
2714 if (status != 0)
2715 {
2716 int errorId = WinAllocateGdiPlusError("Graphics.ResetTransform failed", status);
2717 return Result<bool>(ErrorId(errorId));
2718 }
2719 return Result<bool>(true);
2720 }
2721 [nodiscard]
2722 public Result<bool> RotateTransform(float angle, MatrixOrder order)
2723 {
2724 int status = WinGraphicsRotateTransform(nativeGraphics, angle, cast<int>(order));
2725 if (status != 0)
2726 {
2727 int errorId = WinAllocateGdiPlusError("Graphics.RotateTransform(float, MatrixOrder) failed", status);
2728 return Result<bool>(ErrorId(errorId));
2729 }
2730 return Result<bool>(true);
2731 }
2732 [nodiscard]
2733 public Result<bool> RotateTransform(float angle)
2734 {
2735 return RotateTransform(angle, MatrixOrder.prepend);
2736 }
2737 [nodiscard]
2738 public Result<bool> ScaleTransform(float scaleX, float scaleY, MatrixOrder order)
2739 {
2740 int status = WinGraphicsScaleTransform(nativeGraphics, scaleX, scaleY, cast<int>(order));
2741 if (status != 0)
2742 {
2743 int errorId = WinAllocateGdiPlusError("Graphics.ScaleTransform(float, float, MatrixOrder) failed", status);
2744 return Result<bool>(ErrorId(errorId));
2745 }
2746 return Result<bool>(true);
2747 }
2748 [nodiscard]
2749 public Result<bool> ScaleTransform(float scaleX, float scaleY)
2750 {
2751 return ScaleTransform(scaleX, scaleY, MatrixOrder.prepend);
2752 }
2753 [nodiscard]
2754 public Result<bool> TranslateTransform(float offsetX, float offsetY, MatrixOrder order)
2755 {
2756 int status = WinGraphicsTranslateTransform(nativeGraphics, offsetX, offsetY, cast<int>(order));
2757 if (status != 0)
2758 {
2759 int errorId = WinAllocateGdiPlusError("Graphics.TranslateTransform(float, float, MatrixOrder) failed", status);
2760 return Result<bool>(ErrorId(errorId));
2761 }
2762 return Result<bool>(true);
2763 }
2764 [nodiscard]
2765 public Result<bool> TranslateTransform(float offsetX, float offsetY)
2766 {
2767 return TranslateTransform(offsetX, offsetY, MatrixOrder.prepend);
2768 }
2769 [nodiscard]
2770 public Result<Unit> GetPageUnit()
2771 {
2772 Unit unit = cast<Unit>(WinGraphicsGetPageUnit(nativeGraphics));
2773 int status = WinGraphicsGetLastStatus(nativeGraphics);
2774 if (status != 0)
2775 {
2776 int errorId = WinAllocateGdiPlusError("Graphics.GetPageUnit failed", status);
2777 return Result<Unit>(ErrorId(errorId));
2778 }
2779 return Result<Unit>(unit);
2780 }
2781 [nodiscard]
2782 public Result<bool> SetPageUnit(Unit unit)
2783 {
2784 int status = WinGraphicsSetPageUnit(nativeGraphics, cast<int>(unit));
2785 if (status != 0)
2786 {
2787 int errorId = WinAllocateGdiPlusError("Graphics.SetPageUnit failed", status);
2788 return Result<bool>(ErrorId(errorId));
2789 }
2790 return Result<bool>(true);
2791 }
2792 [nodiscard]
2793 public Result<float> GetPageScale()
2794 {
2795 float pageScale = WinGraphicsGetPageScale(nativeGraphics);
2796 int status = WinGraphicsGetLastStatus(nativeGraphics);
2797 if (status != 0)
2798 {
2799 int errorId = WinAllocateGdiPlusError("Graphics.GetPageScale failed", status);
2800 return Result<float>(ErrorId(errorId));
2801 }
2802 return Result<float>(pageScale);
2803 }
2804 [nodiscard]
2805 public Result<bool> SetPageScale(float scale)
2806 {
2807 int status = WinGraphicsSetPageScale(nativeGraphics, scale);
2808 if (status != 0)
2809 {
2810 int errorId = WinAllocateGdiPlusError("Graphics.SetPageScale failed", status);
2811 return Result<bool>(ErrorId(errorId));
2812 }
2813 return Result<bool>(true);
2814 }
2815 public float GetDpiX()
2816 {
2817 return WinGraphicsGetDpiX(nativeGraphics);
2818 }
2819 public float GetDpiY()
2820 {
2821 return WinGraphicsGetDpiY(nativeGraphics);
2822 }
2823 [nodiscard]
2824 public Result<SmoothingMode> GetSmoothingMode()
2825 {
2826 SmoothingMode smoothingMode = cast<SmoothingMode>(WinGraphicsGetSmoothingMode(nativeGraphics));
2827 int status = WinGraphicsGetLastStatus(nativeGraphics);
2828 if (status != 0)
2829 {
2830 int errorId = WinAllocateGdiPlusError("Graphics.GetSmoothingMode failed", status);
2831 return Result<SmoothingMode>(ErrorId(errorId));
2832 }
2833 return Result<SmoothingMode>(smoothingMode);
2834 }
2835 [nodiscard]
2836 public Result<bool> SetSmoothingMode(SmoothingMode smoothingMode)
2837 {
2838 int status = WinGraphicsSetSmoothingMode(nativeGraphics, smoothingMode);
2839 if (status != 0)
2840 {
2841 int errorId = WinAllocateGdiPlusError("Graphics.SetSmoothingMode failed", status);
2842 return Result<bool>(ErrorId(errorId));
2843 }
2844 return Result<bool>(true);
2845 }
2846 public inline const void* NativeGraphics() const
2847 {
2848 return nativeGraphics;
2849 }
2850 private void* nativeGraphics;
2851 }
2852 }