internal double CalcWidth(ReadOnlySpan <char> text) { if (NumberHelper.AreCloseZero(_fontSize)) { return(0); } if (text.Length == 0) { return(0); } var textHashCode = HashCodeMaker.Make(text); if (_textWidthCache.TryGetValue(textHashCode, out var textWidth)) { return(textWidth); } foreach (var c in text) { textWidth += CalcWidth(c); } _textWidthCache.Add(textHashCode, textWidth); return(textWidth); }
internal static (double Red, double Green, double Blue) HsvToRgb(double hue, double saturation, double value) { var h = NumberHelper.AreClose(hue, 1) ? 0 : hue; var s = saturation; var v = value; if (NumberHelper.AreCloseZero(s)) { return(v, v, v); } var dh = Math.Floor(h / (60.0 / 360)); var p = v * (1 - s); var q = v * (1 - s * (h / (60.0 / 360) - dh)); var t = v * (1 - s * (1 - (h / (60.0 / 360) - dh))); return(dh switch { 0 => (v, t, p), 1 => (q, v, p), 2 => (p, v, t), 3 => (p, q, v), 4 => (t, p, v), 5 => (v, p, q), _ => throw new Exception() });
internal static (double Red, double Green, double Blue) HsvToRgb(double hue, double saturation, double value) { var h = NumberHelper.AreClose(hue, 1) ? 0 : hue; var s = saturation; var v = value; double r, g, b; if (NumberHelper.AreCloseZero(s)) { r = v; g = v; b = v; } else { var dh = Math.Floor(h / (60.0 / 360)); var p = v * (1 - s); var q = v * (1 - s * (h / (60.0 / 360) - dh)); var t = v * (1 - s * (1 - (h / (60.0 / 360) - dh))); switch (dh) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; default: throw new Exception(); } } return(r, g, b); }
internal double Draw( Visual visual, ReadOnlySpan <char> text, double x, double y, Brush brush, DrawingContext dc, double maxWidth, TextAlignment align, BiaTextTrimmingMode trimming, bool isUseCache) { if (NumberHelper.AreCloseZero(_fontSize)) { return(0); } if (text.Length == 0) { return(0); } maxWidth = Math.Ceiling(maxWidth); if (maxWidth <= 0) { return(0); } var gr = trimming switch { BiaTextTrimmingMode.None => MakeGlyphRunNone(visual, text, maxWidth, isUseCache), BiaTextTrimmingMode.Standard => MakeGlyphRunStandard(visual, text, maxWidth, isUseCache), BiaTextTrimmingMode.Filepath => MakeGlyphRunFilepath(visual, text, maxWidth, isUseCache), _ => throw new ArgumentOutOfRangeException(nameof(trimming), trimming, null) }; if (gr == default) { return(0); } switch (align) { case TextAlignment.Left: break; case TextAlignment.Right: x += maxWidth - gr.Width; break; case TextAlignment.Center: x += (maxWidth - gr.Width) / 2; break; default: throw new ArgumentOutOfRangeException(nameof(align), align, null); } if (NumberHelper.AreCloseZero(x) && NumberHelper.AreCloseZero(y)) { dc.DrawGlyphRun(brush, gr.GlyphRun); } else { var hash = HashCodeMaker.Make(x, y); if (_translateCache.TryGetValue(hash, out var t) == false) { t = new TranslateTransform(x, y); _translateCache.Add(hash, t); } dc.PushTransform(t); dc.DrawGlyphRun(brush, gr.GlyphRun); dc.Pop(); } return(gr.Width); }