~ubuntu-branches/ubuntu/raring/scummvm/raring

« back to all changes in this revision

Viewing changes to engines/toon/font.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Moritz Muehlenhoff
  • Date: 2011-05-25 19:02:23 UTC
  • mto: (21.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20110525190223-fiqm0oaec714xk31
Tags: upstream-1.3.0
ImportĀ upstreamĀ versionĀ 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
* $URL$
 
22
* $Id$
 
23
*
 
24
*/
 
25
 
 
26
#include "common/debug.h"
 
27
 
 
28
#include "toon/font.h"
 
29
 
 
30
namespace Toon {
 
31
 
 
32
FontRenderer::FontRenderer(ToonEngine *vm) : _vm(vm) {
 
33
        _currentFontColor[0] = 0;
 
34
        _currentFontColor[1] = 0xc8;
 
35
        _currentFontColor[2] = 0xcb;
 
36
        _currentFontColor[3] = 0xce;
 
37
}
 
38
 
 
39
FontRenderer::~FontRenderer() {
 
40
}
 
41
 
 
42
// mapping extended characters required for foreign versions to font (animation)
 
43
static const byte map_textToFont[0x80] = {
 
44
         '?',  '?',  '?',  '?', 0x03,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', // 0x8x
 
45
         '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', // 0x9x
 
46
         '?', 0x09,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', // 0xAx
 
47
         '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0x0a, // 0xBx
 
48
         '?',  '?',  '?',  '?', 0x1d,  '?',  '?', 0x02,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', // 0xCx
 
49
         '?', 0x0b,  '?',  '?',  '?',  '?', 0x1e,  '?',  '?',  '?',  '?', 0x20, 0x1f,  '?',  '?', 0x19, // 0xDx
 
50
        0x0d, 0x04, 0x0e,  '?', 0x1a,  '?',  '?', 0x18, 0x10, 0x0f, 0x12, 0x11, 0x09, 0x05, 0x14, 0x13, // 0xEx
 
51
        0x23, 0x08, 0x23, 0x06, 0x15, 0x23, 0x1b, 0x23, 0x23, 0x16, 0x07, 0x17, 0x1c, 0x23, 0x23, 0x23  // 0xFx
 
52
};
 
53
 
 
54
byte FontRenderer::textToFont(byte c) {
 
55
        // No need to remap simple characters.
 
56
        if (c < 0x80)
 
57
                return c;
 
58
 
 
59
        // The Spanish version shows grave accent over the 'e' when it should
 
60
        // be acute. This happens both in the original interpreter and when
 
61
        // using the common map which works for other languages, so we add a
 
62
        // special case for it.
 
63
        if (_vm->_language == Common::ES_ESP && c == 0xe9)
 
64
                return 0x10;
 
65
 
 
66
        // Use the common map to convert the extended characters.
 
67
        return map_textToFont[c - 0x80];
 
68
}
 
69
 
 
70
void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 mode) {
 
71
        debugC(5, kDebugFont, "renderText(%d, %d, %s, %d)", x, y, origText.c_str(), mode);
 
72
 
 
73
        int32 xx, yy;
 
74
        computeSize(origText, &xx, &yy);
 
75
 
 
76
        if (mode & 2) {
 
77
                y -= yy / 2;
 
78
        } else if (mode & 4) {
 
79
                y -= yy;
 
80
        }
 
81
 
 
82
        if (mode & 1) {
 
83
                x -= xx / 2;
 
84
        }
 
85
 
 
86
        _vm->addDirtyRect(x, y, x + xx + 2, y + yy);
 
87
 
 
88
        int32 curX = x;
 
89
        int32 curY = y;
 
90
        int32 height = 0;
 
91
 
 
92
        const byte *text = (const byte *)origText.c_str();
 
93
        while (*text) {
 
94
                byte curChar = *text;
 
95
                if (curChar == 13) {
 
96
                        curY = curY + height;
 
97
                        height = 0;
 
98
                        curX = x;
 
99
                } else {
 
100
                        curChar = textToFont(curChar);
 
101
                        _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX, curY, _currentFontColor);
 
102
                        curX = curX + _currentFont->getFrameWidth(curChar) - 1;
 
103
                        height = MAX(height, _currentFont->getFrameHeight(curChar));
 
104
                }
 
105
                text++;
 
106
        }
 
107
}
 
108
 
 
109
void FontRenderer::computeSize(Common::String origText, int32 *retX, int32 *retY) {
 
110
        debugC(4, kDebugFont, "computeSize(%s, retX, retY)", origText.c_str());
 
111
 
 
112
        int32 lineWidth = 0;
 
113
        int32 lineHeight = 0;
 
114
        int32 totalHeight = 0;
 
115
        int32 totalWidth = 0;
 
116
 
 
117
        const byte *text = (const byte *)origText.c_str();
 
118
        while (*text) {
 
119
                byte curChar = *text;
 
120
                if (curChar < 32) {
 
121
                        text++;
 
122
                        continue;
 
123
                } else if (curChar == 13) {
 
124
                        totalWidth = MAX(totalWidth, lineWidth);
 
125
                        totalHeight += lineHeight;
 
126
                        lineHeight = 0;
 
127
                        lineWidth = 0;
 
128
                } else {
 
129
                        curChar = textToFont(curChar);
 
130
                        int32 charWidth = _currentFont->getFrameWidth(curChar) - 1;
 
131
                        int32 charHeight = _currentFont->getFrameHeight(curChar);
 
132
                        lineWidth += charWidth;
 
133
                        lineHeight = MAX(lineHeight, charHeight);
 
134
                }
 
135
                text++;
 
136
        }
 
137
 
 
138
        totalHeight += lineHeight;
 
139
        totalWidth = MAX(totalWidth, lineWidth);
 
140
 
 
141
        *retX = totalWidth;
 
142
        *retY = totalHeight;
 
143
}
 
144
 
 
145
void FontRenderer::setFont(Animation *font) {
 
146
        debugC(5, kDebugFont, "setFont(font)");
 
147
 
 
148
        _currentFont = font;
 
149
}
 
150
 
 
151
void FontRenderer::setFontColorByCharacter(int32 characterId) {
 
152
        debugC(5, kDebugFont, "setFontColorByCharacter(%d)", characterId);
 
153
 
 
154
        // unfortunately this table was hardcoded in the original executable
 
155
        static const byte colorsByCharacters[] = {
 
156
                0xe0, 0xdc, 0xc8,   0xd6, 0xc1, 0xc8,   0xe9, 0xde, 0xc8,   0xeb, 0xe8, 0xc8,
 
157
                0xd1, 0xcf, 0xc8,   0xdb, 0xd5, 0xc8,   0xfb, 0xfa, 0xc8,   0xd9, 0xd7, 0xc8,
 
158
                0xe8, 0xe4, 0xc8,   0xe9, 0xfa, 0xc8,   0xeb, 0xe4, 0xc8,   0xeb, 0xe4, 0xc8,
 
159
                0xd2, 0xea, 0xc8,   0xd3, 0xd0, 0xc8,   0xe1, 0xdd, 0xc8,   0xd9, 0xd7, 0xc8,
 
160
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,
 
161
                0xd2, 0xcf, 0xc8,   0xd1, 0xcf, 0xc8,   0xd9, 0xd7, 0xc8,   0xe3, 0xdd, 0xc8,
 
162
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,
 
163
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,
 
164
                0xd9, 0xd7, 0xc8,   0xe6, 0xe4, 0xc8,   0xd9, 0xd7, 0xc8,   0xcd, 0xca, 0xc8,
 
165
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xeb, 0xe8, 0xc8,   0xdb, 0xd5, 0xc8,
 
166
                0xe0, 0xdc, 0xc8,   0xd6, 0xc1, 0xc8,   0xd3, 0xd0, 0xc8,   0xd1, 0xcf, 0xc8,
 
167
                0xe6, 0xe4, 0xc8,   0xd1, 0xcf, 0xc8,   0xd2, 0xcf, 0xc8,   0xcc, 0xcb, 0xc8,
 
168
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,
 
169
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,
 
170
                0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8,   0xd9, 0xd7, 0xc8
 
171
        };
 
172
 
 
173
        setFontColor(colorsByCharacters[characterId * 3 + 2], colorsByCharacters[characterId * 3 + 1], colorsByCharacters[characterId * 3 + 0]);
 
174
}
 
175
 
 
176
void FontRenderer::setFontColor(int32 fontColor1, int32 fontColor2, int32 fontColor3) {
 
177
        debugC(5, kDebugFont, "setFontColor(%d, %d, %d)", fontColor1, fontColor2, fontColor3);
 
178
 
 
179
        _currentFontColor[0] = 0;
 
180
        _currentFontColor[1] = fontColor1;
 
181
        _currentFontColor[2] = fontColor2;
 
182
        _currentFontColor[3] = fontColor3;
 
183
}
 
184
 
 
185
void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText, int32 mode) {
 
186
        debugC(5, kDebugFont, "renderMultiLineText(%d, %d, %s, %d)", x, y, origText.c_str(), mode);
 
187
 
 
188
        // divide the text in several lines
 
189
        // based on number of characters or size of lines.
 
190
        byte text[1024];
 
191
        strncpy((char *)text, origText.c_str(), 1023);
 
192
        text[1023] = 0;
 
193
 
 
194
        byte *lines[16];
 
195
        int32 lineSize[16];
 
196
        int32 numLines = 0;
 
197
 
 
198
        byte *it = text;
 
199
 
 
200
        int32 maxWidth = 0;
 
201
        int32 curWidth = 0;
 
202
 
 
203
        while (1) {
 
204
                byte *lastLine = it;
 
205
                byte *lastSpace = it;
 
206
                int32 lastSpaceX = 0;
 
207
                int32 curLetterNr = 0;
 
208
                curWidth = 0;
 
209
 
 
210
                while (*it && curLetterNr < 50 && curWidth < 580) {
 
211
                        byte curChar = *it;
 
212
                        if (curChar == 32) {
 
213
                                lastSpace = it;
 
214
                                lastSpaceX = curWidth;
 
215
                        } else
 
216
                                curChar = textToFont(curChar);
 
217
 
 
218
                        int width = _currentFont->getFrameWidth(curChar);
 
219
                        curWidth += MAX<int32>(width - 2, 0);
 
220
                        it++;
 
221
                        curLetterNr++;
 
222
                }
 
223
 
 
224
                if (*lastLine == 0)
 
225
                        break;
 
226
 
 
227
                lines[numLines] = lastLine;
 
228
 
 
229
                if (*it == 0)
 
230
                        lineSize[numLines] = curWidth;
 
231
                else
 
232
                        lineSize[numLines] = lastSpaceX;
 
233
 
 
234
                if (lineSize[numLines] > maxWidth)
 
235
                        maxWidth = lineSize[numLines];
 
236
 
 
237
                lastLine = lastSpace + 1;
 
238
                numLines++;
 
239
 
 
240
                if (*it == 0)
 
241
                        break;
 
242
 
 
243
                it = lastLine;
 
244
                *lastSpace = 0;
 
245
 
 
246
                if (numLines >= 16)
 
247
                        break;
 
248
        }
 
249
 
 
250
        if (curWidth > maxWidth) {
 
251
                maxWidth = curWidth;
 
252
        }
 
253
        //numLines++;
 
254
 
 
255
        // get font height (assumed to be constant)
 
256
        int32 height = _currentFont->getHeight();
 
257
        int textSize = (height - 2) * numLines;
 
258
        y = y - textSize;
 
259
        if (y < 30)
 
260
                y = 30;
 
261
        if (y + textSize > 370)
 
262
                y = 370 - textSize;
 
263
 
 
264
        x -= _vm->state()->_currentScrollValue;
 
265
 
 
266
        // adapt x
 
267
        if (x - 30 - maxWidth / 2 < 0)
 
268
                x = maxWidth / 2 + 30;
 
269
 
 
270
        if (x + 30 + (maxWidth / 2) > TOON_SCREEN_WIDTH)
 
271
                x = TOON_SCREEN_WIDTH - (maxWidth / 2) - 30;
 
272
 
 
273
        // we have good coordinates now, we can render the multi line
 
274
        int32 curX = x;
 
275
        int32 curY = y;
 
276
 
 
277
        for (int32 i = 0; i < numLines; i++) {
 
278
                const byte *line = lines[i];
 
279
                curX = x - lineSize[i] / 2;
 
280
                _vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, curY, curX + lineSize[i] + _vm->state()->_currentScrollValue + 2, curY + height);
 
281
 
 
282
                while (*line) {
 
283
                        byte curChar = textToFont(*line);
 
284
                        if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
 
285
                        curX = curX + MAX<int32>(_currentFont->getFrameWidth(curChar) - 2, 0);
 
286
                        //height = MAX(height, _currentFont->getFrameHeight(curChar));
 
287
                        line++;
 
288
                }
 
289
                curY += height;
 
290
        }
 
291
}
 
292
 
 
293
} // End of namespace Toon