diff options
| -rw-r--r-- | engines/parallaction/balloons.cpp | 512 | 
1 files changed, 264 insertions, 248 deletions
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp index bbd8bc9ca7..222954ec3a 100644 --- a/engines/parallaction/balloons.cpp +++ b/engines/parallaction/balloons.cpp @@ -30,6 +30,183 @@  namespace Parallaction { +class WrappedLineFormatter { + +protected: +	Common::String _line; +	Font *_font; +	uint16 _lines, _lineWidth; + +	virtual void setup() = 0; +	virtual void action() = 0; +	virtual void end() = 0; +	virtual Common::String expand(const Common::String &token) { return token; } + +	void textAccum(const Common::String &token, uint16 width) { +		if (token.empty()) { +			return; +		} + +		_lineWidth += width; +		_line += token; +	} + +	void textNewLine() { +		_lines++; +		_lineWidth = 0; +		_line.clear(); +	} + +public: +	WrappedLineFormatter(Font *font) : _font(font) { } +	virtual ~WrappedLineFormatter() { } + +	virtual void calc(const char *text, uint16 maxwidth) { +		setup(); + +		_lineWidth = 0; +		_line.clear(); +		_lines = 0; + +		Common::StringTokenizer	tokenizer(text, " "); +		Common::String token; +		Common::String blank(" "); + +		uint16 blankWidth = _font->getStringWidth(" "); +		uint16 tokenWidth = 0; + +		while (!tokenizer.empty()) { +			token = tokenizer.nextToken(); +			token = expand(token); + +			if (token == '/') { +				tokenWidth = 0; +				action(); +				textNewLine(); +			} else { +				// todo: expand '%' +				tokenWidth = _font->getStringWidth(token.c_str()); + +				if (_lineWidth == 0) { +					textAccum(token, tokenWidth); +				} else { +					if (_lineWidth + blankWidth + tokenWidth <= maxwidth) { +						textAccum(blank, blankWidth); +						textAccum(token, tokenWidth); +					} else { +						action(); +						textNewLine(); +						textAccum(token, tokenWidth); +					} +				} +			} +		} + +		end(); +	} +}; + +class StringExtent_NS : public WrappedLineFormatter { + +	uint	_width, _height; + +protected: +	virtual Common::String expand(const Common::String &token) { +		if (token.compareToIgnoreCase("%p") == 0) { +			return Common::String("/"); +		} + +		return token; +	} + +	virtual void setup() { +		_width = _height = 0; + +		_line.clear(); +		_lines = 0; +		_width = 0; +	} + +	virtual void action() { +		if (_lineWidth > _width) { +			_width = _lineWidth; +		} +		_height = _lines * _font->height(); +	} + +	virtual void end() { +		action(); +	} + +public: +	StringExtent_NS(Font *font) : WrappedLineFormatter(font) { } + +	uint width() const { return _width; } +	uint height() const { return _height; } +}; + + +class StringWriter_NS : public WrappedLineFormatter { + +	uint	_width, _height; +	byte	_color; + +	Graphics::Surface	*_surf; + +protected: +	virtual Common::String expand(const Common::String& token) { +		if (token.compareToIgnoreCase("%p") == 0) { +			Common::String t("......."); +			for (int i = 0; _password[i]; i++) { +				t.setChar(_password[i], i); +			} +			return Common::String("> ") + t; +		} else +		if (token.compareToIgnoreCase("%s") == 0) { +			char buf[20]; +			sprintf(buf, "%i", _score); +			return Common::String(buf); +		} + +		return token; +	} + +	virtual void setup() { +	} + +	virtual void action() { +		if (_line.empty()) { +			return; +		} +		uint16 rx = 10; +		uint16 ry = 4 + _lines * _font->height();	// y + +		byte *dst = (byte*)_surf->getBasePtr(rx, ry); +		_font->setColor(_color); +		_font->drawString(dst, _surf->w, _line.c_str()); +	} + +	virtual void end() { +		action(); +	} + +public: +	StringWriter_NS(Font *font) : WrappedLineFormatter(font) { } + +	void write(const char *text, uint maxWidth, byte color, Graphics::Surface *surf) { +		StringExtent_NS	se(_font); +		se.calc(text, maxWidth); +		_width = se.width() + 10; +		_height = se.height() + 20; +		_color = color; +		_surf = surf; + +		calc(text, maxWidth); +	} + +}; + +  #define	BALLOON_TRANSPARENT_COLOR_NS 2  #define BALLOON_TRANSPARENT_COLOR_BR 0 @@ -78,8 +255,6 @@ class BalloonManager_ns : public BalloonManager {  	uint	_numBalloons; -	void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height); -	void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);  	int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);  	Balloon *getBalloon(uint id); @@ -152,12 +327,16 @@ int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w  	int16 w, h; -	getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); +	StringExtent_NS	se(_vm->_dialogueFont); +	se.calc(text, MAX_BALLOON_WIDTH); +	w = se.width() + 14; +	h = se.height() + 20;  	int id = createBalloon(w+5, h, winding, 1);  	Balloon *balloon = &_intBalloons[id]; -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); +	StringWriter_NS sw(_vm->_dialogueFont); +	sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);  	// TODO: extract some text to make a name for obj  	balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); @@ -172,12 +351,17 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC  	int16 w, h; -	getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); +	StringExtent_NS	se(_vm->_dialogueFont); +	se.calc(text, MAX_BALLOON_WIDTH); +	w = se.width() + 14; +	h = se.height() + 20; +  	int id = createBalloon(w+5, h, winding, 1);  	Balloon *balloon = &_intBalloons[id]; -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); +	StringWriter_NS sw(_vm->_dialogueFont); +	sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);  	// TODO: extract some text to make a name for obj  	balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); @@ -196,7 +380,9 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC  void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) {  	Balloon *balloon = getBalloon(id);  	balloon->surface->fillRect(balloon->innerBox, 1); -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); + +	StringWriter_NS sw(_vm->_dialogueFont); +	sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);  } @@ -204,11 +390,15 @@ int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) {  	int16 w, h; -	getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); +	StringExtent_NS	se(_vm->_dialogueFont); +	se.calc(text, MAX_BALLOON_WIDTH); +	w = se.width() + 14; +	h = se.height() + 20;  	int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS);  	Balloon *balloon = &_intBalloons[id]; -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH); +	StringWriter_NS sw(_vm->_dialogueFont); +	sw.write(text, MAX_BALLOON_WIDTH, 0, balloon->surface);  	// TODO: extract some text to make a name for obj  	balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); @@ -245,110 +435,99 @@ void BalloonManager_ns::freeBalloons() {  	_numBalloons = 0;  } -// TODO: get rid of parseNextToken from here. Use the -// StringTokenizer instead. -void BalloonManager_ns::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) { -	uint16 lines = 0; -	uint16 linewidth = 0; -	uint16 rx = 10; -	uint16 ry = 4; -	uint16 blankWidth = font->getStringWidth(" "); -	uint16 tokenWidth = 0; -	char token[MAX_TOKEN_LEN]; -	if (wrapwidth == -1) -		wrapwidth = _vm->_screenWidth; -	while (strlen(text) > 0) { -		text = parseNextToken(text, token, MAX_TOKEN_LEN, "   ", true); -		if (!scumm_stricmp(token, "%p")) { -			lines++; -			rx = 10; -			ry = 4 + lines*10;	// y -			strcpy(token, "> ......."); -			strncpy(token+2, _password, strlen(_password)); -			tokenWidth = font->getStringWidth(token); -		} else { -			tokenWidth = font->getStringWidth(token); -			linewidth += tokenWidth; - -			if (linewidth > wrapwidth) { -				// wrap line -				lines++; -				rx = 10;			// x -				ry = 4 + lines*10;	// y -				linewidth = tokenWidth; -			} +class StringExtent_BR : public WrappedLineFormatter { -			if (!scumm_stricmp(token, "%s")) { -				sprintf(token, "%d", _score); -			} +	uint	_width, _height; -		} +protected: +	virtual void setup() { +		_width = _height = 0; -		_gfx->drawText(font, surf, rx, ry, token, color); +		_line.clear(); +		_lines = 0; +		_width = 0; +	} -		rx += tokenWidth + blankWidth; -		linewidth += blankWidth; +	virtual void action() { +		if (_lineWidth > _width) { +			_width = _lineWidth; +		} +		_height = _lines * _font->height(); +	} -		text = Common::ltrim(text); +	virtual void end() { +		action();  	} -} +public: +	StringExtent_BR(Font *font) : WrappedLineFormatter(font) { } -// TODO: get rid of parseNextToken from here. Use the -// StringTokenizer instead. -void BalloonManager_ns::getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height) { +	uint width() const { return _width; } +	uint height() const { return _height; } +}; -	uint16 lines = 0; -	uint16 w = 0; -	*width = 0; -	uint16 blankWidth = font->getStringWidth(" "); -	uint16 tokenWidth = 0; +class StringWriter_BR : public WrappedLineFormatter { -	char token[MAX_TOKEN_LEN]; +	uint	_width, _height; +	byte	_color; +	uint	_x, _y; -	while (strlen(text) != 0) { +	Graphics::Surface	*_surf; -		text = parseNextToken(text, token, MAX_TOKEN_LEN, "   ", true); -		tokenWidth = font->getStringWidth(token); +protected: +	StringWriter_BR(Font *font, byte color) : WrappedLineFormatter(font) { -		w += tokenWidth; +	} -		if (!scumm_stricmp(token, "%p")) { -			lines++; -		} else { -			if (w > maxwidth) { -				w -= tokenWidth; -				lines++; -				if (w > *width) -					*width = w; +	virtual void setup() { +	} -				w = tokenWidth; -			} +	virtual void action() { +		if (_line.empty()) { +			return;  		} +		uint16 rx = _x + (_surf->w - _lineWidth) / 2; +		uint16 ry = _y + _lines * _font->height();	// y -		w += blankWidth; -		text = Common::ltrim(text); +		byte *dst = (byte*)_surf->getBasePtr(rx, ry); +		_font->setColor(_color); +		_font->drawString(dst, _surf->w, _line.c_str());  	} -	if (*width < w) *width = w; -	*width += 10; +	virtual void end() { +		action(); +	} -	*height = lines * 10 + 20; +public: +	StringWriter_BR(Font *font) : WrappedLineFormatter(font) { } -	return; -} +	void write(const char *text, uint maxWidth, byte color, Graphics::Surface *surf) { +		maxWidth = 216; + +		StringExtent_BR	se(_font); +		se.calc(text, maxWidth); +		_width = se.width() + 10; +		_height = se.height() + 12; +		_color = color; +		_surf = surf; +		_x = 0; +		_y = (_surf->h - _height) / 2; +		calc(text, maxWidth); +	} + +}; @@ -370,29 +549,12 @@ class BalloonManager_br : public BalloonManager {  	Frames *_rightBalloon;  	void cacheAnims(); -	void getStringExtent(Font *font, const char *text, uint16 maxwidth, int16* width, int16* height);  	void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);  	int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);  	Balloon *getBalloon(uint id);  	Graphics::Surface *expandBalloon(Frames *data, int frameNum); -	void textSetupRendering(const Common::String &text, Graphics::Surface *dest, Font *font, byte color); -	void textEmitCenteredLine(); -	void textAccum(const Common::String &token, uint16 width); -	void textNewLine(); - -	Common::String _textLine; -	Graphics::Surface *_textSurf; -	Font *_textFont; -	uint16 _textX, _textY; -	byte _textColor; -	uint16 _textLines, _textWidth; - -	void extentSetup(Font *font, int16 *width, int16 *height); -	void extentAction(); - -	int16 *_extentWidth, *_extentHeight; - +	StringWriter_BR	_writer;  public:  	BalloonManager_br(Disk *disk, Gfx *gfx); @@ -451,7 +613,7 @@ int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w  	balloon->surface = expandBalloon(src, srcFrame);  	src->getRect(srcFrame, balloon->box); -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); +	_writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);  	// TODO: extract some text to make a name for obj  	balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); @@ -487,7 +649,7 @@ int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textC  	balloon->surface = expandBalloon(src, srcFrame);  	src->getRect(srcFrame, balloon->box); -	drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH); +	_writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);  	// TODO: extract some text to make a name for obj  	balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0); @@ -558,155 +720,9 @@ void BalloonManager_br::cacheAnims() {  } -void BalloonManager_br::extentSetup(Font *font, int16 *width, int16 *height) { -	_extentWidth = width; -	_extentHeight = height; - -	_textLine.clear(); -	_textLines = 0; -	_textWidth = 0; -	_textFont = font; -} - -void BalloonManager_br::extentAction() { -	if (_textWidth > *_extentWidth) { -		*_extentWidth = _textWidth; -	} -	*_extentHeight = _textLines * _textFont->height(); -} - -void BalloonManager_br::textSetupRendering(const Common::String &text, Graphics::Surface *dest, Font *font, byte color) { -	uint16 maxWidth = 216; - -	int16 w, h; -	getStringExtent(font, text.c_str(), maxWidth, &w, &h); - -	w += 10; -	h += 12; - -	_textLine.clear(); -	_textSurf = dest; -	_textFont = font; -	_textX = 0; -	_textY = (_textSurf->h - h) / 2; -	_textColor = color; -	_textLines = 0; -	_textWidth = 0; -} - -void BalloonManager_br::textEmitCenteredLine() { -	if (_textLine.empty()) { -		return; -	} -	uint16 rx = _textX + (_textSurf->w - _textWidth) / 2; -	uint16 ry = _textY + _textLines * _textFont->height();	// y -	_gfx->drawText(_textFont, _textSurf, rx, ry, _textLine.c_str(), _textColor); -} - -void BalloonManager_br::textAccum(const Common::String &token, uint16 width) { -	if (token.empty()) { -		return; -	} - -	_textWidth += width; -	_textLine += token; -} - -void BalloonManager_br::textNewLine() { -	_textLines++; -	_textWidth = 0; -	_textLine.clear(); -} - - -// TODO: really, base this and getStringExtent on some kind of LineTokenizer, instead of -// repeating the algorithm and changing a couple of lines. -void BalloonManager_br::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapWidth) { -	textSetupRendering(text, surf, font, color); - -	wrapWidth = 216; - -	Common::StringTokenizer	tokenizer(text, " "); -	Common::String token; -	Common::String blank(" "); - -	uint16 blankWidth = font->getStringWidth(" "); -	uint16 tokenWidth = 0; - -	while (!tokenizer.empty()) { -		token = tokenizer.nextToken(); - -		if (token == '/') { -			tokenWidth = 0; -			textEmitCenteredLine(); -			textNewLine(); -		} else { -			// todo: expand '%' -			tokenWidth = font->getStringWidth(token.c_str()); - -			if (_textWidth == 0) { -				textAccum(token, tokenWidth); -			} else { -				if (_textWidth + blankWidth + tokenWidth <= wrapWidth) { -					textAccum(blank, blankWidth); -					textAccum(token, tokenWidth); -				} else { -					textEmitCenteredLine(); -					textNewLine(); -					textAccum(token, tokenWidth); -				} -			} -		} -	} - -	textEmitCenteredLine(); -} - - - -void BalloonManager_br::getStringExtent(Font *font, const char *text, uint16 maxwidth, int16* width, int16* height) { -	extentSetup(font, width, height); - -	Common::StringTokenizer	tokenizer(text, " "); -	Common::String token; -	Common::String blank(" "); - -	uint16 blankWidth = font->getStringWidth(" "); -	uint16 tokenWidth = 0; - -	while (!tokenizer.empty()) { -		token = tokenizer.nextToken(); - -		if (token == '/') { -			tokenWidth = 0; -			extentAction(); -			textNewLine(); -		} else { -			// todo: expand '%' -			tokenWidth = font->getStringWidth(token.c_str()); - -			if (_textWidth == 0) { -				textAccum(token, tokenWidth); -			} else { -				if (_textWidth + blankWidth + tokenWidth <= maxwidth) { -					textAccum(blank, blankWidth); -					textAccum(token, tokenWidth); -				} else { -					extentAction(); -					textNewLine(); -					textAccum(token, tokenWidth); -				} -			} -		} -	} - -	extentAction(); -} - - - -BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), _leftBalloon(0), _rightBalloon(0) { +BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), +	_leftBalloon(0), _rightBalloon(0), _writer(_vm->_dialogueFont) {  }  BalloonManager_br::~BalloonManager_br() {  | 
