protected virtual void GetFontSelection([NotNull] SvgTextBase svgTextBase, float fontSize, out int fontSelection, out int horizontalMultiplier, out int verticalMultiplier) { this.EplTransformer.GetFontSelection(svgTextBase, fontSize, out fontSelection, out horizontalMultiplier, out verticalMultiplier); }
public TextDrawingState(TextDrawingState parent, SvgTextBase element) { this.Element = element; this.Renderer = parent.Renderer; this.Parent = parent; this.Current = parent.Current; this.TextBounds = parent.TextBounds; this.BaselinePath = element.GetBaselinePath(parent.Renderer) ?? parent.BaselinePath; var currPathLength = element.GetAuthorPathLength(); _authorPathLength = currPathLength == 0 ? parent._authorPathLength : currPathLength; }
protected virtual void GetFontSelection([NotNull] SvgTextBase svgTextBase, float fontSize, out string fontName, out int characterHeight, out int slant) { this.FingerPrintTransformer.GetFontSelection(svgTextBase, fontSize, out fontName, out characterHeight, out slant); }
public void Transform([NotNull] SvgTextBase svgTextBase, [NotNull] Matrix sourceMatrix, [NotNull] Matrix viewMatrix, out float startX, out float startY, out float fontSize, out Direction direction) { if (svgTextBase == null) { throw new ArgumentNullException(nameof(svgTextBase)); } if (sourceMatrix == null) { throw new ArgumentNullException(nameof(sourceMatrix)); } if (viewMatrix == null) { throw new ArgumentNullException(nameof(viewMatrix)); } startX = this.SvgUnitReader.GetValue(svgTextBase, svgTextBase.X.FirstOrDefault()); startY = this.SvgUnitReader.GetValue(svgTextBase, svgTextBase.Y.FirstOrDefault()); fontSize = this.SvgUnitReader.GetValue(svgTextBase, svgTextBase.FontSize); direction = this.GetDirection(sourceMatrix, viewMatrix); if ((int)direction % 2 > 0) { var lineHeightFactor = this.GetLineHeightFactor(svgTextBase); if (lineHeightFactor >= float.Epsilon) { startX -= fontSize / lineHeightFactor; } else { startX -= fontSize; } } this.ApplyMatrixOnPoint(startX, startY, sourceMatrix, viewMatrix, out startX, out startY); }
public virtual void GetFontSelection([NotNull] SvgTextBase svgTextBase, float fontSize, [NotNull] out string fontName, out int characterHeight, out int width) { if (svgTextBase == null) { throw new ArgumentNullException(nameof(svgTextBase)); } fontName = "0"; characterHeight = (int)Math.Max(fontSize, 10f); width = 0; }
private void RenderFill(SvgTextBase txt, ISvgRenderer renderer) { if (txt.Fill != null) { var brush = txt.Fill.GetBrush(txt, renderer, 1f); using (var pen = new Pen(brush, 0f)) { pen.TextSize = txt.FontSize.Value; pen.TextAlign = FromAnchor(txt.TextAnchor); var x = txt.X.Any() ? txt.X.FirstOrDefault().Value : 0f; var y = txt.Y.Any() ? txt.Y.FirstOrDefault().Value : 0f; pen.Paint.IsStroke = false; DrawLines(txt, renderer, x, y, pen); } } }
public virtual void GetFontSelection([NotNull] SvgTextBase svgTextBase, float fontSize, out int fontSelection, out int horizontalMultiplier, out int verticalMultiplier) { if (svgTextBase == null) { throw new ArgumentNullException(nameof(svgTextBase)); } // VALUE 203dpi 300dpi // ================================== // 1 20.3cpi 25cpi // 6pts 4pts // 8x12 dots 12x20 dots // 1:1.5 1:1.66 // ================================== // 2 16.9cpi 18.75cpi // 7pts 6pts // 10x16 dots 16x28 dots // 1:1.6 1:1.75 // ================================== // 3 14.5cpi 15cpi // 10pts 8pts // 12x20 dots 20x36 dots // 1:1.66 1:1.8 // ================================== // 4 12.7cpi 12.5cpi // 12pts 10pts // 14x24 dots 24x44 dots // 1:1.71 1:1.83 // ================================== // 5 5.6cpi 6.25cpi // 24pts 21pts // 32x48 dots 48x80 dots // 1:1.5 1:1.6 // ================================== // horizontal multiplier: Accepted Values: 1–6, 8 // vertical multiplier: Accepted Values: 1–9 var fontDefinitions = new SortedList <int, int> { { 12, 1 }, { 16, 2 }, { 20, 3 }, { 24, 4 } }; var lowerFontDefinitionCandidate = default(FontDefinitionCandidate); var upperFontDefinitionCandidate = default(FontDefinitionCandidate); foreach (var factor in new[] { 1, 2, 3, 4, 5, 6, 8 }) { foreach (var fontDefinition in fontDefinitions) { var actualFontSize = fontDefinition.Key * factor; // TODO find a good TOLERANCE if (Math.Abs(actualFontSize - fontSize) < 0.5f) { fontSelection = fontDefinition.Value; horizontalMultiplier = factor; verticalMultiplier = factor; return; } if (actualFontSize < fontSize) { if (lowerFontDefinitionCandidate == null || actualFontSize > lowerFontDefinitionCandidate.ActualHeight) { lowerFontDefinitionCandidate = new FontDefinitionCandidate { FontSelection = fontDefinition.Value, ActualHeight = actualFontSize, Multiplier = factor }; } } else if (actualFontSize <= fontSize + this.MaximumUpperFontSizeOverlap) { if (upperFontDefinitionCandidate == null || actualFontSize < upperFontDefinitionCandidate.ActualHeight) { upperFontDefinitionCandidate = new FontDefinitionCandidate { FontSelection = fontDefinition.Value, ActualHeight = actualFontSize, Multiplier = factor }; } break; } } } if (lowerFontDefinitionCandidate == null && upperFontDefinitionCandidate == null) { throw new ArgumentOutOfRangeException(nameof(fontSize), fontSize, $"Parameter {nameof(fontSize)} must be greater than {fontDefinitions.Keys.Min()}."); } if (lowerFontDefinitionCandidate == null) { fontSelection = upperFontDefinitionCandidate.FontSelection; horizontalMultiplier = upperFontDefinitionCandidate.Multiplier; verticalMultiplier = upperFontDefinitionCandidate.Multiplier; } else if (upperFontDefinitionCandidate == null) { fontSelection = lowerFontDefinitionCandidate.FontSelection; horizontalMultiplier = lowerFontDefinitionCandidate.Multiplier; verticalMultiplier = lowerFontDefinitionCandidate.Multiplier; } else { // :question: why dafuq are you doing it like this, and using no comparisons in the if-clause :question: // reason: idk if lower or upper is better, so I am leveling the playing field here // if I would add this to the if-clauses, the arithmetic behind it would be done // twice for the worst case. with this solution, the cost is stable for all scenarios var differenceLower = fontSize - lowerFontDefinitionCandidate.ActualHeight; var differenceUpper = upperFontDefinitionCandidate.ActualHeight - fontSize; if (differenceLower <= differenceUpper) { fontSelection = lowerFontDefinitionCandidate.FontSelection; horizontalMultiplier = lowerFontDefinitionCandidate.Multiplier; verticalMultiplier = lowerFontDefinitionCandidate.Multiplier; } else { fontSelection = upperFontDefinitionCandidate.FontSelection; horizontalMultiplier = upperFontDefinitionCandidate.Multiplier; verticalMultiplier = upperFontDefinitionCandidate.Multiplier; } } }
internal string PrepareText(SvgTextBase svgTextBase, string value) { value = ApplyTransformation(svgTextBase, value); value = new StringBuilder(value).Replace("\r\n", " ").Replace('\r', ' ').Replace('\n', ' ').Replace('\t', ' ').ToString(); return(svgTextBase.SpaceHandling == XmlSpaceHandling.preserve ? value : s_multipleSpaces.Replace(value.Trim(), " ")); }
internal virtual IEnumerable <ISvgNode> GetContentNodes(SvgTextBase svgTextBase) { return(svgTextBase.Nodes == null || svgTextBase.Nodes.Count < 1 ? svgTextBase.Children.OfType <ISvgNode>().Where(o => !(o is ISvgDescriptiveElement)) : svgTextBase.Nodes); }
public RectangleF GetBounds(SvgTextBase txt, ISvgRenderer renderer) { if (!txt.Visible || !txt.Displayable) { return(new RectangleF(0f, 0f, 0f, 0f)); } bool textIsEmpty = string.IsNullOrEmpty(txt.Text); bool hasNoChildren = !txt.Children.OfType <SvgTextBase>().Any(); if (textIsEmpty && hasNoChildren) { return(new RectangleF(0f, 0f, 0f, 0f)); } if (!textIsEmpty) { var brush = txt.Fill.GetBrush(txt, renderer, 1f); using (var pen = new Pen(brush, txt.StrokeWidth.Value)) { pen.TextSize = txt.FontSize.Value; pen.TextAlign = FromAnchor(txt.TextAnchor); var x = txt.X.Any() ? txt.X.FirstOrDefault().Value : 0f; var y = txt.Y.Any() ? txt.Y.FirstOrDefault().Value : 0f; float width = 0f; float height = 0f; bool isFirstLineRect = true; SKRect firstLineRect = default(SKRect); var lines = txt.Text.Split('\n'); var lineCount = lines.Length; // as android does not know the sense of "lines", we need to split the text and measure ourselves // see: http://stackoverflow.com/questions/6756975/draw-multi-line-text-to-canvas foreach (var line in lines) { SKRect rect = new SKRect(); pen.Paint.MeasureText(line, ref rect); if (isFirstLineRect) { firstLineRect = rect; isFirstLineRect = false; } var w = rect.Right - rect.Left; if (width < w) { width = w; } var h = rect.Bottom - rect.Top; if (height < h) { height = h; } } var x1 = x + firstLineRect.Left; var y1 = y + firstLineRect.Top; SvgTextBase t = txt; var anchor = t.TextAnchor; while (t != null && anchor == SvgTextAnchor.Inherit) { t = t.Parent as SvgTextBase; if (t == null) { anchor = SvgTextAnchor.Start; } else { anchor = t.TextAnchor; } } // textanchor affects boundingbox: // if "Middle" (aka Align.Center) then x is the center of the rectangle if (anchor == SvgTextAnchor.Middle) { x1 -= width / 2; } // if "End" (aka Align.Right) then x is at the very right end of the text else if (anchor == SvgTextAnchor.End) { x1 -= width; } return(new RectangleF(x1, y1, width, height * lineCount)); } } else if (!hasNoChildren) { RectangleF r = null; foreach (var child in txt.Children.OfType <SvgTextBase>()) { var bounds = GetBounds(child, renderer); if (r == null) { r = bounds; } else { r = r.UnionAndCopy(bounds); } } return(r); } return(new RectangleF(0f, 0f, 0f, 0f)); }
public override void Transform(SvgTextBase svgTextBase, Matrix sourceMatrix, Matrix viewMatrix, out float startX, out float startY, out float fontSize) { if (svgTextBase == null) { throw new ArgumentNullException(nameof(svgTextBase)); } if (sourceMatrix == null) { throw new ArgumentNullException(nameof(sourceMatrix)); } if (viewMatrix == null) { throw new ArgumentNullException(nameof(viewMatrix)); } base.Transform(svgTextBase, sourceMatrix, viewMatrix, out startX, out startY, out fontSize); var lineHeightFactor = this.GetLineHeightFactor(svgTextBase); float offset; if (lineHeightFactor >= float.Epsilon) { offset = fontSize / lineHeightFactor; } else { offset = fontSize; } var rotationSector = this.GetRotationSector(sourceMatrix, viewMatrix); var rotationQuotient = Math.DivRem(rotationSector, 2, out var remainder); if (remainder == 0) { if (rotationQuotient % 2 == 0) { startY += offset; } else { startY -= offset; } } else { if (rotationQuotient % 2 == 0) { startX -= offset; } else { startX += offset; } } }