private void DrawParagraph(float x, float y, float width, float mx, float my) { string text = "This is a longer chunk of text.\n \n" + " Would have used lorem ipsum but she was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."; string hoverText = "Hover your mouse over the text to see the calculated caret position."; uint gutter = 0; uint lnum = 0; float gx = 0.0f, gy = 0.0f; Rectangle <float> bounds; float px; _nvg.Save(); _nvg.FontSize(15.0f); _nvg.FontFace("sans"); _nvg.TextAlign(Align.Left | Align.Top); _nvg.TextMetrics(out _, out _, out float lineh); string start = text; string end = null; int nrows; while ((nrows = _nvg.TextBreakLines(start, end, width, out TextRow[] rows, 3)) != 0) { for (uint i = 0; i < nrows; i++) { TextRow row = rows[i]; bool hit = mx > x && mx < (x + width) && my >= y && my < (y + lineh); _nvg.BeginPath(); _nvg.FillColour(_nvg.Rgba(255, 255, 255, hit ? (byte)64 : (byte)16)); _nvg.Rect(x + row.MinX, y, row.MaxX - row.MinX, lineh); _nvg.Fill(); _nvg.FillColour(Colour.White); _ = _nvg.Text(x, y, row.Start, row.End.Length != 0 ? row.End : null); if (hit) { float caretX = (mx < x + row.Width / 2.0f) ? x : x + row.Width; px = x; int glyphCount = _nvg.TextGlyphPositions(x, y, row.Start, row.End, out GlyphPosition[] glyps, 100); for (uint j = 0; j < glyphCount; j++) { float x0 = glyps[j].X; float x1 = (j + 1 < glyphCount) ? glyps[j + 1].X : x + row.Width; gx = x0 * 0.3f + x1 * 0.7f; if (mx >= px && mx < gx) { caretX = glyps[j].X; } px = gx; } _nvg.BeginPath(); _nvg.FillColour(_nvg.Rgba(255, 192, 0, 255)); _nvg.Rect(caretX, y, 1.0f, lineh); _nvg.Fill(); gutter = lnum + 1; gx = x - 10.0f; gy = y + lineh / 2.0f; } lnum++; y += lineh; } start = rows[^ 1].Next;