找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 144|回复: 0

[经验分享探讨] DTA中文换行完善

[复制链接]
发表于 2026-3-22 21:33:48 | 显示全部楼层 |阅读模式
直接完善TextParseReturnValue这个类之前的GetFixedTextLines ()和FixText ()换行对英文比较友好 对中文支持较差 导致的问题就是莫名奇妙的地方换行
特别是GetFixedTextLines ()的段落文本换行

包括战役描述 频道/房间聊天等

以下是论坛里相关的问题贴
https://bbs.ra2diy.com/forum.php?mod=viewthread&tid=25113
https://bbs.ra2diy.com/forum.php?mod=viewthread&tid=19882


以下换行已修好 段首的缩进是打了丑陋的空格
代码由AI进行完善 有其它问题自行修复


public static List<string> GetFixedTextLines(SpriteFont spriteFont, int width, string text, bool splitWords = true, bool keepBlankLines = false)
{
    if (string.IsNullOrEmpty(text))
        return new List<string>();

    List<string> result = new List<string>();
    string[] lines = text.Replace("\r", "").Split('\n');
    HashSet<char> punctuation = new HashSet<char> { '.', '。', ',', ',', ';', ';', '!', '!', '?', '?' };

    foreach (string line in lines)
    {
        if (keepBlankLines && string.IsNullOrEmpty(line))
        {
            result.Add("");
            continue;
        }

        if (string.IsNullOrWhiteSpace(line))
            continue;

        StringBuilder current = new StringBuilder();
        float currentW = 0f;

        for (int i = 0; i < line.Length; i++)
        {
            char c = line;
            float cw = spriteFont.MeasureString(c.ToString()).X;
            float testW = currentW + cw;

            bool isPunc = punctuation.Contains(c);
            if (testW > width && current.Length > 0 && !isPunc)
            {
                result.Add(current.ToString().TrimEnd());
                current.Clear();
                currentW = 0f;
            }

            current.Append(c);
            currentW += cw;
        }

        string final = current.ToString().TrimEnd();
        if (!string.IsNullOrEmpty(final))
            result.Add(final);
    }

    if (splitWords)
    {
        List<string> finalResult = new List<string>(result.Count);
        foreach (string line in result)
        {
            if (string.IsNullOrEmpty(line))
            {
                finalResult.Add("");
                continue;
            }

            if (spriteFont.MeasureString(line).X <= width)
            {
                finalResult.Add(line);
                continue;
            }

            StringBuilder sb = new StringBuilder();
            float w = 0f;

            for (int i = 0; i < line.Length; i++)
            {
                char c = line;
                float cw = spriteFont.MeasureString(c.ToString()).X;
                bool isPunc = punctuation.Contains(c);

                if (w + cw > width && sb.Length > 0 && !isPunc)
                {
                    finalResult.Add(sb.ToString());
                    sb.Clear();
                    w = 0f;
                }

                sb.Append(c);
                w += cw;
            }

            if (sb.Length > 0)
                finalResult.Add(sb.ToString());
        }
        result = finalResult;
    }

    return result;
}

public static TextParseReturnValue FixText(SpriteFont spriteFont, int width, string text)
{
    if (string.IsNullOrEmpty(text))
        return new TextParseReturnValue(string.Empty, 0);

    StringBuilder processedText = new StringBuilder();
    int lineCount = 0;
    string[] originalLines = text.Replace("\r", "").Split(new[] { '\n' }, StringSplitOptions.None);
    float indentWidth = spriteFont.MeasureString("       ").X;
    float spaceWidth = spriteFont.MeasureString(" ").X;
    HashSet<char> punctuation = new HashSet<char> { '.', '。', ',', ',', ';', ';', '!', '!', '?', '?' };

    foreach (string originalLine in originalLines)
    {
        if (string.IsNullOrWhiteSpace(originalLine))
        {
            processedText.AppendLine();
            lineCount++;
            continue;
        }

        string[] words = originalLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        if (words.Length == 0)
        {
            processedText.AppendLine();
            lineCount++;
            continue;
        }

        StringBuilder currentLine = new StringBuilder();
        float currentWidth = 0f;
        bool needIndent = true;

        foreach (string word in words)
        {
            float wordWidth = spriteFont.MeasureString(word).X;
            float requiredWidth = currentWidth + (currentLine.Length > 0 ? spaceWidth : 0) + wordWidth;

            if (needIndent)
                requiredWidth += indentWidth;

            if (requiredWidth <= width)
            {
                if (needIndent)
                {
                    currentLine.Append("       ");
                    currentWidth += indentWidth;
                    needIndent = false;
                }

                if (currentLine.Length > 0)
                    currentLine.Append(' ');

                currentLine.Append(word);
                currentWidth += (currentLine.Length > 1 ? spaceWidth : 0) + wordWidth;
            }
            else
            {
                if (currentLine.Length > 0)
                {
                    processedText.AppendLine(currentLine.ToString());
                    lineCount++;
                    currentLine.Clear();
                    currentWidth = 0f;
                    needIndent = false;
                }

                if (wordWidth > width)
                {
                    StringBuilder charBuf = new StringBuilder();
                    float charBufWidth = 0f;
                    bool firstCharLine = true;

                    for (int i = 0; i < word.Length; i++)
                    {
                        char c = word;
                        float cw = spriteFont.MeasureString(c.ToString()).X;
                        bool isPunc = punctuation.Contains(c);
                        float test = charBufWidth + cw;

                        if (firstCharLine)
                            test += indentWidth;

                        if (test > width && charBuf.Length > 0 && !isPunc)
                        {
                            if (firstCharLine)
                            {
                                charBuf.Insert(0, "       ");
                                charBufWidth += indentWidth;
                                firstCharLine = false;
                            }

                            processedText.AppendLine(charBuf.ToString());
                            lineCount++;
                            charBuf.Clear();
                            charBufWidth = 0f;
                        }

                        if (firstCharLine)
                        {
                            charBuf.Append("       ");
                            charBufWidth += indentWidth;
                            firstCharLine = false;
                        }

                        charBuf.Append(c);
                        charBufWidth += cw;
                    }

                    if (charBuf.Length > 0)
                    {
                        currentLine.Append(charBuf);
                        currentWidth = charBufWidth;
                        needIndent = false;
                    }
                }
                else
                {
                    currentLine.Append("       ");
                    currentLine.Append(word);
                    currentWidth = indentWidth + wordWidth;
                    needIndent = false;
                }
            }
        }

        if (currentLine.Length > 0)
        {
            processedText.AppendLine(currentLine.ToString());
            lineCount++;
        }
    }

    if (processedText.Length > 0)
        processedText.Length -= Environment.NewLine.Length;

    return new TextParseReturnValue(processedText.ToString(), lineCount);
}




您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|Archiver|手机版|管理员邮箱|红警DIY论坛 |网站地图

GMT+8, 2026-4-30 00:55 , Processed in 0.061830 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表