NANCY: Make text rendering pixel-perfect

Made changes to the Textbox and Font classes so the text rendering in nancy1 looks exactly the same as it does in the original engine.
This commit is contained in:
fracturehill 2021-04-17 15:09:18 +03:00
parent 29cf663f45
commit 54d6de7b57
4 changed files with 37 additions and 6 deletions

View File

@ -118,6 +118,27 @@ void Font::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 col
}
}
void Font::wordWrap(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines, int initWidth) const {
Common::String temp;
for (const char *c = str.begin(); c != str.end(); ++c) {
temp += *c;
int size = getStringWidth(temp) + (lines.size() == 0 ? initWidth : 0);
if (size >= maxWidth) {
do {
temp.deleteLastChar();
--c;
} while (temp.size() && temp.lastChar() != ' ');
lines.push_back(temp);
temp.clear();
}
}
if (temp.size()) {
lines.push_back(temp);
}
}
Common::Rect Font::getCharacterSourceRect(char chr) const {
using namespace Common;
uint offset = 0;

View File

@ -49,11 +49,14 @@ public:
void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
// Custom word wrapping function to fix an edge case with overflowing whitespaces
void wordWrap(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines, int initWidth = 0) const;
private:
Common::Rect getCharacterSourceRect(char chr) const;
Common::String _description; // 0xA
Common::Point _colorCoordsOffset; // y is def at 0x34, x is just a guess
Common::Point _colorCoordsOffset; // 0x32
uint16 _spaceWidth; // 0x38

View File

@ -73,10 +73,10 @@ void Textbox::init() {
scrollbarDefaultPos.y = chunk->readUint16LE();
uint16 scrollbarMaxScroll = chunk->readUint16LE();
_firstLineOffset = chunk->readUint16LE();
_firstLineOffset = chunk->readUint16LE() + 1;
_lineHeight = chunk->readUint16LE();
// Not sure why but to get exact results we subtract 1
_borderWidth = chunk->readUint16LE() - 1;
_maxWidthDifference = chunk->readUint16LE();
chunk->seek(0x1FE, SEEK_SET);
_fontID = chunk->readUint16LE();
@ -141,7 +141,7 @@ void Textbox::drawTextbox() {
const Font *font = g_nancy->_graphicsManager->getFont(_fontID);
uint maxWidth = _fullSurface.w - _borderWidth * 2;
uint maxWidth = _fullSurface.w - _maxWidthDifference - _borderWidth - 2;
uint lineDist = _lineHeight + _lineHeight / 4;
for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
@ -211,7 +211,7 @@ void Textbox::drawTextbox() {
Array<Common::String> wrappedLines;
// Do word wrapping on the rest of the text
font->wordWrapText(currentSubLine, maxWidth, wrappedLines, horizontalOffset);
font->wordWrap(currentSubLine, maxWidth, wrappedLines, horizontalOffset);
if (hasHotspot) {
hotspot.left = _borderWidth;
@ -229,6 +229,12 @@ void Textbox::drawTextbox() {
++_numLines;
}
// Simulate a bug in the original engine where player text longer than
// a single line gets a double newline afterwards
if (wrappedLines.size() > 1 && hasHotspot) {
++_numLines;
}
horizontalOffset = 0;
}
@ -295,7 +301,7 @@ void Textbox::onScrollbarMove() {
uint16 Textbox::getInnerHeight() const {
uint lineDist = _lineHeight + _lineHeight / 4;
return _numLines * lineDist + _firstLineOffset + lineDist / 2;
return _numLines * lineDist + _firstLineOffset + lineDist / 2 - 1;
}
} // End of namespace UI

View File

@ -72,6 +72,7 @@ private:
uint16 _firstLineOffset;
uint16 _lineHeight;
uint16 _borderWidth;
uint16 _maxWidthDifference;
uint16 _numLines;
uint16 _fontID;