File: qd_screen_text.cpp

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (244 lines) | stat: -rw-r--r-- 8,430 bytes parent folder | download | duplicates (2)
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
/* 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "common/stream.h"
#include "common/debug.h"

#include "qdengine/qd_fwd.h"
#include "qdengine/xmath.h"
#include "qdengine/qdcore/qd_setup.h"
#include "qdengine/qdcore/qd_screen_text.h"
#include "qdengine/system/graphics/gr_dispatcher.h"

#include "qdengine/qdcore/qd_game_object.h"
#include "qdengine/qdcore/qd_game_object_state.h"

#include "qdengine/qdcore/qd_game_dispatcher.h" // В qdGameDispather хранятся шрифты


namespace QDEngine {

qdScreenTextFormat::qdScreenTextFormat() : _arrangement(ARRANGE_VERTICAL),
	_alignment(ALIGN_LEFT),
	_color(0xFFFFFF),
	_hover_color(0xFFFFFF),
	_font_type(QD_FONT_TYPE_NONE),
	_global_depend(true) {
}

const qdScreenTextFormat &qdScreenTextFormat::default_format() {
	return g_engine->_default_format;
}

const qdScreenTextFormat &qdScreenTextFormat::global_text_format() {
	return g_engine->_global_text_format;
}
void qdScreenTextFormat::set_global_text_format(const qdScreenTextFormat &frmt) {
	g_engine->_global_text_format = frmt;
}

const qdScreenTextFormat &qdScreenTextFormat::global_topic_format() {
	return g_engine->_global_topic_format;
}
void qdScreenTextFormat::set_global_topic_format(const qdScreenTextFormat &frmt) {
	g_engine->_global_topic_format = frmt;
}



bool qdScreenTextFormat::load_script(const xml::tag *p) {
	bool load_global_depend = false;
	for (xml::tag::subtag_iterator it = p->subtags_begin(); it != p->subtags_end(); ++it) {
		switch (it->ID()) {
		case QDSCR_TEXT_ALIGN:
			set_arrangement((qdScreenTextFormat::arrangement_t)xml::tag_buffer(*it).get_int());
			break;
		case QDSCR_ALIGN:
			set_alignment((qdScreenTextFormat::alignment_t)xml::tag_buffer(*it).get_int());
			break;
		case QDSCR_TEXT_COLOR:
			set_color(xml::tag_buffer(*it).get_int());
			break;
		case QDSCR_TEXT_HOVER_COLOR:
			set_hover_color(xml::tag_buffer(*it).get_int());
			break;
		case QDSCR_FONT_TYPE:
			set_font_type(xml::tag_buffer(*it).get_int());
			break;
		case QDSCR_GLOBAL_DEPEND:
			_global_depend = (0 != xml::tag_buffer(*it).get_int());
			load_global_depend = true;
			break;
		}
	}

	// Если скрипт старый и инфа о связи с глобальным форматом отсутствует, то
	// является ли формат связанным с глобальным по содержимому
	if (!load_global_depend)
		_global_depend = (global_text_format() == *this);

	return true;
}

bool qdScreenTextFormat::save_script(Common::WriteStream &fh, int indent) const {
	for (int i = 0; i < indent; i++) {
		fh.writeString("\t");
	}
	fh.writeString("<screen_text_format");

	// Если зависим от глобального формата текста, то пишем только сам факт зависимости
	// (пишем факт или отсутствие зависимости в любом случае)
	if (is_global_depend())
		fh.writeString(" global_depend=\"1\"");
	else {
		// Не зависит от глобальных параметров - значит пишем данные о формате
		fh.writeString(" global_depend=\"0\"");

		if (arrangement() != qdScreenTextFormat::default_format().arrangement()) {
			fh.writeString(Common::String::format(" text_align=\"%d\"", (int)arrangement()));
		}

		if (alignment() != qdScreenTextFormat::default_format().alignment()) {
			fh.writeString(Common::String::format(" align=\"%d\"", (int)alignment()));
		}

		if (color() != qdScreenTextFormat::default_format().color()) {
			fh.writeString(Common::String::format(" text_color=\"%d\"", color()));
		}

		if (hover_color() != qdScreenTextFormat::default_format().hover_color()) {
			fh.writeString(Common::String::format(" text_hover_color=\"%d\"", hover_color()));
		}

		if (font_type() != qdScreenTextFormat::default_format().font_type()) {
			fh.writeString(Common::String::format(" font_type=\"%d\"", font_type()));
		}
	}

	fh.writeString("/>\r\n");

	return true;
}

qdScreenText::qdScreenText(const char *p, const Vect2i &pos, qdGameObjectState *owner) : _pos(pos),
	_size(0, 0),
	_owner(owner),
	_hover_mode(false) {
	set_data(p);
}

qdScreenText::qdScreenText(const char *p, const qdScreenTextFormat &fmt, const Vect2i &pos, qdGameObjectState *owner) : _pos(pos),
	_size(0, 0),
	_text_format(fmt),
	_owner(owner) {
	_hover_mode = false;

	set_data(p);
}

qdScreenText::~qdScreenText() {
}

void qdScreenText::redraw(const Vect2i &owner_pos) const {
	int x = owner_pos.x + _pos.x;
	int y = owner_pos.y + _pos.y;

	uint32 col = _hover_mode ? _text_format.hover_color() : _text_format.color();

	const grFont *font = qdGameDispatcher::get_dispatcher()->find_font(_text_format.font_type());

	debugC(1, kDebugText, "qdScreenText::redraw([%d, %d]): '%s'", x, y, transCyrillic(data()));

	grDispatcher::instance()->drawAlignedText(x, y, _size.x, _size.y, col, data(), grTextAlign(_text_format.alignment()), 0, 0, font);
	if (g_engine->_debugDraw)
		grDispatcher::instance()->rectangle(x, y, _size.x, _size.y, col, 0, GR_OUTLINED);
}

void qdScreenText::set_data(const char *p) {
	_data = p;

	const grFont *font = qdGameDispatcher::get_dispatcher()->find_font(_text_format.font_type());
	_size.x = grDispatcher::instance()->textWidth(data(), 0, font);
	_size.y = grDispatcher::instance()->textHeight(data(), 0, font);
}

bool qdScreenText::is_owned_by(const qdNamedObject *p) const {
	return (_owner && p == _owner->owner());
}

bool qdScreenText::format_text(int max_width) {
	const grFont *font = qdGameDispatcher::get_dispatcher()->find_font(text_format().font_type());
	if (NULL == font)
		font = grDispatcher::get_default_font();

	bool correct = true;
	int safe_space = -1;
	int cur_wid = 0;
	_data += ' ';	// Adding space for simplifying the algorightm (because of the trailing
					// space we will trigger attempt to format the string ending)
					// The space will not affect the output because it is at the end.

	for (uint i = 0; i < _data.size(); i++) {
		if (_data[i] == '\n') {
			if (cur_wid > max_width) {
				// Safe space is present, so it is safe to split it (e.g. everything fits max_width)
				if (safe_space >= 0) {
					_data.setChar('\n', safe_space);
					i = safe_space; // in for(...) we will move to safe_space + 1
				} else { // it didn't fit (no safe space). But we split it anyway, it is at least something...
					_data.setChar('\n', i);
					correct = false;
				}
			}

			safe_space = -1;
			cur_wid = 0;
		} else if (' ' != _data[i]) { // Not a space -- we accumulate width
			cur_wid += font->find_char((byte)_data[i]).size_x();
		} else { // // Space - it is safe to split here (we remember this position or split here)
			cur_wid += font->size_x() / 2;

			// Width is not exceeded -- remember the current _safe_ space and move on
			if (cur_wid < max_width) {
				safe_space = i;
				continue;
			} else { // The width is exceeded, and we saw a safe space -- have to split. (Everything fits max_width)
				if (safe_space >= 0) {
					_data.setChar('\n', safe_space);
					i = safe_space; // in for(...) we will move to safe_space + 1
				} else { // it didn't fit (no safe space). But we split it anyway, it is at least something...
					_data.setChar('\n', i);
					correct = false;
				}
				safe_space = -1; // We have split -- no more safe space
				cur_wid = 0;     // New part has zero width for now
			}
		}
	}

	_data.erase(_data.size() - 1, 1); // We remove the last symbol (the space that we added initially)

	set_data(_data.c_str()); // Set the data (for text dimensions recalc)

	return correct;
}

} // namespace QDEngine