-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathFractionBitmap.cs
More file actions
111 lines (90 loc) · 3.99 KB
/
Copy pathFractionBitmap.cs
File metadata and controls
111 lines (90 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using CSharpCodeAnalyst.TreeMap.Interfaces;
namespace CSharpCodeAnalyst.TreeMap.Bitmap;
public sealed class FractionBitmap
{
public BitmapSource Create(Dictionary<string, uint> workByDevelopers, IBrushFactory brushFactory, bool legend)
{
double allWork = workByDevelopers.Values.Sum(w => w);
const int width = 200;
const int height = 200;
var remainingWidth = width;
var remainingHeight = height;
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
var sorted = workByDevelopers.ToList().OrderByDescending(pair => pair.Value).ToList();
var oneUnitOfWork = width * height / allWork;
var x = 0;
var y = 0;
var vertical = true;
var index = 0;
// Background is white
dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, 2000, 2000));
foreach (var developersWork in sorted)
{
var brush = brushFactory.GetBrush(developersWork.Key);
if (legend)
{
var legendY = index * 30;
var legendX = 250;
var typeface = new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
var formattedText = new FormattedText(
developersWork.Key,
CultureInfo.InvariantCulture,
FlowDirection.LeftToRight,
typeface,
12,
Brushes.Black,
VisualTreeHelper.GetDpi(visual).PixelsPerDip);
dc.DrawText(formattedText, new Point(legendX + 25, legendY));
dc.DrawRectangle(brush, new Pen(Brushes.Black, 1), new Rect(legendX, legendY, 20, 20));
}
var workArea = developersWork.Value;
var pixelArea = oneUnitOfWork * workArea;
if (index == sorted.Count - 1)
{
pixelArea = remainingWidth * remainingHeight;
}
if (vertical)
{
var widthOfWork = (int)Math.Round(pixelArea / remainingHeight);
dc.DrawRectangle(brush, new Pen(Brushes.Black, 1), new Rect(x, y, widthOfWork, remainingHeight));
x += widthOfWork;
remainingWidth -= widthOfWork;
}
else
{
var heightOfWork = (int)Math.Round(pixelArea / remainingWidth);
dc.DrawRectangle(brush, new Pen(Brushes.Black, 1), new Rect(x, y, remainingWidth, heightOfWork));
y += heightOfWork;
remainingHeight -= heightOfWork;
}
vertical = !vertical;
index++;
}
dc.DrawRectangle(null, new Pen(Brushes.Black, 1), new Rect(0, 0, width, height));
}
// Render bit map and save
var renderTarget = new RenderTargetBitmap(2000, 2000, 96, 96, PixelFormats.Pbgra32);
renderTarget.Render(visual);
// The background is drawn as opaque white above, so the alpha-based trim cannot detect it
// (no transparent pixels exist). Trim by the white background color instead, otherwise the
// whole 2000x2000 canvas is returned with a huge white margin around the small content.
var trimmedBitmap = BitmapManipulation.TrimBitmap(renderTarget, Colors.White);
return trimmedBitmap;
}
private void SaveBitmap(BitmapSource bitmap, string filename)
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (var stream = File.Create(filename))
{
encoder.Save(stream);
}
}
}