mirror of
https://github.com/whoahq/whoa.git
synced 2026-03-05 23:52:16 +03:00
477 lines
14 KiB
C++
477 lines
14 KiB
C++
#include "gx/font/Wrap.hpp"
|
|
#include "gx/font/CGxFont.hpp"
|
|
#include "gx/Font.hpp"
|
|
#include <cmath>
|
|
#include <cwctype>
|
|
#include <storm/Unicode.hpp>
|
|
|
|
void CalcWrapPoint(CGxFont* face, const char* currentText, float fontHeight, float blockWidth, uint32_t* numBytes, float* extent, const char** nextText, float a8, uint32_t flags, bool* a10, float* a11, float scale) {
|
|
if (fontHeight < 0.0f || blockWidth <= 0.0f || !currentText || !*currentText) {
|
|
*numBytes = 0;
|
|
*extent = 0.0f;
|
|
*nextText = nullptr;
|
|
|
|
return;
|
|
}
|
|
|
|
if (flags & 0x80) {
|
|
CalcWrapPointBillboarded(
|
|
currentText,
|
|
flags,
|
|
face,
|
|
fontHeight,
|
|
numBytes,
|
|
extent,
|
|
nextText,
|
|
a11,
|
|
scale
|
|
);
|
|
} else {
|
|
CalcWrapPointNonBillboarded(
|
|
currentText,
|
|
face,
|
|
fontHeight,
|
|
blockWidth,
|
|
numBytes,
|
|
extent,
|
|
nextText,
|
|
a8,
|
|
flags,
|
|
a10,
|
|
a11,
|
|
scale
|
|
);
|
|
}
|
|
}
|
|
|
|
void CalcWrapPointBillboarded(const char* currentText, uint32_t flags, CGxFont* face, float fontHeight, uint32_t* numBytes, float* extent, const char** nextText, float* a8, float scale) {
|
|
// TODO
|
|
}
|
|
|
|
void CalcWrapPointNonBillboarded(const char* currentText, CGxFont* face, float fontHeight, float blockWidth, uint32_t* numBytes, float* extent, const char** nextText, float a8, uint32_t flags, bool* a10, float* a11, float scale) {
|
|
if (fontHeight == 0.0f || flags & 0x4) {
|
|
fontHeight = GxuFontGetOneToOneHeight(face);
|
|
}
|
|
|
|
float v46 = 0.0f;
|
|
|
|
if (a8 > 0.0f) {
|
|
v46 += ceil(ScreenToPixelWidth(0, a8));
|
|
}
|
|
|
|
if (face->m_flags & 0x8) {
|
|
v46 += 4.0f;
|
|
} else if (face->m_flags & 0x1) {
|
|
v46 += 2.0f;
|
|
}
|
|
|
|
float pixelFontHeight = ScreenToPixelHeight(0, fontHeight);
|
|
float v41 = static_cast<float>(face->GetPixelSize()) / pixelFontHeight;
|
|
float pixelBlockWidth = ceil(v41 * blockWidth * static_cast<float>(GetScreenPixelWidth()));
|
|
|
|
if (a11) {
|
|
*a11 = 0.0f;
|
|
}
|
|
|
|
uint32_t v18 = 0;
|
|
uint32_t prevCode = 0;
|
|
float v42 = 0.0f;
|
|
float v56 = 0.0f;
|
|
auto startText = currentText;
|
|
int32_t advance = 0;
|
|
QUOTEDCODE quotedCode = CODE_NEWLINE;
|
|
|
|
while (*currentText) {
|
|
uint32_t code;
|
|
quotedCode = GxuDetermineQuotedCode(currentText, advance, 0, flags, code);
|
|
|
|
if (quotedCode == CODE_NEWLINE) {
|
|
currentText += advance;
|
|
v18 = currentText - startText;
|
|
v56 = v42 + v46;
|
|
|
|
break;
|
|
}
|
|
|
|
if (
|
|
quotedCode == CODE_COLORON
|
|
|| quotedCode == CODE_COLORRESTORE
|
|
|| quotedCode == CODE_HYPERLINKSTART
|
|
|| quotedCode == CODE_HYPERLINKSTOP
|
|
|| quotedCode == CODE_TEXTURESTOP
|
|
) {
|
|
currentText += advance;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (quotedCode == CODE_TEXTURESTART) {
|
|
GXUEMBEDDEDTEXTUREINFO textureInfo;
|
|
|
|
// TODO
|
|
// if (!ParseEmbeddedTexture(currentText, textureInfo, pixelFontHeight, scale, fontHeight)) {
|
|
// currentText += advance;
|
|
//
|
|
// continue;
|
|
// }
|
|
|
|
float v21 = textureInfo.float1C + v46;
|
|
|
|
if (pixelBlockWidth >= v21) {
|
|
v46 = v21;
|
|
|
|
if (a11 && *a11 < textureInfo.float18) {
|
|
*a11 = textureInfo.float18;
|
|
}
|
|
|
|
currentText += advance;
|
|
|
|
continue;
|
|
}
|
|
|
|
prevCode = code;
|
|
advance = 0;
|
|
}
|
|
|
|
if (face->NewCodeDesc(code)) {
|
|
float step = 0.0f;
|
|
|
|
if (prevCode) {
|
|
if (flags & 0x10) {
|
|
step = face->ComputeStepFixedWidth(prevCode, code);
|
|
} else {
|
|
step = face->ComputeStep(prevCode, code);
|
|
}
|
|
}
|
|
|
|
if (CanWrapBetween(code, prevCode)) {
|
|
if (*a10 || v18) {
|
|
v18 = currentText - startText;
|
|
}
|
|
|
|
*a10 = true;
|
|
v56 = v42 + v46;
|
|
}
|
|
|
|
float v38 = GetCharacterWidth(¤tText[advance], flags, code, face, fontHeight);
|
|
float v24 = step + v46;
|
|
if (pixelBlockWidth < v38 + v24) {
|
|
break;
|
|
}
|
|
|
|
prevCode = code;
|
|
v46 = v24;
|
|
v42 = v38;
|
|
}
|
|
|
|
currentText += advance;
|
|
}
|
|
|
|
v46 = (v42 + v46) / static_cast<float>(GetScreenPixelWidth());
|
|
float v57 = v56 / static_cast<float>(GetScreenPixelWidth());
|
|
v41 = pixelFontHeight / static_cast<float>(face->GetPixelSize());
|
|
|
|
if (quotedCode == CODE_NEWLINE || !*currentText) {
|
|
*extent = v46 * v41;
|
|
*nextText = currentText;
|
|
*numBytes = currentText - startText;
|
|
} else {
|
|
if (!v18 || flags & 0x2) {
|
|
*a10 = flags & 0x40;
|
|
*numBytes = currentText - startText;
|
|
*extent = v46 * v41;
|
|
} else {
|
|
*numBytes = v18;
|
|
*extent = v57 * v41;
|
|
currentText = &startText[v18];
|
|
}
|
|
|
|
while (*currentText) {
|
|
auto code = SUniSGetUTF8(reinterpret_cast<const uint8_t*>(currentText), &advance);
|
|
|
|
if (!iswspace(code)) {
|
|
break;
|
|
}
|
|
|
|
currentText += advance;
|
|
}
|
|
|
|
*nextText = currentText;
|
|
}
|
|
}
|
|
|
|
int32_t CanWrapBetween(uint32_t codeA, uint32_t codeB) {
|
|
if (!codeB) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeB != '-' && codeB != ';' && codeB != '/' && codeA != ('|') && codeA != '\xFF\xFF\xFF\xFF') {
|
|
if (iswspace(codeB)) {
|
|
return 0;
|
|
}
|
|
|
|
if (!iswspace(codeA)) {
|
|
bool v3, v5;
|
|
|
|
if (codeB > 0x3008) {
|
|
if (codeB <= 0x3014) {
|
|
if (codeB != 0x3014) {
|
|
switch (codeB) {
|
|
case 0x300A:
|
|
case 0x300C:
|
|
case 0x300E:
|
|
case 0x3010:
|
|
return 0;
|
|
|
|
default:
|
|
goto LABEL_18;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (codeB > 0xFF08) {
|
|
switch (codeB) {
|
|
case 0xFF3B:
|
|
case 0xFF5B:
|
|
case 0xFFE1:
|
|
case 0xFFE5:
|
|
case 0xFFE6:
|
|
return 0;
|
|
|
|
default:
|
|
goto LABEL_18;
|
|
}
|
|
}
|
|
|
|
if (codeB == 0xFF08) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeB > 0xFE5B) {
|
|
if (codeB == 0xFE5D) {
|
|
return 0;
|
|
}
|
|
|
|
v3 = codeB == 0xFF04;
|
|
} else {
|
|
if (codeB == 0xFE5B || codeB == 0x301D) {
|
|
return 0;
|
|
}
|
|
|
|
v3 = codeB == 0xFE59;
|
|
}
|
|
} else {
|
|
if (codeB == 0x3008) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeB <= '{') {
|
|
if (codeB != '{') {
|
|
switch (codeB) {
|
|
case '$':
|
|
case '(':
|
|
case '[':
|
|
case '\\':
|
|
return 0;
|
|
|
|
default:
|
|
goto LABEL_18;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (codeB == 0x2018 || codeB == 0x201C) {
|
|
return 0;
|
|
}
|
|
|
|
v3 = codeB == 0x2035;
|
|
}
|
|
|
|
if (v3) {
|
|
return 0;
|
|
}
|
|
|
|
LABEL_18:
|
|
if (codeA <= 0x2014) {
|
|
if (codeA < 0x2013) {
|
|
switch (codeA) {
|
|
case '!':
|
|
case '%':
|
|
case ')':
|
|
case ',':
|
|
case '.':
|
|
case ':':
|
|
case ';':
|
|
case '?':
|
|
case ']':
|
|
case '}':
|
|
case 0xB0:
|
|
case 0xB7:
|
|
return 0;
|
|
|
|
default:
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (codeA > 0xFE30) {
|
|
if (codeA > 0xFF5D) {
|
|
switch (codeA) {
|
|
case 0xFF70:
|
|
case 0xFF9E:
|
|
case 0xFF9F:
|
|
case 0xFFE0:
|
|
return 0;
|
|
|
|
default:
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
}
|
|
|
|
if (codeA != 0xFF5D) {
|
|
switch (codeA) {
|
|
case 0xFE50:
|
|
case 0xFE51:
|
|
case 0xFE52:
|
|
case 0xFE54:
|
|
case 0xFE55:
|
|
case 0xFE56:
|
|
case 0xFE57:
|
|
case 0xFE5A:
|
|
case 0xFE5C:
|
|
case 0xFE5E:
|
|
case 0xFF01:
|
|
case 0xFF05:
|
|
case 0xFF09:
|
|
case 0xFF0C:
|
|
case 0xFF0E:
|
|
case 0xFF1A:
|
|
case 0xFF1B:
|
|
case 0xFF1F:
|
|
case 0xFF3D:
|
|
return 0;
|
|
|
|
default:
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (codeA == 0xFE30) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeA > 0x3009) {
|
|
switch (codeA) {
|
|
case 0x300B:
|
|
case 0x300D:
|
|
case 0x300F:
|
|
case 0x3011:
|
|
case 0x3015:
|
|
case 0x301E:
|
|
case 0x30FC:
|
|
return 0;
|
|
|
|
default:
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
}
|
|
|
|
if (codeA == 0x3009) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeA <= 0x2027) {
|
|
if (codeA >= 0x2026 || codeA == 0x2019 || codeA == 0x201D || codeA == 0x2022) {
|
|
return 0;
|
|
}
|
|
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
|
|
if (codeA > 0x2103) {
|
|
if (codeA < 0x3001) {
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
|
|
v5 = codeA <= 0x3002;
|
|
} else {
|
|
if (codeA == 0x2103) {
|
|
return 0;
|
|
}
|
|
|
|
if (codeA < 0x2032) {
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
|
|
v5 = codeA <= 0x2033;
|
|
}
|
|
|
|
if (v5) {
|
|
return 0;
|
|
}
|
|
|
|
return codeB == 0x3002
|
|
|| codeB == 0xFF0C
|
|
|| (codeA >= 0x1100 && codeA <= 0x11FF)
|
|
|| (codeA >= 0x3000 && codeA <= 0xD7AF)
|
|
|| (codeA >= 0xF900 && codeA <= 0xFAFF)
|
|
|| (codeA >= 0xFF00 && codeA <= 0xFF9F)
|
|
|| codeA - 0xFFA0 <= 0x3C;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|