-
Notifications
You must be signed in to change notification settings - Fork 397
Expand file tree
/
Copy pathBannerFactory.cs
More file actions
129 lines (109 loc) · 4.02 KB
/
BannerFactory.cs
File metadata and controls
129 lines (109 loc) · 4.02 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
namespace ReClassNET.UI
{
public static class BannerFactory
{
private const int StdHeight = 48; // 96 DPI
private const int StdIconDim = 32;
private const int MaxCacheEntries = 20;
private static readonly Dictionary<string, Image> imageCache = new Dictionary<string, Image>();
/// <summary>Creates a banner with the given <paramref name="icon"/>, <paramref name="title"/> and <paramref name="text"/>.</summary>
/// <param name="bannerWidth">Width of the banner.</param>
/// <param name="bannerHeight">Height of the banner.</param>
/// <param name="icon">The icon of the banner.</param>
/// <param name="title">The title of the banner.</param>
/// <param name="text">The text of the banner.</param>
/// <param name="skipCache">True to skip cache.</param>
/// <returns>The created banner.</returns>
public static Image CreateBanner(int bannerWidth, int bannerHeight, Image icon, string title, string text, bool skipCache)
{
Contract.Requires(title != null);
Contract.Requires(text != null);
var bannerId = $"{bannerWidth}x{bannerHeight}:{title}:{text}";
if (skipCache || !imageCache.TryGetValue(bannerId, out var image))
{
image = new Bitmap(bannerWidth, bannerHeight, PixelFormat.Format24bppRgb);
using (var g = Graphics.FromImage(image))
{
int xIcon = DpiScaleInt(10, bannerHeight);
var rect = new Rectangle(0, 0, bannerWidth, bannerHeight);
using (var brush = new LinearGradientBrush(rect, Color.FromArgb(151, 154, 173), Color.FromArgb(27, 27, 37), LinearGradientMode.Vertical))
{
g.FillRectangle(brush, rect);
}
int wIconScaled = StdIconDim;
if (icon != null)
{
var iconRel = icon.Width / (float)icon.Height;
wIconScaled = (int)Math.Round(DpiScaleFloat(iconRel * StdIconDim, bannerHeight));
var hIconScaled = DpiScaleInt(StdIconDim, bannerHeight);
int yIcon = (bannerHeight - hIconScaled) / 2;
if (hIconScaled == icon.Height)
{
g.DrawImageUnscaled(icon, xIcon, yIcon);
}
else
{
g.DrawImage(icon, xIcon, yIcon, wIconScaled, hIconScaled);
}
var attributes = new ImageAttributes();
attributes.SetColorMatrix(new ColorMatrix
{
Matrix33 = 0.1f
});
int w = wIconScaled * 2;
int h = hIconScaled * 2;
int x = bannerWidth - w - xIcon;
int y = (bannerHeight - h) / 2;
g.DrawImage(icon, new Rectangle(x, y, w, h), 0, 0, icon.Width, icon.Height, GraphicsUnit.Pixel, attributes);
}
int tx = 2 * xIcon;
int ty = DpiScaleInt(4, bannerHeight);
if (icon != null)
{
tx += wIconScaled;
}
float fontSize = DpiScaleFloat((12.0f * 96.0f) / g.DpiY, bannerHeight);
using (var font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Bold))
{
DrawText(g, title, tx, ty, font, Color.White);
}
tx += xIcon;
ty += xIcon * 2 + 2;
float fontSizeSmall = DpiScaleFloat((9.0f * 96.0f) / g.DpiY, bannerHeight);
using (var fontSmall = new Font(FontFamily.GenericSansSerif, fontSizeSmall, FontStyle.Regular))
{
DrawText(g, text, tx, ty, fontSmall, Color.White);
}
}
if (!skipCache)
{
while (imageCache.Count > MaxCacheEntries)
{
imageCache.Remove(imageCache.Keys.First());
}
imageCache[bannerId] = image;
}
}
return image;
}
private static void DrawText(Graphics g, string text, int x, int y, Font font, Color color)
{
using (var brush = new SolidBrush(color))
{
using (var format = new StringFormat(StringFormatFlags.FitBlackBox | StringFormatFlags.NoClip))
{
g.DrawString(text, font, brush, x, y, format);
}
}
}
private static int DpiScaleInt(int x, int height) => (int)Math.Round((x * height) / (double)StdHeight);
private static float DpiScaleFloat(float x, int height) => (x * height) / StdHeight;
}
}