diff --git a/Cavern.QuickEQ/Graphing/Overlays/Frame.cs b/Cavern.QuickEQ/Graphing/Overlays/Frame.cs
index 169239c2..a27d5bf0 100644
--- a/Cavern.QuickEQ/Graphing/Overlays/Frame.cs
+++ b/Cavern.QuickEQ/Graphing/Overlays/Frame.cs
@@ -1,4 +1,6 @@
-namespace Cavern.QuickEQ.Graphing.Overlays {
+using System.Runtime.CompilerServices;
+
+namespace Cavern.QuickEQ.Graphing.Overlays {
///
/// Draws a frame of a given over the graph.
///
@@ -27,25 +29,40 @@ public Frame(int width, uint color) {
/// Adds the overlay to a graph.
///
public override void DrawOn(GraphRenderer target) {
- // Edge rows
+ DrawRow(target, 0, Width, color);
+ DrawRow(target, target.Height - Width, Width, color);
+ DrawColumn(target, 0, Width, color);
+ DrawColumn(target, target.Width - Width, Width, color);
+ }
+
+ ///
+ /// Draw a single row at a height of a developing image.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void DrawRow(GraphRenderer target, int offset, int width, uint color) {
uint[] pixels = target.Pixels;
- int until = target.Width * Width;
- for (int i = 0; i < until; i++) {
- pixels[i] = color;
- }
- for (int i = pixels.Length - until; i < pixels.Length; i++) {
- pixels[i] = color;
+ while (width > 0) {
+ for (int y = offset * target.Width, end = y + target.Width; y < end; y++) {
+ pixels[y] = color;
+ }
+ offset++;
+ width--;
}
+ }
- // Edge columns
- for (int x = 0; x < Width; x++) {
- int c = target.Height - Width;
- for (int y = Width; y < c; y++) {
- pixels[y * target.Width + x] = color;
- }
- for (int y = Width; y < c; y++) {
- pixels[pixels.Length - y * target.Width - x] = color;
+ ///
+ /// Draw a single column at a width of a developing image.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void DrawColumn(GraphRenderer target, int offset, int width, uint color) {
+ uint[] pixels = target.Pixels;
+ while (width > 0) {
+ for (int y = 0, pos = offset, step = target.Width; y < target.Height; y++) {
+ pixels[pos] = color;
+ pos += step;
}
+ offset++;
+ width--;
}
}
}
diff --git a/Cavern.QuickEQ/Graphing/Overlays/Grid.cs b/Cavern.QuickEQ/Graphing/Overlays/Grid.cs
index 97c9b889..1178c658 100644
--- a/Cavern.QuickEQ/Graphing/Overlays/Grid.cs
+++ b/Cavern.QuickEQ/Graphing/Overlays/Grid.cs
@@ -37,29 +37,15 @@ public Grid(int borderWidth, int gridWidth, uint color, int xSteps, int ySteps)
///
public override void DrawOn(GraphRenderer target) {
base.DrawOn(target);
- uint[] pixels = target.Pixels;
- int xGap = target.Width / xSteps,
- yGap = target.Height / ySteps,
- yMax = target.Height - Width;
+
+ int gap = target.Width / xSteps;
for (int x = 1; x < xSteps; x++) {
- int xPos = x * xGap;
- for (int y = Width; y <= yMax; y++) {
- int start = y * target.Width + xPos;
- for (int w = 0; w < gridWidth; w++) {
- pixels[start + w] = color;
- }
- }
+ DrawColumn(target, x * gap, gridWidth, color);
}
- int xMax = target.Width - Width;
+ gap = target.Height / ySteps;
for (int y = 1; y < ySteps; y++) {
- int yPos = y * yGap;
- for (int w = 0; w < gridWidth; w++) {
- int start = (yPos + w) * target.Width;
- for (int x = Width; x <= xMax; x++) {
- pixels[start + x] = color;
- }
- }
+ DrawRow(target, y * gap, gridWidth, color);
}
}
}
diff --git a/Cavern.QuickEQ/Graphing/Overlays/LogScaleGrid.cs b/Cavern.QuickEQ/Graphing/Overlays/LogScaleGrid.cs
new file mode 100644
index 00000000..e52cf960
--- /dev/null
+++ b/Cavern.QuickEQ/Graphing/Overlays/LogScaleGrid.cs
@@ -0,0 +1,54 @@
+using Cavern.Utilities;
+using System;
+
+namespace Cavern.QuickEQ.Graphing.Overlays {
+ ///
+ /// Draws a grid over the graph with a gridline at every increment of the highest local value.
+ ///
+ public class LogScaleGrid : Frame {
+ ///
+ /// Inner line stroke width.
+ ///
+ readonly int gridWidth;
+
+ ///
+ /// Number of rows drawn, including the frame lines.
+ ///
+ readonly int ySteps;
+
+ ///
+ /// Draws a grid over the graph with a gridline at every increment of the highest local value.
+ ///
+ /// Border line stroke width
+ /// Inner line stroke width
+ /// RGBA color of the line
+ /// Number of rows drawn, including the frame lines
+ public LogScaleGrid(int borderWidth, int gridWidth, uint color, int ySteps) : base(borderWidth, color) {
+ this.gridWidth = gridWidth;
+ this.ySteps = ySteps;
+ }
+
+ ///
+ /// Adds the overlay to a graph.
+ ///
+ public override void DrawOn(GraphRenderer target) {
+ base.DrawOn(target);
+
+ int gap = target.Height / ySteps;
+ for (int y = 1; y < ySteps; y++) {
+ DrawRow(target, y * gap, gridWidth, color);
+ }
+
+ float logStart = MathF.Log10(target.StartFrequency),
+ logEnd = MathF.Log10(target.EndFrequency);
+ for (int digit = (int)logStart, last = (int)logEnd; digit <= last; digit++) {
+ for (int value = 1; value < 10; value++) {
+ float freq = value * MathF.Pow(10, digit);
+ if (freq > target.StartFrequency && freq < target.EndFrequency) {
+ DrawColumn(target, (int)(target.Width * QMath.LerpInverse(logStart, logEnd, MathF.Log10(freq))), gridWidth, color);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file