mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-06 02:10:28 +00:00
NANCY: Implement Autotext images
Added support for images inside Autotext. Used extensively in nancy7.
This commit is contained in:
parent
b43b66dcc6
commit
9a549a88b2
@ -40,15 +40,19 @@ void Autotext::readData(Common::SeekableReadStream &stream) {
|
||||
_surfWidth = stream.readUint16LE();
|
||||
_surfHeight = stream.readUint16LE();
|
||||
|
||||
readFilename(stream, _imageName);
|
||||
Common::Path imageName;
|
||||
readFilename(stream, imageName);
|
||||
|
||||
uint16 numImages = stream.readUint16LE();
|
||||
if (numImages) {
|
||||
for (uint i = 0; i < numImages; ++i) {
|
||||
uint16 line = stream.readUint16LE();
|
||||
Common::Rect src;
|
||||
readRect(stream, src);
|
||||
addImage(line, src);
|
||||
}
|
||||
|
||||
_imageLineIDs.resize(numImages);
|
||||
_imageSrcs.resize(numImages);
|
||||
for (uint i = 0; i < numImages; ++i) {
|
||||
_imageLineIDs[i] = stream.readUint16LE();
|
||||
readRect(stream, _imageSrcs[i]);
|
||||
setImageName(imageName);
|
||||
}
|
||||
|
||||
stream.skip((5 - numImages) * (2 + 16));
|
||||
@ -139,6 +143,14 @@ void Autotext::execute() {
|
||||
Common::Rect textBounds = surf.getBounds();
|
||||
textBounds.left += _offset.x;
|
||||
textBounds.top += _offset.y;
|
||||
|
||||
const Font *font = g_nancy->_graphicsManager->getFont(_fontID);
|
||||
assert(font);
|
||||
uint d = (font->getFontHeight() + 1) / 2 + 1;
|
||||
|
||||
textBounds.top += d + 1;
|
||||
textBounds.left += d;
|
||||
|
||||
drawAllText(textBounds, _fontID, _fontID);
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,6 @@ protected:
|
||||
uint16 _surfWidth = 0;
|
||||
uint16 _surfHeight = 0;
|
||||
|
||||
// Data for displaying images inside text; not supported yet
|
||||
Common::Path _imageName;
|
||||
|
||||
Common::Array<uint16> _imageLineIDs;
|
||||
Common::Array<Common::Rect> _imageSrcs;
|
||||
|
||||
bool _useAutotextChunk = false;
|
||||
|
||||
// Only one of these is valid
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "engines/nancy/nancy.h"
|
||||
#include "engines/nancy/graphics.h"
|
||||
#include "engines/nancy/resource.h"
|
||||
|
||||
#include "engines/nancy/misc/hypertext.h"
|
||||
|
||||
@ -48,19 +49,35 @@ void HypertextParser::addTextLine(const Common::String &text) {
|
||||
_needsTextRedraw = true;
|
||||
}
|
||||
|
||||
void HypertextParser::addImage(uint16 lineID, const Common::Rect &src) {
|
||||
_imageLineIDs.push_back(lineID);
|
||||
_imageSrcs.push_back(src);
|
||||
}
|
||||
|
||||
void HypertextParser::setImageName(const Common::Path &name) {
|
||||
_imageName = name;
|
||||
}
|
||||
|
||||
void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, uint highlightFontID) {
|
||||
using namespace Common;
|
||||
|
||||
const Font *font = nullptr;
|
||||
const Font *highlightFont = nullptr;
|
||||
Graphics::ManagedSurface image;
|
||||
|
||||
_numDrawnLines = 0;
|
||||
|
||||
if (!_imageName.empty()) {
|
||||
g_nancy->_resource->loadImage(_imageName, image);
|
||||
}
|
||||
|
||||
for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
|
||||
Common::String currentLine;
|
||||
bool hasHotspot = false;
|
||||
Rect hotspot;
|
||||
Common::Queue<ColorFontChange> colorTextChanges;
|
||||
Common::Queue<uint16> newlineTokens;
|
||||
newlineTokens.push(0);
|
||||
int curFontID = fontID;
|
||||
uint numNonSpaceChars = 0;
|
||||
|
||||
@ -107,6 +124,7 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
}
|
||||
|
||||
currentLine += '\n';
|
||||
newlineTokens.push(numNonSpaceChars);
|
||||
continue;
|
||||
case 't' :
|
||||
// Tab
|
||||
@ -158,6 +176,7 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
|
||||
font = g_nancy->_graphicsManager->getFont(curFontID);
|
||||
highlightFont = g_nancy->_graphicsManager->getFont(highlightFontID);
|
||||
assert(font && highlightFont);
|
||||
|
||||
// Do word wrapping on the text, sans tokens. This assumes
|
||||
// all text uses fonts of the same width
|
||||
@ -176,8 +195,41 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
// respect color tokens
|
||||
uint totalCharsDrawn = 0;
|
||||
byte colorID = _defaultTextColor;
|
||||
for (Common::String &line : wrappedLines) {
|
||||
uint horizontalOffset = 0;
|
||||
uint numNewlineTokens = 0;
|
||||
uint horizontalOffset = 0;
|
||||
for (uint lineNumber = 0; lineNumber < wrappedLines.size(); ++lineNumber) {
|
||||
Common::String &line = wrappedLines[lineNumber];
|
||||
horizontalOffset = 0;
|
||||
// Draw images
|
||||
if (newlineTokens.front() <= totalCharsDrawn) {
|
||||
newlineTokens.pop();
|
||||
|
||||
for (uint i = 0; i < _imageLineIDs.size(); ++i) {
|
||||
if (numNewlineTokens == _imageLineIDs[i]) {
|
||||
// A lot of magic numbers that make sure we draw pixel-perfect. This is a mess for three reasons:
|
||||
// - The original engine draws strings with a bottom-left anchor, while ScummVM uses top-left
|
||||
// - The original engine uses inclusive rects, while ScummVM uses non-includive
|
||||
// - The original engine does some stupid stuff with spacing
|
||||
// This works correctly in nancy7, but might fail with different games/fonts
|
||||
if (lineNumber != 0) {
|
||||
_imageVerticalOffset += (font->getFontHeight() + 1) / 2 + 1;
|
||||
}
|
||||
|
||||
_fullSurface.blitFrom(image, _imageSrcs[i],
|
||||
Common::Point( textBounds.left + horizontalOffset + 1,
|
||||
textBounds.top + _numDrawnLines * highlightFont->getFontHeight() + _imageVerticalOffset));
|
||||
_imageVerticalOffset += _imageSrcs[i].height() - 1;
|
||||
|
||||
if (lineNumber == 0) {
|
||||
_imageVerticalOffset += font->getFontHeight() / 2 - 1;
|
||||
} else {
|
||||
_imageVerticalOffset += (font->getFontHeight() + 1) / 2 + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++numNewlineTokens;
|
||||
}
|
||||
|
||||
// Trim whitespaces (only) at beginning and end of wrapped lines
|
||||
while (line.lastChar() == ' ') {
|
||||
@ -220,7 +272,7 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
font->drawString( &_fullSurface,
|
||||
stringToDraw,
|
||||
textBounds.left + horizontalOffset,
|
||||
textBounds.top + _numDrawnLines * font->getFontHeight(),
|
||||
textBounds.top + _numDrawnLines * font->getFontHeight() + _imageVerticalOffset,
|
||||
textBounds.width(),
|
||||
colorID);
|
||||
|
||||
@ -229,7 +281,7 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
highlightFont->drawString( &_textHighlightSurface,
|
||||
stringToDraw,
|
||||
textBounds.left + horizontalOffset,
|
||||
textBounds.top + _numDrawnLines * highlightFont->getFontHeight(),
|
||||
textBounds.top + _numDrawnLines * highlightFont->getFontHeight() + _imageVerticalOffset,
|
||||
textBounds.width(),
|
||||
colorID);
|
||||
}
|
||||
@ -252,7 +304,25 @@ void HypertextParser::drawAllText(const Common::Rect &textBounds, uint fontID, u
|
||||
++_numDrawnLines;
|
||||
|
||||
// Record the height of the text currently drawn. Used for textbox scrolling
|
||||
_drawnTextHeight = (_numDrawnLines - 1) * font->getFontHeight();
|
||||
_drawnTextHeight = (_numDrawnLines - 1) * font->getFontHeight() + _imageVerticalOffset;
|
||||
}
|
||||
|
||||
// Draw the footer image(s)
|
||||
for (uint i = 0; i < _imageLineIDs.size(); ++i) {
|
||||
if (numNewlineTokens <= _imageLineIDs[i]) {
|
||||
_imageVerticalOffset += (font->getFontHeight() + 1) / 2 + 1;
|
||||
|
||||
_fullSurface.blitFrom(image, _imageSrcs[i],
|
||||
Common::Point( textBounds.left + horizontalOffset + 1,
|
||||
textBounds.top + _numDrawnLines * highlightFont->getFontHeight() + _imageVerticalOffset));
|
||||
_imageVerticalOffset += _imageSrcs[i].height() - 1;
|
||||
|
||||
if (i < _imageLineIDs.size() - 1) {
|
||||
_imageVerticalOffset += (font->getFontHeight() + 1) / 2 + 3;
|
||||
}
|
||||
|
||||
_drawnTextHeight = (_numDrawnLines - 1) * font->getFontHeight() + _imageVerticalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the hotspot to the list
|
||||
|
@ -37,13 +37,16 @@ public:
|
||||
_numDrawnLines(0),
|
||||
_drawnTextHeight(0),
|
||||
_needsTextRedraw(false),
|
||||
_defaultTextColor(0) {}
|
||||
_defaultTextColor(0),
|
||||
_imageVerticalOffset(0) {}
|
||||
virtual ~HypertextParser() {};
|
||||
|
||||
protected:
|
||||
void initSurfaces(uint width, uint height, const struct Graphics::PixelFormat &format, uint32 backgroundColor, uint32 highlightBackgroundColor);
|
||||
|
||||
void addTextLine(const Common::String &text);
|
||||
void addImage(uint16 lineID, const Common::Rect &src);
|
||||
void setImageName(const Common::Path &name);
|
||||
|
||||
void drawAllText(const Common::Rect &textBounds, uint fontID, uint highlightFontID);
|
||||
virtual void clear();
|
||||
@ -54,10 +57,16 @@ protected:
|
||||
uint32 _backgroundColor;
|
||||
uint32 _highlightBackgroundColor;
|
||||
uint _defaultTextColor;
|
||||
uint _imageVerticalOffset;
|
||||
|
||||
Common::Array<Common::String> _textLines;
|
||||
Common::Array<Common::Rect> _hotspots;
|
||||
|
||||
// Data for displaying images inside text; used in Hypertext
|
||||
Common::Path _imageName;
|
||||
Common::Array<uint16> _imageLineIDs;
|
||||
Common::Array<Common::Rect> _imageSrcs;
|
||||
|
||||
uint16 _numDrawnLines;
|
||||
uint16 _drawnTextHeight;
|
||||
bool _needsTextRedraw;
|
||||
|
Loading…
x
Reference in New Issue
Block a user