Added naive line break (#7076)

Co-authored-by: Hedara <hedara90@gmail.com>
This commit is contained in:
hedara90 2025-06-07 05:13:07 +02:00 committed by GitHub
parent 020be9d5b0
commit 8489b7a622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 135 additions and 1 deletions

View File

@ -32,6 +32,9 @@ u32 CountLineBreaks(u8 *src);
void BreakStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt);
void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt);
void BreakStringNaive(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt);
void BreakSubStringNaive(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt);
bool32 IsWordSplittingChar(const u8 *src, u32 index);
u32 GetStringBadness(struct StringLine *stringLines, u32 numLines, u32 maxWidth);
void BuildNewString(struct StringLine *stringLines, u32 numLines, u32 maxLines, u8 *str, enum ToggleScrollPrompt toggleScrollPrompt);

View File

@ -47,6 +47,137 @@ void BreakStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enu
BreakSubStringAutomatic(currSrc, maxWidth, screenLines, fontId, toggleScrollPrompt);
}
void BreakStringNaive(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt)
{
u32 currIndex = 0;
u8 *currSrc = src;
while (src[currIndex] != EOS)
{
if (src[currIndex] == CHAR_PROMPT_CLEAR)
{
u8 replacedChar = src[currIndex + 1];
src[currIndex + 1] = EOS;
BreakSubStringNaive(currSrc, maxWidth, screenLines, fontId, toggleScrollPrompt);
src[currIndex + 1] = replacedChar;
currSrc = &src[currIndex + 1];
}
currIndex++;
}
BreakSubStringNaive(currSrc, maxWidth, screenLines, fontId, toggleScrollPrompt);
}
#define SCROLL_PROMPT_WIDTH 8
void BreakSubStringNaive(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt)
{
// If the string already has line breaks, don't interfere with them
if (StringHasManualBreaks(src))
return;
// Sanity check
if (src[0] == EOS)
return;
u32 numChars = 1;
u32 numWords = 1;
u32 currWordIndex = 0;
u32 currWordLength = 1;
bool32 isPrevCharSplitting = FALSE;
bool32 isCurrCharSplitting;
// Get numbers of chars in string and count words
while (src[numChars] != EOS)
{
isCurrCharSplitting = IsWordSplittingChar(src, numChars);
if (isCurrCharSplitting && !isPrevCharSplitting)
numWords++;
isPrevCharSplitting = isCurrCharSplitting;
numChars++;
}
// Allocate enough space for word data
struct StringWord *allWords = Alloc(numWords*sizeof(struct StringWord));
allWords[currWordIndex].startIndex = 0;
allWords[currWordIndex].width = 0;
isPrevCharSplitting = FALSE;
// Fill in word begin index and lengths
for (u32 i = 1; i < numChars; i++)
{
isCurrCharSplitting = IsWordSplittingChar(src, i);
if (isCurrCharSplitting && !isPrevCharSplitting)
{
allWords[currWordIndex].length = currWordLength;
currWordIndex++;
currWordLength = 0;
}
else if (!isCurrCharSplitting && isPrevCharSplitting)
{
allWords[currWordIndex].startIndex = i;
allWords[currWordIndex].width = 0;
currWordLength++;
}
else
{
currWordLength++;
}
isPrevCharSplitting = isCurrCharSplitting;
}
allWords[currWordIndex].length = currWordLength;
// Fill in individual word widths
for (u32 i = 0; i < numWords; i++)
{
for (u32 j = 0; j < allWords[i].length; j++)
allWords[i].width += GetGlyphWidth(src[allWords[i].startIndex + j], FALSE, fontId);
}
// Step 1: Does it all fit one one line? Then no break
// Step 2: Try to split across minimum number of lines
u32 spaceWidth = GetGlyphWidth(CHAR_SPACE, FALSE, fontId);
u32 totalWidth = allWords[0].width;
// Calculate total widths without any line breaks
for (u32 i = 1; i < numWords; i++)
totalWidth += allWords[i].width + spaceWidth;
// If it doesn't fit on 1 line, do line breaks
if (totalWidth > maxWidth)
{
u32 currWidth = 0;
u32 numBreaks = 0;
u32 currWords = 1;
for (u32 wordIndex = 0; wordIndex < numWords; wordIndex++)
{
currWidth += allWords[wordIndex].width;
if (numBreaks == screenLines - 1)
{
if (SCROLL_PROMPT_WIDTH + currWidth + (currWords - 1) * spaceWidth > maxWidth)
{
src[allWords[wordIndex].startIndex - 1] = CHAR_PROMPT_SCROLL;
currWidth = allWords[wordIndex].length;
currWords = 1;
}
else
{
currWords++;
}
}
else
{
if (currWidth + (currWords - 1) * spaceWidth > maxWidth)
{
src[allWords[wordIndex].startIndex - 1] = CHAR_NEWLINE;
currWidth = allWords[wordIndex].width;
currWords = 1;
numBreaks++;
}
else
{
currWords++;
}
}
}
}
Free(allWords);
}
#undef SCROLL_PROMPT_WIDTH
void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId, enum ToggleScrollPrompt toggleScrollPrompt)
{
// If the string already has line breaks, don't interfere with them
@ -109,7 +240,7 @@ void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId,
// Step 1: Does it all fit one one line? Then no break
// Step 2: Try to split across minimum number of lines
u32 spaceWidth = GetGlyphWidth(0, FALSE, fontId);
u32 spaceWidth = GetGlyphWidth(CHAR_SPACE, FALSE, fontId);
u32 totalWidth = allWords[0].width;
// Calculate total widths without any line breaks
for (u32 i = 1; i < numWords; i++)