diff --git a/main/SS/UserModel/FontCharset.cs b/main/Common/UserModel/Fonts/FontCharset.cs similarity index 99% rename from main/SS/UserModel/FontCharset.cs rename to main/Common/UserModel/Fonts/FontCharset.cs index 286d3dd0e..8d0eee70e 100644 --- a/main/SS/UserModel/FontCharset.cs +++ b/main/Common/UserModel/Fonts/FontCharset.cs @@ -15,7 +15,7 @@ the License. You may obtain a copy of the License at limitations under the License. ==================================================================== */ -namespace NPOI.SS.UserModel +namespace NPOI.Common.UserModel.Fonts { diff --git a/main/Common/UserModel/Fonts/FontFacet.cs b/main/Common/UserModel/Fonts/FontFacet.cs new file mode 100644 index 000000000..23a391444 --- /dev/null +++ b/main/Common/UserModel/Fonts/FontFacet.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.Common.UserModel.Fonts +{ + public interface FontFacet + { + int Weight { get; set; } + bool IsItalic { get; set; } + object GetFontData(); + } +} diff --git a/main/SS/UserModel/FontFamily.cs b/main/Common/UserModel/Fonts/FontFamily.cs similarity index 93% rename from main/SS/UserModel/FontFamily.cs rename to main/Common/UserModel/Fonts/FontFamily.cs index e3d61f16f..47a8ba941 100644 --- a/main/SS/UserModel/FontFamily.cs +++ b/main/Common/UserModel/Fonts/FontFamily.cs @@ -15,7 +15,7 @@ the License. You may obtain a copy of the License at limitations under the License. ==================================================================== */ -namespace NPOI.SS.UserModel +namespace NPOI.Common.UserModel.Fonts { /** @@ -33,11 +33,11 @@ public class FontFamily public static readonly FontFamily SCRIPT = new FontFamily(4); public static readonly FontFamily DECORATIVE = new FontFamily(5); - private int family; + private int nativeId; private FontFamily(int value) { - family = value; + nativeId = value; } /** @@ -45,14 +45,13 @@ private FontFamily(int value) * * @return index of this font family */ - public int Value + public int NativeId { get { - return family; + return nativeId; } } - public static FontFamily ValueOf(int family) { switch(family) diff --git a/main/Common/UserModel/Fonts/FontGroup.cs b/main/Common/UserModel/Fonts/FontGroup.cs new file mode 100644 index 000000000..d15e1c75a --- /dev/null +++ b/main/Common/UserModel/Fonts/FontGroup.cs @@ -0,0 +1,173 @@ +using NPOI.Util; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.Common.UserModel.Fonts +{ + public class FontGroup + { + /** type for latin charset (default) - also used for unicode fonts like MS Arial Unicode */ + public static readonly FontGroup LATIN = new FontGroup(1); + /** type for east asian charsets - usually set as fallback for the latin font, e.g. something like MS Gothic or MS Mincho */ + public static readonly FontGroup EAST_ASIAN = new FontGroup(2); + /** type for symbol fonts */ + public static readonly FontGroup SYMBOL = new FontGroup(3); + /** type for complex scripts - see https://msdn.microsoft.com/en-us/library/windows/desktop/dd317698 */ + public static readonly FontGroup COMPLEX_SCRIPT = new FontGroup(4); + + private static Dictionary UCS_RANGES=null; + + static FontGroup() + { + UCS_RANGES = new Dictionary(); + UCS_RANGES.Add(0x0000, new Range(0x007F, LATIN)); + UCS_RANGES.Add(0x0080, new Range(0x00A6, LATIN)); + UCS_RANGES.Add(0x00A9, new Range(0x00AF, LATIN)); + UCS_RANGES.Add(0x00B2, new Range(0x00B3, LATIN)); + UCS_RANGES.Add(0x00B5, new Range(0x00D6, LATIN)); + UCS_RANGES.Add(0x00D8, new Range(0x00F6, LATIN)); + UCS_RANGES.Add(0x00F8, new Range(0x058F, LATIN)); + UCS_RANGES.Add(0x0590, new Range(0x074F, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x0780, new Range(0x07BF, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x0900, new Range(0x109F, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x10A0, new Range(0x10FF, LATIN)); + UCS_RANGES.Add(0x1200, new Range(0x137F, LATIN)); + UCS_RANGES.Add(0x13A0, new Range(0x177F, LATIN)); + UCS_RANGES.Add(0x1D00, new Range(0x1D7F, LATIN)); + UCS_RANGES.Add(0x1E00, new Range(0x1FFF, LATIN)); + UCS_RANGES.Add(0x1780, new Range(0x18AF, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x2000, new Range(0x200B, LATIN)); + UCS_RANGES.Add(0x200C, new Range(0x200F, COMPLEX_SCRIPT)); + // For the quote characters in the range U+2018 - U+201E, use the East Asian font + // if the text has one of the following language identifiers: + // ii-CN, ja-JP, ko-KR, zh-CN,zh-HK, zh-MO, zh-SG, zh-TW + UCS_RANGES.Add(0x2010, new Range(0x2029, LATIN)); + UCS_RANGES.Add(0x202A, new Range(0x202F, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x2030, new Range(0x2046, LATIN)); + UCS_RANGES.Add(0x204A, new Range(0x245F, LATIN)); + UCS_RANGES.Add(0x2670, new Range(0x2671, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0x27C0, new Range(0x2BFF, LATIN)); + UCS_RANGES.Add(0x3099, new Range(0x309A, EAST_ASIAN)); + UCS_RANGES.Add(0xD835, new Range(0xD835, LATIN)); + UCS_RANGES.Add(0xF000, new Range(0xF0FF, SYMBOL)); + UCS_RANGES.Add(0xFB00, new Range(0xFB17, LATIN)); + UCS_RANGES.Add(0xFB1D, new Range(0xFB4F, COMPLEX_SCRIPT)); + UCS_RANGES.Add(0xFE50, new Range(0xFE6F, LATIN)); + // All others EAST_ASIAN + } + private int value = 0; + protected FontGroup(int value) + { + this.value = value; + } + /** + * Try to guess the font group based on the codepoint + * + * @param runText the text which font groups are to be analyzed + * @return the FontGroup + */ + public static List GetFontGroupRanges(String runText) + { + List ttrList = new List(); + if(string.IsNullOrEmpty(runText)) + { + return ttrList; + } + FontGroupRange ttrLast = null; + int rlen = runText.Length; + for(int cp, i = 0, charCount; i < rlen; i += charCount) + { + cp = runText[i]; + charCount = 1; //StringInfo.GetNextTextElementLength(runText); TODO:fix this issue + + // don't switch the font group for a few default characters supposedly available in all fonts + FontGroup tt; + if(ttrLast != null)// && " \n\r".IndexOf() > -1) + { + tt = ttrLast.FontGroup; + } + else + { + tt = lookup(cp); + } + + if(ttrLast == null || ttrLast.FontGroup != tt) + { + ttrLast = new FontGroupRange(tt); + ttrList.Add(ttrLast); + } + ttrLast.IncreaseLength(charCount); + } + return ttrList; + } + public static FontGroup GetFontGroupFirst(String runText) + { + return (runText == null || string.IsNullOrEmpty(runText)) ? LATIN : lookup(runText[0]); + } + + private static FontGroup lookup(int codepoint) + { + // Do a lookup for a match in UCS_RANGES + Range range =UCS_RANGES.ContainsKey(codepoint) ? UCS_RANGES[codepoint]:null; + return (range != null && codepoint <= range.Upper) ? range.FontGroup : EAST_ASIAN; + } + } + + public class FontGroupRange + { + private FontGroup fontGroup; + private int len = 0; + + public FontGroupRange(FontGroup fontGroup) + { + this.fontGroup = fontGroup; + } + + public int Length + { + get + { + return len; + } + } + + public FontGroup FontGroup + { + get + { + return fontGroup; + } + } + + public void IncreaseLength(int len) + { + this.len += len; + } + } + + internal class Range + { + private int upper; + private FontGroup fontGroup; + public Range(int upper, FontGroup fontGroup) + { + this.upper = upper; + this.fontGroup = fontGroup; + } + + public int Upper + { + get + { + return upper; + } + } + public FontGroup FontGroup { + get { return fontGroup; } + } + } +} diff --git a/main/Common/UserModel/Fonts/FontInfo.cs b/main/Common/UserModel/Fonts/FontInfo.cs new file mode 100644 index 000000000..eb09e19d2 --- /dev/null +++ b/main/Common/UserModel/Fonts/FontInfo.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.Common.UserModel.Fonts +{ + public interface FontInfo + { + int Index { get; set; } + string Typeface { get; set; } + FontCharset Charset { get; set; } + FontFamily Family { get; set; } + + byte[] Panose { get; set; } + + List GetFacets(); + } +} diff --git a/main/Common/UserModel/Fonts/FontPitch.cs b/main/Common/UserModel/Fonts/FontPitch.cs new file mode 100644 index 000000000..a7cfcb283 --- /dev/null +++ b/main/Common/UserModel/Fonts/FontPitch.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.Common.UserModel.Fonts +{ + public class FontPitch + { + /** + * The default pitch, which is implementation-dependent. + */ + public static readonly FontPitch DEFAULT = new FontPitch(0x00); + /** + * A fixed pitch, which means that all the characters in the font occupy the same + * width when output in a string. + */ + public static readonly FontPitch FIXED = new FontPitch(0x01); + /** + * A variable pitch, which means that the characters in the font occupy widths + * that are proportional to the actual widths of the glyphs when output in a string. For example, + * the "i" and space characters usually have much smaller widths than a "W" or "O" character. + */ + public static readonly FontPitch VARIABLE= new FontPitch(0x02); + + private int nativeId; + protected FontPitch(int nativeId) + { + this.nativeId= nativeId; + } + public int NativeId { + get { + return nativeId; + } + } + public static FontPitch ValueOf(int flag) + { + switch(flag) + { + case 1: + return FIXED; + case 2: + return VARIABLE; + default: + return DEFAULT; + } + } + /** + * Combine pitch and family to native id + * + * @see LOGFONT structure + * + * @param pitch The pitch-value, cannot be null + * @param family The family-value, cannot be null + * + * @return The resulting combined byte-value with pitch and family encoded into one byte + */ + public static byte GetNativeId(FontPitch pitch, FontFamily family) + { + return (byte) (pitch.NativeId | (family.NativeId << 4)); + } + + /** + * Get FontPitch from native id + * + * @param pitchAndFamily The combined byte value for pitch and family + * + * @return The resulting FontPitch enumeration value + */ + public static FontPitch ValueOfPitchFamily(byte pitchAndFamily) + { + return ValueOf(pitchAndFamily & 0x3); + } + } +} diff --git a/main/SL/Draw/Geom/AdjustPoint.cs b/main/SL/Draw/Geom/AdjustPoint.cs new file mode 100644 index 000000000..674d760de --- /dev/null +++ b/main/SL/Draw/Geom/AdjustPoint.cs @@ -0,0 +1,44 @@ +using Org.BouncyCastle.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public class AdjustPoint : AdjustPointIf + { + public string X { get; set; } + + public bool IsSetX + { + get + { + return X!=null; + } + } + + public string Y { get; set; } + public bool IsSetY + { + get { + return Y!=null; + } + } + + public override bool Equals(object o) + { + if(this == o) + return true; + if(!(o is AdjustPoint)) return false; + AdjustPoint that = (AdjustPoint) o; + return Objects.Equals(X, that.X) && + Objects.Equals(Y, that.Y); + } + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +} diff --git a/main/SL/Draw/Geom/AdjustPointIf.cs b/main/SL/Draw/Geom/AdjustPointIf.cs new file mode 100644 index 000000000..ba831e0e9 --- /dev/null +++ b/main/SL/Draw/Geom/AdjustPointIf.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public interface AdjustPointIf + { + string X { get; set; } + bool IsSetX { get; } + string Y { get; set; } + bool IsSetY { get; } + } +} diff --git a/main/SL/Draw/Geom/BuiltInGuide.cs b/main/SL/Draw/Geom/BuiltInGuide.cs new file mode 100644 index 000000000..1ba9f68b8 --- /dev/null +++ b/main/SL/Draw/Geom/BuiltInGuide.cs @@ -0,0 +1,189 @@ +using Org.BouncyCastle.Pqc.Crypto.Lms; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public class BuiltInGuide:Formula + { + public static readonly BuiltInGuide _3cd4 = new BuiltInGuide("3cd4"); + public static readonly BuiltInGuide _3cd8 = new BuiltInGuide("3cd8"); + public static readonly BuiltInGuide _5cd8 = new BuiltInGuide("5cd8"); + public static readonly BuiltInGuide _7cd8 = new BuiltInGuide("7cd8"); + public static readonly BuiltInGuide b = new BuiltInGuide("b"); + public static readonly BuiltInGuide cd2 = new BuiltInGuide("cd2"); + public static readonly BuiltInGuide cd4 = new BuiltInGuide("cd4"); + public static readonly BuiltInGuide cd8 = new BuiltInGuide("cd8"); + public static readonly BuiltInGuide hc = new BuiltInGuide("hc"); + public static readonly BuiltInGuide h = new BuiltInGuide("cd8"); + public static readonly BuiltInGuide hd2 = new BuiltInGuide("hd2"); + public static readonly BuiltInGuide hd3 = new BuiltInGuide("hd3"); + public static readonly BuiltInGuide hd4 = new BuiltInGuide("hd4"); + public static readonly BuiltInGuide hd5 = new BuiltInGuide("hd5"); + public static readonly BuiltInGuide hd6 = new BuiltInGuide("hd6"); + public static readonly BuiltInGuide hd8 = new BuiltInGuide("hd8"); + public static readonly BuiltInGuide l = new BuiltInGuide("l"); + public static readonly BuiltInGuide ls = new BuiltInGuide("ls"); + public static readonly BuiltInGuide r = new BuiltInGuide("r"); + public static readonly BuiltInGuide ss = new BuiltInGuide("ss"); + public static readonly BuiltInGuide ssd2 = new BuiltInGuide("ssd2"); + public static readonly BuiltInGuide ssd4 = new BuiltInGuide("ssd4"); + public static readonly BuiltInGuide ssd6 = new BuiltInGuide("ssd6"); + public static readonly BuiltInGuide ssd8 = new BuiltInGuide("ssd9"); + public static readonly BuiltInGuide ssd16 = new BuiltInGuide("ssd16"); + public static readonly BuiltInGuide ssd32= new BuiltInGuide("ssd32"); + public static readonly BuiltInGuide t= new BuiltInGuide("t"); + public static readonly BuiltInGuide vc= new BuiltInGuide("vc"); + public static readonly BuiltInGuide w= new BuiltInGuide("w"); + public static readonly BuiltInGuide w2= new BuiltInGuide("w2"); + public static readonly BuiltInGuide w3= new BuiltInGuide("w3"); + public static readonly BuiltInGuide w4= new BuiltInGuide("w4"); + public static readonly BuiltInGuide w5= new BuiltInGuide("w5"); + public static readonly BuiltInGuide w6= new BuiltInGuide("w6"); + public static readonly BuiltInGuide w8= new BuiltInGuide("w8"); + public static readonly BuiltInGuide w10= new BuiltInGuide("w10"); + public static readonly BuiltInGuide w32= new BuiltInGuide("w32"); + + private string name=null; + static Dictionary indexes=new Dictionary(); + protected BuiltInGuide(string name) + { + this.name=name; + indexes.Add(name, this); + } + public string Name { + get { + return this.name.Substring(1); + } + } + + public static BuiltInGuide ValueOf(string name) + { + return indexes[name]; + } + public override double Evaluate(Context ctx) + { + var anchor = ctx.GetShapeAnchor(); + double height = anchor.Height, width = anchor.Width, ss = Math.Min(width, height); + switch(this.name) + { + case "3cd4": + // 3 circles div 4: 3 x 360 / 4 = 270 + return 270 * OOXML_DEGREE; + case "3cd8": + // 3 circles div 8: 3 x 360 / 8 = 135 + return 135 * OOXML_DEGREE; + case "5cd8": + // 5 circles div 8: 5 x 360 / 8 = 225 + return 225 * OOXML_DEGREE; + case "7cd8": + // 7 circles div 8: 7 x 360 / 8 = 315 + return 315 * OOXML_DEGREE; + case "t": + // top + return anchor.Y; + case "b": + // bottom + return anchor.Y; //.getMaxY(); + case "l": + // left + return anchor.X; + case "r": + // right + return anchor.X; //getMaxX(); + case "cd2": + // circle div 2": 360 / 2 = 180 + return 180 * OOXML_DEGREE; + case "cd4": + // circle div 4": 360 / 4 = 90 + return 90 * OOXML_DEGREE; + case "cd8": + // circle div 8": 360 / 8 = 45 + return 45 * OOXML_DEGREE; + case "hc": + // horizontal center + return anchor.X/2.0; + case "h": + // height + return height; + case "hd2": + // height div 2 + return height / 2.0; + case "hd3": + // height div 3 + return height / 3.0; + case "hd4": + // height div 4 + return height / 4.0; + case "hd5": + // height div 5 + return height / 5.0; + case "hd6": + // height div 6 + return height / 6.0; + case "hd8": + // height div 8 + return height / 8.0; + case "ls": + // long side + return Math.Max(width, height); + case "ss": + // short side + return ss; + case "ssd2": + // short side div 2 + return ss / 2.0; + case "ssd4": + // short side div 4 + return ss / 4.0; + case "ssd6": + // short side div 6 + return ss / 6.0; + case "ssd8": + // short side div 8 + return ss / 8.0; + case "ssd16": + // short side div 16 + return ss / 16.0; + case "ssd32": + // short side div 32 + return ss / 32.0; + case "vc": + // vertical center + return anchor.Y/2.0; + case "w": + // width + return width; + case "wd2": + // width div 2 + return width / 2.0; + case "wd3": + // width div 3 + return width / 3.0; + case "wd4": + // width div 4 + return width / 4.0; + case "wd5": + // width div 5 + return width / 5.0; + case "wd6": + // width div 6 + return width / 6.0; + case "wd8": + // width div 8 + return width / 8.0; + case "wd10": + // width div 10 + return width / 10.0; + case "wd32": + // width div 32 + return width / 32.0; + default: + return 0; + } + } + } +} diff --git a/main/SL/Draw/Geom/Context.cs b/main/SL/Draw/Geom/Context.cs new file mode 100644 index 000000000..1ca77d302 --- /dev/null +++ b/main/SL/Draw/Geom/Context.cs @@ -0,0 +1,68 @@ +using SixLabors.ImageSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public class Context + { + private static Regex DOUBLE_PATTERN = new Regex( + "[\\x00-\\x20]*[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)" + + "([eE][+-]?(\\p{Digit}+))?)|(\\.(\\p{Digit}+)([eE][+-]?(\\p{Digit}+))?)|" + + "(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))" + + "[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*", RegexOptions.Compiled); + private Dictionary _ctx= new Dictionary(); + private IAdjustableShape _props; + private Rectangle _anchor; + + public Context(CustomGeometry geom, Rectangle anchor, IAdjustableShape props) + { + _props = props; + _anchor = anchor; + foreach(GuideIf gd in geom.adjusts) + { + Evaluate(gd); + } + foreach(GuideIf gd in geom.guides) + { + Evaluate(gd); + } + } + + public double Evaluate(Formula fmla) + { + double result = fmla.Evaluate(this); + if(fmla is GuideIf) { + String key = ((GuideIf)fmla).Name; + if(key != null) + { + _ctx[key]=result; + } + } + return result; + } + internal Rectangle GetShapeAnchor() + { + return _anchor; + } + + internal GuideIf GetAdjustValue(String name) + { + return _props.GetAdjustValue(name); + } + public double GetValue(String key) + { + if(DOUBLE_PATTERN.Matches(key).Count>0) + { + return Double.Parse(key); + } + + // BuiltInGuide throws IllegalArgumentException if key is not defined + return _ctx.ContainsKey(key) ? _ctx[key] : Evaluate(BuiltInGuide.ValueOf(key)); + } + } +} diff --git a/main/SL/Draw/Geom/Formula.cs b/main/SL/Draw/Geom/Formula.cs new file mode 100644 index 000000000..2ece79040 --- /dev/null +++ b/main/SL/Draw/Geom/Formula.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public abstract class Formula + { + /** + * OOXML units are 60000ths of a degree + */ + public const double OOXML_DEGREE = 60000; + public abstract double Evaluate(Context ctx); + protected double RadianToDegree(double angle) + { + return angle * (180.0 / Math.PI); + } + protected double DegreeToRadian(double angle) + { + return Math.PI * angle / 180.0; + } + } +} diff --git a/main/SL/Draw/Geom/GuideIf.cs b/main/SL/Draw/Geom/GuideIf.cs new file mode 100644 index 000000000..42373d801 --- /dev/null +++ b/main/SL/Draw/Geom/GuideIf.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + enum Op + { + muldiv, addsub, adddiv, ifelse, val, abs, sqrt, max, min, at2, sin, cos, tan, cat2, sat2, pin, mod + } + + public class GuideIf : Formula + { + public string Name { get; set; } + public string Fmla { get; set; } + public override double Evaluate(Context ctx) + { + return evaluateGuide(ctx); + } + double evaluateGuide(Context ctx) + { + Op op; + String[] operands = Fmla.Split([' '], StringSplitOptions.RemoveEmptyEntries); + switch(operands[0]) + { + case "*/": + op = Op.muldiv; + break; + case "+-": + op = Op.addsub; + break; + case "+/": + op = Op.adddiv; + break; + case "?:": + op = Op.ifelse; + break; + default: + op = Op.ValueOf(operands[0]); + break; + } + + double x = (operands.Length > 1) ? ctx.GetValue(operands[1]) : 0; + double y = (operands.Length > 2) ? ctx.GetValue(operands[2]) : 0; + double z = (operands.Length > 3) ? ctx.GetValue(operands[3]) : 0; + switch(op) + { + case Op.abs: + // Absolute Value Formula + return Math.Abs(x); + case Op.adddiv: + // Add Divide Formula + return (z == 0) ? 0 : (x + y) / z; + case Op.addsub: + // Add Subtract Formula + return (x + y) - z; + case Op.at2: + // ArcTan Formula: "at2 x y" = arctan( y / z ) = value of this guide + return RadianToDegree(Math.Atan2(y, x)) * OOXML_DEGREE; + case Op.cos: + // Cosine Formula: "cos x y" = (x * cos( y )) = value of this guide + return x * Math.Cos(DegreeToRadian(y / OOXML_DEGREE)); + case Op.cat2: + // Cosine ArcTan Formula: "cat2 x y z" = (x * cos(arctan(z / y) )) = value of this guide + return x * Math.Cos(Math.Atan2(z, y)); + case Op.ifelse: + // If Else Formula: "?: x y z" = if (x > 0), then y = value of this guide, + // else z = value of this guide + return x > 0 ? y : z; + case Op.val: + // Literal Value Expression + return x; + case Op.max: + // Maximum Value Formula + return Math.Max(x, y); + case Op.min: + // Minimum Value Formula + return Math.Min(x, y); + case Op.mod: + // Modulo Formula: "mod x y z" = sqrt(x^2 + b^2 + c^2) = value of this guide + return Math.Sqrt(x*x + y*y + z*z); + case Op.muldiv: + // Multiply Divide Formula + return (z == 0) ? 0 : (x * y) / z; + case Op.pin: + // Pin To Formula: "pin x y z" = if (y < x), then x = value of this guide + // else if (y > z), then z = value of this guide + // else y = value of this guide + return Math.Max(x, Math.Min(y, z)); + case Op.sat2: + // Sine ArcTan Formula: "sat2 x y z" = (x*sin(arctan(z / y))) = value of this guide + return x * Math.Sin(Math.Atan2(z, y)); + case Op.sin: + // Sine Formula: "sin x y" = (x * sin( y )) = value of this guide + return x * Math.Sin(DegreeToRadian(y / OOXML_DEGREE)); + case Op.sqrt: + // Square Root Formula: "sqrt x" = sqrt(x) = value of this guide + return Math.Sqrt(x); + case Op.tan: + // Tangent Formula: "tan x y" = (x * tan( y )) = value of this guide + return x * Math.Tan(DegreeToRadian(y / OOXML_DEGREE)); + default: + return 0; + } + } + } +} diff --git a/main/SL/Draw/Geom/IAdjustableShape.cs b/main/SL/Draw/Geom/IAdjustableShape.cs new file mode 100644 index 000000000..4e3d51768 --- /dev/null +++ b/main/SL/Draw/Geom/IAdjustableShape.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.Draw.Geom +{ + public interface IAdjustableShape + { + GuideIf GetAdjustValue(string name); + } +} diff --git a/main/SL/UserModel/ColorStyle.cs b/main/SL/UserModel/ColorStyle.cs new file mode 100644 index 000000000..ac9604191 --- /dev/null +++ b/main/SL/UserModel/ColorStyle.cs @@ -0,0 +1,18 @@ +using SixLabors.ImageSharp; + +namespace NPOI.SL.UserModel +{ + public interface ColorStyle + { + Color GetColor(); + int Alpha { get; } + int HueOff { get; } + int HueMod { get; } + int SatOff { get; } + int SatMod { get; } + int LumOff { get; } + int LumMod { get; } + int Shade { get; } + int Tint { get; } + } +} \ No newline at end of file diff --git a/main/SL/UserModel/FillStyle.cs b/main/SL/UserModel/FillStyle.cs new file mode 100644 index 000000000..6658e969a --- /dev/null +++ b/main/SL/UserModel/FillStyle.cs @@ -0,0 +1,6 @@ +namespace NPOI.SL.UserModel +{ + public interface FillStyle { + PaintStyle Paint { get; } + } +} \ No newline at end of file diff --git a/main/SL/UserModel/Insets2D.cs b/main/SL/UserModel/Insets2D.cs new file mode 100644 index 000000000..0aec404e3 --- /dev/null +++ b/main/SL/UserModel/Insets2D.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.UserModel +{ + public sealed class Insets2D:ICloneable + { + public double Top { get; set; } + public double Left { get; set; } + public double Bottom { get; set; } + public double Right { get; set; } + + /// + /// Creates and initializes a new Insets object with the specified top, left, bottom, and right insets. + /// + /// the inset from the top + /// the inset from the left + /// the inset from the bottom + /// the inset from the right + public Insets2D(double top, double left, double bottom, double right) + { + this.Top = top; + this.Left = left; + this.Bottom = bottom; + this.Right = right; + } + public override bool Equals(object obj) + { + if(obj is Insets2D) { + Insets2D insets = (Insets2D)obj; + return ((Top == insets.Top) && (Left == insets.Left) && + (Bottom == insets.Bottom) && (Right == insets.Right)); + } + return false; + } + public override int GetHashCode() + { + double sum1 = Left + Bottom; + double sum2 = Right + Top; + double val1 = sum1 * (sum1 + 1)/2 + Left; + double val2 = sum2 * (sum2 + 1)/2 + Top; + double sum3 = val1 + val2; + return (int) (sum3 * (sum3 + 1)/2 + val2); + } + public override string ToString() + { + return this.GetType().Name+ "[Top=" + Top + ",Left=" + Left + ",Bottom=" + Bottom + ",Right=" + Right + "]"; + } + + public object Clone() + { + return new Insets2D(Top, Left, Bottom, Right); + } + } +} diff --git a/main/SL/UserModel/PaintStyle.cs b/main/SL/UserModel/PaintStyle.cs new file mode 100644 index 000000000..8ec8d16bc --- /dev/null +++ b/main/SL/UserModel/PaintStyle.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NPOI.SL.UserModel +{ + /// + /// The PaintStyle can be modified by secondary sources, e.g. the attributes in the preset shapes. + /// These modifications need to be taken into account when the final color is determined + /// + public enum PaintModifier + { + /** don't use any paint/fill */ + NONE, + /** use the paint/filling as-is */ + NORM, + /** lighten the paint/filling */ + LIGHTEN, + /** lighten (... a bit less) the paint/filling */ + LIGHTEN_LESS, + /** darken the paint/filling */ + DARKEN, + /** darken (... a bit less) the paint/filling */ + DARKEN_LESS + } + + public enum FlipMode + { + /** not flipped/mirrored */ + NONE, + /** flipped/mirrored/duplicated along the x axis */ + X, + /** flipped/mirrored/duplicated along the y axis */ + Y, + /** flipped/mirrored/duplicated along the x and y axis */ + XY + } + + public enum TextureAlignment + { + BOTTOM, + BOTTOM_LEFT, + BOTTOM_RIGHT, + CENTER, + LEFT, + RIGHT, + TOP, + TOP_LEFT, + TOP_RIGHT + } + + public enum GradientType { linear, circular, rectangular, shape } + public interface PaintStyle + { + + } + public interface SolidPaint : PaintStyle + { + ColorStyle SolidColor { get; } + } + public interface GradientPaint : PaintStyle + { + double GradientAngle { get; } + ColorStyle[] GradientColors { get; } + float[] GradientFractions { get; } + bool IsRotatedWithShape { get; } + GradientType GradientType { get; } + + Insets2D GetFillToInsets(); + } + public interface TexturePaint : PaintStyle + { + + } +} diff --git a/ooxml/XSSF/Model/StylesTable.cs b/ooxml/XSSF/Model/StylesTable.cs index cc7150493..9342e6427 100644 --- a/ooxml/XSSF/Model/StylesTable.cs +++ b/ooxml/XSSF/Model/StylesTable.cs @@ -28,6 +28,7 @@ limitations under the License. using System.Collections.ObjectModel; using NPOI.SS; using NPOI.OOXML.XSSF.UserModel; +using NPOI.Common.UserModel.Fonts; namespace NPOI.XSSF.Model { diff --git a/ooxml/XSSF/UserModel/XSSFFont.cs b/ooxml/XSSF/UserModel/XSSFFont.cs index dbbe0b215..e5415a172 100644 --- a/ooxml/XSSF/UserModel/XSSFFont.cs +++ b/ooxml/XSSF/UserModel/XSSFFont.cs @@ -23,6 +23,7 @@ limitations under the License. using Dml = NPOI.OpenXmlFormats.Dml; using NPOI.XSSF.Model; using NPOI.Util; +using NPOI.Common.UserModel.Fonts; namespace NPOI.XSSF.UserModel { diff --git a/testcases/ooxml/XSSF/UserModel/TestXSSFFont.cs b/testcases/ooxml/XSSF/UserModel/TestXSSFFont.cs index 96b106cdc..5d4ad5a33 100644 --- a/testcases/ooxml/XSSF/UserModel/TestXSSFFont.cs +++ b/testcases/ooxml/XSSF/UserModel/TestXSSFFont.cs @@ -16,6 +16,7 @@ limitations under the License. ==================================================================== */ using NPOI; +using NPOI.Common.UserModel.Fonts; using NPOI.OpenXmlFormats.Spreadsheet; using NPOI.SS.UserModel; using NPOI.SS.Util;