diff --git a/MBS.Framework/Drawing/Measurement.cs b/MBS.Framework/Drawing/Measurement.cs new file mode 100644 index 0000000..b053b35 --- /dev/null +++ b/MBS.Framework/Drawing/Measurement.cs @@ -0,0 +1,235 @@ +// +// Measurement.cs - represents a tuple of a numeric value and a unit of measure +// +// Author: +// Michael Becker +// +// Copyright (c) 2011-2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; + +namespace MBS.Framework.Drawing +{ + /// + /// Represents a tuple of a numeric value and a unit of measure. + /// + public struct Measurement + { + public static readonly Measurement Empty; + + public Measurement(double value, MeasurementUnit unit) + { + mvarUnit = unit; + mvarValue = value; + mvarIsFull = true; + } + + private double mvarValue; + public double Value { get { return mvarValue; } set { mvarValue = value; } } + + private MeasurementUnit mvarUnit; + public MeasurementUnit Unit { get { return mvarUnit; } set { mvarUnit = value; } } + + private bool mvarIsFull; + public bool IsEmpty { get { return !mvarIsFull; } } + + public static Measurement Parse(string value) + { + DoubleStringSplitterResult dssr = NumericStringSplitter.SplitDoubleStringParts(value); + double val = dssr.DoublePart; + MeasurementUnit unit; + switch (dssr.StringPart.ToLower()) + { + case "cm": unit = MeasurementUnit.Cm; break; + case "em": unit = MeasurementUnit.Em; break; + case "ex": unit = MeasurementUnit.Ex; break; + case "in": unit = MeasurementUnit.Inch; break; + case "mm": unit = MeasurementUnit.Mm; break; + case "%": unit = MeasurementUnit.Percentage; break; + case "pc": unit = MeasurementUnit.Pica; break; + case "px": unit = MeasurementUnit.Pixel; break; + case "pt": unit = MeasurementUnit.Point; break; + default: unit = MeasurementUnit.Pixel; break; + } + return new Measurement(val, unit); + } + + public double GetValue(MeasurementUnit unit = MeasurementUnit.Pixel, int dpi = 96, Rectangle parentRect = default(Rectangle)) + { + if (Unit == unit) + return Value; + + double conversionFactor = GetConversionFactor(Unit, unit, dpi, parentRect); + return Value * (1 / conversionFactor); + } + + private double GetConversionFactor(MeasurementUnit unit1, MeasurementUnit unit2, int dpi, Rectangle parentRect) + { + if (unit1 == unit2) + return 1.0; + + switch (unit1) + { + case MeasurementUnit.Cm: + { + switch (unit2) + { + case MeasurementUnit.Em: + { + break; + } + case MeasurementUnit.Ex: + { + break; + } + case MeasurementUnit.Inch: + { + return 0.393701; + } + case MeasurementUnit.Mm: + { + return 10; + } + case MeasurementUnit.Percentage: + { + break; + } + case MeasurementUnit.Pica: + { + return 2.36222; + } + case MeasurementUnit.Pixel: + { + // 1 in = 2.54 cm + return 2.54 / dpi; + } + case MeasurementUnit.Point: + { + return 28.3464567; + } + } + break; + } + case MeasurementUnit.Em: + break; + case MeasurementUnit.Ex: + break; + case MeasurementUnit.Inch: + { + switch (unit2) + { + case MeasurementUnit.Cm: + { + return 2.54; + } + case MeasurementUnit.Em: + { + break; + } + case MeasurementUnit.Ex: + { + break; + } + case MeasurementUnit.Mm: + { + return 25.4; + } + case MeasurementUnit.Percentage: + { + break; + } + case MeasurementUnit.Pica: + { + return 6.00005; + } + case MeasurementUnit.Pixel: + { + // 1 in = 2.54 cm + return dpi; + } + case MeasurementUnit.Point: + { + return 72; + } + } + break; + } + case MeasurementUnit.Pixel: + { + switch (unit2) + { + case MeasurementUnit.Inch: + { + return 1 / dpi; + } + case MeasurementUnit.Cm: + { + return dpi / 2.54; + } + case MeasurementUnit.Em: + { + break; + } + case MeasurementUnit.Ex: + { + break; + } + case MeasurementUnit.Mm: + { + return dpi / 25.4; + } + case MeasurementUnit.Percentage: + { + break; + } + case MeasurementUnit.Pica: + { + return dpi / 6.00005; + } + case MeasurementUnit.Pixel: + { + return 1.0; + } + case MeasurementUnit.Point: + { + return 72; + } + } + break; + } + } + throw new NotSupportedException(); + } + + public static Measurement operator -(Measurement left, Measurement right) + { + return new Measurement((left.Value - right.GetValue(left.Unit)), left.Unit); + } + public static Measurement operator +(Measurement left, Measurement right) + { + return new Measurement((left.Value + right.GetValue(left.Unit)), left.Unit); + } + + public static Measurement operator /(Measurement left, Measurement right) + { + return new Measurement((left.Value / right.GetValue(left.Unit)), left.Unit); + } + public static Measurement operator *(Measurement left, Measurement right) + { + return new Measurement((left.Value * right.GetValue(left.Unit)), left.Unit); + } + } +} diff --git a/MBS.Framework/Drawing/MeasurementUnit.cs b/MBS.Framework/Drawing/MeasurementUnit.cs new file mode 100644 index 0000000..cba3091 --- /dev/null +++ b/MBS.Framework/Drawing/MeasurementUnit.cs @@ -0,0 +1,48 @@ +// +// MeasurementUnit.cs - indicates the unit of a Measurement +// +// Author: +// Michael Becker +// +// Copyright (c) 2011-2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +namespace MBS.Framework.Drawing +{ + /// + /// Indicates the unit of a . + /// + public enum MeasurementUnit + { + /// Measurement is in pixels. + Pixel = 1, + /// Measurement is in points. A point represents 1/72 of an inch. + Point, + /// Measurement is in picas. A pica represents 12 points. + Pica, + /// Measurement is in inches. + Inch, + /// Measurement is in millimeters. + Mm, + /// Measurement is in centimeters. + Cm, + /// Measurement is a percentage relative to the parent element. + Percentage, + /// Measurement is relative to the height of the parent element's font. + Em, + /// Measurement is relative to the height of the lowercase letter x of the parent element's font. + Ex + } +} diff --git a/MBS.Framework/MBS.Framework.csproj b/MBS.Framework/MBS.Framework.csproj index 50481c5..adef941 100644 --- a/MBS.Framework/MBS.Framework.csproj +++ b/MBS.Framework/MBS.Framework.csproj @@ -71,6 +71,9 @@ + + + diff --git a/MBS.Framework/NumericStringSplitter.cs b/MBS.Framework/NumericStringSplitter.cs new file mode 100644 index 0000000..5e15428 --- /dev/null +++ b/MBS.Framework/NumericStringSplitter.cs @@ -0,0 +1,109 @@ +// +// NumericStringSplitter.cs - provides functions for splitting a string containing numbers into string and number components +// +// Author: +// Michael Becker +// +// Copyright (c) 2011-2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; + +namespace MBS.Framework +{ + public struct IntStringSplitterResult + { + private int mvarIntegerPart; + public int IntegerPart { get { return mvarIntegerPart; } } + + private string mvarStringPart; + public string StringPart { get { return mvarStringPart; } } + + public IntStringSplitterResult(int integerPart, string stringPart) + { + mvarIntegerPart = integerPart; + mvarStringPart = stringPart; + } + } + public struct DoubleStringSplitterResult + { + private double mvarDoublePart; + public double DoublePart { get { return mvarDoublePart; } } + + private string mvarStringPart; + public string StringPart { get { return mvarStringPart; } } + + public DoubleStringSplitterResult(double doublePart, string stringPart) + { + mvarDoublePart = doublePart; + mvarStringPart = stringPart; + } + } + public static class NumericStringSplitter + { + public static IntStringSplitterResult SplitIntStringParts(this string value) + { + return SplitIntStringParts(value, 0); + } + public static IntStringSplitterResult SplitIntStringParts(this string value, int start) + { + string intval = String.Empty; + string strval = String.Empty; + + int i = start; + for (i = start; i < value.Length; i++) + { + if (value[i] >= '0' && value[i] <= '9') + { + intval += value[i]; + } + else + { + break; + } + } + strval = value.Substring(i); + + int realintval = Int32.Parse(intval); + return new IntStringSplitterResult(realintval, strval); + } + public static DoubleStringSplitterResult SplitDoubleStringParts(this string value) + { + return SplitDoubleStringParts(value, 0); + } + public static DoubleStringSplitterResult SplitDoubleStringParts(this string value, int start) + { + string intval = String.Empty; + string strval = String.Empty; + + int i = start; + for (i = start; i < value.Length; i++) + { + if (value[i] == '.' || (value[i] >= '0' && value[i] <= '9')) + { + intval += value[i]; + } + else + { + break; + } + } + strval = value.Substring(i); + + double realintval = Double.Parse(intval); + return new DoubleStringSplitterResult(realintval, strval); + } + } +} \ No newline at end of file