Skip to content

Commit

Permalink
#92: extract the main rendering code to the RenderElement method
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Nov 27, 2017
1 parent cef7e33 commit 1c7e832
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 130 deletions.
38 changes: 1 addition & 37 deletions src/WpfMath/Box.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using WpfMath.Rendering;

Expand Down Expand Up @@ -87,30 +86,9 @@ public double Shift
set;
}

/// <summary>
/// Draws the box into a <see cref="DrawingContext"/> while providing guidelines for WPF render to snap
/// the box boundaries onto the device pixel grid.
/// </summary>
public void DrawWithGuidelines(DrawingContext drawingContext, double scale, double x, double y)
{
var guidelines = new GuidelineSet
{
GuidelinesX = { scale * x, scale * (x + TotalWidth) },
GuidelinesY = { scale * y, scale * (y + TotalHeight) }
};
drawingContext.PushGuidelineSet(guidelines);

DrawBackground(drawingContext, scale, x, y);
Draw(drawingContext, scale, x, y);

drawingContext.Pop();
}

public abstract void Draw(DrawingContext drawingContext, double scale, double x, double y);

// TODO[F]: Remove this method and replace with GeometryRenderer.
public abstract void RenderGeometry(GeometryGroup geometry, double scale, double x, double y);

// TODO[F]: Make it call DrawWithGuidelines before every render.
public abstract void RenderTo(IElementRenderer renderer, double x, double y);

public virtual void Add(Box box)
Expand All @@ -124,19 +102,5 @@ public virtual void Add(int position, Box box)
}

public abstract int GetLastFontId();

private void DrawBackground(DrawingContext drawingContext, double scale, double x, double y)
{
if (Background != null)
{
// Fill background of box with color:
drawingContext.DrawRectangle(
Background,
null,
new Rect(scale * x, scale * (y - Height),
scale * TotalWidth,
scale * TotalHeight));
}
}
}
}
8 changes: 0 additions & 8 deletions src/WpfMath/CharBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ private GlyphRun GetGlyphRun(double scale, double x, double y)

}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
GlyphRun glyphRun = GetGlyphRun(scale, x, y);

// Draw character at given position.
drawingContext.DrawGlyphRun(this.Foreground ?? Brushes.Black, glyphRun);
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
GlyphRun glyphRun = GetGlyphRun(scale, x, y);
Expand Down
4 changes: 0 additions & 4 deletions src/WpfMath/GlueBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ public double Shrink
private set;
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
}
Expand Down
12 changes: 1 addition & 11 deletions src/WpfMath/HorizontalBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,6 @@ public override void Add(Box box)
this.Italic = Math.Max((this.Children.Count == 0 ? double.NegativeInfinity : Italic), box.Italic);
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
var curX = x;
foreach (var box in Children)
{
box.DrawWithGuidelines(drawingContext, scale, curX, y + box.Shift);
curX += box.Width;
}
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
var curX = x;
Expand All @@ -84,7 +74,7 @@ public override void RenderTo(IElementRenderer renderer, double x, double y)
var curX = x;
foreach (var box in Children)
{
box.RenderTo(renderer, curX, y + box.Shift);
renderer.RenderElement(box, curX, y + box.Shift);
curX += box.Width;
}
}
Expand Down
6 changes: 0 additions & 6 deletions src/WpfMath/HorizontalRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ public HorizontalRule(TexEnvironment environment, double thickness, double width
this.Background = environment.Background; //Not strictly necessary
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
drawingContext.DrawRectangle(this.Foreground ?? Brushes.Black, null, new Rect(
x * scale, (y - this.Height) * scale, this.Width * scale, this.Height * scale));
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
RectangleGeometry rectangleGeometry = new RectangleGeometry(new Rect(
Expand Down
54 changes: 9 additions & 45 deletions src/WpfMath/OverUnderBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,48 +55,6 @@ public bool Over
private set;
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
this.BaseBox.DrawWithGuidelines(drawingContext, scale, x, y);

if (this.Over)
{
// Draw delimeter and script boxes over base box.
var centerY = y - this.BaseBox.Height - this.DelimeterBox.Width;
var translationX = x + this.DelimeterBox.Width / 2;
var translationY = centerY + this.DelimeterBox.Width / 2;

drawingContext.PushTransform(new TranslateTransform(translationX * scale, translationY * scale));
drawingContext.PushTransform(new RotateTransform(90));
this.DelimeterBox.DrawWithGuidelines(drawingContext, scale, -this.DelimeterBox.Width / 2,
-this.DelimeterBox.Depth + this.DelimeterBox.Width / 2);
drawingContext.Pop();
drawingContext.Pop();

// Draw script box as superscript.
if (this.ScriptBox != null)
this.ScriptBox.DrawWithGuidelines(drawingContext, scale, x, centerY - this.Kern - this.ScriptBox.Depth);
}
else
{
// Draw delimeter and script boxes under base box.
var centerY = y + this.BaseBox.Depth + this.DelimeterBox.Width;
var translationX = x + this.DelimeterBox.Width / 2;
var translationY = centerY - this.DelimeterBox.Width / 2;

drawingContext.PushTransform(new TranslateTransform(translationX * scale, translationY * scale));
drawingContext.PushTransform(new RotateTransform(90));
this.DelimeterBox.DrawWithGuidelines(drawingContext, scale, -this.DelimeterBox.Width / 2,
-this.DelimeterBox.Depth + this.DelimeterBox.Width / 2);
drawingContext.Pop();
drawingContext.Pop();

// Draw script box as subscript.
ScriptBox?.DrawWithGuidelines(drawingContext, scale, x, centerY + Kern + ScriptBox.Height);
}

}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
GeometryGroup group = new GeometryGroup();
Expand Down Expand Up @@ -137,7 +95,7 @@ public override void RenderGeometry(GeometryGroup geometry, double scale, double

public override void RenderTo(IElementRenderer renderer, double x, double y)
{
BaseBox.RenderTo(renderer, x, y);
renderer.RenderElement(BaseBox, x, y);

if (Over)
{
Expand All @@ -159,7 +117,10 @@ public override void RenderTo(IElementRenderer renderer, double x, double y)
-DelimeterBox.Depth + DelimeterBox.Width / 2);

// Draw script box as superscript.
ScriptBox?.RenderTo(renderer, x, centerY - Kern - ScriptBox.Depth);
if (ScriptBox != null)
{
renderer.RenderElement(ScriptBox, x, centerY - Kern - ScriptBox.Depth);
}
}
else
{
Expand All @@ -184,7 +145,10 @@ public override void RenderTo(IElementRenderer renderer, double x, double y)
-DelimeterBox.Depth + DelimeterBox.Width / 2);

// Draw script box as subscript.
ScriptBox?.RenderTo(renderer, x, centerY + Kern + ScriptBox.Height);
if (ScriptBox != null)
{
renderer.RenderElement(ScriptBox, x, centerY + Kern + ScriptBox.Height);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/WpfMath/Rendering/IElementRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ namespace WpfMath.Rendering
/// <summary>Renderer interface for WPF-Math elements.</summary>
public interface IElementRenderer
{
/// <summary>Renders a <see cref="Box"/> to the renderer drawing context.</summary>
/// <param name="box">The element that should be rendered.</param>
/// <param name="x">An X coordinate of the top left corner.</param>
/// <param name="y">An Y coordinate of the top left corner.</param>
/// <remarks>Should be called for every element of the formula (including nested ones).</remarks>
void RenderElement(Box box, double x, double y);

/// <summary>Renders a glyph run (e.g. a character).</summary>
/// <param name="scaledGlyphFactory">Function to generate a glyph run for the chosen scale.</param>
/// <param name="x">An X coordinate of the top left corner.</param>
Expand Down
36 changes: 35 additions & 1 deletion src/WpfMath/Rendering/WpfElementRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ public WpfElementRenderer(DrawingContext drawingContext, double scale)
_scale = scale;
}

public void RenderElement(Box box, double x, double y)
{
var guidelines = GenerateGuidelines(box, x, y);
_drawingContext.PushGuidelineSet(guidelines);

RenderBackground(box, x, y);
box.RenderTo(this, x, y);

_drawingContext.Pop();
}

public void RenderGlyphRun(Func<double, GlyphRun> scaledGlyphFactory, double x, double y, Brush foreground)
{
var glyphRun = scaledGlyphFactory(_scale);
Expand All @@ -37,14 +48,37 @@ public void RenderTransformed(Box box, Transform[] transforms, double x, double
_drawingContext.PushTransform(transform);
}

box.RenderTo(this, x, y);
RenderElement(box, x, y);

for (var i = 0; i < scaledTransforms.Count; ++i)
{
_drawingContext.Pop();
}
}

private void RenderBackground(Box box, double x, double y)
{
if (box.Background != null)
{
// Fill background of box with color:
_drawingContext.DrawRectangle(
box.Background,
null,
new Rect(_scale * x, _scale * (y - box.Height),
_scale * box.TotalWidth,
_scale * box.TotalHeight));
}
}

/// <summary>
/// Genetates the guidelines for WPF render to snap the box boundaries onto the device pixel grid.
/// </summary>
private GuidelineSet GenerateGuidelines(Box box, double x, double y) => new GuidelineSet
{
GuidelinesX = {_scale * x, _scale * (x + box.TotalWidth)},
GuidelinesY = {_scale * y, _scale * (y + box.TotalHeight)}
};

private Rect ScaleRectangle(Rect rectangle) =>
new Rect(rectangle.X * _scale, rectangle.Y * _scale, rectangle.Width * _scale, rectangle.Height * _scale);

Expand Down
4 changes: 0 additions & 4 deletions src/WpfMath/StrutBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ public StrutBox(double width, double height, double depth, double shift)
this.Shift = shift;
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
}
Expand Down
2 changes: 1 addition & 1 deletion src/WpfMath/TexRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public BitmapSource RenderToBitmap(double x, double y)
public void Render(DrawingContext drawingContext, double x, double y)
{
var renderer = new WpfElementRenderer(drawingContext, Scale);
Box.RenderTo(renderer, x / Scale, y / Scale + Box.Height);
renderer.RenderElement(Box, x / Scale, y / Scale + Box.Height);
}
}
}
14 changes: 1 addition & 13 deletions src/WpfMath/VerticalBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,6 @@ private void RecalculateWidth(Box box)
this.Width = rightMostPos - leftMostPos;
}

public override void Draw(DrawingContext drawingContext, double scale, double x, double y)
{
var curY = y - Height;
foreach (var child in this.Children)
{
curY += child.Height;

child.DrawWithGuidelines(drawingContext, scale, x + child.Shift - leftMostPos, curY);
curY += child.Depth;
}
}

public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
{
var curY = y - Height;
Expand All @@ -107,7 +95,7 @@ public override void RenderTo(IElementRenderer renderer, double x, double y)
foreach (var child in Children)
{
curY += child.Height;
child.RenderTo(renderer, x + child.Shift - leftMostPos, curY);
renderer.RenderElement(child, x + child.Shift - leftMostPos, curY);
curY += child.Depth;
}
}
Expand Down

0 comments on commit 1c7e832

Please sign in to comment.