ux: pixel perfect rendering for lines

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2026-02-13 11:31:53 +08:00
parent 921d68c01f
commit ce543adbce
4 changed files with 26 additions and 12 deletions

View File

@@ -245,7 +245,7 @@ namespace SourceGit.Views
public override void Render(DrawingContext context)
{
var pen = new Pen(_editor.BorderBrush);
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
context.DrawLine(pen, new Point(0.5, 0), new Point(0.5, Bounds.Height));
}
protected override Size MeasureOverride(Size availableSize)

View File

@@ -136,6 +136,7 @@ namespace SourceGit.Views
base.Render(context);
var w = Bounds.Width;
var pixelHeight = PixelSnapHelpers.GetPixelSize(this).Height;
var pen = new Pen(SubjectLineBrush) { DashStyle = DashStyle.Dash };
if (SubjectLength == 0)
@@ -153,7 +154,7 @@ namespace SourceGit.Views
context.DrawText(formatted, new Point(4, 2));
var y = 6 + formatted.Height;
var y = PixelSnapHelpers.PixelAlign(6 + formatted.Height, pixelHeight);
context.DrawLine(pen, new Point(0, y), new Point(w, y));
}
@@ -183,6 +184,7 @@ namespace SourceGit.Views
if (line.FirstDocumentLine.LineNumber == _subjectEndLine)
{
var y = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.LineBottom) - view.VerticalOffset + 4;
y = PixelSnapHelpers.PixelAlign(y, pixelHeight);
context.DrawLine(pen, new Point(0, y), new Point(w, y));
return;
}

View File

@@ -95,7 +95,7 @@ namespace SourceGit.Views
public override void Render(DrawingContext context)
{
var pen = new Pen(Brushes.DarkGray);
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
context.DrawLine(pen, new Point(0.5, 0), new Point(0.5, Bounds.Height));
}
protected override Size MeasureOverride(Size availableSize)
@@ -150,6 +150,7 @@ namespace SourceGit.Views
return;
var width = textView.Bounds.Width;
var pixelHeight = PixelSnapHelpers.GetPixelSize(_presenter).Height;
foreach (var line in textView.VisualLines)
{
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
@@ -168,15 +169,18 @@ namespace SourceGit.Views
var endY = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.LineBottom) - textView.VerticalOffset;
var rect = new Rect(0, startY, width, endY - startY);
var alignedTop = PixelSnapHelpers.PixelAlign(startY, pixelHeight);
var alignedBottom = PixelSnapHelpers.PixelAlign(endY, pixelHeight);
var lineState = vm.GetLineState(lineIndex);
if (lineState == Models.ConflictLineState.ConflictBlockStart)
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Red, 0.6)), new Point(0, startY + 0.5), new Point(width, startY + 0.5));
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Red, 0.6)), new Point(0, alignedTop), new Point(width, alignedTop));
else if (lineState == Models.ConflictLineState.ConflictBlockEnd)
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Red, 0.6)), new Point(0, endY - 0.5), new Point(width, endY - 0.5));
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Red, 0.6)), new Point(0, alignedBottom), new Point(width, alignedBottom));
else if (lineState == Models.ConflictLineState.ResolvedBlockStart)
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Green, 0.6)), new Point(0, startY + 0.5), new Point(width, startY + 0.5));
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Green, 0.6)), new Point(0, alignedTop), new Point(width, alignedTop));
else if (lineState == Models.ConflictLineState.ResolvedBlockEnd)
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Green, 0.6)), new Point(0, endY - 0.5), new Point(width, endY - 0.5));
drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.Green, 0.6)), new Point(0, alignedBottom), new Point(width, alignedBottom));
if (lineState >= Models.ConflictLineState.ResolvedBlockStart)
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Green, 0.1), null, rect);

View File

@@ -203,6 +203,7 @@ namespace SourceGit.Views
var lines = _presenter.GetLines();
var width = textView.Bounds.Width;
var pixelHeight = PixelSnapHelpers.GetPixelSize(textView).Height;
foreach (var line in textView.VisualLines)
{
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
@@ -265,10 +266,16 @@ namespace SourceGit.Views
continue;
if (index == changeBlock.Start)
drawingContext.DrawLine(changeBlockBorder, new Point(0, startY), new Point(width, startY));
{
var alignedY = PixelSnapHelpers.PixelAlign(startY, pixelHeight);
drawingContext.DrawLine(changeBlockBorder, new Point(0, alignedY), new Point(width, alignedY));
}
if (index == changeBlock.End)
drawingContext.DrawLine(changeBlockBorder, new Point(0, endY), new Point(width, endY));
{
var alignedY = PixelSnapHelpers.PixelAlign(endY, pixelHeight);
drawingContext.DrawLine(changeBlockBorder, new Point(0, alignedY), new Point(width, alignedY));
}
}
}
@@ -488,10 +495,11 @@ namespace SourceGit.Views
var brush = new SolidColorBrush(color, 0.1);
var pen = new Pen(color.ToUInt32());
var rect = new Rect(0, chunk.Y, Bounds.Width, chunk.Height);
var aligned = PixelSnapHelpers.PixelAlign(rect, PixelSnapHelpers.GetPixelSize(this));
context.DrawRectangle(brush, null, rect);
context.DrawLine(pen, rect.TopLeft, rect.TopRight);
context.DrawLine(pen, rect.BottomLeft, rect.BottomRight);
context.DrawRectangle(brush, null, aligned);
context.DrawLine(pen, aligned.TopLeft, aligned.TopRight);
context.DrawLine(pen, aligned.BottomLeft, aligned.BottomRight);
}
protected override void OnLoaded(RoutedEventArgs e)