Browse Source

Fixed pixel snapping of lines in folding margin.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5218 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
5778efa82e
  1. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretLayer.cs
  2. 18
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs
  3. 16
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs
  4. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/BackgroundGeometryBuilder.cs
  5. 55
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/PixelSnapHelpers.cs

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretLayer.cs

@ -79,7 +79,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -79,7 +79,7 @@ namespace ICSharpCode.AvalonEdit.Editing
caretRectangle.Y - textView.VerticalOffset,
caretRectangle.Width,
caretRectangle.Height);
drawingContext.DrawRectangle(caretBrush, null, PixelSnapHelpers.ToPixels(r));
drawingContext.DrawRectangle(caretBrush, null, PixelSnapHelpers.PixelAlign(r));
}
}
}

18
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs

@ -37,7 +37,8 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -37,7 +37,8 @@ namespace ICSharpCode.AvalonEdit.Folding
foreach (FoldingMarginMarker m in markers) {
m.Measure(availableSize);
}
return new Size(SizeFactor * (double)GetValue(TextBlock.FontSizeProperty), 0);
double width = SizeFactor * (double)GetValue(TextBlock.FontSizeProperty);
return new Size(PixelSnapHelpers.RoundToOdd(width), 0);
}
/// <inheritdoc/>
@ -49,7 +50,7 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -49,7 +50,7 @@ namespace ICSharpCode.AvalonEdit.Folding
double yPos = m.VisualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineTop) - TextView.VerticalOffset;
yPos += (textLine.Height - m.DesiredSize.Height) / 2;
double xPos = (finalSize.Width - m.DesiredSize.Width) / 2;
m.Arrange(new Rect(new Point(xPos, yPos), m.DesiredSize));
m.Arrange(new Rect(PixelSnapHelpers.Round(new Point(xPos, yPos)), m.DesiredSize));
}
return base.ArrangeOverride(finalSize);
}
@ -84,7 +85,6 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -84,7 +85,6 @@ namespace ICSharpCode.AvalonEdit.Folding
if (fs.StartOffset <= line.LastDocumentLine.Offset + line.LastDocumentLine.Length) {
FoldingMarginMarker m = new FoldingMarginMarker {
IsExpanded = !fs.IsFolded,
SnapsToDevicePixels = true,
VisualLine = line,
FoldingSection = fs
};
@ -208,6 +208,10 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -208,6 +208,10 @@ namespace ICSharpCode.AvalonEdit.Folding
/// </summary>
void DrawFoldLines(DrawingContext drawingContext, Pen[] colors, Pen[] endMarker)
{
// Because we are using PenLineCap.Flat (the default), for vertical lines,
// Y coordinates must be on pixel boundaries, whereas the X coordinate must be in the
// middle of a pixel. (and the other way round for horizontal lines)
Size pixelSize = PixelSnapHelpers.GetPixelSize();
double markerXPos = PixelSnapHelpers.PixelAlign(RenderSize.Width / 2);
double startY = 0;
Pen currentPen = colors[0];
@ -216,12 +220,12 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -216,12 +220,12 @@ namespace ICSharpCode.AvalonEdit.Folding
foreach (TextLine tl in vl.TextLines) {
if (endMarker[tlNumber] != null) {
double visualPos = GetVisualPos(vl, tl);
drawingContext.DrawLine(endMarker[tlNumber], new Point(markerXPos, visualPos), new Point(RenderSize.Width, visualPos));
drawingContext.DrawLine(endMarker[tlNumber], new Point(markerXPos - pixelSize.Width / 2, visualPos), new Point(RenderSize.Width, visualPos));
}
if (colors[tlNumber + 1] != currentPen) {
double visualPos = GetVisualPos(vl, tl);
if (currentPen != null) {
drawingContext.DrawLine(currentPen, new Point(markerXPos, startY), new Point(markerXPos, visualPos));
drawingContext.DrawLine(currentPen, new Point(markerXPos, startY + pixelSize.Height / 2), new Point(markerXPos, visualPos - pixelSize.Height / 2));
}
currentPen = colors[tlNumber + 1];
startY = visualPos;
@ -230,14 +234,14 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -230,14 +234,14 @@ namespace ICSharpCode.AvalonEdit.Folding
}
}
if (currentPen != null) {
drawingContext.DrawLine(currentPen, new Point(markerXPos, startY), new Point(markerXPos, RenderSize.Height));
drawingContext.DrawLine(currentPen, new Point(markerXPos, startY + pixelSize.Height / 2), new Point(markerXPos, RenderSize.Height));
}
}
double GetVisualPos(VisualLine vl, TextLine tl)
{
double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) + tl.Height / 2 - TextView.VerticalOffset;
return Math.Round(pos) + 0.5;
return PixelSnapHelpers.PixelAlign(pos);
}
int GetTextLineIndexFromOffset(List<TextLine> textLines, int offset)

16
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs

@ -12,6 +12,7 @@ using System.Windows.Input; @@ -12,6 +12,7 @@ using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Folding
{
@ -50,23 +51,26 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -50,23 +51,26 @@ namespace ICSharpCode.AvalonEdit.Folding
protected override Size MeasureCore(Size availableSize)
{
double size = MarginSizeFactor * FoldingMargin.SizeFactor * (double)GetValue(TextBlock.FontSizeProperty);
size = Math.Round(size);
if (Math.Abs((size % 2) - 1) < 0.001) {
size -= 1;
}
size = PixelSnapHelpers.RoundToOdd(size);
return new Size(size, size);
}
protected override void OnRender(DrawingContext drawingContext)
{
Pen blackPen = new Pen(Brushes.Black, 1);
Rect rect = new Rect(new Point(0.5, 0.5), this.RenderSize);
blackPen.StartLineCap = PenLineCap.Square;
blackPen.EndLineCap = PenLineCap.Square;
Size pixelSize = PixelSnapHelpers.GetPixelSize();
Rect rect = new Rect(pixelSize.Width / 2,
pixelSize.Height / 2,
this.RenderSize.Width - pixelSize.Width,
this.RenderSize.Height - pixelSize.Height);
drawingContext.DrawRectangle(Brushes.White,
IsMouseDirectlyOver ? blackPen : new Pen(Brushes.Gray, 1),
rect);
double middleX = rect.Left + rect.Width / 2;
double middleY = rect.Top + rect.Height / 2;
double space = Math.Round(rect.Width / 8) + 1;
double space = PixelSnapHelpers.Round(rect.Width / 8) + pixelSize.Width;
drawingContext.DrawLine(blackPen,
new Point(rect.Left + space, middleY),
new Point(rect.Right - space, middleY));

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/BackgroundGeometryBuilder.cs

@ -44,8 +44,10 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -44,8 +44,10 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary>
public void AddSegment(TextView textView, ISegment segment)
{
foreach (Rect r in GetRectsForSegment(textView, segment))
AddRectangle(r.Left, r.Top, r.Right, r.Bottom);
foreach (Rect r in GetRectsForSegment(textView, segment)) {
Rect roundedRect = PixelSnapHelpers.PixelAlign(r);
AddRectangle(roundedRect.Left, roundedRect.Top, roundedRect.Right, roundedRect.Bottom);
}
}
/// <summary>

55
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/PixelSnapHelpers.cs

@ -12,18 +12,67 @@ namespace ICSharpCode.AvalonEdit.Utils @@ -12,18 +12,67 @@ namespace ICSharpCode.AvalonEdit.Utils
{
static class PixelSnapHelpers
{
public static Size GetPixelSize()
{
return new Size(1, 1);
}
/// <summary>
/// Aligns val on the next middle of a pixel.
/// </summary>
public static double PixelAlign(double val)
{
// 0 -> 0.5
// 0.1 -> 0.5
// 0.5 -> 0.5
// 0.9 -> 0.5
// 1 -> 1.5
return Math.Round(val + 0.5) - 0.5;
}
public static Rect ToPixels(Rect rect)
/// <summary>
/// Aligns the borders of rect on the middles of pixels.
/// </summary>
public static Rect PixelAlign(Rect rect)
{
rect.X = PixelAlign(rect.X);
rect.Y = PixelAlign(rect.Y);
rect.Width = Math.Round(rect.Width);
rect.Height = Math.Round(rect.Height);
rect.Width = Round(rect.Width);
rect.Height = Round(rect.Height);
return rect;
}
public static Point Round(Point val)
{
return new Point(Round(val.X), Round(val.Y));
}
/// <summary>
/// Rounds val to a whole number of pixels.
/// </summary>
public static double Round(double val)
{
return Math.Round(val);
}
/// <summary>
/// Rounds val to an even number of pixels.
/// </summary>
public static double RoundToEven(double val)
{
// 0 -> 0
// 1 -> 2
// 2 -> 2
// 3 -> 4
return Math.Round(val / 2) * 2;
}
/// <summary>
/// Rounds val to an odd number of pixels.
/// </summary>
public static double RoundToOdd(double val)
{
return RoundToEven(val - 1) + 1;
}
}
}

Loading…
Cancel
Save