1 // =================================
   2 // Copyright (c) 2024 Seppo Laakko
   3 // Distributed under the MIT license
   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_USEDEFAULTCW_USEDEFAULT);
  25         }
  26         public string ToString() const
  27         {
  28             return "(" + ToString(x) + ", " + ToString(y) + ")";
  29         }
  30         public inline void Offset(int dxint 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& leftconst 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_USEDEFAULTCW_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& leftconst 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 dxfloat 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& leftconst PointF& right)
  93     {
  94         return left.x == right.x && left.y == right.y;
  95     }
  96 
  97     public float Distance(const PointF& startconst 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(xy);
 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& vconst Vector& u)
 133     {
 134         return v.x == u.x && v.y == u.y;
 135     }
 136 
 137     public Vector operator*(const Vector& vfloat a)
 138     {
 139         return Vector(v.x * av.y * a);
 140     }
 141 
 142     public Vector operator*(float aconst Vector& v)
 143     {
 144         return Vector(v.x * av.y * a);
 145     }
 146 
 147     public Vector operator+(const Vector& leftconst Vector& right)
 148     {
 149         return Vector(left.x + right.xleft.y + right.y);
 150     }
 151 
 152     public Vector operator-(const Vector& leftconst Vector& right)
 153     {
 154         return Vector(left.x - right.xleft.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     // Dot product of vectors u and v:
 164 
 165     public float Dot(const Vector& uconst Vector& v)
 166     {
 167         return u.x * v.x + u.y * v.y;
 168     }
 169 
 170     public float ProjectionFactor(const Vector& aconst Vector& b)
 171     {
 172         return Dot(ab * (1 / b.Length()));
 173     }
 174 
 175     // Projection of vector a onto b:
 176 
 177     public Vector Projection(const Vector& aconst Vector& b)
 178     {
 179         return UnitVector(b) * ProjectionFactor(ab);
 180     }
 181 
 182     //  MainDirection returns:
 183     //      0, if angle between vector v and positive x axis is between 315 and 45 degrees clockwise
 184     //      90, if angle between vector v and positive x axis is between 45 and 135 degrees clockwise
 185     //      180, if angle between vector v and positive x axis is between 135 and 225 degrees clockwise
 186     //      270, if angle between vector v and positive x axis is between 225 and 315 degrees clockwise
 187     //      In this coordinate system x axis points to the right and y axis points downwards.
 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(vu) >= 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(vu) >= 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(11);
 223                 if (Dot(vu) >= 0)
 224                 {
 225                     return 90;
 226                 }
 227                 else
 228                 {
 229                     return 180u;
 230                 }
 231             }
 232             else
 233             {
 234                 Vector u(-11);
 235                 if (Dot(vu) >= 0)
 236                 {
 237                     return 180u;
 238                 }
 239                 else
 240                 {
 241                     return 270;
 242                 }
 243             }
 244         }
 245     }
 246 
 247     public Vector Rotate(const Vector& vdouble angleRad)
 248     {
 249         float cosTheta = cast<float>(Cos(angleRad));
 250         float sinTheta = cast<float>(Sin(angleRad));
 251         Vector r(v.x * cosTheta - v.y * sinThetav.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(startend);
 269         }
 270         public Vector ToVector() const
 271         {
 272             return Vector(end.x - start.xend.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& leftconst Line& right)
 283     {
 284         return left.start == right.start && left.end == right.end;
 285     }
 286 
 287     public Line Rotate(const Line& linedouble angleDeg)
 288     {
 289         double angleRad = PI() / 180.000000 * angleDeg;
 290         Vector v = line.ToVector();
 291         Vector r = Rotate(vangleRad);
 292         Line result(line.startr);
 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& leftconst 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.leftwinRect.top)size(winRect.right - winRect.leftwinRect.bottom - winRect.top)
 326         {
 327         }
 328         public WinRect ToWinRect() const
 329         {
 330             return WinRect(location.xlocation.ylocation.x + size.wlocation.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 dxint 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 dxint dy)
 364         {
 365             location.Offset(dxdy);
 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& aconst 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(lefttop)Size(right - leftbottom - 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& leftconst 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 dxfloat 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 dxfloat dy)
 436         {
 437             location.Offset(dxdy);
 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& aconst 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(lefttop)SizeF(right - leftbottom - 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 = 0inset = 1
 514         }
 515         public Pen(const Color& colorfloat width) : base()nativePen(WinGraphicsCreatePen(color.alphacolor.redcolor.greencolor.bluewidth))
 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(color1.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(nativePencast<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(nativePenbrush.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(nativePencolor.alphacolor.redcolor.greencolor.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(nativePencolor.alphacolor.redcolor.greencolor.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(nativePencast<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(nativePencast<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(nativePencast<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(nativePendashOffset);
 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(nativePencast<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(nativePencast<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& leftconst 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.alphacolor.redcolor.greencolor.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(thatNativeBrushnativeBrush);
 807             that.SetNativeBrush(thatNativeBrush);
 808             SetNativeBrush(nativeBrush);
 809             Swap(nativeSolidBrushthat.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(nativeFontFamilystr);
 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& familyfloat emSizeFontStyle styleUnit unit) : 
1018             base()nativeFont(WinGraphicsCreateFont(family.NativeFontFamily()emSizestyleunit))
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& familyfloat emSize) : this(familyemSizeFontStyle.regularUnit.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(nativeFontgraphics.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(nativeFontfontFamily.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* hdcvoid* hfont)
1100         {
1101             Font font(WinGraphicsCreateFontFromHFont(hdchfont));
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(nativeFontgraphics.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& leftconst 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         nearcenterfar
1245     }
1246 
1247     public enum HotKeyPrefix : int
1248     {
1249         noneshowhide
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 horizontalAlignmentStringAlignment verticalAlignmentHotKeyPrefix 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 horizontalAlignmentStringAlignment verticalAlignment) : this(horizontalAlignmentverticalAlignmentHotKeyPrefix.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(nativeFormatalignment);
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(nativeFormatalignment);
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(nativeFormathotKeyPrefix);
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(hdcpaintStruct);
1420             }
1421         }
1422         private void* hdc;
1423         private void* paintStruct;
1424     }
1425 
1426     public enum CombineMode : int
1427     {
1428         replaceintersectunionxorexcludecomplement
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     // image formats: image/bmp, image/jpeg, image/gif, image/tiff, image/png
1488 
1489     public enum ImageFormat : int
1490     {
1491         bmpjpeggiftiffpng
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& fileNamebool 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* fileNameconst Uuid& encoderClsId)
1585         {
1586             int status = WinGraphicsImageSave(nativeImagefileName&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& fileNamebool 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 widthint heightconst Graphics& graphics) : base(WinGraphicsCreateBitmapWidthHeight(widthheightgraphics.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& winBitmapvoid* 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 xint y) const
1694         {
1695             Color color;
1696             int status = WinGraphicsBitmapGetPixel(NativeImage()xycolor.alphacolor.redcolor.greencolor.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 xint yconst Color& color)
1706         {
1707             int status = WinGraphicsBitmapSetPixel(NativeImage()xycolor.alphacolor.redcolor.greencolor.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 pixelFormatconst Color& bitmapTransparentColor)
1717         {
1718             int w = cast<int>(GetWidth());
1719             int h = cast<int>(GetHeight());
1720             Bitmap grayBitmap(WinGraphicsCloneBitmap(NativeImage()00whpixelFormat));
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(xy);
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(xygray);
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.pixelFormat24bppRGBColor.DefaultBitmapTransparent());
1749         }
1750         public ~Bitmap()
1751         {
1752         }
1753     }
1754 
1755     public enum MatrixOrder
1756     {
1757         prependappend
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& rectconst Point& pt) : nativeMatrix(WinGraphicsCreateMatrixRectPoint(rect.location.xrect.location.yrect.size.wrect.size.hpt.xpt.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& rectconst PointF& pt) : nativeMatrix(WinGraphicsCreateMatrixRectFPointF(rect.location.xrect.location.yrect.size.wrect.size.hpt.xpt.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& thatMatrixOrder order)
1831         {
1832             int status = WinGraphicsMultiplyMatrix(nativeMatrixthat.nativeMatrixcast<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(nativeMatrixthat.nativeMatrixcast<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 angleMatrixOrder order)
1883         {
1884             int status = WinGraphicsMatrixRotate(nativeMatrixanglecast<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(nativeMatrixanglecast<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 angleconst PointF& centerMatrixOrder order)
1905         {
1906             int status = WinGraphicsMatrixRotateAt(nativeMatrixanglecenter.xcenter.ycast<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 angleconst PointF& center)
1916         {
1917             return RotateAt(anglecenterMatrixOrder.prepend);
1918         }
1919         [nodiscard]
1920         public Result<bool> Scale(float scaleXfloat scaleYMatrixOrder order)
1921         {
1922             int status = WinGraphicsMatrixScale(nativeMatrixscaleXscaleYcast<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 scaleXfloat scaleY)
1932         {
1933             return Scale(scaleXscaleYMatrixOrder.prepend);
1934         }
1935         [nodiscard]
1936         public Result<bool> Shear(float shearXfloat shearYMatrixOrder order)
1937         {
1938             int status = WinGraphicsMatrixShear(nativeMatrixshearXshearYcast<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 shearXfloat shearY)
1948         {
1949             return Shear(shearXshearYMatrixOrder.prepend);
1950         }
1951         [nodiscard]
1952         public Result<bool> Translate(float offsetXfloat offsetYMatrixOrder order)
1953         {
1954             int status = WinGraphicsMatrixTranslate(nativeMatrixoffsetXoffsetYcast<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 offsetXfloat offsetY)
1964         {
1965             return Translate(offsetXoffsetYMatrixOrder.prepend);
1966         }
1967         [nodiscard]
1968         public Result<bool> SetElements(float m11float m12float m21float m22float dxfloat dy)
1969         {
1970             int status = WinGraphicsMatrixSetElements(nativeMatrixm11m12m21m22dxdy);
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(nativeMatrixpoints.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(nativeMatrixpoints.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& leftconst 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& mfloat 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& mfloat angleconst 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(anglecenter);
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& mfloat scaleXfloat scaleY)
2057     {
2058         Matrix sm(m);
2059         if (sm.Error())
2060         {
2061             return Result<Matrix>(ErrorId(sm.GetErrorId()));
2062         }
2063         auto result = sm.Scale(scaleXscaleY);
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& mfloat shearXfloat shearY)
2073     {
2074         Matrix sm(m);
2075         if (sm.Error())
2076         {
2077             return Result<Matrix>(ErrorId(sm.GetErrorId()));
2078         }
2079         auto result = sm.Shear(shearXshearY);
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& mfloat offsetXfloat offsetY)
2089     {
2090         Matrix tm(m);
2091         if (tm.Error())
2092         {
2093             return Result<Matrix>(ErrorId(tm.GetErrorId()));
2094         }
2095         auto result = tm.Translate(offsetXoffsetY);
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& colorLowconst Color& colorHighColorAdjustType type)
2199         {
2200             int status = WinGraphicsImageAttributesSetColorKey(nativeImageAttributescolorLow.alphacolorLow.redcolorLow.greencolorLow.blue
2201                 colorHigh.alphacolorHigh.redcolorHigh.greencolorHigh.bluecast<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& penconst Point& startconst Point& end)
2283         {
2284             int status = WinGraphicsDrawLine(nativeGraphicspen.NativePen()start.xstart.yend.xend.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& penconst PointF& startconst PointF& end)
2294         {
2295             int status = WinGraphicsDrawLineF(nativeGraphicspen.NativePen()start.xstart.yend.xend.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& penint numPointsconst Point* points)
2305         {
2306             int status = WinGraphicsDrawLines(nativeGraphicspen.NativePen()numPointspoints);
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& penint numPointsconst PointF* points)
2316         {
2317             int status = WinGraphicsDrawLinesF(nativeGraphicspen.NativePen()numPointspoints);
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& strconst Font& fontconst PointF& originconst Brush& brush)
2327         {
2328             int status = WinGraphicsDrawString(nativeGraphicsstr.Chars()font.NativeFont()origin.xorigin.ybrush.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& strconst Font& fontconst PointF& originconst StringFormat& formatconst Brush& brush)
2338         {
2339             int status = WinGraphicsDrawStringFormatPoint(nativeGraphicsstr.Chars()font.NativeFont()
2340                 origin.xorigin.yformat.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& strconst Font& fontconst RectF& rectconst StringFormat& formatconst Brush& brush)
2350         {
2351             int status = WinGraphicsDrawStringFormatRect(nativeGraphicsstr.Chars()font.NativeFont()
2352                 rect.location.xrect.location.yrect.size.wrect.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& strconst Font& fontconst SizeF& layoutRectSizeconst StringFormat& format
2363             int* codePointsFittedint* linesFilled)
2364         {
2365             SizeF size;
2366             int status = WinGraphicsMeasureStringFormatSize(nativeGraphicsstr.Chars()font.NativeFont()
2367                 layoutRectSize.wlayoutRectSize.hformat.NativeFormat()
2368                 size.wsize.hcodePointsFittedlinesFilled);
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& strconst Font& fontconst SizeF& layoutRectSizeconst StringFormat& format)
2378         {
2379             SizeF size;
2380             int status = WinGraphicsMeasureStringFormatSize(nativeGraphicsstr.Chars()font.NativeFont()
2381                 layoutRectSize.wlayoutRectSize.hformat.NativeFormat()size.wsize.hnullnull);
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& strconst Font& fontconst RectF& layoutRectconst StringFormat& format
2391             int* codePointsFittedint* linesFilled)
2392         {
2393             RectF boundingBox;
2394             int status = WinGraphicsMeasureStringFormatRect(nativeGraphicsstr.Chars()font.NativeFont()
2395                 layoutRect.location.xlayoutRect.location.ylayoutRect.size.wlayoutRect.size.hformat.NativeFormat()
2396                 boundingBox.location.xboundingBox.location.yboundingBox.size.wboundingBox.size.h
2397                 codePointsFittedlinesFilled);
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& strconst Font& fontconst RectF& layoutRectconst StringFormat& format)
2407         {
2408             RectF boundingBox;
2409             int status = WinGraphicsMeasureStringFormatRect(nativeGraphicsstr.Chars()font.NativeFont()
2410                 layoutRect.location.xlayoutRect.location.ylayoutRect.size.wlayoutRect.size.hformat.NativeFormat()
2411                 boundingBox.location.xboundingBox.location.yboundingBox.size.wboundingBox.size.h
2412                 nullnull);
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& strconst Font& fontconst PointF& originconst StringFormat& format)
2422         {
2423             RectF boundingBox;
2424             int status = WinGraphicsMeasureStringFormatPoint(nativeGraphicsstr.Chars()font.NativeFont()origin.xorigin.yformat.NativeFormat()
2425                 boundingBox.location.xboundingBox.location.yboundingBox.size.wboundingBox.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(nativeGraphicscast<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(nativeGraphicscolor.alphacolor.redcolor.greencolor.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& penconst Rect& rect)
2461         {
2462             int status = WinGraphicsDrawRectangle(nativeGraphicspen.NativePen()rect.location.xrect.location.yrect.size.wrect.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& penconst RectF& rect)
2472         {
2473             int status = WinGraphicsDrawRectangleF(nativeGraphicspen.NativePen()rect.location.xrect.location.yrect.size.wrect.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& brushconst Rect& rect)
2483         {
2484             int status = WinGraphicsFillRectangle(nativeGraphicsbrush.NativeBrush()rect.location.xrect.location.yrect.size.wrect.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& brushconst RectF& rect)
2494         {
2495             int status = WinGraphicsFillRectangleF(nativeGraphicsbrush.NativeBrush()rect.location.xrect.location.yrect.size.wrect.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& brushint numPointsconst Point* points)
2505         {
2506             int status = WinGraphicsFillPolygon(nativeGraphicsbrush.NativeBrush()numPointspoints);
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& brushint numPointsconst PointF* points)
2516         {
2517             int status = WinGraphicsFillPolygonF(nativeGraphicsbrush.NativeBrush()numPointspoints);
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& penconst RectF& rectfloat startAnglefloat sweepAngle)
2527         {
2528             int status = WinGraphicsDrawArc(nativeGraphicspen.NativePen()rect.location.xrect.location.yrect.size.wrect.size.hstartAnglesweepAngle);
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& penconst RectF& rect)
2538         {
2539             int status = WinGraphicsDrawEllipse(nativeGraphicspen.NativePen()rect.location.xrect.location.yrect.size.wrect.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& brushconst RectF& rect)
2549         {
2550             int status = WinGraphicsFillEllipse(nativeGraphicsbrush.NativeBrush()rect.location.xrect.location.yrect.size.wrect.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& imageconst PointF& point)
2560         {
2561             int status = WinGraphicsDrawImagePoint(nativeGraphicsimage.NativeImage()point.xpoint.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& imageconst RectF& rect)
2571         {
2572             int status = WinGraphicsDrawImageRect(nativeGraphicsimage.NativeImage()rect.location.xrect.location.yrect.size.wrect.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& imageconst Rect& destRectint srcXint srcYint srcWint srcHUnit srcUnitconst ImageAttributes& attributes)
2582         {
2583             int status = WinGraphicsDrawImageWithAttributes(nativeGraphicsimage.NativeImage()destRect.location.xdestRect.location.ydestRect.size.wdestRect.size.h
2584                 srcXsrcYsrcWsrcHsrcUnitattributes.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& imageconst RectF& destRectconst RectF& sourceRectUnit srcUnitconst ImageAttributes& attributes)
2594         {
2595             int status = WinGraphicsDrawImageWithAttributesF(nativeGraphicsimage.NativeImage()destRect.location.xdestRect.location.ydestRect.size.wdestRect.size.h
2596                 sourceRect.location.xsourceRect.location.ysourceRect.size.wsourceRect.size.hsrcUnitattributes.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(nativeGraphicsregion.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& rectCombineMode combineMode)
2618         {
2619             int status = WinGraphicsSetClipRect(nativeGraphicsrect.location.xrect.location.yrect.size.wrect.size.hcombineMode);
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(nativeGraphicsrect.location.xrect.location.yrect.size.wrect.size.hCombineMode.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(nativeGraphicsregion.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(nativeGraphicscast<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(nativeGraphicsm.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(nativeGraphicsm.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& matrixMatrixOrder order)
2696         {
2697             int status = WinGraphicsMultiplyTransform(nativeGraphicsmatrix.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(matrixMatrixOrder.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 angleMatrixOrder order)
2723         {
2724             int status = WinGraphicsRotateTransform(nativeGraphicsanglecast<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(angleMatrixOrder.prepend);
2736         }
2737         [nodiscard]
2738         public Result<bool> ScaleTransform(float scaleXfloat scaleYMatrixOrder order)
2739         {
2740             int status = WinGraphicsScaleTransform(nativeGraphicsscaleXscaleYcast<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 scaleXfloat scaleY)
2750         {
2751             return ScaleTransform(scaleXscaleYMatrixOrder.prepend);
2752         }
2753         [nodiscard]
2754         public Result<bool> TranslateTransform(float offsetXfloat offsetYMatrixOrder order)
2755         {
2756             int status = WinGraphicsTranslateTransform(nativeGraphicsoffsetXoffsetYcast<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 offsetXfloat offsetY)
2766         {
2767             return TranslateTransform(offsetXoffsetYMatrixOrder.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(nativeGraphicscast<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(nativeGraphicsscale);
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(nativeGraphicssmoothingMode);
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 }