mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-06 03:58:02 +08:00
Clean up line wrapping logic.
This commit is contained in:
parent
1d52cba6c4
commit
25105346ab
@ -488,74 +488,117 @@ float screen_get_font_height(float scaleY) {
|
|||||||
return scaleY * fontGetInfo()->lineFeed;
|
return scaleY * fontGetInfo()->lineFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void screen_get_string_size_internal(float* width, float* height, const char* text, float scaleX, float scaleY, bool oneLine, bool wrap, float wrapWidth) {
|
#define MAX_LINES 64
|
||||||
|
|
||||||
|
inline static void screen_wrap_string_finish_line(float* w, float* h, float* lw, float* lh, u32* line, u32* linePos, u32* lastAlignPos,
|
||||||
|
u32* lines, float* lineWidths, float* lineHeights,
|
||||||
|
u32 maxLines) {
|
||||||
|
if(*lw > *w) {
|
||||||
|
*w = *lw;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h += *lh;
|
||||||
|
|
||||||
|
if(*line < maxLines) {
|
||||||
|
if(lines != NULL) {
|
||||||
|
lines[*line] = *linePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lineWidths != NULL) {
|
||||||
|
lineWidths[*line] = *lw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lineHeights != NULL) {
|
||||||
|
lineHeights[*line] = *lh;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*line)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lw = 0;
|
||||||
|
*lh = 0;
|
||||||
|
*linePos = 0;
|
||||||
|
*lastAlignPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void screen_wrap_string(u32* lines, float* lineWidths, float* lineHeights, u32* numLines, float* totalWidth, float* totalHeight,
|
||||||
|
const char* text, u32 maxLines, float maxWidth, float scaleX, float scaleY, bool wordWrap) {
|
||||||
scaleX *= font_scale;
|
scaleX *= font_scale;
|
||||||
scaleY *= font_scale;
|
scaleY *= font_scale;
|
||||||
|
|
||||||
float w = 0;
|
float w = 0;
|
||||||
float h = 0;
|
float h = 0;
|
||||||
float lineWidth = 0;
|
|
||||||
|
|
||||||
if(text != NULL) {
|
u32 line = 0;
|
||||||
h = scaleY * fontGetInfo()->lineFeed;
|
float lw = 0;
|
||||||
|
float lh = 0;
|
||||||
|
u32 linePos = 0;
|
||||||
|
u32 lastAlignPos = 0;
|
||||||
|
|
||||||
const uint8_t* p = (const uint8_t*) text;
|
const uint8_t* p = (const uint8_t*) text;
|
||||||
const uint8_t* lastAlign = p;
|
u32 code = 0;
|
||||||
u32 code = 0;
|
ssize_t units = -1;
|
||||||
ssize_t units = -1;
|
|
||||||
while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) {
|
|
||||||
p += units;
|
|
||||||
|
|
||||||
if(code == '\n' || (wrap && lineWidth + scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= wrapWidth)) {
|
while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) {
|
||||||
lastAlign = p;
|
p += units;
|
||||||
|
|
||||||
if(lineWidth > w) {
|
float charWidth = scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth;
|
||||||
w = lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
lineWidth = 0;
|
if(code == '\n' || (wordWrap && lw + charWidth >= maxWidth)) {
|
||||||
|
if(code == '\n') {
|
||||||
if(oneLine) {
|
linePos++;
|
||||||
break;
|
lh = scaleY * fontGetInfo()->lineFeed;
|
||||||
}
|
|
||||||
|
|
||||||
h += scaleY * fontGetInfo()->lineFeed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code != '\n') {
|
screen_wrap_string_finish_line(&w, &h, &lw, &lh, &line, &linePos, &lastAlignPos,
|
||||||
u32 num = 1;
|
lines, lineWidths, lineHeights,
|
||||||
if(code == '\t') {
|
maxLines);
|
||||||
code = ' ';
|
}
|
||||||
num = 4 - (p - units - lastAlign) % 4;
|
|
||||||
|
|
||||||
lastAlign = p;
|
if(code != '\n') {
|
||||||
}
|
u32 num = 1;
|
||||||
|
if(code == '\t') {
|
||||||
|
code = ' ';
|
||||||
|
num = 4 - (linePos - lastAlignPos) % 4;
|
||||||
|
|
||||||
lineWidth += (scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth) * num;
|
lastAlignPos = linePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lw += charWidth * num;
|
||||||
|
lh = scaleY * fontGetInfo()->lineFeed;
|
||||||
|
|
||||||
|
linePos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(width) {
|
if(linePos > 0) {
|
||||||
*width = lineWidth > w ? lineWidth : w;
|
screen_wrap_string_finish_line(&w, &h, &lw, &lh, &line, &linePos, &lastAlignPos,
|
||||||
|
lines, lineWidths, lineHeights,
|
||||||
|
maxLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(height) {
|
if(numLines != NULL) {
|
||||||
*height = h;
|
*numLines = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(totalWidth != NULL) {
|
||||||
|
*totalWidth = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(totalHeight != NULL) {
|
||||||
|
*totalHeight = h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_get_string_size(float* width, float* height, const char* text, float scaleX, float scaleY) {
|
void screen_get_string_size(float* width, float* height, const char* text, float scaleX, float scaleY) {
|
||||||
screen_get_string_size_internal(width, height, text, scaleX, scaleY, false, false, 0);
|
screen_wrap_string(NULL, NULL, NULL, NULL, width, height, text, 0, 0, scaleX, scaleY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_get_string_size_wrap(float* width, float* height, const char* text, float scaleX, float scaleY, float wrapWidth) {
|
void screen_get_string_size_wrap(float* width, float* height, const char* text, float scaleX, float scaleY, float wrapWidth) {
|
||||||
screen_get_string_size_internal(width, height, text, scaleX, scaleY, false, true, wrapWidth);
|
screen_wrap_string(NULL, NULL, NULL, NULL, width, height, text, 0, wrapWidth, scaleX, scaleY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void screen_draw_string_internal(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines, bool wrap, float wrapX) {
|
static void screen_draw_string_internal(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines, bool wrap, float wrapX) {
|
||||||
// Note: Do not just multiply scaleX and scaleY by font_scale, as they would then be double-scaled when passed into screen_get_string_size_internal.
|
|
||||||
|
|
||||||
if(text == NULL) {
|
if(text == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -576,62 +619,65 @@ static void screen_draw_string_internal(const char* text, float x, float y, floa
|
|||||||
|
|
||||||
screen_set_blend(blendColor, true, true);
|
screen_set_blend(blendColor, true, true);
|
||||||
|
|
||||||
float stringWidth;
|
u32 lines[MAX_LINES];
|
||||||
screen_get_string_size_internal(&stringWidth, NULL, text, scaleX, scaleY, false, wrap, wrapX - x);
|
float lineWidths[MAX_LINES];
|
||||||
|
float lineHeights[MAX_LINES];
|
||||||
float lineWidth;
|
u32 numLines = 0;
|
||||||
screen_get_string_size_internal(&lineWidth, NULL, text, scaleX, scaleY, true, wrap, wrapX - x);
|
float totalWidth = 0;
|
||||||
|
float totalHeight = 0;
|
||||||
|
screen_wrap_string(lines, lineWidths, lineHeights, &numLines, &totalWidth, &totalHeight, text, MAX_LINES, wrapX - x, scaleX, scaleY, wrap);
|
||||||
|
|
||||||
float currX = x;
|
float currX = x;
|
||||||
if(centerLines) {
|
float currY = y;
|
||||||
currX += (stringWidth - lineWidth) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
u32 linePos = 0;
|
||||||
|
u32 lastAlignPos = 0;
|
||||||
int lastSheet = -1;
|
int lastSheet = -1;
|
||||||
|
|
||||||
const uint8_t* p = (const uint8_t*) text;
|
const uint8_t* p = (const uint8_t*) text;
|
||||||
const uint8_t* lastAlign = p;
|
|
||||||
u32 code = 0;
|
u32 code = 0;
|
||||||
ssize_t units = -1;
|
ssize_t units = -1;
|
||||||
while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) {
|
|
||||||
p += units;
|
|
||||||
|
|
||||||
if(code == '\n' || (wrap && currX + scaleX * font_scale * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= wrapX)) {
|
for(u32 i = 0; i < numLines; i++) {
|
||||||
lastAlign = p;
|
currX = x;
|
||||||
|
if(centerLines) {
|
||||||
screen_get_string_size_internal(&lineWidth, NULL, (const char*) p, scaleX, scaleY, true, wrap, wrapX - x);
|
currX += (totalWidth - lineWidths[i]) / 2;
|
||||||
|
|
||||||
currX = x;
|
|
||||||
if(centerLines) {
|
|
||||||
currX += (stringWidth - lineWidth) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
y += scaleY * font_scale * fontGetInfo()->lineFeed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code != '\n') {
|
while(linePos < lines[i] && *p && (units = decode_utf8(&code, p)) != -1 && code > 0) {
|
||||||
u32 num = 1;
|
p += units;
|
||||||
if(code == '\t') {
|
|
||||||
code = ' ';
|
|
||||||
num = 4 - (p - units - lastAlign) % 4;
|
|
||||||
|
|
||||||
lastAlign = p;
|
if(code != '\n') {
|
||||||
|
u32 num = 1;
|
||||||
|
if(code == '\t') {
|
||||||
|
code = ' ';
|
||||||
|
num = 4 - (linePos - lastAlignPos) % 4;
|
||||||
|
|
||||||
|
lastAlignPos = linePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
fontGlyphPos_s data;
|
||||||
|
fontCalcGlyphPos(&data, fontGlyphIndexFromCodePoint(code), GLYPH_POS_CALC_VTXCOORD, scaleX * font_scale, scaleY * font_scale);
|
||||||
|
|
||||||
|
if(data.sheetIndex != lastSheet) {
|
||||||
|
lastSheet = data.sheetIndex;
|
||||||
|
C3D_TexBind(0, &glyph_sheets[lastSheet]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u32 j = 0; j < num; j++) {
|
||||||
|
screen_draw_quad(currX + data.vtxcoord.left, currY + data.vtxcoord.top, currX + data.vtxcoord.right, currY + data.vtxcoord.bottom, data.texcoord.left, data.texcoord.bottom, data.texcoord.right, data.texcoord.top);
|
||||||
|
|
||||||
|
currX += data.xAdvance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fontGlyphPos_s data;
|
linePos++;
|
||||||
fontCalcGlyphPos(&data, fontGlyphIndexFromCodePoint(code), GLYPH_POS_CALC_VTXCOORD, scaleX * font_scale, scaleY * font_scale);
|
|
||||||
|
|
||||||
if(data.sheetIndex != lastSheet) {
|
|
||||||
lastSheet = data.sheetIndex;
|
|
||||||
C3D_TexBind(0, &glyph_sheets[lastSheet]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i = 0; i < num; i++) {
|
|
||||||
screen_draw_quad(currX + data.vtxcoord.left, y + data.vtxcoord.top, currX + data.vtxcoord.right, y + data.vtxcoord.bottom, data.texcoord.left, data.texcoord.bottom, data.texcoord.right, data.texcoord.top);
|
|
||||||
|
|
||||||
currX += data.xAdvance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currY += lineHeights[i];
|
||||||
|
|
||||||
|
linePos = 0;
|
||||||
|
lastAlignPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_set_blend(0, false, false);
|
screen_set_blend(0, false, false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user