Box CreateTestBox1(string text = null, float fontSize = 20) { HorizontalStackBox hbox = new HorizontalStackBox(); //hbox.SetBounds(20, 20, 100, 21); // if (text != null) { LoadFont(); int length = text.Length; char[] ch = text.ToCharArray(); float font_size_in_Point = fontSize; _glyphMeshStore.SetFont(_latinModernMathFont, font_size_in_Point);//20= font size _glyphMeshStore.FlipGlyphUpward = true; float px_scale = _latinModernMathFont.CalculateScaleToPixelFromPointSize(font_size_in_Point); for (int i = 0; i < length; ++i) { ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)ch[i]); ushort advW = _latinModernMathFont.GetAdvanceWidthFromGlyphIndex(glyphIndex);//unscale glyph width var t = _latinModernMathFont.GetGlyph(glyphIndex); //now scale it to specific font size int advW_s = (int)System.Math.Round(px_scale * advW); GlyphBox b1 = NewGlyphBox(); b1.Character = ch[i]; b1.GlyphIndex = glyphIndex; b1.AdvanceWidthScale = advW_s; //b1.SetBounds(0, 0, 10, fontSize*2); if (b1 is VxsGlyphBox vxsGlyphBox) { vxsGlyphBox.GlyphVxs = _glyphMeshStore.GetGlyphMesh(glyphIndex); } hbox.AddChild(b1); }//*/ } else { for (int i = 0; i < 5; ++i) { GlyphBox b1 = NewGlyphBox(); b1.SetBounds(0, 0, 10, 20); hbox.AddChild(b1); } } hbox.Layout(); return(hbox); }
Box CreateTestBox4() { VerticalStackBox vbox1 = new VerticalStackBox(); vbox1.AddChild(CreateTestBox3()); vbox1.AddChild(CreateTestBox3()); vbox1.Layout(); GlyphBox h_sepBar = NewGlyphBox(); h_sepBar.SetSize(vbox1.Width, 5); vbox1.Insert(1, h_sepBar); vbox1.Layout(); return(vbox1); }
protected override void SetGlyphVxs(GlyphBox glyphBox, Typeface typeface, float sizeInPoint) { if (glyphBox is VxsGlyphBox vxsGlyphBox) { _glyphMeshStore.SetFont(typeface, sizeInPoint);//20= font size _glyphMeshStore.FlipGlyphUpward = true; if (glyphBox.IsItalic) { _glyphMeshStore.SimulateOblique = glyphBox.IsItalic; } vxsGlyphBox.GlyphVxs = _glyphMeshStore.GetGlyphMesh(glyphBox.GlyphIndex); if (_glyphMeshStore.SimulateOblique) { _glyphMeshStore.SimulateOblique = false; } } }
void AssignGlyphVxs(GlyphBox glyphBox, float fontSize = 20) { LoadFont(); float font_size_in_Point = fontSize; char ch = glyphBox.Character; _glyphMeshStore.SetFont(_latinModernMathFont, font_size_in_Point);//20= font size _glyphMeshStore.FlipGlyphUpward = true; float px_scale = _latinModernMathFont.CalculateScaleToPixelFromPointSize(font_size_in_Point); ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)ch); ushort advW = _latinModernMathFont.GetAdvanceWidthFromGlyphIndex(glyphIndex);//unscale glyph width //now scale it to specific font size int advW_s = (int)System.Math.Round(px_scale * advW); glyphBox.GlyphIndex = glyphIndex; glyphBox.AdvanceWidthScale = advW_s; if (glyphBox is VxsGlyphBox vxsGlyphBox) { vxsGlyphBox.GlyphVxs = _glyphMeshStore.GetGlyphMesh(glyphIndex); } }
Box CreateTestBox5() { HorizontalStackBox hbox = new HorizontalStackBox(); hbox.SetLocation(50, 50); hbox.AddChild(CreateTestBox4()); hbox.AddChild(CreateTestBox4_1()); hbox.Layout(); float height = hbox.Height;//set height to cover all blog GlyphBox openBar = NewGlyphBox(); openBar.SetSize(5, height); hbox.Insert(0, openBar); GlyphBox verticalBar2 = NewGlyphBox(); verticalBar2.SetSize(5, height); hbox.AddChild(verticalBar2);//add last hbox.Layout(); return(hbox); }
protected override void CreateCustomNotation(EncloseNotation notation, float thickness, float w, float h, HorizontalStackBox hbox, float maxLeft, float maxTop, float extend, float over, EncloseBox encloseBox) { //notations that only custom lines using (Tools.BorrowVxs(out VertexStore vsx1, out VertexStore vsx2)) using (Tools.BorrowStroke(out Stroke stroke)) using (Tools.BorrowPathWriter(vsx1, out PathWriter pathWriter)) { var customVsxBox = new MyCustomNotationVsxBox(); stroke.LineJoin = LineJoin.Bevel; stroke.Width = thickness; int useVxs = 1;//default = vxs1 switch (notation) { default: useVxs = 0;//not match only lines notation break; case EncloseNotation.actuarial: pathWriter.MoveTo(0, 0); pathWriter.LineTo(w, 0); pathWriter.LineTo(w, h); break; case EncloseNotation.box: pathWriter.MoveTo(0, 0); pathWriter.LineTo(0, h); pathWriter.LineTo(w, h); pathWriter.LineTo(w, 0); pathWriter.LineTo(0, 0); break; case EncloseNotation.left: pathWriter.MoveTo(0, 0); pathWriter.LineTo(0, h); break; case EncloseNotation.right: pathWriter.MoveTo(w, 0); pathWriter.LineTo(w, h); break; case EncloseNotation.top: pathWriter.MoveTo(0, 0); pathWriter.LineTo(w, 0); break; case EncloseNotation.bottom: pathWriter.MoveTo(0, h); pathWriter.LineTo(w, h); break; case EncloseNotation.updiagonalstrike: pathWriter.MoveTo(0, h); pathWriter.LineTo(w, 0); break; case EncloseNotation.downdiagonalstrike: pathWriter.MoveTo(0, 0); pathWriter.LineTo(w, h); break; case EncloseNotation.verticalstrike: pathWriter.MoveTo(w / 2f, 0); pathWriter.LineTo(w / 2f, h); break; case EncloseNotation.horizontalstrike: pathWriter.MoveTo(0, h / 2f); pathWriter.LineTo(w, h / 2f); break; case EncloseNotation.madruwb: pathWriter.MoveTo(w, 0); pathWriter.LineTo(w, h); pathWriter.LineTo(0, h); break; case EncloseNotation.updiagonalarrow: double arrowAngleDegree = Math.Atan(h / w) * 180.0 / Math.PI; double arrowLength = Math.Sqrt(Math.Pow(h, 2) + Math.Pow(w, 2));//pythagoras float arrowWing = GetPixelScale() * 150; pathWriter.MoveTo(0, 0); pathWriter.LineTo(arrowLength, 0); pathWriter.LineTo(arrowLength - arrowWing, -arrowWing); pathWriter.LineTo(arrowLength - arrowWing, arrowWing); pathWriter.LineTo(arrowLength, 0); AffineMat mat = AffineMat.Iden(); mat.RotateDeg(-arrowAngleDegree); mat.Translate(0, h); mat.TransformToVxs(vsx1, vsx2); useVxs = 2; break; case EncloseNotation.phasorangle: float angleWidth = 640 * GetPixelScale(); //x 637.5 float angleHeight = 1160 * GetPixelScale(); //y 1162.5 float shiftH = h - angleHeight; pathWriter.MoveTo(angleWidth, shiftH); pathWriter.LineTo(0, angleHeight + shiftH); pathWriter.LineTo(maxLeft - angleWidth + w, angleHeight + shiftH); customVsxBox.BeforeBaseBox = angleWidth; break; case EncloseNotation.longdiv: GlyphBox ldiv = NewGlyphBox(); ldiv.Character = ')'; AssignGlyphVxs(ldiv); ldiv.Layout(); Box actualDiv = StretchHeightIfStretchable(ldiv, hbox.Height + over); actualDiv.Layout(); customVsxBox.NotationBox = actualDiv; float shiftLeft = maxLeft - actualDiv.Width; float shiftTop = maxTop - over; actualDiv.SetLocation(shiftLeft, -shiftTop - over); pathWriter.MoveTo(shiftLeft, shiftTop); pathWriter.LineTo(shiftLeft + hbox.Width + actualDiv.Width + extend, shiftTop); pathWriter.Stop(); customVsxBox.BeforeBaseBox = actualDiv.Width + extend; break; case EncloseNotation.radical: GlyphBox radical = NewGlyphBox(); radical.Character = (char)0x221A; AssignGlyphVxs(radical); radical.Layout(); Box actualRadical = StretchHeightIfStretchable(radical, hbox.Height + over); actualRadical.Layout(); float shiftLeft1 = maxLeft - actualRadical.Width; float shiftTop1 = maxTop - over; actualRadical.SetLocation(shiftLeft1, -shiftTop1 - over); customVsxBox.NotationBox = actualRadical; pathWriter.MoveTo(shiftLeft1 + actualRadical.Width, shiftTop1); pathWriter.LineTo(shiftLeft1 + actualRadical.Width + hbox.Width + extend, shiftTop1); pathWriter.Stop(); customVsxBox.BeforeBaseBox = actualRadical.Width + extend; break; case EncloseNotation.roundedbox: using (Tools.BorrowRoundedRect(out var roundedRect)) { roundedRect.SetRadius(over, over, over, over, over, over, over, over); roundedRect.SetRect(0, 0, w, h); roundedRect.MakeVxs(vsx1); customVsxBox.CustomVxs = stroke.CreateTrim(vsx1); } customVsxBox.BeforeBaseBox = over; break; case EncloseNotation.circle: using (Tools.BorrowEllipse(out Ellipse ellipse)) { float xLength = hbox.Width / 2 + maxLeft; float yLength = hbox.Height / 2 + maxTop; ellipse.Set(xLength, yLength, xLength, yLength); ellipse.MakeVxs(vsx1); customVsxBox.CustomVxs = stroke.CreateTrim(vsx1); customVsxBox.BeforeBaseBox = maxLeft; } break; } if (useVxs > 0) { if (useVxs == 1) { customVsxBox.CustomVxs = stroke.CreateTrim(vsx1); } else if (useVxs == 2) { customVsxBox.CustomVxs = stroke.CreateTrim(vsx2); } encloseBox.NotationBoxs.Add(customVsxBox); } } }
Box CreateMathBox(MathNode node) { //create box foreach node //TODO: most box are glyph box + its text content //except some boxes are Horizontal (eg. mrow) or some box are vertical (...) //this should be config from DomSpec.xml or Autogen code Box result = null; switch (node.Name) { default: { //text span box if (node.Text == null) { return(null); } char[] text_buff = node.Text.ToCharArray(); if (text_buff.Length == 0) { //???? return(null); } else if (text_buff.Length > 1) { HorizontalStackBox textSpan = new HorizontalStackBox(); textSpan.MathNode = node; for (int i = 0; i < text_buff.Length; ++i) { GlyphBox glyphBox = NewGlyphBox(); glyphBox.Character = text_buff[i]; textSpan.AddChild(glyphBox); } //return textSpan; result = textSpan; } else { //len=1 GlyphBox glyphBox = NewGlyphBox(); glyphBox.MathNode = node; glyphBox.Character = text_buff[0]; //return glyphBox; result = glyphBox; } } break; case "math": case "mrow": case "msub": case "msup": { HorizontalStackBox hbox = new HorizontalStackBox(); hbox.MathNode = node; // int child_count = node.ChildCount; for (int i = 0; i < child_count; ++i) { Box childBox = CreateMathBox(node.GetNode(i)); if (childBox != null) { hbox.AddChild(childBox); } } //return hbox; result = hbox; } break; case "mfrac": case "munder": { VerticalStackBox vbox = new VerticalStackBox(); vbox.MathNode = node; int child_count = node.ChildCount; for (int i = 0; i < child_count; ++i) { Box childBox = CreateMathBox(node.GetNode(i)); if (childBox != null) { vbox.AddChild(childBox); } } //return hbox; result = vbox; } break; case "mover": { VerticalStackBox vbox = new VerticalStackBox(); vbox.MathNode = node; int child_count = node.ChildCount; if (child_count != 2) //expect 2 { return(null); } Box baseBox = CreateMathBox(node.GetNode(0)); Box overBox = CreateMathBox(node.GetNode(1)); vbox.AddChild(overBox); vbox.AddChild(baseBox); //return hbox; result = vbox; } break; } if (result != null) { AssignGlyphVxs(result); } return(result); }
void PaintGlyphBox(GlyphBox box) { if (box.IsInvisible) { return; } float ox = Painter.OriginX;//*** float oy = Painter.OriginY; if (box.HasVxs) { Color color = Color.Black; float shiftHeight = 0; float shiftWidth = 0; var glyphBound = box.GetBoundingRect(); { if (_fromPaintHorizontal.Count > 0 && _fromPaintHorizontal.Peek() && _horizontalHeight.Count > 0) { shiftHeight = _horizontalHeight.Peek(); } else { shiftHeight = box.Height; } } shiftHeight -= box.Height - (float)glyphBound.Height; if (MathMLOperatorTable.IsStretchyPropertyOperator(box.Character + "")) { var bounds = box.GetBoundingRect(); float bottom = (float)bounds.Bottom; float top = (float)bounds.Top; if (MathMLOperatorTable.IsFencePropertyOperator(box.Character + "")) { if (box.Stretched) { shiftHeight -= top; } } else if (_fromPaintHorizontal.Peek()) { shiftHeight -= top; } } float x = box.Left + ox + shiftWidth; float y = box.Top + oy + shiftHeight; Painter.SetOrigin(box.Left + ox + shiftWidth, box.Top + oy + shiftHeight); if (box is VxsGlyphBox vxsGlyphBox) { Painter.Fill(vxsGlyphBox.GlyphVxs, color); } Painter.SetOrigin(ox, oy);//restore } else { Color color = Color.FromArgb(100, Color.Black); Painter.FillRect(box.Left + ox, box.Top + oy, box.Width, box.Height, color); } }