Permalink
Browse files

MUTATIONOFJB: Implement word wrapping for subtitles.

  • Loading branch information...
MiroslavR authored and sev- committed Jul 17, 2018
1 parent f70eb01 commit f94ff7aa8ec510de8dc353c9c2e079db5e05d5da
@@ -27,9 +27,9 @@

namespace MutationOfJB {

Font::Font(const Common::String &fileName, int horizSpacing, int vertSpacing) :
Font::Font(const Common::String &fileName, int horizSpacing, int lineHeight) :
_horizSpacing(horizSpacing),
_vertSpacing(vertSpacing) {
_lineHeight(lineHeight) {

load(fileName);
}
@@ -67,15 +67,14 @@ bool Font::load(const Common::String &fileName) {
}
}

if (_vertSpacing == -1) {
_vertSpacing = maxHeight;
if (_lineHeight == -1) {
_lineHeight = maxHeight;
}

return true;
}


void Font::drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf) {
void Font::drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf) const {
GlyphMap::iterator it = _glyphs.find(glyph);
if (it == _glyphs.end()) {
warning("Glyph %d not found", glyph);
@@ -99,21 +98,62 @@ void Font::drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics:
x += glyphSurface.w + _horizSpacing;
}

void Font::drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf) {
int16 Font::getWidth(const Common::String &str) const {
int16 width = 0;
for (uint i = 0; i < str.size(); ++i) {
GlyphMap::iterator it = _glyphs.find(str[i]);
if (it == _glyphs.end()) {
continue;
}

width += it->_value.w + _horizSpacing;
}
return width;
}

int Font::getLineHeight() const {
return _lineHeight;
}

void Font::drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf) const {
for (uint i = 0; i < str.size(); ++i) {
drawGlyph(str[i], baseColor, x, y, surf); // "x" is updated.
}
}

uint8 Font::transformColor(uint8 baseColor, uint8 glyphColor) {
void Font::wordWrap(const Common::String &str, int16 maxLineWidth, Common::Array<Common::String> &lines) const {
lines.push_back("");

for (Common::String::const_iterator it = str.begin(); it != str.end();) {
Common::String::const_iterator partStart = it;
it = Common::find(partStart, str.end(), ' ');
if (it != str.end()) {
while (*it == ' ' && it != str.end()) {
++it;
}
}

Common::String part(partStart, it); // Word + following whitespace
Common::String line = lines.back() + part;
if (getWidth(line) <= maxLineWidth) {
// The part fits in the current line
lines.back() = line;
} else {
// The part must go to the next line
lines.push_back(part);
}
}
}

uint8 Font::transformColor(uint8 baseColor, uint8 glyphColor) const {
return baseColor + glyphColor - 0x10;
}

SystemFont::SystemFont() : Font("sysfnt.aft", 1, 7) {}

SpeechFont::SpeechFont() : Font("font1.aft", -1, -1) {}

uint8 SpeechFont::transformColor(uint8 baseColor, uint8 glyphColor) {
uint8 SpeechFont::transformColor(uint8 baseColor, uint8 glyphColor) const {
// Hack in original game.
if (glyphColor == 0x11) {
return 0xC0;
@@ -37,17 +37,20 @@ class Font {
public:
Font(const Common::String &fileName, int horizSpacing, int vertSpacing);
virtual ~Font() {}
void drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf);
int getLineHeight() const;
int16 getWidth(const Common::String &text) const;
void drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf) const;
void wordWrap(const Common::String &str, int16 maxLineWidth, Common::Array<Common::String> &lines) const;

protected:
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor);
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) const;

private:
void drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf);
void drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf) const;
bool load(const Common::String &fileName);

int _horizSpacing;
int _vertSpacing;
int _lineHeight;
typedef Common::HashMap<uint8, Graphics::ManagedSurface> GlyphMap;
GlyphMap _glyphs;
};
@@ -62,7 +65,7 @@ class SpeechFont : public Font {
SpeechFont();

protected:
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) override;
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) const override;
};

}
@@ -27,6 +27,7 @@
#include "mutationofjb/game.h"
#include "mutationofjb/gamedata.h"
#include "mutationofjb/room.h"
#include "mutationofjb/util.h"

#include "graphics/managed_surface.h"
#include "graphics/screen.h"
@@ -36,8 +37,7 @@ namespace MutationOfJB {
SayTask::SayTask(const Common::String &toSay, uint8 color) : _toSay(toSay), _color(color), _timer(1000) {}

void SayTask::start() {

getTaskManager()->getGame().getAssets().getSpeechFont().drawString(_toSay, _color, 0, 0, getTaskManager()->getGame().getScreen());
drawSubtitle(_toSay, 160, 0, _color); // TODO: Respect PTALK and LTALK commands.
_timer.start();
setState(RUNNING);
}
@@ -52,4 +52,39 @@ void SayTask::update() {
}
}

void SayTask::drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, uint8 color) {
const int MAX_LINE_WIDTH = 250;

const Font &font = getTaskManager()->getGame().getAssets().getSpeechFont();

Common::Array<Common::String> lines;
font.wordWrap(text, MAX_LINE_WIDTH, lines);

int16 x = talkX;
int16 y = talkY - (lines.size() - 1) * font.getLineHeight() - 15; // Get the top y

// Clamp to screen edges
y = MAX<int16>(y, 3);
int16 maxWidth = 0;
for (uint i = 0; i < lines.size(); i++) {
int16 lineWidth = font.getWidth(lines[i]);
if (lineWidth > maxWidth) {
maxWidth = lineWidth;
}
x = MAX<int16>(x, 3 + lineWidth / 2);
x = MIN<int16>(x, 317 - lineWidth / 2);
}

// Draw lines
for (uint i = 0; i < lines.size(); i++) {
font.drawString(lines[i], color, x - font.getWidth(lines[i]) / 2, y + i * font.getLineHeight(), getTaskManager()->getGame().getScreen());
}

// Remember the area occupied by the text
_boundingBox.top = x - maxWidth / 2;
_boundingBox.left = y;
_boundingBox.setWidth(maxWidth);
_boundingBox.setHeight(lines.size() * font.getLineHeight());
}

}
@@ -24,6 +24,7 @@

#include "mutationofjb/timer.h"

#include "common/rect.h"
#include "common/str.h"

namespace MutationOfJB {
@@ -36,9 +37,12 @@ class SayTask : public Task {
virtual void update() override;

private:
void drawSubtitle(const Common::String &text, int16 talkX, int16 talkY, uint8 color);

Common::String _toSay;
uint8 _color;
Timer _timer;
Common::Rect _boundingBox;
};

}

0 comments on commit f94ff7a

Please sign in to comment.