public override void RenderText(TextRenderInfo renderInfo) { base.RenderText(renderInfo); //GraphicsState gs = (GraphicsState)gsField.GetValue(renderInfo);//expensive??? //Font font = new Font { Name = string.Join(", ", gs.Font.FullFontName[0]), Size = gs.FontSize }; List <CharBox> cbs = new List <CharBox>(); IList <TextRenderInfo> cris = renderInfo.GetCharacterRenderInfos(); foreach (TextRenderInfo cri in cris) { Vector baseLeft = cri.GetBaseline().GetStartPoint(); Vector topRight = cri.GetAscentLine().GetEndPoint(); float x = baseLeft[Vector.I1]; float y = topRight[Vector.I2]; CharBox cb = new CharBox { Char = cri.GetText(), R = new System.Drawing.RectangleF { X = x - pageSize.X, Y = pageSize.Height + pageSize.Y - y,//(!)basic positioning point is char's baseLine, not ascentLine Width = topRight[Vector.I1] - x, Height = y - baseLeft[Vector.I2], }, //Font = font }; cbs.Add(cb); } CharBoxs.AddRange(cbs); }
public static List <Line <CharBoxT> > GetLines <CharBoxT>(IEnumerable <CharBoxT> cbs, TextAutoInsertSpace textAutoInsertSpace) where CharBoxT : CharBox, new() { bool spaceAutoInsert = textAutoInsertSpace != null && textAutoInsertSpace.Threshold > 0; cbs = cbs.OrderBy(a => a.R.X).ToList(); List <Line <CharBoxT> > lines = new List <Line <CharBoxT> >(); foreach (CharBoxT cb in cbs) { for (int i = 0; i < lines.Count; i++) { if (cb.R.Bottom < lines[i].Top) { Line <CharBoxT> l = new Line <CharBoxT> { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Insert(i, l); goto CONTINUE; } if (cb.R.Bottom - cb.R.Height / 2 <= lines[i].Bottom) { if (spaceAutoInsert && /*cb.Char != " " &&*/ lines[i].CharBoxs.Count > 0) { CharBox cb0 = lines[i].CharBoxs[lines[i].CharBoxs.Count - 1]; if (/*cb0.Char != " " && */ cb.R.Left - cb0.R.Right > (/*cb0.R.Width*/ 0.8 / cb0.R.Height + /*cb.R.Width*/ 0.8 / cb.R.Height) * textAutoInsertSpace.Threshold) { float spaceWidth = (cb0.R.Width + cb.R.Width) / 2; int spaceNumber = (int)Math.Ceiling((cb.R.Left - cb0.R.Right) / spaceWidth); for (int j = 0; j < spaceNumber; j++) { lines[i].CharBoxs.Add(new CharBoxT { Char = textAutoInsertSpace.Representative, R = new RectangleF(cb0.R.Right + spaceWidth * j, cb0.R.Y, spaceWidth, cb.R.Height) }); } } } lines[i].CharBoxs.Add(cb); if (lines[i].Top > cb.R.Top) { lines[i].Top = cb.R.Top; } if (lines[i].Bottom < cb.R.Bottom) { lines[i].Bottom = cb.R.Bottom; } goto CONTINUE; } } { Line <CharBoxT> l = new Line <CharBoxT> { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Add(l); } CONTINUE :; } return(lines); }
protected override Box CreateBoxCore(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; try { var charInfo = texFont.GetCharInfo(AlphanumericSymbol, style).Value; var resultBox = new CharBox(environment, charInfo); return(resultBox); } catch (Exception) { try { var charInfo = texFont.GetCharInfo(DefaultAlphanumericSymbol, style).Value; var resultBox = new CharBox(environment, charInfo); return(resultBox); } catch (Exception) { throw new TexParseException($"The symbol \" {AlphanumericSymbol}\" or \" {DefaultAlphanumericSymbol}\" cannot be found in the current math font package."); } } }
public override void UpdateBox() { // 부착하는 박스가 현재 박스와 다를 경우 서로 정보 바꾸기(swap) if (_attachBox != _curBox) { CharBox curLinkBox = _curBox.BoxInfo.LinkedBox; if (_attachBox.BoxInfo != null) { CharBox attachLinkBox = _attachBox.BoxInfo.LinkedBox; attachLinkBox.BoxInfo.LinkedBox = _curBox; attachLinkBox.ContainerColor = _curBox.ContainerColor; } curLinkBox.BoxInfo.LinkedBox = _attachBox; curLinkBox.ContainerColor = _attachBox.ContainerColor; CharBoxInfo tempInfo = _curBox.BoxInfo; _curBox.BoxInfo = _attachBox.BoxInfo; _attachBox.BoxInfo = tempInfo; _curBox.ApplyBoxInfo(); _curBox = _attachBox; UpdateStatus(); } _curBox.ApplyBoxInfo(); _curBox.SwitchOutline(true); }
public void OnEndDrag(PointerEventData eventData) { if (!_cursorImage.isActiveAndEnabled) { return; } TeamSetPanel teamSetPanel = (TeamSetPanel)_panelDic[PanelType.TeamSet]; CharBox attachableBox = teamSetPanel.GetAttachableBox(eventData.position); CursorImage.MoveEndHandler moveEndHandler; Vector2 cursorDestPos; // 팀 편성 박스에 부착 가능 박스 여부에 따른 작업 // 시작 지점이 CharGrid 였을 경우 커서 박스 원위치 // 시작 지점이 TeamSet 였을 경우 커서 박스는 기존 링크됐던 CharGrid의 위치로 돌아감과 동시에 링크 해제 (편성 해제) if (attachableBox != null) { _selectedBox.BoxInfo.LinkedBox = attachableBox; moveEndHandler = new CursorImage.MoveEndHandler(_panelDic[_selectedPanelType].UpdateBox); cursorDestPos = attachableBox.TrRect.center; } else { moveEndHandler = new CursorImage.MoveEndHandler(_panelDic[_selectedPanelType].ReturnBox); cursorDestPos = _panelDic[_selectedPanelType].GetOriginPos(); } moveEndHandler += teamSetPanel.UpdateStatus; _cursorImage.MoveBegin(cursorDestPos, moveEndHandler); }
public void OnPointerDown(PointerEventData eventData) { // 기존에 선택된 박스가 있을 경우 흰색 아웃라인 숨기기 if (_selectedPanelType != PanelType.None) { _showCharProfile.CloseProfile(); SetOutline(false); } // 선택 정보 초기화 _selectedPanelType = PanelType.None; _selectedBox = null; // 선택된 박스 불러오기 foreach (PanelType key in _panelDic.Keys) { _selectedBox = _panelDic[key].GetSelectedBox(eventData.position); if (_selectedBox != null) { _selectedPanelType = key; break; } } if (_selectedPanelType == PanelType.None) { return; } // 선택 박스 존재시 해당 박스의 캐릭터 정보를 우측 상단에 출력 ShowSelectedBox(); }
public string Convert(string s, int numRows) { //如果只有一行 if(numRows==1) return Convert(s); if(numRows>=s.Length)return Convert(s); if(string.IsNullOrEmpty(s)) Convert(s); //如果超过一行 List<CharBox> boxes=new List<CharBox>(); int i=0; while(true) { CharBox box=new CharBox(numRows); while(!box.IsFull()&&i<s.Length) { box.Insert(s[i]); i++; } boxes.Add(box); if(i==s.Length) break; } string res=string.Empty; for(int j=0;j<numRows;j++) { for(int k=0;k<boxes.Count;k++) { res+=boxes[k].GetString(j).Trim(); } } return res; }
public override void RenderText(TextRenderInfo renderInfo) { base.RenderText(renderInfo); List <CharBox> cbs = new List <CharBox>(); IList <TextRenderInfo> cris = renderInfo.GetCharacterRenderInfos(); foreach (TextRenderInfo cri in cris) { Vector baseLeft = cri.GetBaseline().GetStartPoint(); Vector topRight = cri.GetAscentLine().GetEndPoint(); float x = baseLeft[Vector.I1]; float y = topRight[Vector.I2]; CharBox cb = new CharBox { Char = cri.GetText(), R = new System.Drawing.RectangleF { X = x - pageSize.X, Y = pageSize.Height + pageSize.Y - y,//(!)basic positioning point is char's baseLine, not ascentLine Width = topRight[Vector.I1] - x, Height = y - baseLeft[Vector.I2], }, //Font = font, //FontSize = fontSize }; cbs.Add(cb); } CharBoxs.AddRange(cbs); }
private void makePuzzle(char[] alphabet, int puzzleBoxWidth, int boxWidth, int boxHeight, double boxSizeVariance, int minBoxWidth, int minBoxHeight) { alphabet = toss(alphabet); double wvar = boxWidth * boxSizeVariance; double hvar = boxHeight * boxSizeVariance; double wvar2 = wvar / 2d; double hvar2 = hvar / 2d; var x = 1 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); int ybase = (int)hvar + 1; var puzzleWidth = 0; var maxHeight = 0; foreach (var ch in alphabet) { int w = boxWidth + (int)(-wvar2 + (wvar * ExternalRandomGenerator.Instance.NextRandomDouble)); int h = boxHeight + (int)(-hvar2 + (hvar * ExternalRandomGenerator.Instance.NextRandomDouble)); if (w < minBoxWidth) { w = minBoxWidth; } if (h < minBoxHeight) { h = minBoxHeight; } int y = ybase + (int)(-hvar2 + (hvar * ExternalRandomGenerator.Instance.NextRandomDouble)); var cbox = new CharBox(); cbox.Char = ch; cbox.Rect = new Rectangle(x, y, w, h); m_Boxes.Add(cbox); if (cbox.Rect.Bottom - ybase > maxHeight) { maxHeight = cbox.Rect.Bottom - ybase; } puzzleWidth++; if (puzzleWidth == puzzleBoxWidth) { puzzleWidth = 0; ybase += maxHeight + 2; x = 1 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); continue; } x += w + 2 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); } }
public override void ReturnBox() { CharBox linkedBox = _curBox.BoxInfo.LinkedBox; linkedBox.ContainerColor = _baseContainerColor; _curBox.BoxInfo = null; linkedBox.BoxInfo.LinkedBox = null; }
public CharBoxInfo(TeamCharInfo info) { charInfo = info; modelInfo = InfoManager.Instance.modelDic[charInfo.modelID]; charSprite = ResourceManager.Instance.GetSprite(ResourceManager.SpriteType.Models, modelInfo.imgName); levelText = charInfo.level.ToString(); LinkedBox = null; }
public override void EventOccurred(IEventData data, EventType type) { base.EventOccurred(data, type); TextRenderInfo tri = data as TextRenderInfo; //if (type != EventType.RENDER_TEXT) if (tri == null) { return; } PdfFont font = tri.GetFont();//it has been checked that it returns the same font object. float fontSize = Math.Abs/*sometimes it is negative in iText7*/ (tri.GetFontSize()); //if (font.GetAscent("I", fontSize) == 0) // fontSize = 0; List <CharBox> cbs = new List <CharBox>(); IList <TextRenderInfo> cris = tri.GetCharacterRenderInfos(); foreach (TextRenderInfo cri in cris) { Vector baseLeft = cri.GetBaseline().GetStartPoint(); Vector topRight = cri.GetAscentLine().GetEndPoint(); //float rise = cri.GetRise(); //if (rise != 0) // rise = rise; float fontHeightFromBaseLine = topRight.Get(Vector.I2) - baseLeft.Get(Vector.I2); //if (fontSize > 0) //{ // float fontHeightFromBaseLine2 = fontSize * 0.75f/*(?)convertion from PX to PT*/;//!!!this calculation is heuristic and coincides with cri.GetAscentLine().GetEndPoint().Get(Vector.I2) - bottomLeft.Get(Vector.I2) in iText5 // if (fontHeightFromBaseLine > fontHeightFromBaseLine2) // fontHeightFromBaseLine = fontHeightFromBaseLine2; //} float x = baseLeft.Get(Vector.I1); //float y = topRight.Get(Vector.I2); CharBox cb = new CharBox { Char = cri.GetText(), R = new System.Drawing.RectangleF { X = x - pageSize.X, Y = pageSize.Height + pageSize.Y - baseLeft.Get(Vector.I2) - fontHeightFromBaseLine,//(!)basic positioning point is char's baseLine, not ascentLine Width = topRight.Get(Vector.I1) - x, //Height = y - bottomLeft.Get(Vector.I2)// + d, Height = fontHeightFromBaseLine }, Font = font, FontSize = fontSize }; cbs.Add(cb); } CharBoxs.AddRange(cbs); }
// 흰 아웃라인으로 강조하는 부분 제어 public void SetOutline(bool on) { _selectedBox.SwitchOutline(on); CharBox linkedBox = _selectedBox.BoxInfo.LinkedBox; if (linkedBox != null) { linkedBox.SwitchOutline(on); } }
public CharBox GetAttachableBox(Vector2 cursorPos) { for (int i = 0; i < _charBoxList.Count; ++i) { if (_charBoxList[i].IsIn(cursorPos)) { _attachBox = _charBoxList[i]; return(_attachBox); } } return(null); }
public override void UpdateBox() { ReturnBox(); CharBox linkedBox = _curBox.BoxInfo.LinkedBox; // 등록된 팀 컨테이너의 색깔로 현재 박스의 색깔을 바꿔줌 _curBox.ContainerColor = linkedBox.ContainerColor; // 팀 컨테이너에 현재 박스의 정보 넣기 linkedBox.BoxInfo = _curBox.BoxInfo.CopyCharBoxInfo(); linkedBox.BoxInfo.LinkedBox = _curBox; linkedBox.SwitchOutline(true); }
protected override Box __Translate(LetterSym s) { /* TODO: need to handle accent, format */ char c = s.Letter; CharBox cb = new CharBox(s, c, false, (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= 'α' && c <= 'ω') || c == Unicode.G.GREEK_PHI_SYMBOL, Syntax.TType.Ord); if (s.Subscript != new NullExpr()) { return(new AtomBox(null, cb, Translate(s.Subscript), null, Syntax.TType.Ord)); } else { return(cb); } }
public string Convert(string s, int numRows) { //如果只有一行 if (numRows == 1) { return(Convert(s)); } if (numRows >= s.Length) { return(Convert(s)); } if (string.IsNullOrEmpty(s)) { Convert(s); } //如果超过一行 List <CharBox> boxes = new List <CharBox>(); int i = 0; while (true) { CharBox box = new CharBox(numRows); while (!box.IsFull() && i < s.Length) { box.Insert(s[i]); i++; } boxes.Add(box); if (i == s.Length) { break; } } string res = string.Empty; for (int j = 0; j < numRows; j++) { for (int k = 0; k < boxes.Count; k++) { res += boxes[k].GetString(j).Trim(); } } return(res); }
protected override void Init() { base.Init(); Dictionary <int, TeamCharInfo> _teamDic = InfoManager.Instance.teamInfoDic; for (int i = 0; i < _teamDic.Count; ++i) { CharBox charBox = Instantiate(_charBoxPrefab, _tr).GetComponent <CharBox>(); charBox.SetBoxInfo(_teamDic[i + 1]); _charBoxList.Add(charBox); } //남은 칸은 empty 이미지로 채우기 for (int i = 0; i < (_maxBoxCount - _teamDic.Count); ++i) { Instantiate(_emptyImgPrefab, _tr); } }
public CharBox GetSelectedBox(Vector2 cursorPos) { for (int i = 0; i < _charBoxList.Count; ++i) { // 만일 셀의 영역이 지정되지 않았다면(초기) 지정해주기 if (_charBoxList[i].IsRectEmpty()) { _charBoxList[i].SetRect(); } if (_charBoxList[i].IsIn(cursorPos) && _charBoxList[i].BoxInfo != null) { _curBox = _charBoxList[i]; return(_curBox); } } return(null); }
public void OnBeginDrag(PointerEventData eventData) { // 선택된 박스가 없을 경우 드래그 하지 않음 if (_selectedPanelType == PanelType.None) { return; } // 팀 세팅으로 옮겨진 박스는 캐릭터 리스트에서 이동 불가 if (_selectedPanelType == PanelType.CharGrid && _selectedBox.BoxInfo.LinkedBox != null) { return; } _cursorImage.Activate(_selectedBox.BoxInfo.charSprite); _panelDic[_selectedPanelType].DisableBox(); _cursorImage.tr.position = eventData.position; if (_selectedPanelType == PanelType.TeamSet) { _selectedBox = _selectedBox.BoxInfo.LinkedBox; } }
public static List <Line> GetLines(IEnumerable <CharBox> cbs, TextAutoInsertSpace textAutoInsertSpace /*, bool removeDuplicates - no need because input collection is already filtered*/) { //if (removeDuplicates) // cbs = RemoveDuplicates(cbs); bool spaceAutoInsert = textAutoInsertSpace != null && textAutoInsertSpace.Threshold > 0; cbs = cbs.OrderBy(a => a.R.X).ToList(); List <Line> lines = new List <Line>(); foreach (CharBox cb in cbs) { for (int i = 0; i < lines.Count; i++) { if (cb.R.Bottom < lines[i].Top) { Line l = new Line { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Insert(i, l); goto CONTINUE; } if (cb.R.Bottom - cb.R.Height / 2 <= lines[i].Bottom) { if (spaceAutoInsert && /*cb.Char != " " &&*/ lines[i].CharBoxs.Count > 0) { CharBox cb0 = lines[i].CharBoxs[lines[i].CharBoxs.Count - 1]; if (/*cb0.Char != " " && */ cb.R.Left - cb0.R.Right > (cb.R.Width + cb.R.Height) / textAutoInsertSpace.Threshold) { float spaceWidth = (cb.R.Width + cb.R.Width) / 2; int spaceNumber = (int)Math.Ceiling((cb.R.Left - cb0.R.Right) / spaceWidth); for (int j = 0; j < spaceNumber; j++) { lines[i].CharBoxs.Add(new CharBox { Char = textAutoInsertSpace.Representative, R = new System.Drawing.RectangleF(cb.R.Left + spaceWidth * j, 0, 0, 0) }); } } } lines[i].CharBoxs.Add(cb); if (lines[i].Top > cb.R.Top) { lines[i].Top = cb.R.Top; } if (lines[i].Bottom < cb.R.Bottom) { lines[i].Bottom = cb.R.Bottom; } goto CONTINUE; } } { Line l = new Line { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Add(l); } CONTINUE :; } return(lines); }
protected override Box CreateBoxCore(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; // Create box for base atom. var baseBox = this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment); if (this.SubscriptAtom == null && this.SuperscriptAtom == null) { if (baseBox is CharBox) { // This situation should only happen when CreateBox called on a temporary ScriptsAtom created from // BigOperatorAtom.CreateBox. The CharBox's Shift should then be fixed up. baseBox.Shift = -(baseBox.Height + baseBox.Depth) / 2 - environment.MathFont.GetAxisHeight(environment.Style); } return(baseBox); } // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. int 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 (this.BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)this.BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style).Value; 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.MathFont.GetAxisHeight( environment.Style); resultBox = new HorizontalBox(charBox); delta = charInfo.Metrics.Italic; if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == 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 (this.BaseAtom is CharSymbol charSymbol) { var charFont = charSymbol.GetCharFont(texFont).Value; if (!charSymbol.IsTextSymbol || !texFont.HasSpace(charFont.FontId)) { delta = texFont.GetCharInfo(charFont, style).Value.Metrics.Italic; } if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == 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 (this.SuperscriptAtom != null) { // Create box for superscript atom. superscriptBox = this.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 (this.SubscriptAtom != null) { // Create box for subscript atom. subscriptBox = this.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 == null) { superscriptContainerBox.Shift = -shiftUp; resultBox.Add(superscriptContainerBox); return(resultBox); } // Check if only subscript is set. if (superscriptBox == null) { subscriptContainerBox.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. double defaultLineThickness = texFont.GetDefaultLineThickness(style); // Space between subscript and superscript. double 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. double 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); }
public static Box CreateBox(string symbol, double minHeight, TexEnvironment environment, SourceSpan source = null) { var texFont = environment.MathFont; var style = environment.Style; var charInfo = texFont.GetCharInfo(symbol, style).Value; // Find first version of character that has at least minimum height. var metrics = charInfo.Metrics; var totalHeight = metrics.Height + metrics.Depth; while (totalHeight < minHeight && texFont.HasNextLarger(charInfo)) { charInfo = texFont.GetNextLargerCharInfo(charInfo, style); metrics = charInfo.Metrics; totalHeight = metrics.Height + metrics.Depth; } if (totalHeight >= minHeight) { // Character of sufficient height was found. return(new CharBox(environment, charInfo)); } else if (texFont.IsExtensionChar(charInfo)) { var resultBox = new VerticalBox() { Source = source }; // Construct box from extension character. var extension = texFont.GetExtension(charInfo, style); if (extension.Top != null) { resultBox.Add(new CharBox(environment, extension.Top) { Source = source }); } if (extension.Middle != null) { resultBox.Add(new CharBox(environment, extension.Middle) { Source = source }); } if (extension.Bottom != null) { resultBox.Add(new CharBox(environment, extension.Bottom) { Source = source }); } // Insert repeatable part multiple times until box is high enough. var repeatBox = new CharBox(environment, extension.Repeat) { Source = source }; do { if (extension.Top != null && extension.Bottom != null) { resultBox.Add(1, repeatBox); if (extension.Middle != null) { resultBox.Add(resultBox.Children.Count - 1, repeatBox); } } else if (extension.Bottom != null) { resultBox.Add(0, repeatBox); } else { resultBox.Add(repeatBox); } } while (resultBox.Height + resultBox.Depth < minHeight); return(resultBox); } else { // No extensions available, so use tallest available version of character. return(new CharBox(environment, charInfo) { Source = source }); } }
public static List <Line <CharBoxT> > GetLines <CharBoxT>(IEnumerable <CharBoxT> cbs, TextAutoInsertSpace textAutoInsertSpace, CharFilter charFilter) where CharBoxT : CharBox, new() { if (textAutoInsertSpace?.IgnoreSourceSpaces == true) { cbs = cbs.Where(a => a.Char != " "); } if (charFilter != null)//to filter out wrong OCR chars like borders etc which brakes lines { //SizeF s=new SizeF(ignoreCharsBiggerThan.Width*Settings.Constants.Pdf2ImageResolutionRatio) float maxWidth = charFilter.MaxWidth <= 0 ? float.MaxValue : charFilter.MaxWidth; float maxHeight = charFilter.MaxHeight <= 0 ? float.MaxValue : charFilter.MaxHeight; cbs = cbs.Where(a => a.R.Width >= charFilter.MinWidth && a.R.Width <= maxWidth && a.R.Height >= charFilter.MinHeight && a.R.Height <= maxHeight); } List <Line <CharBoxT> > lines = new List <Line <CharBoxT> >(); foreach (CharBoxT cb in cbs) { for (int i = 0; i < lines.Count; i++) { float mY = cb.R.Bottom - cb.R.Height / 2; if (mY < lines[i].Top) { Line <CharBoxT> l = new Line <CharBoxT> { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Insert(i, l); goto NEXT_CHAR; } if (mY <= lines[i].Bottom)//the char's center is in the line { lines[i].CharBoxs.Add(cb); if (lines[i].Top > cb.R.Top) { lines[i].Top = cb.R.Top; } if (lines[i].Bottom < cb.R.Bottom) { lines[i].Bottom = cb.R.Bottom; } goto NEXT_CHAR; } } { Line <CharBoxT> l = new Line <CharBoxT> { Top = cb.R.Top, Bottom = cb.R.Bottom }; l.CharBoxs.Add(cb); lines.Add(l); } NEXT_CHAR :; } for (int i = 1; i < lines.Count; i++) { float intersectionH2 = (lines[i - 1].Bottom - lines[i].Top) * 2; if (intersectionH2 > lines[i - 1].Height || intersectionH2 > lines[i].Height) { lines[i - 1].CharBoxs.AddRange(lines[i].CharBoxs); if (lines[i - 1].Top > lines[i].Top) { lines[i - 1].Top = lines[i].Top; } if (lines[i - 1].Bottom < lines[i].Bottom) { lines[i - 1].Bottom = lines[i].Bottom; } lines.RemoveAt(i); i--; } } lines.ForEach(a => a.CharBoxs = a.CharBoxs.OrderBy(b => b.R.X).ToList()); if (textAutoInsertSpace?.Threshold > 0) { foreach (Line <CharBoxT> l in lines) { for (int i = 1; i < l.CharBoxs.Count; i++) { CharBox cb0 = l.CharBoxs[i - 1]; CharBox cb = l.CharBoxs[i]; if (/*cb0.Char != " " && */ cb.R.Left - cb0.R.Right > (/*cb0.R.Width*/ 0.8 / cb0.R.Height + /*cb.R.Width*/ 0.8 / cb.R.Height) * textAutoInsertSpace.Threshold) { float spaceWidth = (cb0.R.Width + cb.R.Width) / 2; int spaceNumber = (int)Math.Ceiling((cb.R.Left - cb0.R.Right) / spaceWidth); for (int j = 0; j < spaceNumber; j++) { l.CharBoxs.Insert(i, new CharBoxT { Char = textAutoInsertSpace.Representative, R = new RectangleF(cb0.R.Right + spaceWidth * j, cb0.R.Y, spaceWidth, cb.R.Height) }); } i += spaceNumber; } } } } return(lines); }
private void ConsiderPairSpacing() { if (A == null || B == null) { return; } Box a = A.Final.Target; Box b = B.Final.Target; /* Do TeX atom type and spacing fixup rules from p 170 and appendix G */ Syntax.TType atype = GetTType(a), btype = GetTType(b); /* rule 20 */ int spacing = IBSpacing[(int)atype, (int)btype]; Trace.Assert(spacing != 5); Box space = null; switch (spacing) { case 0: // all the code for this case is *not* part of TeX's rule 20. It comes from p 169 and applies specifically to factorial // operators, so won't be correct for other possible uses of '!' if (atype == Syntax.TType.Ord && a is CharBox && ((CharBox)a).C == '!') { CharBox cb = b as CharBox; StringBox sb = b as StringBox; AtomBox ab = b as AtomBox; if ((btype == Syntax.TType.Ord && ((cb != null && (Char.IsLetter(cb.C) || Char.IsDigit(cb.C))) || (sb != null && (Char.IsLetter(sb.S, 0) || Char.IsDigit(sb.S, 0))))) || btype == Syntax.TType.Open) { space = ThinSkip(); } else if (btype == Syntax.TType.Ord && ab != null) { cb = ab.Nucleus as CharBox; sb = ab.Nucleus as StringBox; if ((cb != null && (Char.IsLetter(cb.C) || Char.IsDigit(cb.C))) || (sb != null && (Char.IsLetter(sb.S, 0) || Char.IsDigit(sb.S, 0)))) { space = ThinSkip(); } } } break; case 1: space = ThinSkip(); break; case 2: space = MedSkip(); break; case 3: space = ThickSkip(); break; case -1: space = DTThinSkip(); break; case -2: space = DTMedSkip(); break; case -3: space = DTThickSkip(); break; } /* apply the spacing */ if (space != null) { /* Find the lowest common ancestor */ int found = -1; for (int i = 0; i < A.P.Count && i < B.P.Count; i++) { if (A.P[i].Target != B.P[i].Target) { found = i; break; } } Trace.Assert(found != -1, "adjacent boxes are the same?"); Trace.Assert(A.P[found].B == B.P[found].B); Trace.Assert(A.P[found].GetType() == B.P[found].GetType()); List <Box> boxes; int ix; if (A.P[found] is HBoxLink) { HBoxLink hba = (HBoxLink)A.P[found]; HBoxLink hbb = (HBoxLink)B.P[found]; Trace.Assert(hba.I < hbb.I); for (int i = hba.I + 1; i < hbb.I; i++) { Trace.Assert(hba.HB.Boxes[i] is MuSkipBox || hba.HB.Boxes[i] is DTMuSkipBox); } boxes = hba.HB.Boxes; ix = hbb.I; } else { DelimitedBoxLink dba = (DelimitedBoxLink)A.P[found]; DelimitedBoxLink dbb = (DelimitedBoxLink)B.P[found]; boxes = dba.DB.Contents.Boxes; if (dba.Piece == DelimitedBoxLink.Which.Left) { Trace.Assert(dbb.Piece != DelimitedBoxLink.Which.Left); ix = 0; } else { Trace.Assert(dba.Piece == DelimitedBoxLink.Which.Contents); Trace.Assert(dbb.Piece == DelimitedBoxLink.Which.Right); ix = boxes.Count; } } SortedDictionary <int, Box> inserts; if (!_listBoxInserts.TryGetValue(boxes, out inserts)) { inserts = new SortedDictionary <int, Box>(); _listBoxInserts[boxes] = inserts; } inserts.Add(ix, space); } }
public override Box CreateBox() { return(CharBox.Get(Character)); }
public override Box CreateBox(TexStyle style) { return(CharBox.Get(style, TEXPreference.main.GetCharMetric(Character, style))); }
public static void Main(string[] args) { if (args.Length == 0) { args = new string[] { "FreeSerifBold24pt7b.h" } } ; Byte[] bmp; Int32[] descr; int chars; using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read)) { using (StreamReader sr = new StreamReader(fs)) { string file; file = sr.ReadToEnd(); int startPos, endPos; startPos = file.IndexOf("{"); endPos = file.IndexOf("}", startPos); string bytes = file.Substring(startPos + 1, endPos - startPos - 1); file = file.Substring(endPos + 1); bmp = readHexs(bytes); startPos = file.IndexOf("{"); bytes = file.Substring(startPos + 1); descr = readInts(bytes); chars = descr.Length / 6; sr.Close(); } fs.Close(); } string charData, font = ""; int bitSize, fontBitSize = 0, fixedSize = 0, dynamicSize = 0, GFXsize = 0, blockSize = 0; int maxW = 0, maxH = 0, mixedDifference = 0; for (int i = 0; i < chars - 1; i++) { if (descr[(i * 6) + 1] > maxW) { maxW = descr[(i * 6) + 1]; } if (descr[(i * 6) + 2] > maxH) { maxH = descr[(i * 6) + 2]; } } //int zeros = 0, zerosHalf = 0; int shortest = 20, longest = 0; for (int i = 0; i < chars - 1; i++) { CharBox b = new CharBox(bmp, descr, i); string[] dataRows = GFX2ASCII(bmp, descr, i); if (dataRows == null) { bitSize = 0; } else { bitSize = string.Join("", dataRows).Length; } if ((bitSize & 7) > 0) { bitSize += 8 - (bitSize & 7); } fontBitSize += bitSize; //bitSize = b.getFixedBitSize(maxW, maxH); //bitSize = b.getGFXbitSize(); b.Xor(); // if(b.box != null) { // zeros += b.countZeros(b.getGFXmap()); // 4111 // zerosHalf += b.countHalfByte(); // 5171 // } string[] dataRowsX = b.getASCII(); if (b.box != null) { String sizes = ""; int min = int.MaxValue, minpos = 99; for (int j = 1; j < descr[(i * 6) + 1] * descr[(i * 6) + 2]; j++) { int len = b.encode(j).Length; sizes += j + "-" + len + "/"; if ((len % 8) > 0) { len = 1 + (len / 8); } else { len /= 8; } if (min > len) { min = len; minpos = j; } sizes += len + " "; } if (shortest > minpos) { shortest = minpos; } if (longest < minpos) { longest = minpos; } blockSize += min; bitSize = b.getFixedBitSize(-1, -1, false); int commonSize = bitSize; font += b.box[0].Width + "x" + b.box.Length + " byte width size:" + bitSize; dynamicSize += bitSize; bitSize = b.getFixedBitSize(maxW, maxH, false); /*b.UnXor(); * CharBox bR = new CharBox(b); * b.Xor(); * bR.Xor(); * bitSize = bR.getFixedBitSize(-1,-1);*/ font += " block size (" + minpos + "):" + min; font += " arithmetic size:" + bitSize; fixedSize += bitSize; bitSize = b.getGFXbitSize(); font += " GFX size:" + bitSize; GFXsize += bitSize; if (bitSize - commonSize > 0) { mixedDifference += bitSize - commonSize; } // if(b.setSquareMode()) { // int bitSizeSq = b.getGFXbitSize(); // if(bitSizeSq < bitSize) { // bitSize = bitSizeSq; // font += " GFX square size:" + bitSize; // descr[i*6] = 0; // reset char pos // CharBox bSquare = new CharBox(b.getGFXmap(), descr, i); // string[] dataRowsXsq = bSquare.getASCII(); // for(int y=0;y<dataRowsX.Length;y++) dataRowsX[y] += "||" + dataRowsXsq[y]; // } // } charData = ""; if (dataRows != null) { for (int idx = 0; idx < dataRows.Length - 1; idx++) { charData += dataRows[idx] + "|" + dataRowsX[idx] + Environment.NewLine; } } charData += sizes + Environment.NewLine; charData += b.decodeStringStream(b.getPackedStream(b.box[0].Width, b.box.Length, false)); //GFXsquareSize += bitSize; font += Environment.NewLine + charData + Environment.NewLine; } } //CharBox.maxZeros; font += "Chars: " + chars + " bits: " + fontBitSize + Environment.NewLine + "Max X * Y: " + maxW + "x" + maxH + " bits " + maxW * maxH * chars + " " + Perc(fontBitSize, maxW * maxH * chars) + "% of fixed" + Environment.NewLine + "Byte width xored data size:" + dynamicSize + " fixed(" + maxW + "," + maxH + "):" + fixedSize + " GFX size: " + GFXsize + //" GFX square size: " + GFXsquareSize + " of " + bmp.Length + " => " + Perc(dynamicSize, bmp.Length) + "% " + Perc(fixedSize, bmp.Length) + "% " + Perc(GFXsize, bmp.Length) + "% " + Perc(blockSize, bmp.Length) + "% (" + shortest + "-" + longest + " " + blockSize + ")" ; using (FileStream fs = new FileStream(args[0].Substring(0, args[0].Length - 4) + ".txt", FileMode.Create, FileAccess.Write)) { using (StreamWriter sw = new StreamWriter(fs)) { sw.Write(font); } fs.Close(); } }
protected override Box CreateBoxCore(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; if ((this.UseVerticalLimits.HasValue && !this.UseVerticalLimits.Value) || (!this.UseVerticalLimits.HasValue && style >= TexStyle.Text)) { // Attach atoms for limits as scripts. return(new ScriptsAtom(this.Source, 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).Value; if (style < TexStyle.Text && texFont.HasNextLarger(opChar)) { opChar = texFont.GetNextLargerCharInfo(opChar, style); } var charBox = new CharBox(environment, opChar) { Source = this.BaseAtom.Source }; 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 : this.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 (this.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 (this.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); }
private void makePuzzle(char[] alphabet, int puzzleBoxWidth, int boxWidth, int boxHeight, double boxSizeVariance, int minBoxWidth, int minBoxHeight) { alphabet = toss(alphabet); double wvar = boxWidth * boxSizeVariance; double hvar = boxHeight * boxSizeVariance; double wvar2 = wvar / 2d; double hvar2 = hvar / 2d; var x = 1 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); int ybase = (int)hvar + 1; var puzzleWidth = 0; var maxHeight = 0; foreach(var ch in alphabet) { int w = boxWidth + (int)(-wvar2 + (wvar * ExternalRandomGenerator.Instance.NextRandomDouble)); int h = boxHeight + (int)(-hvar2 + (hvar * ExternalRandomGenerator.Instance.NextRandomDouble)); if (w<minBoxWidth) w = minBoxWidth; if (h<minBoxHeight) h = minBoxHeight; int y = ybase + (int)(-hvar2 + (hvar * ExternalRandomGenerator.Instance.NextRandomDouble)); var cbox = new CharBox(); cbox.Char = ch; cbox.Rect = new Rectangle(x, y, w, h); m_Boxes.Add(cbox); if(cbox.Rect.Bottom-ybase>maxHeight) { maxHeight = cbox.Rect.Bottom-ybase; } puzzleWidth++; if (puzzleWidth==puzzleBoxWidth) { puzzleWidth = 0; ybase += maxHeight + 2; x = 1 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); continue; } x+= w + 2 + (int)(wvar2 * ExternalRandomGenerator.Instance.NextRandomDouble); } }
protected override Box CreateBoxCore(TexEnvironment environment) { CharSymbol GetBaseChar() { var baseAtom = this.BaseAtom; while (baseAtom is AccentedAtom a) { baseAtom = a.BaseAtom; } return(baseAtom as CharSymbol); } var texFont = environment.MathFont; var style = environment.Style; // Create box for base atom. var baseBox = this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment.GetCrampedStyle()); var baseCharFont = GetBaseChar()?.GetCharFont(texFont).Value; var skew = baseCharFont == null ? 0.0 : texFont.GetSkew(baseCharFont, style); // Find character of best scale for accent symbol. var accentChar = texFont.GetCharInfo(this.AccentAtom.Name, style).Value; while (texFont.HasNextLarger(accentChar)) { var nextLargerChar = texFont.GetNextLargerCharInfo(accentChar, style); if (nextLargerChar.Metrics.Width > baseBox.Width) { break; } accentChar = nextLargerChar; } var resultBox = new VerticalBox(); // Create and add box for accent symbol. Box accentBox; var accentItalicWidth = accentChar.Metrics.Italic; if (accentItalicWidth > TexUtilities.FloatPrecision) { accentBox = new HorizontalBox(new CharBox(environment, accentChar)); accentBox.Add(new StrutBox(accentItalicWidth, 0, 0, 0)); } else { accentBox = new CharBox(environment, accentChar); } resultBox.Add(accentBox); var delta = Math.Min(baseBox.Height, texFont.GetXHeight(style, accentChar.FontId)); resultBox.Add(new StrutBox(0, -delta, 0, 0)); // Centre and add box for base atom. Centre base box and accent box with respect to each other. var boxWidthsDiff = (baseBox.Width - accentBox.Width) / 2; accentBox.Shift = skew + Math.Max(boxWidthsDiff, 0); if (boxWidthsDiff < 0) { baseBox = new HorizontalBox(baseBox, accentBox.Width, TexAlignment.Center); } resultBox.Add(baseBox); // Adjust height and depth of result box. var depth = baseBox.Depth; var totalHeight = resultBox.Height + resultBox.Depth; resultBox.Depth = depth; resultBox.Height = totalHeight - depth; return(resultBox); }
protected override Box CreateBoxCore(TexEnvironment environment) { var texFont = environment.MathFont; var style = environment.Style; // Create box for base atom. var baseBox = this.BaseAtom == null ? StrutBox.Empty : this.BaseAtom.CreateBox(environment); if (this.SubscriptAtom == null && this.SuperscriptAtom == null) { if (baseBox is CharBox) { // This situation should only happen when CreateBox called on a temporary ScriptsAtom created from // BigOperatorAtom.CreateBox. The CharBox's Shift should then be fixed up. baseBox.Shift = -(baseBox.Height + baseBox.Depth) / 2 - environment.MathFont.GetAxisHeight(environment.Style); } return(baseBox); } // Create result box. var resultBox = new HorizontalBox(baseBox); // Get last font used or default Mu font. int 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 (this.BaseAtom is AccentedAtom) { var accentedBox = ((AccentedAtom)this.BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle()); shiftUp = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style); shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style); } else if (this.BaseAtom is SymbolAtom && this.BaseAtom.Type == TexAtomType.BigOperator) { var charInfo = texFont.GetCharInfo(((SymbolAtom)this.BaseAtom).Name, style).Value; 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.MathFont.GetAxisHeight( environment.Style); resultBox = new HorizontalBox(charBox); delta = charInfo.Metrics.Italic; if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == 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 (this.BaseAtom is CharSymbol charSymbol && charSymbol.IsSupportedByFont(texFont, style)) { var charFont = charSymbol.GetCharFont(texFont).Value; if (!charSymbol.IsTextSymbol || !texFont.HasSpace(charFont.FontId)) { delta = texFont.GetCharInfo(charFont, style).Value.Metrics.Italic; } if (delta > TexUtilities.FloatPrecision && this.SubscriptAtom == null) { resultBox.Add(new StrutBox(delta, 0, 0, 0)); delta = 0; } shiftUp = 0; shiftDown = 0; }