Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

CKeyStyle.cs

v0.1.0-build.85 Latest Commit ede38f5

Size
6.7 KB
Lines
160
Language
csharp
SHA-256
79a4cbfc6d07…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1using System;
2using OpenCKey.Interop;
3
4namespace OpenCKey
5{
6 /// <summary>
7 /// How a Profile 0 symbol is painted (<c>ckey_style</c>). Styling never
8 /// moves where a reader samples: site geometry, the frame, finders, keys
9 /// and the quiet margin are fixed. The core checks every style
10 /// (<see cref="CKeySymbol.CheckStyle"/>) and, under the default
11 /// <see cref="StylePolicy.Strict"/> policy, renderers refuse one that fails.
12 /// </summary>
13 public sealed class CKeyStyle
14 {
15 private CKeyColor[] _accents = Array.Empty<CKeyColor>();
16
17 /// <summary>A default style: black ink on white (the same as <see cref="Plain"/>).</summary>
18 public CKeyStyle()
19 {
20 unsafe
21 {
22 NativeStyle s;
23 Native.EnsureAbi();
24 NativeMethods.ckey_style_default(&s);
25 Load(in s);
26 }
27 }
28
29 /// <summary>A new copy of the <see cref="CKeyStylePreset.Plain"/> preset.</summary>
30 public static CKeyStyle Plain => FromPreset(CKeyStylePreset.Plain);
31
32 /// <summary>A new copy of the <see cref="CKeyStylePreset.Concept"/> preset.</summary>
33 public static CKeyStyle Concept => FromPreset(CKeyStylePreset.Concept);
34
35 /// <summary>A new style filled from a named preset.</summary>
36 public static unsafe CKeyStyle FromPreset(CKeyStylePreset preset)
37 {
38 Native.EnsureAbi();
39 NativeStyle s;
40 Native.Check(NativeMethods.ckey_style_preset_fill(&s, (int)preset), "ckey_style_preset_fill");
41 var style = new CKeyStyle(skipDefault: true);
42 style.Load(in s);
43 return style;
44 }
45
46 private CKeyStyle(bool skipDefault)
47 {
48 _ = skipDefault;
49 }
50
51 /// <summary>Background colour at the centre.</summary>
52 public CKeyColor Background { get; set; }
53 /// <summary>Background colour at the edge (radial vignette); equal to <see cref="Background"/> for a solid fill.</summary>
54 public CKeyColor BackgroundEdge { get; set; }
55 /// <summary>Mark colour; the light side of a metallic sheen.</summary>
56 public CKeyColor Ink { get; set; }
57 /// <summary>Sheen shade across the symbol; equal to <see cref="Ink"/> for flat ink.</summary>
58 public CKeyColor InkShade { get; set; }
59
60 /// <summary>Up to four accent colours for payload marks.</summary>
61 public CKeyColor[] Accents
62 {
63 get => (CKeyColor[])_accents.Clone();
64 set
65 {
66 if (value == null) throw new ArgumentNullException(nameof(value));
67 if (value.Length > 4) throw new ArgumentOutOfRangeException(nameof(value), "A style has at most four accents.");
68 _accents = (CKeyColor[])value.Clone();
69 }
70 }
71
72 /// <summary>0..100: share of payload marks drawn in accent colours.</summary>
73 public int AccentPercent { get; set; }
74 /// <summary>Payload module shape.</summary>
75 public ModuleShape Modules { get; set; }
76 /// <summary>Ring mark style.</summary>
77 public RingStyle Rings { get; set; }
78 /// <summary>Ray caps.</summary>
79 public RayCap Rays { get; set; }
80 /// <summary>0..1 embossed highlight.</summary>
81 public double Bevel { get; set; }
82 /// <summary>0..1 drop-shadow depth.</summary>
83 public double Shadow { get; set; }
84 /// <summary>0..1 background grain.</summary>
85 public double Texture { get; set; }
86 /// <summary>Logo image URL or data: URI (SVG export); null or empty for none.</summary>
87 public string? LogoHref { get; set; }
88 /// <summary>Logo radius in canonical units; 0 = the empty centre's size.</summary>
89 public double LogoRadius { get; set; }
90 /// <summary>Draw a background disc behind the logo.</summary>
91 public bool LogoPlate { get; set; }
92 /// <summary>Optical-safety policy (default <see cref="StylePolicy.Strict"/>).</summary>
93 public StylePolicy Policy { get; set; }
94
95 /// <summary>A deep copy.</summary>
96 public CKeyStyle Clone()
97 {
98 var c = (CKeyStyle)MemberwiseClone();
99 c._accents = (CKeyColor[])_accents.Clone();
100 return c;
101 }
102
103 internal unsafe void Load(in NativeStyle s)
104 {
105 Background = CKeyColor.FromNative(s.Background);
106 BackgroundEdge = CKeyColor.FromNative(s.BackgroundEdge);
107 Ink = CKeyColor.FromNative(s.Ink);
108 InkShade = CKeyColor.FromNative(s.InkShade);
109 int count = (int)Math.Min(s.AccentCount, 4u);
110 var all = new[] { s.Accent0, s.Accent1, s.Accent2, s.Accent3 };
111 _accents = new CKeyColor[count];
112 for (int i = 0; i < count; i++) _accents[i] = CKeyColor.FromNative(all[i]);
113 AccentPercent = (int)s.AccentPercent;
114 Modules = (ModuleShape)s.Modules;
115 Rings = (RingStyle)s.Rings;
116 Rays = (RayCap)s.Rays;
117 Bevel = s.Bevel;
118 Shadow = s.Shadow;
119 Texture = s.Texture;
120 LogoHref = Native.FromUtf8Z((byte*)s.LogoHref);
121 LogoRadius = s.LogoRadius;
122 LogoPlate = s.LogoPlate != 0;
123 Policy = (StylePolicy)s.Policy;
124 }
125
126 /// <summary>UTF-8, NUL-terminated logo href to pin for the duration of a native call.</summary>
127 internal byte[]? LogoHrefUtf8Z() => string.IsNullOrEmpty(LogoHref) ? null : Native.ToUtf8Z(LogoHref);
128
129 /// <summary>Fills a native style. logoHref must stay pinned while the native style is in use.</summary>
130 internal NativeStyle ToNative(IntPtr logoHref)
131 {
132 if (AccentPercent < 0) throw new ArgumentOutOfRangeException(nameof(AccentPercent));
133 var a = new NativeRgb[4];
134 for (int i = 0; i < _accents.Length; i++) a[i] = _accents[i].ToNative();
135 return new NativeStyle
136 {
137 Background = Background.ToNative(),
138 BackgroundEdge = BackgroundEdge.ToNative(),
139 Ink = Ink.ToNative(),
140 InkShade = InkShade.ToNative(),
141 Accent0 = a[0],
142 Accent1 = a[1],
143 Accent2 = a[2],
144 Accent3 = a[3],
145 AccentCount = (uint)_accents.Length,
146 AccentPercent = (uint)AccentPercent,
147 Modules = (int)Modules,
148 Rings = (int)Rings,
149 Rays = (int)Rays,
150 Bevel = Bevel,
151 Shadow = Shadow,
152 Texture = Texture,
153 LogoHref = logoHref,
154 LogoRadius = LogoRadius,
155 LogoPlate = LogoPlate ? 1u : 0u,
156 Policy = (uint)Policy,
157 };
158 }
159 }
160}