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 #ifndef SCI_GRAPHICS_TEXT32_H
24 #define SCI_GRAPHICS_TEXT32_H
25 
26 #include "sci/engine/state.h"
27 #include "sci/graphics/celobj32.h"
28 #include "sci/graphics/frameout.h"
29 #include "sci/graphics/helpers.h"
30 
31 namespace Sci {
32 
33 enum TextAlign {
34 	kTextAlignDefault = -1,
35 	kTextAlignLeft    = 0,
36 	kTextAlignCenter  = 1,
37 	kTextAlignRight   = 2
38 };
39 
40 enum ScrollDirection {
41 	kScrollUp,
42 	kScrollDown
43 };
44 
45 class GfxFont;
46 
47 /**
48  * This class handles text calculation and rendering for SCI32 games. The text
49  * calculation system in SCI32 is nearly the same as SCI16, which means this
50  * class behaves similarly. Notably, GfxText32 maintains drawing parameters
51  * across multiple calls, instead of requiring all text parameters to be
52  * provided on every draw call.
53  */
54 class GfxText32 {
55 private:
56 	SegManager *_segMan;
57 	GfxCache *_cache;
58 
59 	/**
60 	 * The width and height of the currently active text bitmap, in text-system
61 	 * coordinates.
62 	 *
63 	 * @note These are unsigned in SSCI.
64 	 */
65 	int16 _width, _height;
66 
67 	/**
68 	 * The color used to draw text.
69 	 */
70 	uint8 _foreColor;
71 
72 	/**
73 	 * The background color of the text box.
74 	 */
75 	uint8 _backColor;
76 
77 	/**
78 	 * The transparent color of the text box. Used when compositing the bitmap
79 	 * onto the screen.
80 	 */
81 	uint8 _skipColor;
82 
83 	/**
84 	 * The rect where the text is drawn within the bitmap. This rect is clipped
85 	 * to the dimensions of the bitmap.
86 	 */
87 	Common::Rect _textRect;
88 
89 	/**
90 	 * The text being drawn to the currently active text bitmap.
91 	 */
92 	Common::String _text;
93 
94 	/**
95 	 * The font being used to draw the text.
96 	 */
97 	GuiResourceId _fontId;
98 
99 	/**
100 	 * The color of the text box border.
101 	 */
102 	int16 _borderColor;
103 
104 	/**
105 	 * If true, text will be drawn using a dither that draws only every other
106 	 * pixel of the text.
107 	 */
108 	bool _dimmed;
109 
110 	/**
111 	 * The text alignment for the drawn text.
112 	 */
113 	TextAlign _alignment;
114 
115 	/**
116 	 * The position of the text draw cursor.
117 	 */
118 	Common::Point _drawPosition;
119 
120 	void drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling);
121 
122 	void drawChar(const char charIndex);
123 	void drawText(const uint index, uint length);
124 
125 	/**
126 	 * Gets the length of the longest run of text available within the currently
127 	 * loaded text, starting from the given `charIndex` and running for up to
128 	 * `maxWidth` pixels. Returns the number of characters that can be written,
129 	 * and mutates the value pointed to by `charIndex` to point to the index of
130 	 * the next character to render.
131 	 */
132 	uint getLongest(uint *charIndex, const int16 maxWidth);
133 
134 	/**
135 	 * Gets the pixel width of a substring of the currently loaded text, without
136 	 * scaling.
137 	 */
138 	int16 getTextWidth(const uint index, uint length) const;
139 
scaleRect(const Common::Rect & rect)140 	inline Common::Rect scaleRect(const Common::Rect &rect) {
141 		Common::Rect scaledRect(rect);
142 		const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
143 		const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
144 		const Ratio scaleX(_xResolution, scriptWidth);
145 		const Ratio scaleY(_yResolution, scriptHeight);
146 		mulinc(scaledRect, scaleX, scaleY);
147 		return scaledRect;
148 	}
149 
150 public:
151 	GfxText32(SegManager *segMan, GfxCache *fonts);
152 
153 	/**
154 	 * Initialises static GfxText32 members.
155 	 */
156 	static void init();
157 
158 	/**
159 	 * The memory handle of the currently active bitmap.
160 	 */
161 	reg_t _bitmap;
162 
163 	/**
164 	 * The size of the x-dimension of the coordinate system used by the text
165 	 * renderer. Static since it was global in SSCI.
166 	 */
167 	static int16 _xResolution;
168 
169 	/**
170 	 * The size of the y-dimension of the coordinate system used by the text
171 	 * renderer. Static since it was global in SSCI.
172 	 */
173 	static int16 _yResolution;
174 
175 	/**
176 	 * The currently active font resource used to write text into the bitmap.
177 	 *
178 	 * @note SSCI builds the font table directly inside of FontMgr; we use
179 	 * GfxFont instead.
180 	 */
181 	GfxFont *_font;
182 
183 	/**
184 	 * Creates a plain font bitmap with a flat color background.
185 	 */
186 	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);
187 
188 	/**
189 	 * Creates a font bitmap with a view background.
190 	 */
191 	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);
192 
scaleUpWidth(int value)193 	inline int scaleUpWidth(int value) const {
194 		const int scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
195 		return (value * scriptWidth + _xResolution - 1) / _xResolution;
196 	}
197 
scaleUpHeight(int value)198 	inline int scaleUpHeight(int value) const {
199 		const int scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
200 		return (value * scriptHeight + _yResolution - 1) / _yResolution;
201 	}
202 
203 	/**
204 	 * Draws the text to the bitmap.
205 	 */
206 	void drawTextBox();
207 
208 	/**
209 	 * Draws the given text to the bitmap.
210 	 *
211 	 * @note SSCI holds a reference to a shared string which lets the text be
212 	 * updated from outside of the font manager. Instead, we use this extra
213 	 * signature to send the text to draw.
214 	 */
215 	void drawTextBox(const Common::String &text);
216 
217 	/**
218 	 * Erases the given rect by filling with the background color.
219 	 */
220 	void erase(const Common::Rect &rect, const bool doScaling);
221 
222 	void invertRect(const reg_t bitmap, const int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling);
223 
224 	/**
225 	 * Sets the font to be used for rendering and calculation of text
226 	 * dimensions.
227 	 */
228 	void setFont(const GuiResourceId fontId);
229 
230 	/**
231 	 * Gets the pixel height of the currently loaded font.
232 	 */
233 	int16 getScaledFontHeight() const;
234 
235 	/**
236 	 * Gets the width of a character.
237 	 */
238 	uint16 getCharWidth(const char charIndex, const bool doScaling) const;
239 
240 	/**
241 	 * Retrieves the width and height of a block of text.
242 	 */
243 	Common::Rect getTextSize(const Common::String &text, const int16 maxWidth, bool doScaling);
244 
245 	/**
246 	 * Gets the pixel width of a substring of the currently loaded text, with
247 	 * scaling.
248 	 */
249 	int16 getTextWidth(const Common::String &text, const uint index, const uint length);
250 
251 	/**
252 	 * Retrieves the width of a line of text.
253 	 */
254 	int16 getStringWidth(const Common::String &text);
255 
256 	/**
257 	 * Gets the number of characters of `text`, starting from `index`, that can
258 	 * be safely rendered into `textRect`.
259 	 */
260 	int16 getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling);
261 
262 	/**
263 	 * Gets the number of characters of `text`, starting from `index`, that can
264 	 * be safely rendered into `textRect` using the given font.
265 	 */
266 	int16 getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling);
267 
268 	/**
269 	 * Scroll up/down one line. `numLines` is the number of the lines in the
270 	 * textarea, and `textLine` contains the text to draw as the newly visible
271 	 * line. Originally FontMgr::DrawOneLine and FontMgr::UpOneLine.
272 	 */
273 	void scrollLine(const Common::String &textLine, int numLines, uint8 color, TextAlign align, GuiResourceId fontId, ScrollDirection dir);
274 };
275 
276 } // End of namespace Sci
277 
278 #endif
279