1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/file.h"
24 
25 #include "sludge/fonttext.h"
26 #include "sludge/graphics.h"
27 #include "sludge/moreio.h"
28 #include "sludge/newfatal.h"
29 #include "sludge/sludge.h"
30 #include "sludge/version.h"
31 
32 namespace Sludge {
33 
TextManager()34 TextManager::TextManager() {
35 	init();
36 }
37 
~TextManager()38 TextManager::~TextManager() {
39 	kill();
40 }
41 
init()42 void TextManager::init() {
43 	_theFont.total = 0;
44 	_theFont.sprites = nullptr;
45 
46 	_fontHeight = 0;
47 	_numFontColours = 0;
48 	_loadedFontNum = 0;
49 	_fontSpace = -1;
50 
51 	_pastePalette.init();
52 	_fontTable.clear();
53 }
54 
kill()55 void TextManager::kill() {
56 	GraphicsManager::forgetSpriteBank(_theFont);
57 	_pastePalette.kill();
58 }
59 
isInFont(const Common::String & theText)60 bool TextManager::isInFont(const Common::String &theText) {
61 	if (_fontTable.empty())
62 		return 0;
63 	if (theText.empty())
64 		return 0;
65 
66 	Common::U32String str32 = theText.decode(Common::kUtf8);
67 
68 	// We don't want to compare strings. Only single characters allowed!
69 	if (str32.size() > 1)
70 		return false;
71 
72 	uint32 c = str32[0];
73 
74 	// check if font order contains the utf8 char
75 	return _fontOrder.contains(c);
76 }
77 
stringLength(const Common::String & theText)78 int TextManager::stringLength(const Common::String &theText) {
79 	Common::U32String str32 = theText.decode(Common::kUtf8);
80 	return str32.size();
81 }
82 
stringWidth(const Common::String & theText)83 int TextManager::stringWidth(const Common::String &theText) {
84 	int xOff = 0;
85 
86 	if (_fontTable.empty())
87 		return 0;
88 
89 	Common::U32String str32 = theText.decode(Common::kUtf8);
90 
91 	for (uint i = 0; i < str32.size(); ++i) {
92 		uint32 c = str32[i];
93 		xOff += _theFont.sprites[fontInTable(c)].surface.w + _fontSpace;
94 	}
95 
96 	return xOff;
97 }
98 
pasteString(const Common::String & theText,int xOff,int y,SpritePalette & thePal)99 void TextManager::pasteString(const Common::String &theText, int xOff, int y, SpritePalette &thePal) {
100 	if (_fontTable.empty())
101 		return;
102 
103 	xOff += (int)((float)(_fontSpace >> 1) / g_sludge->_gfxMan->getCamZoom());
104 
105 	Common::U32String str32 = theText.decode(Common::kUtf8);
106 
107 	for (uint32 i = 0; i < str32.size(); ++i) {
108 		uint32 c = str32[i];
109 		Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
110 		g_sludge->_gfxMan->fontSprite(xOff, y, *mySprite, thePal);
111 		xOff += (int)((double)(mySprite->surface.w + _fontSpace) / g_sludge->_gfxMan->getCamZoom());
112 	}
113 }
114 
pasteStringToBackdrop(const Common::String & theText,int xOff,int y)115 void TextManager::pasteStringToBackdrop(const Common::String &theText, int xOff, int y) {
116 	if (_fontTable.empty())
117 		return;
118 
119 	Common::U32String str32 = theText.decode(Common::kUtf8);
120 
121 	xOff += _fontSpace >> 1;
122 	for (uint32 i = 0; i < str32.size(); ++i) {
123 		uint32 c = str32[i];
124 		Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
125 		g_sludge->_gfxMan->pasteSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
126 		xOff += mySprite->surface.w + _fontSpace;
127 	}
128 }
129 
burnStringToBackdrop(const Common::String & theText,int xOff,int y)130 void TextManager::burnStringToBackdrop(const Common::String &theText, int xOff, int y) {
131 	if (_fontTable.empty())
132 		return;
133 
134 	Common::U32String str32 = theText.decode(Common::kUtf8);
135 
136 	xOff += _fontSpace >> 1;
137 	for (uint i = 0; i < str32.size(); ++i) {
138 		uint32 c = str32[i];
139 		Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
140 		g_sludge->_gfxMan->burnSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
141 		xOff += mySprite->surface.w + _fontSpace;
142 	}
143 }
144 
loadFont(int filenum,const Common::String & charOrder,int h)145 bool TextManager::loadFont(int filenum, const Common::String &charOrder, int h) {
146 	_fontOrder = charOrder.decode(Common::kUtf8);
147 
148 	g_sludge->_gfxMan->forgetSpriteBank(_theFont);
149 
150 	_loadedFontNum = filenum;
151 
152 	// get max value among all utf8 chars
153 	Common::U32String fontOrderString = _fontOrder;
154 
155 	// create an index table from utf8 char to the index
156 	if (!_fontTable.empty()) {
157 		_fontTable.clear();
158 	}
159 
160 	for (uint i = 0; i < fontOrderString.size(); ++i) {
161 		uint32 c = fontOrderString[i];
162 		_fontTable[c] = i;
163 	}
164 
165 	if (!g_sludge->_gfxMan->loadSpriteBank(filenum, _theFont, true)) {
166 		fatal("Can't load font");
167 		return false;
168 	}
169 
170 	_numFontColours = _theFont.myPalette.total;
171 	_fontHeight = h;
172 	return true;
173 }
174 
175 // load & save
saveFont(Common::WriteStream * stream)176 void TextManager::saveFont(Common::WriteStream *stream) {
177 	stream->writeByte(!_fontTable.empty());
178 	if (!_fontTable.empty()) {
179 		stream->writeUint16BE(_loadedFontNum);
180 		stream->writeUint16BE(_fontHeight);
181 		writeString(_fontOrder.encode(Common::kUtf8), stream);
182 	}
183 	stream->writeSint16LE(_fontSpace);
184 }
185 
loadFont(int ssgVersion,Common::SeekableReadStream * stream)186 void TextManager::loadFont(int ssgVersion, Common::SeekableReadStream *stream) {
187 	bool fontLoaded = stream->readByte();
188 	int fontNum = 0;
189 	Common::String charOrder = "";
190 	if (fontLoaded) {
191 		fontNum = stream->readUint16BE();
192 		_fontHeight = stream->readUint16BE();
193 
194 		if (ssgVersion < VERSION(2, 2)) {
195 			char *tmp = new char[257];
196 			for (int a = 0; a < 256; a++) {
197 				int x = stream->readByte();
198 				tmp[x] = a;
199 			}
200 			tmp[256] = 0;
201 			charOrder = tmp;
202 			delete []tmp;
203 		} else {
204 			charOrder = readString(stream);
205 		}
206 	}
207 	loadFont(fontNum, charOrder, _fontHeight);
208 
209 	_fontSpace = stream->readSint16LE();
210 }
211 
212 } // End of namespace Sludge
213