Better encapsulation of glyph placement

This commit is contained in:
2017-05-26 15:01:15 -04:00
parent 08eb58f513
commit 4b0617824f
2 changed files with 70 additions and 76 deletions

View File

@@ -43,7 +43,7 @@ namespace LatexEditor
// var seg = Segment.ToLatexSegment(LatexParser.Tokenize(Content)); // 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(); var gds = seg.GlyphDescriptors.ToList();

View File

@@ -50,7 +50,7 @@ namespace LatexEditor.Parser.Segments
return new GlyphSegment(CmFont.Serif, tok.Value[0]); return new GlyphSegment(CmFont.Serif, tok.Value[0]);
if (tok.TokenName == "open") if (tok.TokenName == "open")
{ {
var seg = new NullSegment(); var seg = new Run();
var i = index + 1; var i = index + 1;
var total = 1; var total = 1;
while (true) while (true)
@@ -85,7 +85,7 @@ namespace LatexEditor.Parser.Segments
return null; return null;
numTokens = n + 1; numTokens = n + 1;
Segment sub = new NullSegment(); Segment sub = new Run();
if (index + numTokens < _tokens.Count) if (index + numTokens < _tokens.Count)
{ {
@@ -111,7 +111,7 @@ namespace LatexEditor.Parser.Segments
return null; return null;
numTokens = n + 1; numTokens = n + 1;
Segment sup = new NullSegment(); Segment sup = new Run();
if (index + numTokens < _tokens.Count) if (index + numTokens < _tokens.Count)
{ {
@@ -136,9 +136,9 @@ namespace LatexEditor.Parser.Segments
return new Return(); return new Return();
} }
if (tok.TokenName == "whitespace") 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() IEnumerator IEnumerable.GetEnumerator()
@@ -149,8 +149,6 @@ namespace LatexEditor.Parser.Segments
public abstract class Segment public abstract class Segment
{ {
public List<Segment> Contents { get; } = new List<Segment>();
public abstract double Width { get; } public abstract double Width { get; }
public abstract double Height { get; } public abstract double Height { get; }
@@ -159,36 +157,21 @@ namespace LatexEditor.Parser.Segments
public override string ToString() public override string ToString()
{ {
return $"{GetType().Name}: [{string.Join(", ", Contents.Select(c => "{" + c + "}"))}]"; return GetType().Name;
} }
public virtual IEnumerable<GlyphDescriptor> GlyphDescriptors protected GlyphDescriptor Localized(GlyphDescriptor gd) => Localized(gd, 0, 0);
protected GlyphDescriptor Localized(GlyphDescriptor gd, double x, double y)
{ {
get // value type, just mutate the parameter
{ gd.Size *= Size;
var o_x = 0d; gd.Offset.X += Offset.X + x;
var o_y = 0d; gd.Offset.Y += Offset.Y + y;
foreach (var seg in Contents) return gd;
{
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;
}
}
} }
public abstract IEnumerable<GlyphDescriptor> GlyphDescriptors { get; }
} }
public class GlyphSegment : Segment public class GlyphSegment : Segment
@@ -214,28 +197,23 @@ namespace LatexEditor.Parser.Segments
public override IEnumerable<GlyphDescriptor> GlyphDescriptors public override IEnumerable<GlyphDescriptor> GlyphDescriptors
{ {
get get { yield return Localized(_glyphDescriptor); }
{
var cp = _glyphDescriptor;
cp.Size *= Size;
cp.Offset.X += Offset.X;
cp.Offset.Y += Offset.Y;
yield return cp;
}
} }
} }
// todo: should be able to implement Return through Space.
public class Return : Segment public class Return : Segment
{ {
public override double Width => 0; public override double Width => 0;
public override double Height => 0; public override double Height => 0;
public override IEnumerable<GlyphDescriptor> GlyphDescriptors => Enumerable.Empty<GlyphDescriptor>();
} }
// todo: should be able to implement Return through latexspace.
public class Space : Segment public class Space : Segment
{ {
public override double Width { get; } public override double Width { get; }
public override double Height { get; } public override double Height { get; }
public override IEnumerable<GlyphDescriptor> GlyphDescriptors => Enumerable.Empty<GlyphDescriptor>();
public Space(double width, double height = 0) 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<Segment> contents)
{
Contents.AddRange(contents);
}
}
public class SupSub : Segment public class SupSub : Segment
{ {
public override double Width => Contents.Max(s => s.Width); public Segment Super { get; set; }
public override double Height => Contents.Sum(s => s.Height) + .1; 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) public SupSub(Segment super, Segment sub)
{ {
Contents.Add(super); Super = super;
Contents.Add(sub); 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<GlyphDescriptor> GlyphDescriptors public override IEnumerable<GlyphDescriptor> GlyphDescriptors
{ {
get 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<Segment> Contents;
public override double Width => Contents.Sum(ls => ls.Width);
public override double Height => Contents.Max(ls => ls.Height);
public Run(IEnumerable<Segment> contents = null)
{
Contents = contents?.ToList() ?? new List<Segment>();
}
public override IEnumerable<GlyphDescriptor> GlyphDescriptors
{
get
{
var x = 0d;
var y = 0d;
foreach (var seg in Contents)
{ {
var cp = sup; if (seg is Return)
cp.Offset.X += Offset.X; {
cp.Offset.Y += 0.45; x = 0;
cp.Size *= 0.7; y -= 1;
yield return cp; continue;
} }
foreach (var sub in Contents[1].GlyphDescriptors) foreach (var gd in seg.GlyphDescriptors)
{ yield return Localized(gd, x, y);
var cp = sub;
cp.Offset.X += Offset.X; x += seg.Width;
cp.Offset.Y -= 0.2;
cp.Size *= 0.7;
yield return cp;
} }
} }
} }