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