// TODO: store the TickCollection in the Axis module, not in the Ticks module. // https://github.com/ScottPlot/ScottPlot/pull/1647 public void Render(PlotDimensions dims, Bitmap bmp, bool lowQuality = false) { if (!IsVisible) { return; } double[] majorTicks = TickCollection.GetVisibleMajorTicks(dims) .Select(t => t.Position) .ToArray(); double[] minorTicks = TickCollection.GetVisibleMinorTicks(dims) .Select(t => t.Position) .ToArray(); RenderTicksAndGridLines(dims, bmp, lowQuality || SnapPx, majorTicks, minorTicks); RenderTickLabels(dims, bmp, lowQuality); }
public static void RenderTickLabels(PlotDimensions dims, Graphics gfx, TickCollection tc, Drawing.Font tickFont, Edge edge, float rotation, bool rulerMode, float PixelOffset, float MajorTickLength, float MinorTickLength) { if (tc.tickLabels is null || tc.tickLabels.Length == 0) { return; } using var font = GDI.Font(tickFont); using var brush = GDI.Brush(tickFont.Color); using var sf = GDI.StringFormat(); Tick[] visibleMajorTicks = tc.GetVisibleMajorTicks(dims); switch (edge) { case Edge.Bottom: for (int i = 0; i < visibleMajorTicks.Length; i++) { float x = dims.GetPixelX(visibleMajorTicks[i].Position); float y = dims.DataOffsetY + dims.DataHeight + MajorTickLength; gfx.TranslateTransform(x, y); gfx.RotateTransform(-rotation); sf.Alignment = rotation == 0 ? StringAlignment.Center : StringAlignment.Far; if (rulerMode) { sf.Alignment = StringAlignment.Near; } sf.LineAlignment = rotation == 0 ? StringAlignment.Near : StringAlignment.Center; gfx.DrawString(visibleMajorTicks[i].Label, font, brush, 0, 0, sf); GDI.ResetTransformPreservingScale(gfx, dims); } break; case Edge.Top: for (int i = 0; i < visibleMajorTicks.Length; i++) { float x = dims.GetPixelX(visibleMajorTicks[i].Position); float y = dims.DataOffsetY - MajorTickLength; gfx.TranslateTransform(x, y); gfx.RotateTransform(-rotation); sf.Alignment = rotation == 0 ? StringAlignment.Center : StringAlignment.Near; if (rulerMode) { sf.Alignment = StringAlignment.Near; } sf.LineAlignment = rotation == 0 ? StringAlignment.Far : StringAlignment.Center; gfx.DrawString(visibleMajorTicks[i].Label, font, brush, 0, 0, sf); GDI.ResetTransformPreservingScale(gfx, dims); } break; case Edge.Left: for (int i = 0; i < visibleMajorTicks.Length; i++) { float x = dims.DataOffsetX - PixelOffset - MajorTickLength; float y = dims.GetPixelY(visibleMajorTicks[i].Position); gfx.TranslateTransform(x, y); gfx.RotateTransform(-rotation); sf.Alignment = StringAlignment.Far; sf.LineAlignment = rulerMode ? StringAlignment.Far : StringAlignment.Center; if (rotation == 90) { sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Far; } gfx.DrawString(visibleMajorTicks[i].Label, font, brush, 0, 0, sf); GDI.ResetTransformPreservingScale(gfx, dims); } break; case Edge.Right: for (int i = 0; i < visibleMajorTicks.Length; i++) { float x = dims.DataOffsetX + PixelOffset + MajorTickLength + dims.DataWidth; float y = dims.GetPixelY(visibleMajorTicks[i].Position); gfx.TranslateTransform(x, y); gfx.RotateTransform(-rotation); sf.Alignment = StringAlignment.Near; sf.LineAlignment = rulerMode ? StringAlignment.Far : StringAlignment.Center; if (rotation == 90) { sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Near; } gfx.DrawString(visibleMajorTicks[i].Label, font, brush, 0, 0, sf); GDI.ResetTransformPreservingScale(gfx, dims); } break; default: throw new NotImplementedException($"unsupported edge type {edge}"); } if (!string.IsNullOrWhiteSpace(tc.CornerLabel)) { switch (edge) { case Edge.Bottom: sf.Alignment = StringAlignment.Far; sf.LineAlignment = StringAlignment.Near; gfx.DrawString(s: "\n" + tc.CornerLabel, x: dims.DataOffsetX + dims.DataWidth, y: dims.DataOffsetY + dims.DataHeight + MajorTickLength, font: font, brush: brush, format: sf); break; case Edge.Left: sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Far; gfx.DrawString(s: "\n" + tc.CornerLabel, x: dims.DataOffsetX, y: dims.DataOffsetY, font: font, brush: brush, format: sf); break; case Edge.Top: throw new NotImplementedException("multiplier and offset notation is not supported for right and top axes"); case Edge.Right: throw new NotImplementedException("multiplier and offset notation is not supported for right and top axes"); default: throw new NotImplementedException($"unsupported edge type {edge}"); } } }