private void PopulateMesh( LocalRectTransform rectTransform, float4x4 localToWorld, TextRenderer textRenderer, float4 color, TextData textData, DynamicBuffer <Vertex> vertices, DynamicBuffer <VertexIndex> triangles, DynamicBuffer <TextLine> lines) { var verticalAlignment = (_VerticalAlignmentOptions)textRenderer.Alignment; var horizontalAlignment = (_HorizontalAlignmentOptions)textRenderer.Alignment; var font = FontAssetFromEntity[textRenderer.Font]; var glyphData = FontGlyphFromEntity[textRenderer.Font]; float2 canvasScale = textRenderer.Size / font.PointSize * 0.1f; float stylePadding = 1.25f + (textRenderer.Bold ? font.BoldStyle / 4.0f : font.NormalStyle / 4.0f); float styleSpaceMultiplier = 1.0f + (textRenderer.Bold ? font.BoldSpace * 0.01f : font.NormalSpace * 0.01f); TextUtility.CalculateLines(rectTransform, canvasScale, styleSpaceMultiplier, glyphData, textData, lines); float textBlockHeight = lines.Length * font.LineHeight * canvasScale.y; float2 alignedStartPosition = TextUtility.GetAlignedStartPosition(rectTransform, textRenderer, font, textBlockHeight, canvasScale); float2 currentCharacter = alignedStartPosition; int lineIdx = 0; for (int i = 0; i < textData.Value.LengthInBytes; i++) { if (lineIdx < lines.Length && i == lines[lineIdx].CharacterOffset) { currentCharacter = new float2( TextUtility.GetAlignedLinePosition(rectTransform, lines[lineIdx].LineWidth, horizontalAlignment), alignedStartPosition.y - font.LineHeight * canvasScale.y * lineIdx); lineIdx++; } var character = textData.Value.GetChar(i); if (TextUtility.GetGlyph(character, glyphData, out FontGlyph ch)) { int startVertexIndex = i * 4; int startTriangleIndex = i * 6; float2 uv2 = new float2(ch.Scale, ch.Scale) * math.select(canvasScale, -canvasScale, textRenderer.Bold); float3 min = new float3(currentCharacter, 0) + new float3(ch.Metrics.horizontalBearingX - stylePadding, ch.Metrics.horizontalBearingY - ch.Metrics.height - stylePadding, 0) * new float3(canvasScale, 1f); float3 max = min + new float3(ch.Metrics.width + stylePadding * 2.0f, ch.Metrics.height + stylePadding * 2.0f, 0) * new float3(canvasScale, 1f); var v0 = math.mul(localToWorld, float4x4.Translate(min)).Position(); var v1 = math.mul(localToWorld, float4x4.Translate(new float3(max.x, min.y, min.z))).Position(); var v2 = math.mul(localToWorld, float4x4.Translate(max)).Position(); var v3 = math.mul(localToWorld, float4x4.Translate(new float3(min.x, max.y, min.z))).Position(); var normal = math.mul( new float4x4(localToWorld.Rotation(), new float3()), float4x4.Translate(new float3(0, 0, -1))).c3; float4 uv = new float4( ch.Rect.x - stylePadding, ch.Rect.y - stylePadding, ch.Rect.x + ch.Rect.width + stylePadding, ch.Rect.y + ch.Rect.height + stylePadding) / new float4(font.AtlasSize, font.AtlasSize); triangles[startTriangleIndex] = startVertexIndex + 2; triangles[startTriangleIndex + 1] = startVertexIndex + 1; triangles[startTriangleIndex + 2] = startVertexIndex; triangles[startTriangleIndex + 3] = startVertexIndex + 3; triangles[startTriangleIndex + 4] = startVertexIndex + 2; triangles[startTriangleIndex + 5] = startVertexIndex; vertices[startVertexIndex] = new Vertex() { Position = v0, Normal = (half4)normal, TexCoord0 = (half2)uv.xy, TexCoord1 = (half2)uv2, Color = (half4)color }; vertices[startVertexIndex + 1] = new Vertex() { Position = v1, Normal = (half4)normal, TexCoord0 = (half2)uv.zy, TexCoord1 = (half2)uv2, Color = (half4)color }; vertices[startVertexIndex + 2] = new Vertex() { Position = v2, Normal = (half4)normal, TexCoord0 = (half2)uv.zw, TexCoord1 = (half2)uv2, Color = (half4)color }; vertices[startVertexIndex + 3] = new Vertex() { Position = v3, Normal = (half4)normal, TexCoord0 = (half2)uv.xw, TexCoord1 = (half2)uv2, Color = (half4)color }; currentCharacter += new float2(ch.Metrics.horizontalAdvance * styleSpaceMultiplier, 0.0f) * canvasScale; } } }
public static void CalculateLines( LocalRectTransform renderBounds, float2 canvasScale, float styleSpaceMultiplier, DynamicBuffer <FontGlyph> glyphData, TextData textData, DynamicBuffer <TextLine> ret) { var maxLineWidth = renderBounds.Value.Size.x; //rect.Max.x - rect.Min.x; CurrentLineData currentLine = default; for (int i = 0; i < textData.Value.LengthInBytes; i++) { var character = textData.Value.GetChar(i); if (character == '\n') { ret.Add(new TextLine { CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth, }); currentLine.CharacterOffset = i + 1; currentLine.LineWidth = 0.0f; currentLine.LineWordIndex = 0; currentLine.WordCharacterCount = 0; currentLine.WordWidth = 0.0f; continue; } if (character == ' ') { currentLine.LineWordIndex++; currentLine.WordCharacterCount = -1; currentLine.WordWidth = 0.0f; } if (GetGlyph(character, glyphData, out var ch)) { if ((ch.Metrics.width * styleSpaceMultiplier * canvasScale.x) < renderBounds.Value.Size.x) { currentLine.WordCharacterCount++; float characterWidth = ch.Metrics.horizontalAdvance * styleSpaceMultiplier * canvasScale.x; currentLine.LineWidth += characterWidth; currentLine.WordWidth += characterWidth; if (currentLine.LineWidth > maxLineWidth) { if (currentLine.LineWordIndex != 0) { ret.Add(new TextLine { CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth - currentLine.WordWidth, }); currentLine.CharacterOffset = i - currentLine.WordCharacterCount + 1; currentLine.LineWidth = 0.0f; currentLine.WordWidth = 0.0f; i = i - currentLine.WordCharacterCount + 1; currentLine.LineWordIndex = 0; currentLine.WordCharacterCount = 0; } else { ret.Add(new TextLine { CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth, }); currentLine.CharacterOffset = i; currentLine.LineWidth = 0.0f; currentLine.WordWidth = 0.0f; currentLine.LineWordIndex = 0; currentLine.WordCharacterCount = 0; } } continue; } ret.Add(new TextLine { CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth, }); currentLine.CharacterOffset = i; currentLine.LineWidth = 0.0f; currentLine.WordWidth = 0.0f; currentLine.LineWordIndex = 0; currentLine.WordCharacterCount = 0; } } ret.Add(new TextLine { CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth }); }