Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
DrawingState.cs
1using SkiaSharp;
2using System;
5using Waher.Script;
6
8{
12 public delegate string ElementToString(ILayoutElement Element);
13
17 public class DrawingState : IDisposable
18 {
19 private Dictionary<ILayoutElement, bool> relativeElements = null;
20 private readonly Variables session;
21 private readonly SKPaint textPenRoot;
22 private readonly SKFont fontRoot;
23 private readonly SKPaint defaultPen;
24 private SKCanvas canvas;
25 private SKPaint shapePen;
26 private SKPaint shapeFill;
27 private SKFont font;
28 private SKPaint textPen;
29 private float? width_0;
30 private float? height_x;
31 private SKSize areaSize;
32 private SKSize viewportSize;
33 private readonly float pixelsPerInch;
34 private bool logRelativeElements = false;
35
42 public DrawingState(SKCanvas Canvas, RenderSettings Settings, Variables Session)
43 {
44 this.canvas = Canvas;
45 this.session = Session;
46 this.pixelsPerInch = Settings.PixelsPerInch;
47 this.areaSize = this.viewportSize = new SKSize(Settings.Width, Settings.Height);
48
49 this.font = this.fontRoot = new SKFont()
50 {
51 Edging = SKFontEdging.SubpixelAntialias,
52 Hinting = SKFontHinting.Full,
53 Subpixel = true,
54 Size = (float)(Settings.FontSize * this.pixelsPerInch / 72),
55 Typeface = SKTypeface.FromFamilyName(Settings.FontName, SKFontStyle.Normal)
56 ?? SKTypeface.Default
57 };
58
59 this.textPen = this.textPenRoot = new SKPaint()
60 {
61 IsAntialias = true,
62 Style = SKPaintStyle.Fill,
63 Color = Settings.TextColor
64 };
65
66 this.defaultPen = new SKPaint()
67 {
68 IsAntialias = true,
69 Style = SKPaintStyle.Stroke,
70 Color = Settings.PenColor
71 };
72 }
73
77 public void Dispose()
78 {
79 this.textPen?.Dispose();
80 this.textPenRoot?.Dispose();
81 this.font?.Dispose();
82 this.fontRoot?.Dispose();
83 this.defaultPen?.Dispose();
84 }
85
89 public Variables Session => this.session;
90
94 public float PixelsPerInch => this.pixelsPerInch;
95
99 public SKCanvas Canvas
100 {
101 get => this.canvas;
102 internal set => this.canvas = value;
103 }
104
108 public SKPaint TextPen
109 {
110 get => this.textPen;
111 set => this.textPen = value;
112 }
113
117 public SKFont Font
118 {
119 get => this.font;
120 set => this.font = value;
121 }
122
126 public SKPaint DefaultPen => this.defaultPen;
127
131 public SKPaint ShapePen
132 {
133 get => this.shapePen;
134 set => this.shapePen = value;
135 }
136
140 public SKPaint ShapeFill
141 {
142 get => this.shapeFill;
143 set => this.shapeFill = value;
144 }
145
149 public float AreaWidth => this.areaSize.Width;
150
154 public float AreaHeight => this.areaSize.Height;
155
163 public void CalcDrawingSize(Length L, ref float Size, bool Horizontal, ILayoutElement Element)
164 {
165 switch (L.Unit)
166 {
167 // pixels (1px = 1/96th of 1in) (absolute)
168 case LengthUnit.Px:
169 Size = L.Value * this.pixelsPerInch / 96;
170 break;
171
172 // points (1pt = 1/72 of 1in) (absolute)
173 case LengthUnit.Pt:
174 Size = L.Value * this.pixelsPerInch / 72;
175 break;
176
177 // picas (1pc = 12 pt) (absolute)
178 case LengthUnit.Pc:
179 Size = L.Value * this.pixelsPerInch / 12;
180 break;
181
182 // centimeters (absolute)
183 case LengthUnit.Cm:
184 Size = L.Value * this.pixelsPerInch / 2.54f;
185 break;
186
187 // inches (1in = 96px = 2.54cm)
188 case LengthUnit.In:
189 Size = L.Value * this.pixelsPerInch;
190 break;
191
192 // millimeters (absolute)
193 case LengthUnit.Mm:
194 Size = L.Value * this.pixelsPerInch / 25.4f;
195 break;
196
197 // Relative to the font-size of the element (2em means 2 times the size of the current font)
198 case LengthUnit.Em:
199 float Size2 = L.Value * this.font.Size;
200 if (Size != Size2)
201 {
202 this.ReportMeasureRelative(Element);
203 Size = Size2;
204 }
205 break;
206
207 // Relative to the x-height of the current font (rarely used)
208 case LengthUnit.Ex:
209 if (!this.height_x.HasValue)
210 {
211 this.font.MeasureText("x", out SKRect Bounds, this.textPen);
212 this.height_x = Bounds.Height;
213 }
214
215 Size2 = L.Value * this.height_x.Value;
216 if (Size != Size2)
217 {
218 this.ReportMeasureRelative(Element);
219 Size = Size2;
220 }
221 break;
222
223 // Relative to the width of the "0" (zero)
224 case LengthUnit.Ch:
225 if (!this.width_0.HasValue)
226 this.width_0 = this.font.MeasureText("0", this.textPen);
227
228 Size2 = L.Value * this.width_0.Value;
229 if (Size != Size2)
230 {
231 this.ReportMeasureRelative(Element);
232 Size = Size2;
233 }
234 break;
235
236 // Relative to font-size of the root element
237 case LengthUnit.Rem:
238 Size2 = L.Value * this.fontRoot.Size;
239 if (Size != Size2)
240 {
241 this.ReportMeasureRelative(Element);
242 Size = Size2;
243 }
244 break;
245
246 // Relative to 1% of the width of the viewport
247 case LengthUnit.Vw:
248 Size2 = L.Value * this.viewportSize.Width / 100;
249 if (Size != Size2)
250 {
251 this.ReportMeasureRelative(Element);
252 Size = Size2;
253 }
254 break;
255
256 // Relative to 1% of the height of the viewport
257 case LengthUnit.Vh:
258 Size2 = L.Value * this.viewportSize.Height / 100;
259 if (Size != Size2)
260 {
261 this.ReportMeasureRelative(Element);
262 Size = Size2;
263 }
264 break;
265
266 // Relative to 1% of viewport's* smaller dimension
267 case LengthUnit.Vmin:
268 if (this.viewportSize.Width < this.viewportSize.Height)
269 Size2 = L.Value * this.viewportSize.Width / 100;
270 else
271 Size2 = L.Value * this.viewportSize.Height / 100;
272
273 if (Size != Size2)
274 {
275 this.ReportMeasureRelative(Element);
276 Size = Size2;
277 }
278 break;
279
280 // Relative to 1% of viewport's* larger dimension
281 case LengthUnit.Vmax:
282 if (this.viewportSize.Width > this.viewportSize.Height)
283 Size2 = L.Value * this.viewportSize.Width / 100;
284 else
285 Size2 = L.Value * this.viewportSize.Height / 100;
286
287 if (Size != Size2)
288 {
289 this.ReportMeasureRelative(Element);
290 Size = Size2;
291 }
292 break;
293
294 // Relative to the parent element
295 case LengthUnit.Percent:
296 if (Horizontal)
297 Size2 = L.Value * this.areaSize.Width / 100;
298 else
299 Size2 = L.Value * this.areaSize.Height / 100;
300
301 if (Size != Size2)
302 {
303 this.ReportMeasureRelative(Element);
304 Size = Size2;
305 }
306 break;
307
308 default:
309 Size = L.Value;
310 break;
311 }
312 }
313
319 public SKSize SetAreaSize(SKSize AreaSize)
320 {
321 SKSize Prev = this.areaSize;
322 this.areaSize = AreaSize;
323 return Prev;
324 }
325
332 {
333 if (Font is null)
334 return null;
335 else
336 return new FontState(Font.TextPen, Font.FontDef);
337 }
338
344 {
345 if (!(FontState is null))
346 {
347 this.textPen = FontState.Pen;
348 this.font = FontState.Font;
349 }
350 }
351
355 public bool MeasureRelative
356 {
357 get;
358 private set;
359 }
360
364 public IEnumerable<ILayoutElement> RelativeElements => this.relativeElements.Keys;
365
370 {
371 this.MeasureRelative = true;
372 if (this.logRelativeElements)
373 this.relativeElements[Element] = true;
374 }
375
380 public void ClearRelativeMeasurement(bool LogRelativeElements)
381 {
382 this.MeasureRelative = false;
383 this.logRelativeElements = LogRelativeElements;
384 if (this.logRelativeElements)
385 {
386 if (this.relativeElements is null)
387 this.relativeElements = new Dictionary<ILayoutElement, bool>();
388 else
389 this.relativeElements.Clear();
390 }
391 }
392
397 public string GetShortestRelativeMeasurement(ElementToString Map)
398 {
399 string Best = string.Empty;
400 int BestLen = int.MaxValue;
401
402 foreach (ILayoutElement Element in this.relativeElements.Keys)
403 {
404 string Item = Map(Element);
405 int Len = Item.Length;
406
407 if (Len < BestLen)
408 {
409 Best = Item;
410 BestLen = Len;
411 }
412 }
413
414 return Best;
415 }
416
421 {
422 return this.GetShortestRelativeMeasurement((E) => E.ToXml());
423 }
424
429 {
430 return this.GetShortestRelativeMeasurement((E) => E.ExportState());
431 }
432 }
433}
Contains information about an actionable area in a generated image.
Definition: Map.cs:7
SKCanvas Canvas
Current drawing canvas.
void Restore(FontState FontState)
Restores font settings, from a previous call to Push
float AreaWidth
Width of current area
FontState Push(Font Font)
Pushes new font settings.
float AreaHeight
Height of current area
SKSize SetAreaSize(SKSize AreaSize)
Sets the current area size.
string GetShortestRelativeMeasurement(ElementToString Map)
Gets the shortest relative measurements element, given an element to string mapping.
Variables Session
Current session.
Definition: DrawingState.cs:89
string GetShortestRelativeMeasurementXml()
Gets the shortest subtree XML of an element with relative measurements.
IEnumerable< ILayoutElement > RelativeElements
Relative elements.
SKPaint ShapeFill
Fill to use for shape, if no other is specified in the shape.
SKPaint TextPen
Current text paint settings
void Dispose()
IDisposable.Dispose
Definition: DrawingState.cs:77
DrawingState(SKCanvas Canvas, RenderSettings Settings, Variables Session)
Current drawing state.
Definition: DrawingState.cs:42
SKPaint ShapePen
Pen to use for shape, if no other is specified in the shape.
void ReportMeasureRelative(ILayoutElement Element)
Reports an element as having relative measurements.
void CalcDrawingSize(Length L, ref float Size, bool Horizontal, ILayoutElement Element)
Converts a defined length to drawing size.
string GetShortestRelativeMeasurementStateXml()
Gets the shortest subtree State XML of an element with relative measurements.
void ClearRelativeMeasurement(bool LogRelativeElements)
Clears information about first relative measurement.
bool MeasureRelative
If layout contains relative sizes and dimensions should be recalculated.
Drawing state for text.
Definition: FontState.cs:9
Abstract base class for fonts.
Definition: Font.cs:12
SKFont FontDef
Measured Font
Definition: Font.cs:241
LengthUnit Unit
Unit of length.
Definition: Length.cs:113
float Value
Value of length
Definition: Length.cs:104
float PixelsPerInch
Pixels per inch (default=96 pixels/inch)
float FontSize
Font size, in points
Collection of variables.
Definition: Variables.cs:25
Base interface for all layout elements.
LengthUnit
Unit of length
Definition: Length.cs:7
delegate string ElementToString(ILayoutElement Element)
Delegate to methods that return a string from a layout element.