#include #include

// 定义一个结构体表示一个断点 struct BreakPoint { int pos; // 断点位置 int score; // 断点得分 };

// 计算从start到end的字符串宽度 int measureWidth(const std::vector& widths, int start, int end) { int width = 0; for (int i = start; i < end; i++) { width += widths[i]; } return width; }

// 根据行宽、中断点位置、后断点位置、断点得分和上一个断点位置进行换行 std::vector lineBreak(const std::vector& widths, int maxLineWidth, const std::vector& breakPoints, int lastBreakpoint) { std::vector lineBreaks; int currentLineWidth = 0; int lastBreakPos = -1; int lastBreakScore = 0;

for (int i = 0; i < breakPoints.size(); i++) {
    int breakPos = breakPoints[i];
    int breakScore = 0;

    // 计算断点得分
    if (i > 0) {
        int prevBreakPos = breakPoints[i - 1];
        int prevBreakWidth = measureWidth(widths, prevBreakPos, breakPos);
        int prevLineWidth = measureWidth(widths, lastBreakPos + 1, prevBreakPos);
        int remainingSpace = maxLineWidth - currentLineWidth - prevLineWidth;
        breakScore = remainingSpace - prevBreakWidth;
    }

    // 如果当前行宽加上当前断点宽度超过了最大行宽,则需要换行
    if (currentLineWidth + widths[breakPos] > maxLineWidth) {
        // 如果上一个断点位置不是-1,说明当前断点不能作为行首
        if (lastBreakPos != -1) {
            lineBreaks.push_back(lastBreakPos);
            currentLineWidth = measureWidth(widths, lastBreakPos + 1, breakPos);
            lastBreakScore = 0;
        }
        // 否则,当前断点作为行首,需要计算得分
        else {
            int remainingSpace = maxLineWidth - currentLineWidth;
            int breakScore = remainingSpace - widths[breakPos];
            if (breakScore < 0) {
                breakScore = std::numeric_limits<int>::min();
            }
            currentLineWidth = widths[breakPos];
        }
    }
    // 否则,当前断点可以加入当前行
    else {
        currentLineWidth += widths[breakPos];
    }

    // 如果当前断点得分比上一个断点得分高,则将当前断点作为下一个断点
    if (breakScore > lastBreakScore) {
        lastBreakPos = breakPos;
        lastBreakScore = breakScore;
    }
}

// 如果最后一个断点位置不是行尾,则将最后一个断点作为行尾
if (lastBreakPos != breakPoints.back()) {
    lineBreaks.push_back(lastBreakPos);
}

return lineBreaks;

}

// 该算法接受一个字符宽度数组widths,一个最大行宽maxLineWidth,一个断点位置数组breakPoints,和一个上一个断点位置lastBreakpoint。 // 它计算出一组行断点,用于将给定的字符串划分为多行,使每行的宽度不超过最大行宽。 // 断点位置是指字符串中可以换行的位置,比如空格、连字符、标点等。

// 算法的基本思路是遍历断点位置,计算当前行宽和断点得分,并根据最大行宽和得分决定是否换行。 // 如果需要换行,则将上一个断点作为行尾,并将当前断点作为下一个行首。 // 如果当前断点得分比上一个断点得分高,则将当前断点作为下一个断点。 // 最后,如果最后一个断点位置不是行尾,则将最后一个断点作为行尾。

// 这个算法类似于minikin库的HIGHQUALITY算法,但是没有考虑字体和字号等因素,只考虑了字符宽度。 // 如果需要考虑字体和字号等因素,可以在计算字符宽度时加入这些因素的影响。

C++ 代码示例:基于行宽、中断点位置和得分的换行算法 (类似于 Minikin 库的 HIGHQUALITY 算法)

原文地址: https://www.cveoy.top/t/topic/oiRX 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录