public static Point PivotPoint(Align align, Rectangle rect) // computes the pivot of a given rectangle { int pivotPosX = align.HasFlag(Align.Left) ? 0 : align.HasFlag(Align.Right) ? rect.Width : rect.Width / 2; int pivotPosY = align.HasFlag(Align.Top) ? 0 : align.HasFlag(Align.Bottom) ? rect.Height : rect.Height / 2; return(new Point(pivotPosX, pivotPosY)); }
public static Align Flip(Align al) // switches left/right flag if present { if (al.HasFlag(Align.Left)) { al += Align.Right - Align.Left; } else if (al.HasFlag(Align.Right)) { al -= Align.Right - Align.Left; } return(al); }
/// <summary> /// Draws multi-line text string at specified location wrapped at the specified width. Only the sub-string up to the end is drawn. /// White space is stripped at the beginning of the rows, the text is split at word boundries or when new-line characters are encountered. /// Words longer than the max width are slit at nearest character (i.e. no hyphenation). /// </summary> public static void TextBox(this Nvg nvg, Vector2D <float> pos, float breakRowWidth, string @string, string end) { State state = nvg.stateStack.CurrentState; int rowCount; Align oldAlign = state.TextAlign; Align hAlign = state.TextAlign & (Align.Left | Align.Centre | Align.Right); Align vAlign = state.TextAlign & (Align.Top | Align.Middle | Align.Bottom | Align.Baseline); if (state.FontId == Fontstash.INVALID) { return; } TextMetrics(nvg, out _, out _, out float lineh); state.TextAlign = Align.Left | vAlign; while ((rowCount = TextBreakLines(nvg, @string, end, breakRowWidth, out TextRow[] rows, 2)) != 0) { for (int i = 0; i < rowCount; i++) { if (hAlign.HasFlag(Align.Left)) { _ = Text(nvg, pos, rows[i].Start, rows[i].End.Length > 0 ? rows[i].End : null); } else if (hAlign.HasFlag(Align.Centre)) { _ = Text(nvg, pos.X + breakRowWidth * 0.5f, pos.Y - rows[i].Width * 0.5f, rows[i].Start, rows[i].End.Length > 0 ? rows[i].End : null); } else if (hAlign.HasFlag(Align.Right)) { _ = Text(nvg, pos.X + breakRowWidth - rows[i].Width, pos.Y, rows[i].Start, rows[i].End.Length > 0 ? rows[i].End : null); } pos.Y += lineh * state.LineHeight; } @string = rows[rowCount - 1].Next; } state.TextAlign = oldAlign; }
public static Vector2 Offset(this Align align, Vector2 size, Rectangle bounds, Vector2 origin, Vector2 scale) { var offset = new Vector2(bounds.Width / 2 - size.X / 2 + origin.X * scale.X, bounds.Height / 2 - size.Y / 2 + origin.Y * scale.Y); if (align.HasFlag(Align.Left)) { offset.X -= offset.X; } if (align.HasFlag(Align.Right)) { offset.X += offset.X; } if (align.HasFlag(Align.Top)) { offset.Y -= offset.Y; } if (align.HasFlag(Align.Bottom)) { offset.Y += offset.Y; } return(new Vector2(bounds.X + offset.X, bounds.Y + offset.Y)); }
/// <summary> /// Measures the specified multi-text string.<br/> /// Measured values are returned in local space. /// </summary> /// <param name="bounds">Contains the bounds box of the multi-text when returned.</param> public static void TextBoxBounds(this Nvg nvg, Vector2D <float> pos, float breakRowWidth, string @string, string end, out Rectangle <float> bounds) { Fontstash fons = nvg.fontManager.Fontstash; State state = nvg.stateStack.CurrentState; float scale = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio; float invscale = 1.0f / scale; int nrows; Align oldAlign = state.TextAlign; Align hAlign = state.TextAlign & (Align.Left | Align.Centre | Align.Right); Align vAlign = state.TextAlign & (Align.Top | Align.Middle | Align.Bottom | Align.Baseline); if (state.FontId == Fontstash.INVALID) { bounds = default; return; } nvg.TextMetrics(out _, out _, out float lineh); state.TextAlign = Align.Left | vAlign; float minX = pos.X, maxX = pos.X; float minY = pos.Y, maxY = pos.Y; fons.SetSize(state.FontSize * scale); fons.SetSpacing(state.LetterSpacing * scale); fons.SetBlur(state.FontBlur * scale); fons.SetAlign((int)state.TextAlign); fons.SetFont(state.FontId); fons.LineBounds(0, out float rMinY, out float rMaxY); rMinY *= invscale; rMaxY *= invscale; while ((nrows = TextBreakLines(nvg, @string, end, breakRowWidth, out TextRow[] rows, 2)) != 0) { for (uint i = 0; i < nrows; i++) { float rMinX, rMaxX; float dx = 0.0f; if (hAlign.HasFlag(Align.Left)) { dx = 0.0f; } else if (hAlign.HasFlag(Align.Centre)) { dx = breakRowWidth * 0.5f - rows[i].Width * 0.5f; } else if (hAlign.HasFlag(Align.Right)) { dx = breakRowWidth - rows[i].Width; } rMinX = pos.X + rows[i].MinX + dx; rMaxX = pos.X + rows[i].MaxX + dx; minX = MathF.Min(minX, rMinX); maxX = MathF.Max(maxX, rMaxX); minY = MathF.Min(minY, pos.Y + rMinY); maxY = MathF.Max(maxY, pos.Y + rMaxY); pos.Y += lineh * state.LineHeight; } @string = rows[nrows - 1].Next; } state.TextAlign = oldAlign; bounds = new Rectangle <float>(new Vector2D <float>(minX, minY), new Vector2D <float>(maxX, maxY) - new Vector2D <float>(minX, minY)); }