public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case TKHD: _atomTkhd = (AtomTKHD)atom; break; case MDIA: _atomMdia = (AtomMDIA)atom; break; case HDLR: _atomHdlr = (AtomHdlr)atom; break; case MINF: _atomMinf = (AtomMINF)atom; break; case DINF: _atomDinf = (AtomDINF)atom; break; case STBL: _atomStbl = (AtomSTBL)atom; break; case UDTA: _atomUdta = (AtomUDTA)atom; break; case META: _atomMeta = (AtomMETA)atom; break; } }
public override BaseAtom Run(string list) { string lambdaContent = LispUtil.SplitInAtom(list); bool shouldRunResult = false; if (!LispUtil.IsAtom(lambdaContent)) { lambdaContent = LispUtil.RemoveBracket(lambdaContent); shouldRunResult = true; } else { lambdaContent = list; shouldRunResult = false; } // 解析得到LambdaAtom string[] args = GetArgs(lambdaContent); LambdaAtom lambdaAtom = new LambdaAtom(Parser, args[0], args[1]); // @TODO: 如果list后面没有内容,则直接返回这个LambdaAtom BaseAtom result = lambdaAtom; if (shouldRunResult) { result = lambdaAtom.Run(list); } return(result); }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case STSD: _atomSTSD = (AtomSTSD) atom; break; case STTS: _atomSTTS = (AtomSTTS) atom; break; case STSC: _atomSTSC = (AtomSTSC) atom; break; case STSZ: _atomSTSZ = (AtomSTSZ) atom; break; case STCO: _atomSTCO = (AtomSTCO) atom; break; case CO64: _atomCO64 = (AtomCO64) atom; break; case CTTS: _atomCTTS = (AtomCTTS) atom; break; case STSS: _atomSTSS = (AtomSTSS) atom; break; } }
/// <summary> /// 解析指定的已绑定Value的Template /// </summary> protected BaseAtom ParseTemplate(Template template) { BaseAtom result = null; result = Parser.ParseAndGetAtom(template.BindingValue); return(result); }
public BaseAtom this[string key] { get { BaseAtom result = null; // 检查是否为整型 if (!ContainKey(key) && CheckIsNum(key)) { // 如果是则创建此原子,并注册进库中 this.RegisterAtom(key, new IntAtom(Parser, key)); } if (ContainKey(key)) { result = m_AtomDict[key]; } if (result == null && CheckIsLambdaAtom(key)) { result = m_AtomDict["LambdaFactory"]; } if (result == null && CheckIsCond(key)) { result = m_AtomDict["CondFactory"]; } return(result); } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case SMHD: _atomSMHD = (AtomSMHD)atom; return; case DINF: _atomDINF = (AtomDINF)atom; return; case STBL: _atomSTBL = (AtomSTBL)atom; return; case VMHD: _atomVMHD = (AtomVMHD)atom; return; case HDLR: _atomHDLR = (AtomHdlr)atom; return; } }
public override BaseAtom Run(string list) { // 解析list中的参数 string[] args = GetArgs(list); // 先对args进行绑定,因为可能args中有些东西已经被定义过了 BindingArgs(args); // @TODO: 对SignalsDict进行Signal的BindingValue进行绑定 BindingSignalValue(args); // @TODO:向RuntimeAtomStack注册此Atom Parser.RuntimeAtomStack.RegisterSignals(this); // 将此函数注册到运行时栈中 Parser.RuntimeAtomStack.RegisterAtom(this); // 将所有的templateResult交给具体自类处理 BaseAtom result = this.Handle(); // @TODO:向RuntimeAtomStack取消注册此Atom Parser.RuntimeAtomStack.Unregister(this); return(result); // @TODO:对所有Template用运行时栈进行替换 //BindingTemplateValue(); //Parser.RuntimeAtomStack.RegisterTemplate(this); }
public override Box CreateBox(TexEnvironment environment) { // Create boxes for base, delimeter, and script atoms. var baseBox = BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment); var delimeterBox = DelimiterFactory.CreateBox(Symbol.Name, baseBox.Width, environment); var scriptBox = Script?.CreateBox(Over ? environment.GetSuperscriptStyle() : environment.GetSubscriptStyle()); // Create centered horizontal box if any box is smaller than maximum width. var maxWidth = GetMaxWidth(baseBox, delimeterBox, scriptBox); if (Math.Abs(maxWidth - baseBox.Width) > TexUtilities.FloatPrecision) { baseBox = new HorizontalBox(baseBox, maxWidth, TexAlignment.Center); } if (Math.Abs(maxWidth - delimeterBox.Height - delimeterBox.Depth) > TexUtilities.FloatPrecision) { delimeterBox = new VerticalBox(delimeterBox, maxWidth, TexAlignment.Center); } if (scriptBox != null && Math.Abs(maxWidth - scriptBox.Width) > TexUtilities.FloatPrecision) { scriptBox = new HorizontalBox(scriptBox, maxWidth, TexAlignment.Center); } return(new OverUnderBox(baseBox, delimeterBox, scriptBox, Kern.CreateBox(environment).Height, Over)); }
/// <summary> /// 注册一个BaseAtom中所有(已绑定)参数到运行时原子库栈中 /// </summary> public void RegisterSignals(BaseAtom atom) { Signal[] signals = atom.Signals; foreach (Signal signal in signals) { PushRuntimeSignal(signal); } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case DREF: _atomDREF = (AtomDREF)atom; break; } }
/// <summary> /// 解析所有的已绑定的Template /// </summary> /// <returns></returns> protected BaseAtom[] ParseTemplateAll() { BaseAtom[] results = new BaseAtom[Templates.Length]; for (int i = 0; i < Templates.Length; i++) { results[i] = ParseTemplate(Templates[i]); } return(results); }
/// <summary> /// 注册一个Atom /// </summary> public bool RegisterAtom(string key, BaseAtom atom) { if (ContainKey(key)) { return(false); } m_AtomDict[key] = atom; return(true); }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case AVCC: _atomAVCC = (AtomAVCC) atom; return; } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case AVCC: _atomAVCC = (AtomAVCC)atom; return; } }
public MP4Document Build(Movie movie) { if (Fragmenter == null) { Fragmenter = new TimeBasedFragmenter(); } Track2Sample = movie.Tracks.ToDictionary(x => x, y => y.Samples); Track2SampleSizes = movie.Tracks.ToDictionary(x => x, y => y.Samples.Select(x => x.Size).ToArray()); var meta = Variant.Get(); MP4Document doc = new MP4Document(meta); doc.AddAtom(CreateFileTypeBox(movie)); var chunks = movie.Tracks.ToDictionary(x => x, GetChunkSizes); var moov = CreateMovieBox(movie, chunks); doc.AddAtom(moov); var contentSize = moov.GetPath(TRAK, MDIA, MINF, STBL, STSZ).OfType <AtomSTSZ>().Sum(x => x.SampleSize); var mdat = new AtomMDAT(movie, chunks, contentSize); doc.AddAtom(mdat); /* * dataOffset is where the first sample starts. In this special mdat the samples always start * at offset 16 so that we can use the same offset for large boxes and small boxes */ uint dataOffset = mdat.DataOffset; foreach (var chunkOffsetBox in ChunkOffsetBoxes.Values) { for (var i = 0; i < chunkOffsetBox.Entries.Count; i++) { chunkOffsetBox.Entries[i] += dataOffset; } } foreach (var saio in SampleAuxiliaryInformationOffsetsBoxes) { long offset = saio.Size; // the calculation is systematically wrong by 4, I don't want to debug why. Just a quick correction --san 14.May.13 offset += 4 + 4 + 4 + 4 + 4 + 24; // size of all header we were missing otherwise (moov, trak, mdia, minf, stbl) object b = saio; do { BaseAtom current = (BaseAtom)b; b = current.Parent; offset += ((IBoxContainer)b).SubAtoms.TakeWhile(box => box != current).Sum(box => box.Size); } while (b is BoxAtom); long[] saioOffsets = saio.Offsets; for (int i = 0; i < saioOffsets.Length; i++) { saioOffsets[i] += offset; } } return(doc); }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case HDLR: _atomHDLR = (AtomHdlr) atom; return; case ILST: _atomILST = (AtomILST)atom; return; } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case MP4A: _atomMp4A = atom as AtomMP4A; break; case AVC1: _atomAvc1 = atom as AtomAVC1; break; } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case HDLR: _atomHDLR = (AtomHdlr)atom; return; case ILST: _atomILST = (AtomILST)atom; return; } }
public override Box CreateBox(TexEnvironment environment) { // Create box for base atom. var baseBox = BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment); // Create boxes for over and under atoms. Box overBox = null, underBox = null; var maxWidth = baseBox.Width; if (OverAtom != null) { overBox = OverAtom.CreateBox(OverScriptSmaller ? environment.GetSubscriptStyle() : environment); maxWidth = Math.Max(maxWidth, overBox.Width); } if (UnderAtom != null) { underBox = UnderAtom.CreateBox(UnderScriptSmaller ? environment.GetSubscriptStyle() : environment); maxWidth = Math.Max(maxWidth, underBox.Width); } // Create result box. var resultBox = new VerticalBox(); environment.LastFontId = baseBox.GetLastFontId(); // Create and add box for over atom. if (OverAtom != null) { resultBox.Add(ChangeWidth(overBox, maxWidth)); resultBox.Add(new SpaceAtom(OverSpaceUnit, 0, OverSpace, 0).CreateBox(environment)); } // Add box for base atom. resultBox.Add(ChangeWidth(baseBox, maxWidth)); var totalHeight = resultBox.Height + resultBox.Depth - baseBox.Depth; // Create and add box for under atom. if (UnderAtom != null) { resultBox.Add(new SpaceAtom(OverSpaceUnit, 0, UnderSpace, 0).CreateBox(environment)); resultBox.Add(ChangeWidth(underBox, maxWidth)); } resultBox.Depth = resultBox.Height + resultBox.Depth - totalHeight; resultBox.Height = totalHeight; return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Create box for base atom. var baseBox = BaseAtom.CreateBox(environment); // Create result box. var resultBox = new HorizontalBox(); var axis = texFont.GetAxisHeight(style); var delta = Math.Max(baseBox.Height - axis, baseBox.Depth + axis); var minHeight = Math.Max((delta / 500) * delimeterFactor, 2 * delta - delimeterShortfall); // Create and add box for left delimeter. if (LeftDelimeter != null) { var leftDelimeterBox = DelimiterFactory.CreateBox(LeftDelimeter.Name, minHeight, environment); CentreBox(leftDelimeterBox, axis); resultBox.Add(leftDelimeterBox); } // add glueElement between left delimeter and base Atom, unless base Atom is whitespace. if (!(BaseAtom is SpaceAtom)) { resultBox.Add(Glue.CreateBox(TexAtomType.Opening, BaseAtom.GetLeftType(), environment)); } // add box for base Atom. resultBox.Add(baseBox); // add glueElement between right delimeter and base Atom, unless base Atom is whitespace. if (!(BaseAtom is SpaceAtom)) { resultBox.Add(Glue.CreateBox(BaseAtom.GetRightType(), TexAtomType.Closing, environment)); } // Create and add box for right delimeter. if (RightDelimeter is null) { return(resultBox); } var rightDelimeterBox = DelimiterFactory.CreateBox(RightDelimeter.Name, minHeight, environment); CentreBox(rightDelimeterBox, axis); resultBox.Add(rightDelimeterBox); return(resultBox); }
public void Unregister(BaseAtom atom) { Signal[] signals = atom.Signals; foreach (Signal signal in signals) { PopRuntimeSignal(signal); } m_AtomStack.Pop(); //Template[] templates = atom.Templates; //foreach (Template template in templates) //{ // PopRuntimeTemplate(template); //} }
protected override BaseAtom Handle() { BaseAtom[] templateResults = ParseTemplateAll(); BaseAtom result = null; if (templateResults[0].GetResult().Equals(templateResults[1].GetResult())) { result = Parser.AtomStorage["True"]; } else { result = Parser.AtomStorage["False"]; } return(result); }
public override BaseAtom Run(string list) { // 获取参数 string[] args = base.GetArgs(list); string key = args[0]; string defineFrom = args[1]; BaseAtom defineFromAtom = null; // 调用Parser的解释列表的函数,得到一个原子 defineFromAtom = Parser.ParseAndGetAtom(defineFrom); // 将key值和被定义的原子注册到原子库当中 Parser.AtomStorage.RegisterAtom(key, defineFromAtom); return(this); }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case ESDS: _atomESDS = (AtomESDS)atom; break; case WAVE: _atomWAVE = (AtomWAVE)atom; break; case CHAN: // _atomCHAN = (AtomCHAN)atom; break; } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case MP4A: _atomMp4A = atom as AtomMP4A; return; case ESDS: _atomEsds = atom as AtomESDS; return; case NULL: return; default: return; } }
public override BaseAtom Run(string list) { BaseAtom result = null; string resultToBind = null; string[] args = LispUtil.SplitInAtomAll(list); for (int i = 1; i < args.Length; i++) { // 将每个CondArg交给CondArgsParser处理 CondArgsParser condArgsParser = new CondArgsParser(Parser, args[i]); // 如果CondArgsParser得到的结果是True,说明使用此CondArg的列表 if (condArgsParser.ArgIsTrue) { resultToBind = condArgsParser.ArgResult; break; } } result = Parser.ParseAndGetAtom(resultToBind); return(result); }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case MDHD: _atomMDHD = (AtomMdhd) atom; return; case HDLR: _atomHDLR = (AtomHdlr) atom; return; case MINF: _atomMINF = (AtomMINF) atom; return; case DINF: _atomDINF = (AtomDINF) atom; return; case STBL: _atomSTBL = (AtomSTBL) atom; return; } }
/// <summary> /// 解析得到一个原子 /// </summary> public BaseAtom ParseAndGetAtom(string list) { // 判断list是否为原子,如果是原子,则直接从原子库中获取 if (LispUtil.IsAtom(list)) { // 如果RuntimeAtomStack中有,则先绑定 if (RuntimeAtomStack.IsHaveSignalValue(list)) { list = RuntimeAtomStack.GetSignalValue(list); } BaseAtom atom = AtomStorage[list]; return(atom); } // 否则是列表,则调用对应的原子进行运算 else { list = LispUtil.RemoveBracket(list); string key = LispUtil.SplitInAtom(list); BaseAtom atom = AtomStorage[key]; return(atom.Run(list)); } }
public override void AtomCreated(BaseAtom atom) { switch (atom.Type) { case STSD: _atomSTSD = (AtomSTSD)atom; break; case STTS: _atomSTTS = (AtomSTTS)atom; break; case STSC: _atomSTSC = (AtomSTSC)atom; break; case STSZ: _atomSTSZ = (AtomSTSZ)atom; break; case STCO: _atomSTCO = (AtomSTCO)atom; break; case CO64: _atomCO64 = (AtomCO64)atom; break; case CTTS: _atomCTTS = (AtomCTTS)atom; break; case STSS: _atomSTSS = (AtomSTSS)atom; break; } }
public BaseAtom ReadAtom(IBoxContainer parentAtom) { BaseAtom atom = null; uint type = 0; var currentPos = MediaFile.Position; long size = MediaFile.Br.ReadUInt32(); if (size == 0) { atom = new AtomNULL(this, type, size, currentPos) { Parent = parentAtom }; return(atom); } type = MediaFile.Br.ReadUInt32(); if (size == 1) { size = MediaFile.Br.ReadInt64(); if (size == 0) { atom = new AtomNULL(this, type, size, currentPos) { Parent = parentAtom }; return(atom); } } switch (type) { case FTYP: atom = new AtomFTYP(this, size, currentPos); break; case MOOV: atom = new AtomMOOV(this, type, size, currentPos); break; case MOOF: atom = new AtomMOOF(this, type, size, currentPos); break; case MVEX: atom = new AtomMVEX(this, type, size, currentPos); break; case MVHD: atom = new AtomMVHD(this, type, size, currentPos); break; case MFHD: atom = new AtomMFHD(this, type, size, currentPos); break; case TRAK: atom = new AtomTRAK(this, type, size, currentPos); break; case TRAF: atom = new AtomTRAF(this, type, size, currentPos); break; case TREX: atom = new AtomTREX(this, type, size, currentPos); break; case TRUN: atom = new AtomTRUN(this, type, size, currentPos); break; case TKHD: atom = new AtomTKHD(this, type, size, currentPos); break; case TFHD: atom = new AtomTFHD(this, type, size, currentPos); break; case MDIA: atom = new AtomMDIA(this, type, size, currentPos); break; case MDHD: atom = new AtomMdhd(this, type, size, currentPos); break; case HDLR: atom = new AtomHdlr(this, type, size, currentPos); break; case MINF: atom = new AtomMINF(this, type, size, currentPos); break; case SMHD: atom = new AtomSMHD(this, type, size, currentPos); break; case DINF: atom = new AtomDINF(this, type, size, currentPos); break; case STBL: atom = new AtomSTBL(this, type, size, currentPos); break; case VMHD: atom = new AtomVMHD(this, type, size, currentPos); break; case DREF: atom = new AtomDREF(this, type, size, currentPos); break; case STSD: atom = new AtomSTSD(this, type, size, currentPos); break; case STTS: atom = new AtomSTTS(this, type, size, currentPos); break; case STSC: atom = new AtomSTSC(this, type, size, currentPos); break; case STSZ: atom = new AtomSTSZ(this, type, size, currentPos); break; case STCO: atom = new AtomSTCO(this, type, size, currentPos); break; case CTTS: atom = new AtomCTTS(this, type, size, currentPos); break; case STSS: atom = new AtomSTSS(this, type, size, currentPos); break; case URL: atom = new AtomURL(this, type, size, currentPos); break; case MP4A: atom = new AtomMP4A(this, type, size, currentPos); break; case AVC1: atom = new AtomAVC1(this, type, size, currentPos); break; case ESDS: atom = new AtomESDS(this, type, size, currentPos); break; case AVCC: atom = new AtomAVCC(this, type, size, currentPos); break; case UDTA: atom = new AtomUDTA(this, type, size, currentPos); break; case WAVE: atom = new AtomWAVE(this, type, size, currentPos); break; case META: atom = new AtomMETA(this, type, size, currentPos); break; case NULL: atom = new AtomNULL(this, type, size, currentPos); break; case ILST: atom = new AtomILST(this, type, size, currentPos); break; case DATA: atom = new AtomDATA(this, type, size, currentPos); break; case CO64: atom = new AtomCO64(this, type, size, currentPos); break; case _COM: case NAME: case COVR: case AART: case _WRT: case _GRP: case _LYR: case _NAM: case _ART1: case _ART2: case _PRT: case _TOO: case _DAY: case _CMT: case _CPY: case _DES: case _ALB: case TRKN: case CPIL: case PGAP: case TMPO: case GNRE: case DISK: case _GEN: case DESC: case TVSH: case TVEN: case TVSN: case TVES: atom = new AtomMetaField(this, type, size, currentPos); break; default: { atom = new IgnoredAtom(this, type, size, currentPos); break; } } atom.Parent = parentAtom; atom.Read(); if (currentPos + atom.Size != MediaFile.Position) { FATAL("atom start:{0};Atom Size:{1};currentPostion:{2}", currentPos, atom.Size, MediaFile.Position); } return(atom); }
public void AddAtom(BaseAtom atom) { atom.Document = this; atom.Parent = this; SubAtoms.Add(atom); }
public override TexAtomType GetRightType() => BaseAtom.GetRightType();
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; if ((this.UseVerticalLimits.HasValue && !UseVerticalLimits.Value) || (!this.UseVerticalLimits.HasValue && style >= TexStyle.Text)) { // Attach atoms for limits as scripts. return(new ScriptsAtom(this.BaseAtom, this.LowerLimitAtom, this.UpperLimitAtom).CreateBox(environment)); } // Create box for base atom. Box baseBox; double delta; if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { // Find character of best scale for operator symbol. var opChar = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(opChar)) { opChar = texFont.GetNextLargerCharInfo(opChar, style); } var charBox = new CharBox(environment, opChar); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.MathFont.GetAxisHeight(environment.Style); baseBox = new HorizontalBox(charBox); delta = opChar.Metrics.Italic; if (delta > TexUtilities.FloatPrecision) { baseBox.Add(new StrutBox(delta, 0, 0, 0)); } } else { baseBox = new HorizontalBox(this.BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(environment)); delta = 0; } // Create boxes for upper and lower limits. var upperLimitBox = this.UpperLimitAtom == null ? null : this.UpperLimitAtom.CreateBox( environment.GetSuperscriptStyle()); var lowerLimitBox = this.LowerLimitAtom == null ? null : this.LowerLimitAtom.CreateBox( environment.GetSubscriptStyle()); // Make all component boxes equally wide. var maxWidth = Math.Max(Math.Max(baseBox.Width, upperLimitBox == null ? 0 : upperLimitBox.Width), lowerLimitBox == null ? 0 : lowerLimitBox.Width); if (baseBox != null) { baseBox = ChangeWidth(baseBox, maxWidth); } if (upperLimitBox != null) { upperLimitBox = ChangeWidth(upperLimitBox, maxWidth); } if (lowerLimitBox != null) { lowerLimitBox = ChangeWidth(lowerLimitBox, maxWidth); } var resultBox = new VerticalBox(); var opSpacing5 = texFont.GetBigOpSpacing5(style); var kern = 0d; // Create and add box for upper limit. if (UpperLimitAtom != null) { resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); upperLimitBox.Shift = delta / 2; resultBox.Add(upperLimitBox); kern = Math.Max(texFont.GetBigOpSpacing1(style), texFont.GetBigOpSpacing3(style) - upperLimitBox.Depth); resultBox.Add(new StrutBox(0, kern, 0, 0)); } // Add box for base atom. resultBox.Add(baseBox); // Create and add box for lower limit. if (LowerLimitAtom != null) { resultBox.Add(new StrutBox(0, Math.Max(texFont.GetBigOpSpacing2(style), texFont.GetBigOpSpacing4(style) - lowerLimitBox.Height), 0, 0)); lowerLimitBox.Shift = -delta / 2; resultBox.Add(lowerLimitBox); resultBox.Add(new StrutBox(0, opSpacing5, 0, 0)); } // Adjust height and depth of result box. var baseBoxHeight = baseBox.Height; var totalHeight = resultBox.Height + resultBox.Depth; if (upperLimitBox != null) { baseBoxHeight += opSpacing5 + kern + upperLimitBox.Height + upperLimitBox.Depth; } resultBox.Height = baseBoxHeight; resultBox.Depth = totalHeight - baseBoxHeight; return(resultBox); }
public override Box CreateBox(TexEnvironment environment) { var texFont = environment.TexFont; var style = environment.Style; // Create box for base atom. var baseBox = (BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment)); if (SubscriptAtom is null && SuperscriptAtom is null) { return(baseBox); } // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. var lastFontId = baseBox.GetLastFontId(); if (lastFontId == TexFontUtilities.NoFontId) { lastFontId = texFont.GetMuFontId(); } var subscriptStyle = environment.GetSubscriptStyle(); var superscriptStyle = environment.GetSuperscriptStyle(); // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom. var delta = 0d; double shiftUp, shiftDown; if (BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (BaseAtom is SymbolAtom && BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)BaseAtom).Name, style); if (style < TexStyle.Text && texFont.HasNextLarger(charInfo)) { charInfo = texFont.GetNextLargerCharInfo(charInfo, style); } var charBox = new CharBox(environment, charInfo); charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.TexFont.GetAxisHeight( environment.Style); resultBox = new HorizontalBox(charBox); delta = charInfo.Metrics.Italic; if (delta > TexUtilities.FloatPrecision && SubscriptAtom is null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); } shiftUp = resultBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = resultBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (BaseAtom is CharSymbol) { var charFont = ((CharSymbol)BaseAtom).GetCharFont(texFont); if (!((CharSymbol)BaseAtom).IsTextSymbol || !texFont.HasSpace(charFont.FontId)) { delta = texFont.GetCharInfo(charFont, style).Metrics.Italic; } if (delta > TexUtilities.FloatPrecision && SubscriptAtom is null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); delta = 0; } shiftUp = 0; shiftDown = 0; } else { shiftUp = baseBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = baseBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } Box superscriptBox = null; Box superscriptContainerBox = null; Box subscriptBox = null; Box subscriptContainerBox = null; if (SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = SuperscriptAtom.CreateBox(superscriptStyle); superscriptContainerBox = new HorizontalBox(superscriptBox); // Add box for script space. superscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); // Adjust shift-up amount. double p; if (style == TexStyle.Display) { p = texFont.GetSup1(style); } else if (environment.GetCrampedStyle().Style == style) { p = texFont.GetSup3(style); } else { p = texFont.GetSup2(style); } shiftUp = Math.Max(Math.Max(shiftUp, p), superscriptBox.Depth + Math.Abs(texFont.GetXHeight( style, lastFontId)) / 4); } if (SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = SubscriptAtom.CreateBox(subscriptStyle); subscriptContainerBox = new HorizontalBox(subscriptBox); // Add box for script space. subscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment)); } // Check if only superscript is set. if (subscriptBox is null) { superscriptContainerBox.Shift = -shiftUp; resultBox.Add(superscriptContainerBox); return(resultBox); } // Check if only subscript is set. if (superscriptBox is null) { subscriptBox.Shift = Math.Max(Math.Max(shiftDown, texFont.GetSub1(style)), subscriptBox.Height - 4 * Math.Abs(texFont.GetXHeight(style, lastFontId)) / 5); resultBox.Add(subscriptContainerBox); return(resultBox); } // Adjust shift-down amount. shiftDown = Math.Max(shiftDown, texFont.GetSub2(style)); // Reposition both subscript and superscript. var defaultLineThickness = texFont.GetDefaultLineThickness(style); // Space between subscript and superscript. var scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; if (scriptsInterSpace < 4 * defaultLineThickness) { shiftUp += 4 * defaultLineThickness - scriptsInterSpace; // Position bottom of superscript at least 4/5 of X-height above baseline. var psi = 0.8 * Math.Abs(texFont.GetXHeight(style, lastFontId)) - (shiftUp - superscriptBox.Depth); if (psi > 0) { shiftUp += psi; shiftDown -= psi; } } scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height; // Create box containing both superscript and subscript. var scriptsBox = new VerticalBox(); superscriptContainerBox.Shift = delta; scriptsBox.Add(superscriptContainerBox); scriptsBox.Add(new StrutBox(0, scriptsInterSpace, 0, 0)); scriptsBox.Add(subscriptContainerBox); scriptsBox.Height = shiftUp + superscriptBox.Height; scriptsBox.Depth = shiftDown + subscriptBox.Depth; resultBox.Add(scriptsBox); return(resultBox); }