Mercurial > otakunoraifu
annotate font/text_stream.cc @ 52:15a18fbe6f21
* Known bugs added to the README
* Code cleaning (0 -> NULL when needed, indentation, spaces, ...)
author | thib |
---|---|
date | Sat, 18 Apr 2009 18:35:39 +0000 |
parents | 658272d883ed |
children | ddbcbd000206 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (c) 2004 Kazunori "jagarl" Ueno | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 #include "text.h" | |
29 #include "codeconv.h" | |
52 | 30 #include <string.h> |
31 #include <stdio.h> | |
0 | 32 |
33 /************************************************************************ | |
34 ** | |
35 ** TextStream | |
36 ** | |
37 */ | |
38 | |
39 TextStream::TextStream(void) { | |
40 kanji_type = euc; | |
41 } | |
52 | 42 |
0 | 43 void TextStream::SetSize(double scale) { |
44 TextElem elem; | |
45 elem.type = TextElem::size; | |
46 elem.impl.Size.scale = scale; | |
47 container.push_back(elem); | |
48 } | |
52 | 49 |
0 | 50 void TextStream::SetColor(unsigned char r, unsigned char g, unsigned char b) { |
51 TextElem elem; | |
52 elem.type = TextElem::color; | |
53 elem.impl.Color.r = r; | |
54 elem.impl.Color.g = g; | |
55 elem.impl.Color.b = b; | |
56 container.push_back(elem); | |
57 } | |
52 | 58 |
0 | 59 void TextStream::InsertColor(int begin_pos, int end_pos, unsigned char r, unsigned char g, unsigned char b) { |
60 TextElem elem; | |
61 if (begin_pos < 0) begin_pos = 0; | |
62 if (begin_pos > container.size()) begin_pos = container.size(); | |
63 if (end_pos < 0) end_pos = 0; | |
64 if (end_pos > container.size()) end_pos = container.size(); | |
65 if (begin_pos >= end_pos) return; | |
66 | |
67 elem.type = TextElem::color; | |
68 elem.impl.Color.r = 255; | |
69 elem.impl.Color.g = 255; | |
70 elem.impl.Color.b = 255; | |
71 container.insert(container.begin()+end_pos, elem); | |
72 elem.impl.Color.r = r; | |
73 elem.impl.Color.g = g; | |
74 elem.impl.Color.b = b; | |
75 container.insert(container.begin()+begin_pos, elem); | |
76 Iterator it = container.begin()+begin_pos+1; | |
77 Iterator end = container.begin()+end_pos+1; | |
78 for (; it != end; it++) { | |
79 if (it->type == TextElem::color) { | |
80 TextElem& elem = *it; | |
81 if (elem.impl.Color.r == 255 && elem.impl.Color.g == 255 && elem.impl.Color.b == 255) { | |
82 elem.impl.Color.r = r; | |
83 elem.impl.Color.g = g; | |
84 elem.impl.Color.b = b; | |
85 } | |
86 } | |
87 } | |
88 } | |
52 | 89 |
0 | 90 void TextStream::Clear(void) { |
91 container.clear(); | |
92 } | |
52 | 93 |
0 | 94 void TextStream::Add(const char* str) { |
95 TextElem elem; | |
96 for (; *str; str++) { | |
97 if (*str >= 0x20) { | |
38
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
98 if (*str == '#') { // Commands |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
99 str++; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
100 char command = (*str)|32; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
101 str++; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
102 const char *tmp = str; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
103 while (isdigit(*str)) { |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
104 str++; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
105 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
106 char *args = new char[str+1-tmp]; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
107 strncpy(args, tmp, str-tmp); |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
108 args[str-tmp] = 0; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
109 // Different commands: |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
110 switch(command) { |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
111 case 'c': |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
112 /*TODO: int r, g, b; char key[17]; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
113 sprintf(key, "#COLOR_TABLE.%03d", args); |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
114 if (config.GetParam(key, 3, &r, &g, &b)) { // color not found |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
115 r = g = b = 0; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
116 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
117 elem.type = TextElem::color; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
118 elem.impl.Color.r = r; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
119 elem.impl.Color.g = g; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
120 elem.impl.Color.b = b;*/ |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
121 break; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
122 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
123 delete[] args; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
124 } |
0 | 125 elem.type = TextElem::glyph; |
126 elem.impl.Glyph.code = *str; | |
127 } else if (*str < 0 && str[1] != 0) { | |
128 elem.type = TextElem::glyph; | |
129 elem.impl.Glyph.code = ((int(*(unsigned char*)str))<<8) | int(*(unsigned char*)(str+1)); | |
130 if (kanji_type == sjis) elem.impl.Glyph.code = codeconv_sjis_to_euc(elem.impl.Glyph.code); | |
131 str++; | |
132 } else { | |
133 continue; | |
134 } | |
135 container.push_back(elem); | |
136 } | |
137 } | |
52 | 138 |
0 | 139 void TextStream::AddReturn(void) { |
140 TextElem elem; | |
141 elem.type = TextElem::escape; | |
142 elem.impl.Escape.type = TextElem::ret; | |
143 container.push_back(elem); | |
144 } | |
52 | 145 |
0 | 146 void TextStream::AddName(const char* str) { |
147 TextElem elem; | |
148 elem.type = TextElem::escape; | |
149 elem.impl.Escape.type = TextElem::name_start; | |
150 container.push_back(elem); | |
151 Add(str); | |
152 elem.impl.Escape.type = TextElem::name_end; | |
153 container.push_back(elem); | |
154 } | |
155 | |
156 void TextStream::AddRuby(const char* str, const char* ruby) { | |
157 TextElem elem; | |
158 elem.type = TextElem::escape; | |
159 elem.impl.Escape.type = TextElem::ruby_start; | |
160 container.push_back(elem); | |
161 Add(str); | |
162 elem.impl.Escape.type = TextElem::ruby_startruby; | |
163 container.push_back(elem); | |
164 Add(ruby); | |
165 elem.impl.Escape.type = TextElem::ruby_end; | |
166 container.push_back(elem); | |
167 } | |
168 | |
169 void TextStream::RemoveName(char* name, int namelen) { | |
170 Iterator it; | |
171 for (it = container.begin(); it != container.end(); it++) { | |
172 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::name_start) { | |
173 // 行頭の名前? | |
174 int pt = it - container.begin(); | |
175 Iterator name_start = it; | |
176 for (; it != container.end(); it++) { | |
177 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::name_end) break; | |
178 } | |
179 if (it != container.end()) { | |
180 // 名前が見つかったので削除 | |
181 if (name) { // 保存先があるなら保存する | |
182 Iterator name_end = it; | |
183 int pos = 0; | |
184 namelen--; | |
185 for (it=name_start; it != name_end; it++) { | |
186 if (it->type == TextElem::glyph) { | |
187 unsigned int code = it->impl.Glyph.code; | |
188 if (code < 0x100) { | |
189 if (pos < namelen) name[pos++] = code; | |
190 } else { | |
191 if (pos < namelen) name[pos++] = code>>8; | |
192 if (pos < namelen) name[pos++] = code; | |
193 } | |
194 } | |
195 } | |
196 name[pos] = 0; | |
197 name = 0; // 最初に出た名前のみ保存する | |
198 } | |
199 it++; | |
200 container.erase(name_start, it); | |
201 it = container.begin() + pt; | |
202 } | |
203 } | |
204 for (;it != container.end(); it++) { | |
205 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::ret) break; | |
206 } | |
207 if (it == container.end()) break; | |
208 } | |
209 } | |
210 | |
211 /************************************************************************ | |
212 ** | |
213 ** TextStream::Save | |
214 ** | |
215 */ | |
216 | |
217 /* escape sequence : '=XX' ; x < 0x30 || 'x>0x39 && x<0x40' (symbols) */ | |
218 /* !"#$%&'()*+,-./:;<=>? */ | |
219 | |
220 void TextStream::Load(const std::string& from_s) { | |
221 /* kigou : !"#$%&'()*+,-./:;<=>? */ | |
222 const char* s = from_s.c_str(); | |
223 container.clear(); | |
224 if (*s == '=' && *s == 'e') {kanji_type = euc; s+=2;} | |
225 | |
226 TextElem e; | |
227 while(s && *s) { | |
228 e.type = TextElem::glyph; | |
229 if (*s == '=') { | |
230 if (s[1] >= 'A' && s[1] <= 'Q' && s[2] >= 'A' && s[2] <= 'Q') { // symbols | |
231 e.type = TextElem::glyph; | |
232 e.impl.Glyph.code = (s[1]-'A')*16 + (s[2]-'A'); | |
233 s += 3; | |
234 } else if (s[1] == 'x') { | |
235 e.type = TextElem::escape; | |
236 e.impl.Escape.type = TextElem::EscapeType(s[2]-'A'); | |
237 s += 3; | |
238 } else if (s[1] == 'c') { | |
239 int c; | |
240 e.type = TextElem::color; | |
241 sscanf(s+2, "%x", &c); | |
242 e.impl.Color.r = (c>>16)&0xff; | |
243 e.impl.Color.g = (c>>8)&0xff; | |
244 e.impl.Color.b = (c)&0xff; | |
245 s = strchr(s, '.'); | |
246 if (s) s++; | |
247 } else if (s[1] == 's') { | |
248 e.impl.Size.scale = TextElem::size; | |
249 sscanf(s+2, "%f", &e.impl.Size.scale); | |
250 s = strchr(s, '.'); | |
251 if (s) s++; | |
252 } else { | |
253 fprintf(stderr,"TextStream::Load(): Cannot convert text-stream from Serialized-data\n"); | |
254 s++; | |
255 } | |
256 } else { | |
257 if (*s < 0) { // kanji-code | |
258 if (s[1] == 0) break; | |
259 if (s[1] >= 0 && s[1] < 0x40) break; // not EUC nor SJIS | |
260 e.type = TextElem::glyph; | |
261 e.impl.Glyph.code = codeconv_sjis_to_euc(int(*(unsigned char*)(s))*0x100 + int(*(unsigned char*)(s+1))); | |
262 s += 2; | |
263 } else { // ascii-code | |
264 if (s[0] < 0x30) break; // must be escaped | |
265 if (s[0] > 0x39 && s[0] < 0x40) break; // must be escaped | |
266 e.type = TextElem::glyph; | |
267 e.impl.Glyph.code = s[0]; | |
268 s++; | |
269 } | |
270 } | |
271 container.push_back(e); | |
272 } | |
273 } | |
274 | |
275 std::string TextStream::Save(void) { | |
276 /* kigou : !"#$%&'()*+,-./:;<=>? */ | |
277 Iterator it; | |
278 std::string ret_s; | |
279 char buf_orig[1024]; | |
280 char* buf = buf_orig; | |
281 for (it=container.begin(); it != container.end(); it++) { | |
282 TextElem& e = *it; | |
283 switch(e.type) { | |
284 case TextElem::glyph: { | |
285 int code = e.impl.Glyph.code; | |
286 if (code < 0x30 || (code > 0x39 && code < 0x40)) { | |
287 *buf++ = '='; | |
288 *buf++ = (code/0x10) + 'A'; | |
289 *buf++ = (code%0x10) + 'A'; | |
290 } else { | |
291 code = codeconv_euc_to_sjis(code); // save file の漢字コードはSJIS | |
292 *buf++ = code/256; | |
293 *buf++ = code%256; | |
294 } | |
295 break; | |
296 } | |
297 case TextElem::escape: | |
298 sprintf(buf, "=x%c", e.impl.Escape.type+'A'); | |
299 buf += 3; | |
300 break; | |
301 case TextElem::color: | |
302 sprintf(buf, "=c%x.",int(e.impl.Color.r)*256*256+int(e.impl.Color.g)*256+e.impl.Color.b); | |
303 buf += strlen(buf); | |
304 break; | |
305 case TextElem::size: | |
306 sprintf(buf, "=s%f.", e.impl.Size.scale); | |
307 buf += strlen(buf); | |
308 break; | |
309 } | |
310 if (buf-buf_orig > 1000) { | |
311 *buf = 0; | |
312 ret_s += buf_orig; | |
313 buf = buf_orig; | |
314 } | |
315 } | |
316 *buf = 0; | |
317 ret_s += buf_orig; | |
318 buf = buf_orig; | |
319 return ret_s; | |
320 } | |
321 | |
322 /************************************************************************ | |
323 ** | |
324 ** TextGlyphStream | |
325 ** | |
326 */ | |
327 | |
328 void TextGlyphStream::SetColor(int r, int g, int b) { | |
329 iterator it; | |
330 for (it=begin(); it != end(); it++) { | |
331 // if (it->r == 255 && it->g == 255 && it->b == 255) { | |
332 it->r = r; | |
333 it->g = g; | |
334 it->b = b; | |
335 // } | |
336 } | |
337 } | |
338 void TextGlyphStream::SetReverse(bool is_rev) { | |
339 iterator it; | |
340 for (it=begin(); it != end(); it++) { | |
341 it->is_rev = is_rev; | |
342 } | |
343 } |