aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/text32.h
blob: 945cc81130771596da1b3cf8d27568b47e1eb5e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef SCI_GRAPHICS_TEXT32_H
#define SCI_GRAPHICS_TEXT32_H

#include "sci/engine/state.h"
#include "sci/graphics/celobj32.h"
#include "sci/graphics/frameout.h"
#include "sci/graphics/helpers.h"

namespace Sci {

enum TextAlign {
	kTextAlignDefault = -1,
	kTextAlignLeft    = 0,
	kTextAlignCenter  = 1,
	kTextAlignRight   = 2
};

enum ScrollDirection {
	kScrollUp,
	kScrollDown
};

class GfxFont;

/**
 * This class handles text calculation and rendering for SCI32 games. The text
 * calculation system in SCI32 is nearly the same as SCI16, which means this
 * class behaves similarly. Notably, GfxText32 maintains drawing parameters
 * across multiple calls, instead of requiring all text parameters to be
 * provided on every draw call.
 */
class GfxText32 {
private:
	SegManager *_segMan;
	GfxCache *_cache;

	/**
	 * The width and height of the currently active text bitmap, in text-system
	 * coordinates.
	 *
	 * @note These are unsigned in SSCI.
	 */
	int16 _width, _height;

	/**
	 * The color used to draw text.
	 */
	uint8 _foreColor;

	/**
	 * The background color of the text box.
	 */
	uint8 _backColor;

	/**
	 * The transparent color of the text box. Used when compositing the bitmap
	 * onto the screen.
	 */
	uint8 _skipColor;

	/**
	 * The rect where the text is drawn within the bitmap. This rect is clipped
	 * to the dimensions of the bitmap.
	 */
	Common::Rect _textRect;

	/**
	 * The text being drawn to the currently active text bitmap.
	 */
	Common::String _text;

	/**
	 * The font being used to draw the text.
	 */
	GuiResourceId _fontId;

	/**
	 * The color of the text box border.
	 */
	int16 _borderColor;

	/**
	 * If true, text will be drawn using a dither that draws only every other
	 * pixel of the text.
	 */
	bool _dimmed;

	/**
	 * The text alignment for the drawn text.
	 */
	TextAlign _alignment;

	/**
	 * The position of the text draw cursor.
	 */
	Common::Point _drawPosition;

	void drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling);

	void drawChar(const char charIndex);
	void drawText(const uint index, uint length);

	/**
	 * Gets the length of the longest run of text available within the currently
	 * loaded text, starting from the given `charIndex` and running for up to
	 * `maxWidth` pixels. Returns the number of characters that can be written,
	 * and mutates the value pointed to by `charIndex` to point to the index of
	 * the next character to render.
	 */
	uint getLongest(uint *charIndex, const int16 maxWidth);

	/**
	 * Gets the pixel width of a substring of the currently loaded text, without
	 * scaling.
	 */
	int16 getTextWidth(const uint index, uint length) const;

	inline Common::Rect scaleRect(const Common::Rect &rect) {
		Common::Rect scaledRect(rect);
		int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
		int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
		Ratio scaleX(_xResolution, scriptWidth);
		Ratio scaleY(_yResolution, scriptHeight);
		mulinc(scaledRect, scaleX, scaleY);
		return scaledRect;
	}

public:
	GfxText32(SegManager *segMan, GfxCache *fonts);

	/**
	 * Initialises static GfxText32 members.
	 */
	static void init();

	/**
	 * The memory handle of the currently active bitmap.
	 */
	reg_t _bitmap;

	/**
	 * The size of the x-dimension of the coordinate system used by the text
	 * renderer. Static since it was global in SSCI.
	 */
	static int16 _xResolution;

	/**
	 * The size of the y-dimension of the coordinate system used by the text
	 * renderer. Static since it was global in SSCI.
	 */
	static int16 _yResolution;

	/**
	 * The currently active font resource used to write text into the bitmap.
	 *
	 * @note SSCI builds the font table directly inside of FontMgr; we use
	 * GfxFont instead.
	 */
	GfxFont *_font;

	/**
	 * Creates a plain font bitmap with a flat color background.
	 */
	reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling, const bool gc);

	/**
	 * Creates a font bitmap with a view background.
	 */
	reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc);

	inline int scaleUpWidth(int value) const {
		const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
		return (value * scriptWidth + _xResolution - 1) / _xResolution;
	}

	inline int scaleUpHeight(int value) const {
		const int scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
		return (value * scriptHeight + _yResolution - 1) / _yResolution;
	}

	/**
	 * Draws the text to the bitmap.
	 */
	void drawTextBox();

	/**
	 * Draws the given text to the bitmap.
	 *
	 * @note SSCI holds a reference to a shared string which lets the text be
	 * updated from outside of the font manager. Instead, we use this extra
	 * signature to send the text to draw.
	 */
	void drawTextBox(const Common::String &text);

	/**
	 * Erases the given rect by filling with the background color.
	 */
	void erase(const Common::Rect &rect, const bool doScaling);

	void invertRect(const reg_t bitmap, const int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling);

	/**
	 * Sets the font to be used for rendering and calculation of text
	 * dimensions.
	 */
	void setFont(const GuiResourceId fontId);

	/**
	 * Gets the pixel height of the currently loaded font.
	 */
	int16 getScaledFontHeight() const;

	/**
	 * Gets the width of a character.
	 */
	uint16 getCharWidth(const char charIndex, const bool doScaling) const;

	/**
	 * Retrieves the width and height of a block of text.
	 */
	Common::Rect getTextSize(const Common::String &text, const int16 maxWidth, bool doScaling);

	/**
	 * Gets the pixel width of a substring of the currently loaded text, with
	 * scaling.
	 */
	int16 getTextWidth(const Common::String &text, const uint index, const uint length);

	/**
	 * Retrieves the width of a line of text.
	 */
	int16 getStringWidth(const Common::String &text);

	/**
	 * Gets the number of characters of `text`, starting from `index`, that can
	 * be safely rendered into `textRect`.
	 */
	int16 getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling);

	/**
	 * Gets the number of characters of `text`, starting from `index`, that can
	 * be safely rendered into `textRect` using the given font.
	 */
	int16 getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling);

	/**
	 * Scroll up/down one line. `numLines` is the number of the lines in the
	 * textarea, and `textLine` contains the text to draw as the newly visible
	 * line. Originally FontMgr::DrawOneLine and FontMgr::UpOneLine.
	 */
	void scrollLine(const Common::String &textLine, int numLines, uint8 color, TextAlign align, GuiResourceId fontId, ScrollDirection dir);
};

} // End of namespace Sci

#endif