void FFont::FixXMoves() { for (int i = 0; i <= LastChar - FirstChar; ++i) { if (Chars[i].XMove == INT_MIN) { // Try an uppercase character. if (myislower(i + FirstChar)) { int upper = upperforlower[FirstChar + i]; if (upper >= FirstChar && upper <= LastChar ) { Chars[i].XMove = Chars[upper - FirstChar].XMove; continue; } } // Try an unnaccented character. int noaccent = stripaccent(i + FirstChar); if (noaccent != i + FirstChar) { noaccent -= FirstChar; if (noaccent >= 0) { Chars[i].XMove = Chars[noaccent].XMove; continue; } } Chars[i].XMove = SpaceWidth; } } }
void FFont::CheckCase() { int lowercount = 0, uppercount = 0; for (unsigned i = 0; i < Chars.Size(); i++) { unsigned chr = i + FirstChar; if (lowerforupper[chr] == chr && upperforlower[chr] == chr) { continue; // not a letter; } if (myislower(chr)) { if (Chars[i].TranslatedPic != nullptr) lowercount++; } else { if (Chars[i].TranslatedPic != nullptr) uppercount++; } } if (lowercount == 0) return; // This is an uppercase-only font and we are done. // The ß needs special treatment because it is far more likely to be supplied lowercase only, even in an uppercase font. if (Chars[0xdf - FirstChar].TranslatedPic != nullptr) { if (LastChar < 0x1e9e) { Chars.Resize(0x1e9f - FirstChar); LastChar = 0x1e9e; } if (Chars[0x1e9e - FirstChar].TranslatedPic == nullptr) { std::swap(Chars[0xdf - FirstChar], Chars[0x1e9e - FirstChar]); lowercount--; uppercount++; if (lowercount == 0) return; } } }
unsigned int mytoupper(unsigned int c) { if (myislower(c)) c -=1; return c; }
bool myisupper(unsigned int c) { return !myislower(c); }
int FFont::GetCharCode(int code, bool needpic) const { if (code < 0 && code >= -128) { // regular chars turn negative when the 8th bit is set. code &= 255; } if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr)) { return code; } // Use different substitution logic based on the fonts content: // In a font which has both upper and lower case, prefer unaccented small characters over capital ones. // In a pure upper-case font, do not check for lower case replacements. if (!MixedCase) { // Try converting lowercase characters to uppercase. if (myislower(code)) { code = upperforlower[code]; if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr)) { return code; } } // Try stripping accents from accented characters. int newcode = stripaccent(code); if (newcode != code) { code = newcode; if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr)) { return code; } } } else { int originalcode = code; int newcode; // Try stripping accents from accented characters. This may repeat to allow multi-step fallbacks. while ((newcode = stripaccent(code)) != code) { code = newcode; if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr)) { return code; } } code = originalcode; if (myislower(code)) { int upper = upperforlower[code]; // Stripping accents did not help - now try uppercase for lowercase if (upper != code) return GetCharCode(upper, needpic); } // Same for the uppercase character. Since we restart at the accented version this must go through the entire thing again. while ((newcode = stripaccent(code)) != code) { code = newcode; if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr)) { return code; } } } return -1; }