1+ // Copyright 2019-2025 Chris Mohan, Jaben Cargman
2+ // and GotenbergSharpApiClient Contributors
3+ //
4+ // Licensed under the Apache License, Version 2.0 (the "License");
5+ // you may not use this file except in compliance with the License.
6+ // You may obtain a copy of the License at
7+ //
8+ // http://www.apache.org/licenses/LICENSE-2.0
9+ //
10+ // Unless required by applicable law or agreed to in writing, software
11+ // distributed under the License is distributed on an "AS IS" BASIS,
12+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ // See the License for the specific language governing permissions and
14+ // limitations under the License.
15+
16+ using System . ComponentModel ;
17+ using System . Reflection ;
18+ using System . Runtime . CompilerServices ;
19+ using System . Text . RegularExpressions ;
20+
21+ namespace Gotenberg . Sharp . API . Client . Domain . Dimensions ;
22+
23+ public sealed class Dimension ( double value , DimensionUnitType unitType ) : IEquatable < Dimension ? >
24+ {
25+ private static readonly Regex ValidDimensionRegex =
26+ new ( @"^\s*(\d+(\.\d+)?)\s*(pt|px|in|mm|cm|pc)\s*$" , RegexOptions . IgnoreCase ) ;
27+
28+ /// <summary>
29+ /// UnitType value
30+ /// </summary>
31+ public double Value { get ; init ; } = value ;
32+
33+ /// <summary>
34+ /// pt|px|in|mm|cm|pc
35+ /// </summary>
36+ public DimensionUnitType UnitType { get ; init ; } = unitType ;
37+
38+ public bool Equals ( Dimension ? other )
39+ {
40+ return other is not null &&
41+ Math . Abs ( Value - other . Value ) < 1e-6 &&
42+ UnitType == other . UnitType ;
43+ }
44+
45+ public static Dimension Parse ( string dimension )
46+ {
47+ if ( string . IsNullOrWhiteSpace ( dimension ) )
48+ {
49+ throw new ArgumentException ( "Dimension cannot be null or empty." ,
50+ nameof ( dimension ) ) ;
51+ }
52+
53+ var match = ValidDimensionRegex . Match ( dimension ) ;
54+ if ( ! match . Success )
55+ {
56+ throw new ArgumentException (
57+ "Invalid dimension format. Expected formats: '200px', '11in', etc." ,
58+ nameof ( dimension ) ) ;
59+ }
60+
61+ var value = double . Parse ( match . Groups [ 1 ] . Value ) ;
62+ var unitStr = match . Groups [ 3 ] . Value . ToLower ( ) ;
63+
64+ if ( ! TryParseUnit ( unitStr , out var unit ) )
65+ {
66+ throw new ArgumentException ( $ "Unknown unitType '{ unitStr } '", nameof ( dimension ) ) ;
67+ }
68+
69+ return new Dimension ( value , unit ) ;
70+ }
71+
72+ private static bool TryParseUnit ( string unitStr , out DimensionUnitType unitType )
73+ {
74+ foreach ( DimensionUnitType type in Enum . GetValues ( typeof ( DimensionUnitType ) ) )
75+ {
76+ if ( type . GetDescription ( ) == unitStr )
77+ {
78+ unitType = type ;
79+ return true ;
80+ }
81+ }
82+ unitType = default ;
83+
84+ return false ;
85+ }
86+
87+ public static Dimension FromPoints ( double points )
88+ {
89+ return new Dimension ( points , DimensionUnitType . Points ) ;
90+ }
91+
92+ public static Dimension FromPixels ( double pixels )
93+ {
94+ return new Dimension ( pixels , DimensionUnitType . Pixels ) ;
95+ }
96+
97+ public static Dimension FromInches ( double inches )
98+ {
99+ return new Dimension ( inches , DimensionUnitType . Inches ) ;
100+ }
101+
102+ public static Dimension FromMillimeters ( double millimeters )
103+ {
104+ return new Dimension ( millimeters , DimensionUnitType . Millimeters ) ;
105+ }
106+
107+ public static Dimension FromCentimeters ( double centimeters )
108+ {
109+ return new Dimension ( centimeters , DimensionUnitType . Centimeters ) ;
110+ }
111+
112+ public static Dimension FromPicas ( double picas )
113+ {
114+ return new Dimension ( picas , DimensionUnitType . Picas ) ;
115+ }
116+
117+ public override string ToString ( )
118+ {
119+ return $ "{ Value } { UnitType . GetDescription ( ) } ";
120+ }
121+
122+ public override bool Equals ( object ? obj )
123+ {
124+ return Equals ( obj as Dimension ) ;
125+ }
126+
127+ public override int GetHashCode ( )
128+ {
129+ return HashCode . Combine ( Value , UnitType ) ;
130+ }
131+
132+ public static bool operator == ( Dimension ? left , Dimension ? right )
133+ {
134+ return Equals ( left , right ) ;
135+ }
136+
137+ public static bool operator != ( Dimension ? left , Dimension ? right )
138+ {
139+ return ! Equals ( left , right ) ;
140+ }
141+ }
0 commit comments