From 4b0617824f7ce89cf582310924cfc80bad70a1d3 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Fri, 26 May 2017 15:01:15 -0400 Subject: [PATCH] Better encapsulation of glyph placement --- WpfTex/LatexEditor/LatexViewer.cs | 2 +- WpfTex/LatexEditor/Parser/Segments/Segment.cs | 144 +++++++++--------- 2 files changed, 70 insertions(+), 76 deletions(-) diff --git a/WpfTex/LatexEditor/LatexViewer.cs b/WpfTex/LatexEditor/LatexViewer.cs index c787b21..ec0865a 100644 --- a/WpfTex/LatexEditor/LatexViewer.cs +++ b/WpfTex/LatexEditor/LatexViewer.cs @@ -43,7 +43,7 @@ namespace LatexEditor // var seg = Segment.ToLatexSegment(LatexParser.Tokenize(Content)); - var seg = new NullSegment(new SegmentCollection(LatexParser.Tokenize(Content))); + var seg = new Run(new SegmentCollection(LatexParser.Tokenize(Content))); var gds = seg.GlyphDescriptors.ToList(); diff --git a/WpfTex/LatexEditor/Parser/Segments/Segment.cs b/WpfTex/LatexEditor/Parser/Segments/Segment.cs index 44fda9f..7fb5643 100644 --- a/WpfTex/LatexEditor/Parser/Segments/Segment.cs +++ b/WpfTex/LatexEditor/Parser/Segments/Segment.cs @@ -50,7 +50,7 @@ namespace LatexEditor.Parser.Segments return new GlyphSegment(CmFont.Serif, tok.Value[0]); if (tok.TokenName == "open") { - var seg = new NullSegment(); + var seg = new Run(); var i = index + 1; var total = 1; while (true) @@ -85,7 +85,7 @@ namespace LatexEditor.Parser.Segments return null; numTokens = n + 1; - Segment sub = new NullSegment(); + Segment sub = new Run(); if (index + numTokens < _tokens.Count) { @@ -111,7 +111,7 @@ namespace LatexEditor.Parser.Segments return null; numTokens = n + 1; - Segment sup = new NullSegment(); + Segment sup = new Run(); if (index + numTokens < _tokens.Count) { @@ -136,9 +136,9 @@ namespace LatexEditor.Parser.Segments return new Return(); } if (tok.TokenName == "whitespace") - return new NullSegment(); + return new Run(); - return new NullSegment(_tokens[index].Value.Select(c => new GlyphSegment(CmFont.Serif, c))); + return new Run(_tokens[index].Value.Select(c => new GlyphSegment(CmFont.Serif, c))); } IEnumerator IEnumerable.GetEnumerator() @@ -149,8 +149,6 @@ namespace LatexEditor.Parser.Segments public abstract class Segment { - public List Contents { get; } = new List(); - public abstract double Width { get; } public abstract double Height { get; } @@ -159,36 +157,21 @@ namespace LatexEditor.Parser.Segments public override string ToString() { - return $"{GetType().Name}: [{string.Join(", ", Contents.Select(c => "{" + c + "}"))}]"; + return GetType().Name; } - public virtual IEnumerable GlyphDescriptors + protected GlyphDescriptor Localized(GlyphDescriptor gd) => Localized(gd, 0, 0); + + protected GlyphDescriptor Localized(GlyphDescriptor gd, double x, double y) { - get - { - var o_x = 0d; - var o_y = 0d; - foreach (var seg in Contents) - { - if (seg is Return) - { - o_x = 0; - o_y -= Size; - continue; - } - foreach (var gd in seg.GlyphDescriptors) - { - var cp = gd; - cp.Size *= Size; - cp.Offset.X += o_x + Offset.X; - cp.Offset.Y += o_y + Offset.Y; - yield return cp; - } - - o_x += seg.Width * Size; - } - } + // value type, just mutate the parameter + gd.Size *= Size; + gd.Offset.X += Offset.X + x; + gd.Offset.Y += Offset.Y + y; + return gd; } + + public abstract IEnumerable GlyphDescriptors { get; } } public class GlyphSegment : Segment @@ -214,28 +197,23 @@ namespace LatexEditor.Parser.Segments public override IEnumerable GlyphDescriptors { - get - { - var cp = _glyphDescriptor; - cp.Size *= Size; - cp.Offset.X += Offset.X; - cp.Offset.Y += Offset.Y; - yield return cp; - } + get { yield return Localized(_glyphDescriptor); } } } + // todo: should be able to implement Return through Space. public class Return : Segment { public override double Width => 0; public override double Height => 0; + public override IEnumerable GlyphDescriptors => Enumerable.Empty(); } - // todo: should be able to implement Return through latexspace. public class Space : Segment { public override double Width { get; } public override double Height { get; } + public override IEnumerable GlyphDescriptors => Enumerable.Empty(); public Space(double width, double height = 0) { @@ -244,51 +222,67 @@ namespace LatexEditor.Parser.Segments } } - public class NullSegment : Segment - { - public override double Width => Contents.Sum(ls => ls.Width); - public override double Height => Contents.Max(ls => ls.Height); - - public NullSegment() - { - } - - public NullSegment(IEnumerable contents) - { - Contents.AddRange(contents); - } - } - public class SupSub : Segment { - public override double Width => Contents.Max(s => s.Width); - public override double Height => Contents.Sum(s => s.Height) + .1; + public Segment Super { get; set; } + public Segment Sub { get; set; } + public override double Width => Math.Max(Super.Width, Sub.Width); + public override double Height => Super.Height + Sub.Height + .1; public SupSub(Segment super, Segment sub) { - Contents.Add(super); - Contents.Add(sub); + Super = super; + Super.Offset = new Point(0, 0.45); + Super.Size = 0.7; + + Sub = sub; + Sub.Offset = new Point(0, -0.2); + Sub.Size = 0.7; } public override IEnumerable GlyphDescriptors { get { - foreach (var sup in Contents[0].GlyphDescriptors) + foreach (var gd in Super.GlyphDescriptors) + yield return Localized(gd); + + foreach (var gd in Sub.GlyphDescriptors) + yield return Localized(gd); + } + } + } + + public class Run : Segment + { + public List Contents; + public override double Width => Contents.Sum(ls => ls.Width); + public override double Height => Contents.Max(ls => ls.Height); + + public Run(IEnumerable contents = null) + { + Contents = contents?.ToList() ?? new List(); + } + + public override IEnumerable GlyphDescriptors + { + get + { + var x = 0d; + var y = 0d; + + foreach (var seg in Contents) { - var cp = sup; - cp.Offset.X += Offset.X; - cp.Offset.Y += 0.45; - cp.Size *= 0.7; - yield return cp; - } - foreach (var sub in Contents[1].GlyphDescriptors) - { - var cp = sub; - cp.Offset.X += Offset.X; - cp.Offset.Y -= 0.2; - cp.Size *= 0.7; - yield return cp; + if (seg is Return) + { + x = 0; + y -= 1; + continue; + } + foreach (var gd in seg.GlyphDescriptors) + yield return Localized(gd, x, y); + + x += seg.Width; } } }