Mercurial > otakunoraifu
annotate font/text_stream.cc @ 39:de29c4d2d043
(none)
author | thib |
---|---|
date | Tue, 17 Mar 2009 22:00:05 +0000 |
parents | 658272d883ed |
children | 15a18fbe6f21 |
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" | |
1 | 30 #include<string.h> |
0 | 31 #include<stdio.h> |
32 | |
33 /************************************************************************ | |
34 ** | |
35 ** TextStream | |
36 ** | |
37 */ | |
38 | |
39 TextStream::TextStream(void) { | |
40 kanji_type = euc; | |
41 } | |
42 void TextStream::SetSize(double scale) { | |
43 TextElem elem; | |
44 elem.type = TextElem::size; | |
45 elem.impl.Size.scale = scale; | |
46 container.push_back(elem); | |
47 } | |
48 void TextStream::SetColor(unsigned char r, unsigned char g, unsigned char b) { | |
49 TextElem elem; | |
50 elem.type = TextElem::color; | |
51 elem.impl.Color.r = r; | |
52 elem.impl.Color.g = g; | |
53 elem.impl.Color.b = b; | |
54 container.push_back(elem); | |
55 } | |
56 void TextStream::InsertColor(int begin_pos, int end_pos, unsigned char r, unsigned char g, unsigned char b) { | |
57 TextElem elem; | |
58 if (begin_pos < 0) begin_pos = 0; | |
59 if (begin_pos > container.size()) begin_pos = container.size(); | |
60 if (end_pos < 0) end_pos = 0; | |
61 if (end_pos > container.size()) end_pos = container.size(); | |
62 if (begin_pos >= end_pos) return; | |
63 | |
64 elem.type = TextElem::color; | |
65 elem.impl.Color.r = 255; | |
66 elem.impl.Color.g = 255; | |
67 elem.impl.Color.b = 255; | |
68 container.insert(container.begin()+end_pos, elem); | |
69 elem.impl.Color.r = r; | |
70 elem.impl.Color.g = g; | |
71 elem.impl.Color.b = b; | |
72 container.insert(container.begin()+begin_pos, elem); | |
73 Iterator it = container.begin()+begin_pos+1; | |
74 Iterator end = container.begin()+end_pos+1; | |
75 for (; it != end; it++) { | |
76 if (it->type == TextElem::color) { | |
77 TextElem& elem = *it; | |
78 if (elem.impl.Color.r == 255 && elem.impl.Color.g == 255 && elem.impl.Color.b == 255) { | |
79 elem.impl.Color.r = r; | |
80 elem.impl.Color.g = g; | |
81 elem.impl.Color.b = b; | |
82 } | |
83 } | |
84 } | |
85 } | |
86 void TextStream::Clear(void) { | |
87 container.clear(); | |
88 } | |
89 void TextStream::Add(const char* str) { | |
90 TextElem elem; | |
91 for (; *str; str++) { | |
92 if (*str >= 0x20) { | |
38
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
93 if (*str == '#') { // Commands |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
94 str++; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
95 char command = (*str)|32; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
96 str++; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
97 const char *tmp = str; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
98 while (isdigit(*str)) { |
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 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
101 char *args = new char[str+1-tmp]; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
102 strncpy(args, tmp, str-tmp); |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
103 args[str-tmp] = 0; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
104 // Different commands: |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
105 switch(command) { |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
106 case 'c': |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
107 /*TODO: int r, g, b; char key[17]; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
108 sprintf(key, "#COLOR_TABLE.%03d", args); |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
109 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
|
110 r = g = b = 0; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
111 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
112 elem.type = TextElem::color; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
113 elem.impl.Color.r = r; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
114 elem.impl.Color.g = g; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
115 elem.impl.Color.b = b;*/ |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
116 break; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
117 } |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
118 delete[] args; |
658272d883ed
* Support (more or less) button style selects (fuuko's ones)
thib
parents:
1
diff
changeset
|
119 } |
0 | 120 elem.type = TextElem::glyph; |
121 elem.impl.Glyph.code = *str; | |
122 } else if (*str < 0 && str[1] != 0) { | |
123 elem.type = TextElem::glyph; | |
124 elem.impl.Glyph.code = ((int(*(unsigned char*)str))<<8) | int(*(unsigned char*)(str+1)); | |
125 if (kanji_type == sjis) elem.impl.Glyph.code = codeconv_sjis_to_euc(elem.impl.Glyph.code); | |
126 str++; | |
127 } else { | |
128 continue; | |
129 } | |
130 container.push_back(elem); | |
131 } | |
132 } | |
133 void TextStream::AddReturn(void) { | |
134 TextElem elem; | |
135 elem.type = TextElem::escape; | |
136 elem.impl.Escape.type = TextElem::ret; | |
137 container.push_back(elem); | |
138 } | |
139 void TextStream::AddName(const char* str) { | |
140 TextElem elem; | |
141 elem.type = TextElem::escape; | |
142 elem.impl.Escape.type = TextElem::name_start; | |
143 container.push_back(elem); | |
144 Add(str); | |
145 elem.impl.Escape.type = TextElem::name_end; | |
146 container.push_back(elem); | |
147 } | |
148 | |
149 void TextStream::AddRuby(const char* str, const char* ruby) { | |
150 TextElem elem; | |
151 elem.type = TextElem::escape; | |
152 elem.impl.Escape.type = TextElem::ruby_start; | |
153 container.push_back(elem); | |
154 Add(str); | |
155 elem.impl.Escape.type = TextElem::ruby_startruby; | |
156 container.push_back(elem); | |
157 Add(ruby); | |
158 elem.impl.Escape.type = TextElem::ruby_end; | |
159 container.push_back(elem); | |
160 } | |
161 | |
162 void TextStream::RemoveName(char* name, int namelen) { | |
163 Iterator it; | |
164 for (it = container.begin(); it != container.end(); it++) { | |
165 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::name_start) { | |
166 // 行頭の名前? | |
167 int pt = it - container.begin(); | |
168 Iterator name_start = it; | |
169 for (; it != container.end(); it++) { | |
170 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::name_end) break; | |
171 } | |
172 if (it != container.end()) { | |
173 // 名前が見つかったので削除 | |
174 if (name) { // 保存先があるなら保存する | |
175 Iterator name_end = it; | |
176 int pos = 0; | |
177 namelen--; | |
178 for (it=name_start; it != name_end; it++) { | |
179 if (it->type == TextElem::glyph) { | |
180 unsigned int code = it->impl.Glyph.code; | |
181 if (code < 0x100) { | |
182 if (pos < namelen) name[pos++] = code; | |
183 } else { | |
184 if (pos < namelen) name[pos++] = code>>8; | |
185 if (pos < namelen) name[pos++] = code; | |
186 } | |
187 } | |
188 } | |
189 name[pos] = 0; | |
190 name = 0; // 最初に出た名前のみ保存する | |
191 } | |
192 it++; | |
193 container.erase(name_start, it); | |
194 it = container.begin() + pt; | |
195 } | |
196 } | |
197 for (;it != container.end(); it++) { | |
198 if (it->type == TextElem::escape && it->impl.Escape.type == TextElem::ret) break; | |
199 } | |
200 if (it == container.end()) break; | |
201 } | |
202 } | |
203 | |
204 /************************************************************************ | |
205 ** | |
206 ** TextStream::Save | |
207 ** | |
208 */ | |
209 | |
210 /* escape sequence : '=XX' ; x < 0x30 || 'x>0x39 && x<0x40' (symbols) */ | |
211 /* !"#$%&'()*+,-./:;<=>? */ | |
212 | |
213 void TextStream::Load(const std::string& from_s) { | |
214 /* kigou : !"#$%&'()*+,-./:;<=>? */ | |
215 const char* s = from_s.c_str(); | |
216 container.clear(); | |
217 if (*s == '=' && *s == 'e') {kanji_type = euc; s+=2;} | |
218 | |
219 TextElem e; | |
220 while(s && *s) { | |
221 e.type = TextElem::glyph; | |
222 if (*s == '=') { | |
223 if (s[1] >= 'A' && s[1] <= 'Q' && s[2] >= 'A' && s[2] <= 'Q') { // symbols | |
224 e.type = TextElem::glyph; | |
225 e.impl.Glyph.code = (s[1]-'A')*16 + (s[2]-'A'); | |
226 s += 3; | |
227 } else if (s[1] == 'x') { | |
228 e.type = TextElem::escape; | |
229 e.impl.Escape.type = TextElem::EscapeType(s[2]-'A'); | |
230 s += 3; | |
231 } else if (s[1] == 'c') { | |
232 int c; | |
233 e.type = TextElem::color; | |
234 sscanf(s+2, "%x", &c); | |
235 e.impl.Color.r = (c>>16)&0xff; | |
236 e.impl.Color.g = (c>>8)&0xff; | |
237 e.impl.Color.b = (c)&0xff; | |
238 s = strchr(s, '.'); | |
239 if (s) s++; | |
240 } else if (s[1] == 's') { | |
241 e.impl.Size.scale = TextElem::size; | |
242 sscanf(s+2, "%f", &e.impl.Size.scale); | |
243 s = strchr(s, '.'); | |
244 if (s) s++; | |
245 } else { | |
246 fprintf(stderr,"TextStream::Load(): Cannot convert text-stream from Serialized-data\n"); | |
247 s++; | |
248 } | |
249 } else { | |
250 if (*s < 0) { // kanji-code | |
251 if (s[1] == 0) break; | |
252 if (s[1] >= 0 && s[1] < 0x40) break; // not EUC nor SJIS | |
253 e.type = TextElem::glyph; | |
254 e.impl.Glyph.code = codeconv_sjis_to_euc(int(*(unsigned char*)(s))*0x100 + int(*(unsigned char*)(s+1))); | |
255 s += 2; | |
256 } else { // ascii-code | |
257 if (s[0] < 0x30) break; // must be escaped | |
258 if (s[0] > 0x39 && s[0] < 0x40) break; // must be escaped | |
259 e.type = TextElem::glyph; | |
260 e.impl.Glyph.code = s[0]; | |
261 s++; | |
262 } | |
263 } | |
264 container.push_back(e); | |
265 } | |
266 } | |
267 | |
268 std::string TextStream::Save(void) { | |
269 /* kigou : !"#$%&'()*+,-./:;<=>? */ | |
270 Iterator it; | |
271 std::string ret_s; | |
272 char buf_orig[1024]; | |
273 char* buf = buf_orig; | |
274 for (it=container.begin(); it != container.end(); it++) { | |
275 TextElem& e = *it; | |
276 switch(e.type) { | |
277 case TextElem::glyph: { | |
278 int code = e.impl.Glyph.code; | |
279 if (code < 0x30 || (code > 0x39 && code < 0x40)) { | |
280 *buf++ = '='; | |
281 *buf++ = (code/0x10) + 'A'; | |
282 *buf++ = (code%0x10) + 'A'; | |
283 } else { | |
284 code = codeconv_euc_to_sjis(code); // save file の漢字コードはSJIS | |
285 *buf++ = code/256; | |
286 *buf++ = code%256; | |
287 } | |
288 break; | |
289 } | |
290 case TextElem::escape: | |
291 sprintf(buf, "=x%c", e.impl.Escape.type+'A'); | |
292 buf += 3; | |
293 break; | |
294 case TextElem::color: | |
295 sprintf(buf, "=c%x.",int(e.impl.Color.r)*256*256+int(e.impl.Color.g)*256+e.impl.Color.b); | |
296 buf += strlen(buf); | |
297 break; | |
298 case TextElem::size: | |
299 sprintf(buf, "=s%f.", e.impl.Size.scale); | |
300 buf += strlen(buf); | |
301 break; | |
302 } | |
303 if (buf-buf_orig > 1000) { | |
304 *buf = 0; | |
305 ret_s += buf_orig; | |
306 buf = buf_orig; | |
307 } | |
308 } | |
309 *buf = 0; | |
310 ret_s += buf_orig; | |
311 buf = buf_orig; | |
312 return ret_s; | |
313 } | |
314 | |
315 /************************************************************************ | |
316 ** | |
317 ** TextGlyphStream | |
318 ** | |
319 */ | |
320 | |
321 void TextGlyphStream::SetColor(int r, int g, int b) { | |
322 iterator it; | |
323 for (it=begin(); it != end(); it++) { | |
324 // if (it->r == 255 && it->g == 255 && it->b == 255) { | |
325 it->r = r; | |
326 it->g = g; | |
327 it->b = b; | |
328 // } | |
329 } | |
330 } | |
331 void TextGlyphStream::SetReverse(bool is_rev) { | |
332 iterator it; | |
333 for (it=begin(); it != end(); it++) { | |
334 it->is_rev = is_rev; | |
335 } | |
336 } |