Mercurial > otakunoraifu
annotate window/picture.cc @ 41:4c832144b3f2
OtakuNoRaifu is born! (Changed 'xclannad' to 'OtakuNoRaifu')
author | thib |
---|---|
date | Mon, 23 Mar 2009 18:17:57 +0000 |
parents | 97b752b43502 |
children | 01aa5ddf7dc8 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (c) 2004-2006 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<stdio.h> | |
29 #include<vector> | |
30 #include<list> | |
31 #include<algorithm> | |
32 | |
33 #include"rect.h" | |
34 #include"event.h" | |
35 #include"font/font.h" | |
36 #include"font/text.h" | |
32
97b752b43502
* Removed SDL_rotozoom.{cc,h} (now uses SDL_gfx). TODO: improve configure.ac
thib
parents:
0
diff
changeset
|
37 #include<SDL_rotozoom.h> |
0 | 38 #include"system/file.h" |
39 | |
40 #include"picture.h" | |
41 | |
42 using namespace std; | |
43 | |
44 int print_blit=0; | |
45 inline void dprintf(const char* fmt, ...) {} | |
46 /* render.cc */ | |
47 void DSurfaceBlitAlpha(Surface* src_o, const Rect& srcrect_o, Surface* dst_o, const Rect& dstrect_o, const unsigned char* alpha, const Rect& alpharect); | |
48 void DSurfaceBlitSaturate(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect, unsigned char alpha); | |
49 void DSurfaceBlitMultiply(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect); | |
50 void DSurfaceFill(Surface* src, const Rect& rect, int r, int g, int b, int a=0xff); // クリア | |
51 #if 0 /* DEBUG */ | |
52 #include<sys/types.h> | |
53 #include<sys/time.h> | |
54 #define dprintf printf | |
55 static struct timeval tv; | |
56 void gettm(void) { | |
57 gettimeofday(&tv, 0); | |
58 } | |
59 int calctm(void) { | |
60 struct timeval tv2; | |
61 gettimeofday(&tv2, 0); | |
62 int n = (tv2.tv_sec-tv.tv_sec)*100000 + (tv2.tv_usec-tv.tv_usec)/10; | |
63 return n; | |
64 } | |
65 #endif | |
66 | |
67 /****************************************** | |
68 ** PicBase | |
69 */ | |
70 PicBase::PicBase(const Rect& _rel_pos, PicContainer* _parent, int _attr) : | |
71 parent(_parent), rel_pos(_rel_pos), rel_solid_area(0,0,0,0), clip_area(0,0,0,0), | |
72 is_hidden(true), is_hidden_now(true), is_cached(false), attribute(_attr), surface_alpha_rect(0,0) { | |
73 | |
74 if (parent) root = parent->root; | |
75 else root = 0; | |
76 surface_back = 0; | |
77 surface_own = 0; | |
78 surface_alpha = 0; | |
79 surface_x = 0; surface_y = 0; | |
80 surface_w = -1; surface_h = -1; | |
81 widget = 0; | |
82 attribute |= NO_PICTURE; | |
83 if ( (attribute & CACHE_BACK) && root) { | |
84 surface_back = root->NewSurface(rel_pos.width(), rel_pos.height(), NO_MASK); | |
85 } | |
86 | |
87 if (parent) { | |
88 parent->children.push_back(this); | |
89 z_pos = parent->children.end(); z_pos--; | |
90 distance_root = parent->DistanceRoot() + 1; | |
91 } else { | |
92 distance_root = 1; | |
93 } | |
94 } | |
95 PicBase::~PicBase() { | |
96 ClearAnm(); | |
97 if (widget) { | |
98 fprintf(stderr,"Warning: PicBase::~PicBase: surface is disallocated but widget is still alive.\n"); | |
99 widget->deactivate(); | |
100 } | |
101 if (surface_back) root->DeleteSurface(surface_back); | |
102 if (surface_own && (attribute & SURFACE_FREE)) root->DeleteSurface(surface_own); | |
103 if (surface_alpha && (attribute & ALPHA_FREE)) delete surface_alpha; | |
104 iterator it; | |
105 if (parent) { // 自分を親から削除 | |
106 parent->children.remove(this); | |
107 // root の update 情報から自分を削除 | |
108 parent->Root().DeleteUpdatePic(this); | |
109 // 自分の領域を書き直す | |
110 Rect old_ppos = rel_pos; | |
111 parent->QueryAbsPos(old_ppos); | |
112 parent->ReBlit(old_ppos); | |
113 } | |
114 } | |
115 void PicBase::Blit(const Rect& rpos_orig) { | |
116 // 実際に描画する領域を得る | |
117 Rect rpos = rpos_orig; | |
118 // 親widget上に設定されたclip area 内に描画を限定する | |
119 if (clip_area.width() != 0) { | |
120 Rect clip = clip_area; | |
121 clip = child_pos(clip, this); | |
122 rpos.intersect(clip); | |
123 } | |
124 Rect apos = QueryAbsPos(rpos); | |
125 if (rpos.empty()) return; | |
126 // 必要に応じて保存、描画 | |
127 if (attribute & CACHE_BACK) root->BlitSurface(root->surface, apos, surface_back, rpos); | |
128 if (! (attribute & NO_PICTURE)) { | |
129 rpos.rmove(surface_x, surface_y); | |
130 if (surface_w >= 0 && surface_h >= 0) { | |
131 Rect clip(surface_x, surface_y, surface_x+surface_w, surface_y+surface_h); | |
132 rpos.intersect(clip); | |
133 } | |
134 //if (apos.ty < 200) fprintf(stderr,"Blit: %08x : (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",surface_own,rpos_orig.lx,rpos_orig.ty,rpos_orig.rx,rpos_orig.by,apos.lx,apos.ty,apos.rx,apos.by); | |
135 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, root->surface, apos, attribute); | |
136 rpos.rmove(-surface_x, -surface_y); | |
137 } else if (parent == 0) { // 親がいないなら背景消去の責任をもつ | |
138 DSurfaceFill(root->surface, apos, 0, 0, 0); | |
139 } | |
140 PicContainer* cur = dynamic_cast<PicContainer*>(this); | |
141 if (cur && (!cur->children.empty())) { | |
142 cur->BlitChildren(rpos); | |
143 } | |
144 } | |
145 void PicBase::SimpleBlit(Surface* screen) { | |
146 // 実際に描画する領域を得る | |
147 Rect rpos(0, 0, rel_pos.width(), rel_pos.height()); | |
148 Rect apos = QueryAbsPos(rpos); | |
149 if (rpos.empty()) return; | |
150 rpos.rmove(surface_x, surface_y); | |
151 if (surface_w >= 0 && surface_h >= 0) { | |
152 Rect clip(surface_x, surface_y, surface_x+surface_w, surface_y+surface_h); | |
153 rpos.intersect(clip); | |
154 } | |
155 //if (apos.ty < 200) fprintf(stderr,"S-Blit: %08x : (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",surface_own,rel_pos.lx,rel_pos.ty,rel_pos.rx,rel_pos.by,apos.lx,apos.ty,apos.rx,apos.by); | |
156 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, screen, apos, attribute); | |
157 } | |
158 | |
159 Rect PicBase::QueryAbsPos(Rect& rpos) { | |
160 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
161 if (parent == 0) { // root container | |
162 return rpos; | |
163 } | |
164 // 親の座標に変換後、Query する | |
165 Rect ppos = parent_pos(rpos); | |
166 Rect apos = parent->QueryAbsPos(ppos); | |
167 rpos = child_pos(ppos, this); | |
168 return apos; | |
169 }; | |
170 void PicBase::ReBlit(const Rect& rpos_c) { | |
171 Rect rpos = rpos_c; | |
172 Rect apos = QueryAbsPos(rpos); | |
173 | |
174 root->Update(this, rpos, apos); | |
175 } | |
176 void PicBase::ExecReBlit(const Rect& rpos_c) { | |
177 Rect rpos = rpos_c; | |
178 Rect abs_r = QueryAbsPos(rpos); | |
179 Rect ppos = parent_pos(rpos); | |
180 if(print_blit) fprintf(stderr,"back."); | |
181 if (parent) parent->BlitBack(z_pos, ppos); | |
182 if(print_blit) fprintf(stderr,"self."); | |
183 if (!is_hidden_now) Blit(rpos); | |
184 if(print_blit) fprintf(stderr,"front."); | |
185 if (parent) parent->BlitFront(z_pos, ppos); | |
186 if(print_blit) fprintf(stderr,"end."); | |
187 } | |
188 | |
189 void PicBase::ZMove(PicBase* move_to) { | |
190 if (parent == 0) { | |
191 fprintf(stderr,"Warning: PicBase::ZMove is called by root.\n"); | |
192 return; | |
193 } | |
194 if (move_to == ZMOVE_TOP) { | |
195 if (this == parent->children.back()) return; | |
196 } else if (move_to == ZMOVE_BOTTOM) { | |
197 if (this == parent->children.front()) return; | |
198 } else if (move_to == this) { | |
199 fprintf(stderr,"Error: PicBase::ZMove : move in front of itself!\n"); | |
200 return; | |
201 } else if (move_to && move_to->parent != parent) { | |
202 fprintf(stderr,"Error: PicBase::ZMove was called with a no-brother picture\n"); | |
203 return; | |
204 } | |
205 // move_to と zpos のうち、後ろの方の picture から書きなおす必要がある | |
206 iterator redraw_zpos = z_pos; redraw_zpos++; | |
207 if (move_to == ZMOVE_BOTTOM) { // 最背面へ | |
208 parent->children.erase(z_pos); | |
209 parent->children.push_front(this); | |
210 z_pos = parent->children.begin(); | |
211 redraw_zpos = parent->children.begin(); | |
212 } else if (move_to == ZMOVE_TOP) { // 最前面へ | |
213 redraw_zpos = z_pos; redraw_zpos++; | |
214 parent->children.erase(z_pos); | |
215 parent->children.push_back(this); | |
216 z_pos = parent->children.end(); z_pos--; | |
217 } else { | |
218 int dis_to = distance(move_to->parent->children.begin(), move_to->z_pos); | |
219 int dis_cur = distance(parent->children.begin(), z_pos); | |
220 if (dis_cur < dis_to) redraw_zpos = move_to->z_pos; | |
221 parent->children.erase(z_pos); | |
222 iterator insert_pos = move_to->z_pos; insert_pos++; | |
223 parent->children.insert(insert_pos, this); | |
224 z_pos = move_to->z_pos; z_pos++; | |
225 } | |
226 if (! is_hidden_now) { | |
227 is_cached = false; | |
228 ReBlit(); | |
229 /* @@@ parent->Blit() と Blit() の違いが分からないので修正 06/12/02 | |
230 Rect ppos = rel_pos; | |
231 parent->QueryAbsPos(ppos); | |
232 parent->ReBlit(ppos); | |
233 */ | |
234 } | |
235 }; | |
236 void PicBase::RMove(int add_x, int add_y) { | |
237 Rect old_ppos = rel_pos; | |
238 rel_pos.rmove(add_x, add_y); | |
239 parent->QueryAbsPos(old_ppos); | |
240 parent->ReBlit(old_ppos); | |
241 ReBlit(); | |
242 | |
243 if (widget) { | |
244 Rect new_ppos = rel_pos; | |
245 Rect new_apos = parent->QueryAbsPos(new_ppos); | |
246 widget->SetRegion(new_apos); | |
247 } | |
248 } | |
249 void PicBase::Move(int new_rx, int new_ry) { | |
250 RMove(new_rx-rel_pos.lx, new_ry-rel_pos.ty); | |
251 } | |
252 void PicBase::SetEventWidget(PicWidget* new_widget) { | |
253 widget = new_widget; | |
254 if (widget) { | |
255 Rect new_ppos = rel_pos; | |
256 Rect apos = parent->QueryAbsPos(new_ppos); | |
257 widget->SetRegion(apos); | |
258 } | |
259 } | |
260 void PicBase::show_all(void) { | |
261 PicContainer* cont = dynamic_cast<PicContainer*>(this); | |
262 if (cont && (!cont->children.empty())) cont->set_showflag(); | |
263 show(); | |
264 } | |
265 bool PicBase::IsParent(PicBase* to) { | |
266 if (parent == 0) return false; | |
267 if (parent == to) return true; | |
268 return parent->IsParent(to); | |
269 } | |
270 void PicBase::show(void) { | |
271 /* 自分の親がすべて shown か? */ | |
272 PicContainer* cur; | |
273 for (cur = parent; cur != 0; cur = cur->parent) | |
274 if (cur->is_hidden) break; | |
275 if (cur) { // 親が隠れているので表示はしない | |
276 is_hidden = false; | |
277 is_hidden_now = true; | |
278 return; | |
279 } | |
280 if (is_hidden == false) return; // すでに表示されているのでなにもしない | |
281 if (widget) { | |
282 widget->activate(); | |
283 } | |
284 is_hidden = false; | |
285 is_hidden_now = false; | |
286 is_cached = false; | |
287 cur = dynamic_cast<PicContainer*>(this); | |
288 if (cur && (!cur->children.empty())) cur->set_nowhiddenflag(false); | |
289 ReBlit(); | |
290 } | |
291 void PicBase::hide(void) { | |
292 if (is_hidden) return; | |
293 if (widget) { | |
294 widget->deactivate(); | |
295 } | |
296 is_hidden = true; | |
297 is_hidden_now = true; | |
298 is_cached = false; | |
299 PicContainer* cur = dynamic_cast<PicContainer*>(this); | |
300 if (cur && (!cur->children.empty())) cur->set_nowhiddenflag(true); | |
301 ReBlit(); | |
302 } | |
303 void PicBase::SetSurfaceAlpha(const unsigned char* alpha, const Rect& alpha_r) { | |
304 if (attribute & ALPHA_FREE) { | |
305 if (surface_alpha) delete[] surface_alpha; | |
306 surface_alpha = 0; | |
307 } | |
308 surface_alpha = alpha; | |
309 surface_alpha_rect = alpha_r; | |
310 if (!is_hidden) ReBlit(); | |
311 } | |
312 void PicBase::SetSurfaceColorKey(int r, int g, int b) { | |
313 surface_alpha = 0; | |
314 surface_alpha_rect = Rect(0,0); | |
315 attribute &= ~(BLIT_SATURATE | BLIT_MULTIPLY); | |
316 if (surface_own) { | |
317 int key = SDL_MapRGB( ((SDL_Surface*)surface_own)->format, r, g, b); | |
318 key |= 0xff000000; | |
319 SDL_SetColorKey( (SDL_Surface*)surface_own, SDL_SRCCOLORKEY, key); | |
320 } | |
321 if (!is_hidden) ReBlit(); | |
322 } | |
323 void PicBase::SetSurfaceAlphaFile(const char* file) { | |
324 | |
325 /* ファイルを元に alpha 画像を作成する */ | |
326 /* ファイル: パルフェの 'fil' ファイル */ | |
327 ARCINFO* info = file_searcher.Find(FILESEARCH::PDT, file,"fil"); | |
328 if (info == 0) return; | |
329 char* new_alpha = info->CopyRead(); | |
330 int alpha_size = info->Size(); | |
331 delete info; | |
332 Rect sr(0,0); int w,h; | |
333 if (surface_own == 0 || new_alpha == 0) { | |
334 err_ret: | |
335 if (new_alpha) delete[] new_alpha; | |
336 SetSurfaceAlpha(0,Rect(0,0)); | |
337 return; | |
338 } | |
339 sr = Rect(*surface_own); | |
340 w = sr.width(); | |
341 h = sr.height(); | |
342 if (alpha_size < w*h) goto err_ret; | |
343 int i,j; | |
344 if ( ((SDL_Surface*)surface_own)->format->Amask == 0) { // mask を surface に繰り込む | |
345 Surface* dest = root->NewSurface(w,h, ALPHA_MASK); | |
346 for (i=0; i<h; i++) { | |
347 char* a = new_alpha + w*i; | |
348 char* s = (char*)((SDL_Surface*)surface_own)->pixels + ((SDL_Surface*)surface_own)->pitch*i; | |
349 char* d = (char*)((SDL_Surface*)dest)->pixels + ((SDL_Surface*)dest)->pitch*i; | |
350 int sbpp = ((SDL_Surface*)surface_own)->format->BytesPerPixel; | |
351 int dbpp = ((SDL_Surface*)dest)->format->BytesPerPixel; | |
352 | |
353 for (j=0; j<w; j++) { | |
354 int d = read_little_endian_int(s); | |
355 d &= 0xffffff; | |
356 if (d == 0) ; | |
357 else if (*a == 0) d |= 0xff000000; | |
358 else d |= (int(*a) << 24); | |
359 s += sbpp; d += dbpp; a++; | |
360 } | |
361 } | |
362 delete new_alpha; | |
363 root->DeleteSurface(surface_own); | |
364 surface_own = dest; | |
365 SetSurfaceAlpha(0, Rect(0,0)); | |
366 } else { // 外部にマスク作成 | |
367 /* マスクのうち、0xff であるべき部分を画像から判別、変更する */ | |
368 for (i=0; i<h; i++) { | |
369 char* a = new_alpha + w*i; | |
370 char* s = (char*)((SDL_Surface*)surface_own)->pixels + ((SDL_Surface*)surface_own)->pitch*i; | |
371 int bpp = ((SDL_Surface*)surface_own)->format->BytesPerPixel; | |
372 for (j=0; j<w; j++) { | |
373 if ( ((*(int*)s) & 0xffffff) == 0) *a = 0; | |
374 else if (*a == 0) *a = 0xff; | |
375 s += bpp; a++; | |
376 } | |
377 } | |
378 SetSurfaceAlpha( (unsigned char*)new_alpha, Rect(0,0,w,h)); | |
379 attribute |= ALPHA_FREE; | |
380 } | |
381 } | |
382 void PicBase::SetSurface(const char* filename, int x, int y) { | |
383 Surface* s = root->NewSurface(filename); | |
384 SetSurface(s, x, y, SURFACE_FREE); | |
385 } | |
386 void PicBase::SetSurface(Surface* new_surface, int x, int y, int new_attr) { | |
387 if (surface_own && (attribute & SURFACE_FREE)) { | |
388 root->DeleteSurface(surface_own); | |
389 } | |
390 attribute &= ~(SURFACE_FREE | BLIT_SATURATE | BLIT_MULTIPLY | NO_PICTURE | SOLID); | |
391 attribute |= new_attr; | |
392 surface_own = new_surface; | |
393 surface_x = x; | |
394 surface_y = y; | |
395 surface_w = -1; | |
396 surface_h = -1; | |
397 | |
398 if (attribute & FIT_SURFACE) { | |
399 // surface の大きさに自分の大きさを変更 | |
400 parent->ReBlit(rel_pos); | |
401 if (surface_own == 0) { | |
402 rel_pos = Rect(rel_pos.lx, rel_pos.ty); | |
403 } else { | |
404 Rect r(*surface_own); | |
405 int w = r.width(), h = r.height(); | |
406 w -= x; h -= y; | |
407 rel_pos = Rect(rel_pos.lx, rel_pos.ty, rel_pos.lx+w, rel_pos.ty+h); | |
408 } | |
409 } | |
410 | |
411 rel_solid_area = Rect(0,0,0,0); | |
412 if (! surface_own) attribute |= NO_PICTURE; | |
413 else if (root->with_mask(surface_own) == 0) { | |
414 attribute |= SOLID; | |
415 rel_solid_area = rel_pos; | |
416 } | |
417 if (!is_hidden) ReBlit(); | |
418 } | |
419 void PicBase::SetSurfacePos(int x, int y) { | |
420 if (surface_x == x && surface_y == y && surface_w == -1 && surface_h == -1) return; | |
421 surface_x = x; surface_y = y; | |
422 surface_w = -1; surface_h = -1; | |
423 if (!is_hidden_now) ReBlit(); | |
424 } | |
425 int PicBase::SurfacePosX(void) { | |
426 return surface_x; | |
427 } | |
428 int PicBase::SurfacePosY(void) { | |
429 return surface_y; | |
430 } | |
431 void PicBase::SetSurfaceRect(const Rect& r) { | |
432 if (surface_x == r.lx && surface_y == r.ty && surface_w == r.width() && surface_h == r.height()) return; | |
433 surface_x = r.lx; surface_y = r.ty; | |
434 surface_w = r.width(); surface_h = r.height(); | |
435 parent->ReBlit(rel_pos); | |
436 rel_pos = Rect(rel_pos.lx, rel_pos.ty, rel_pos.lx+surface_w, rel_pos.ty+surface_h); | |
437 if (widget) { | |
438 Rect new_ppos = rel_pos; | |
439 Rect apos = parent->QueryAbsPos(new_ppos); | |
440 widget->SetRegion(apos); | |
441 } | |
442 if (!is_hidden_now) ReBlit(); | |
443 } | |
444 void PicBase::SetClipArea(const Rect& r) { | |
445 if (clip_area == r) return; | |
446 clip_area = r; | |
447 parent->ReBlit(rel_pos); | |
448 } | |
449 | |
450 void PicBase::SetSurfaceAttribute(int new_attribute) { | |
451 attribute &= ~(BLIT_SATURATE | BLIT_MULTIPLY); | |
452 attribute |= new_attribute & (BLIT_SATURATE | BLIT_MULTIPLY); | |
453 if (new_attribute & (BLIT_SATURATE | BLIT_MULTIPLY)) { | |
454 rel_solid_area = Rect(0,0); | |
455 } | |
456 } | |
457 void PicBase::SetSurfaceFreeFlag(bool flag) { | |
458 if (flag) attribute |= SURFACE_FREE; | |
459 else attribute &= ~SURFACE_FREE; | |
460 | |
461 } | |
462 | |
463 /****************************************** | |
464 ** PicContainer | |
465 */ | |
466 PicContainer::PicContainer(const Rect& rel_pos, PicContainer* parent, int attr) : | |
467 PicBase(rel_pos, parent, attr) { | |
468 } | |
469 PicContainer::~PicContainer() { | |
470 iterator end = children.end(); | |
471 for (iterator it = children.begin(); it != end; ) { | |
472 iterator it_next = it; it_next++; | |
473 if ((*it)->widget) delete (*it)->widget; // picture にwidget が付属しているなら、そちらをdelete | |
474 else delete (*it); | |
475 it = it_next; | |
476 } | |
477 } | |
478 void PicContainer::BlitBack(iterator z, Rect rpos) { | |
479 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
480 if (rpos.empty()) return; | |
481 iterator end = children.end(), begin = children.begin(); iterator it = begin; | |
482 | |
483 Rect ppos = parent_pos(rpos); | |
484 if (is_hidden_now) goto parent_redraw; | |
485 // cache されている領域を探す | |
486 // z自身がキャッシュしていれば、ここで終了 | |
487 if ( ((*z)->attribute & CACHE_BACK) && ( (*z)->is_cached) && (*z)->rel_pos.is_inner(rpos)) { | |
488 Rect cpos = child_pos(rpos, *z); | |
489 Rect apos = (*z)->QueryAbsPos(cpos); | |
490 root->BlitSurface( (*z)->surface_back, cpos, root->surface, apos); | |
491 return; | |
492 } | |
493 // z より下の子がキャッシュ、あるいは SOLID 描画できないか? | |
494 for (it = z; it != begin;) { // 子がcontainerの場合のチェックは省略 | |
495 it--; | |
496 if ( (*it)->is_hidden_now) continue; | |
497 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
498 if ( ((*it)->attribute & CACHE_BACK) && ((*it)->is_cached) && (*it)->rel_pos.is_inner(rpos)) { | |
499 Rect cpos = child_pos(rpos, *it); | |
500 Rect apos = (*it)->QueryAbsPos(cpos); | |
501 root->BlitSurface( (*it)->surface_back, cpos, root->surface, apos); | |
502 goto children_redraw; | |
503 } | |
504 if ( (*it)->rel_solid_area.is_inner(rpos)) { | |
505 goto children_redraw; | |
506 } | |
507 } | |
508 } | |
509 // 自分自身がキャッシュ、あるいは SOLID 描画できないか? | |
510 if (rel_solid_area.is_inner(ppos)) { | |
511 goto self_redraw; | |
512 } | |
513 if ( (attribute & CACHE_BACK) && is_cached) { | |
514 Rect cpos = child_pos(rpos, *z); | |
515 Rect apos = (*z)->QueryAbsPos(cpos); | |
516 Rect draw_rpos = (*z)->parent_pos(cpos); | |
517 if(print_blit) fprintf(stderr,"cahce."); | |
518 root->BlitSurface(surface_back, draw_rpos, root->surface, apos); | |
519 goto self_redraw; | |
520 } | |
521 parent_redraw: | |
522 if (parent) { | |
523 Rect ppos = parent_pos(rpos); | |
524 if(print_blit) fprintf(stderr,"parent-back."); | |
525 parent->BlitBack(z_pos, ppos); | |
526 } | |
527 if (is_hidden_now) return; | |
528 self_redraw: | |
529 if(print_blit) fprintf(stderr,"back-self."); | |
530 BlitSelf(rpos); // 子は描画せず、自分だけ描画 | |
531 children_redraw: | |
532 for (; it != z; it++) { | |
533 if ( (*it)->is_hidden_now) continue; | |
534 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
535 Rect cpos = child_pos(rpos, *it); | |
536 (*it)->Blit(cpos); | |
537 } | |
538 } | |
539 } | |
540 void PicContainer::BlitChildren(Rect rpos) { | |
541 if (print_blit) fprintf(stderr,"bc."); | |
542 iterator end = children.end(); | |
543 for (iterator it = children.begin(); it != end; it++) { | |
544 if ( (*it)->is_hidden_now) if(print_blit) fprintf(stderr,"bch %08x;",*it); | |
545 if ( (*it)->is_hidden_now) continue; | |
546 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
547 Rect cpos = child_pos(rpos, *it); | |
548 (*it)->Blit(cpos); | |
549 } | |
550 } | |
551 } | |
552 void PicContainer::BlitFront(iterator z, Rect rpos) { | |
553 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
554 if (rpos.empty()) return; | |
555 iterator end = children.end(); iterator it; | |
556 z++; | |
557 for (it = z; it != end; it++) { | |
558 if ( (*it)->is_hidden_now) continue; | |
559 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
560 Rect cpos = child_pos(rpos, *it); | |
561 (*it)->Blit(cpos); | |
562 } | |
563 } | |
564 if (parent) { | |
565 Rect ppos = parent_pos(rpos); | |
566 parent->BlitFront(z_pos, ppos); | |
567 } | |
568 }; | |
569 void PicContainer::BlitSelf(Rect rpos) { | |
570 // 実際に描画する領域を得る | |
571 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
572 if (rpos.empty()) return; | |
573 Rect apos = QueryAbsPos(rpos); | |
574 // 必要に応じて保存、描画 | |
575 if(print_blit) fprintf(stderr,"self-back."); | |
576 if (attribute & CACHE_BACK) root->BlitSurface(root->surface, apos, surface_back, rpos); | |
577 if (! (attribute & NO_PICTURE)) { | |
578 rpos.rmove(surface_x, surface_y); | |
579 if (surface_w >= 0 && surface_h >= 0) { | |
580 Rect clip(0, 0, surface_w, surface_h); | |
581 clip.rmove(rpos.lx, rpos.ty); | |
582 rpos.intersect(clip); | |
583 } | |
584 if(print_blit) fprintf(stderr,"self-blit."); | |
585 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, root->surface, apos, attribute); | |
586 } else if (parent == 0) { // 親がいないなら背景消去の責任をもつ | |
587 DSurfaceFill(root->surface, apos, 0, 0, 0); | |
588 } | |
589 } | |
590 | |
591 void PicContainer::set_showflag(void) { | |
592 iterator end = children.end(); | |
593 for (iterator it = children.begin(); it != end; it++) { | |
594 (*it)->is_hidden = false; | |
595 PicContainer* next = dynamic_cast<PicContainer*>(*it); | |
596 if (next && (!next->children.empty())) next->set_showflag(); | |
597 } | |
598 } | |
599 void PicContainer::set_nowhiddenflag(bool is_hide) { | |
600 iterator end = children.end(); | |
601 for (iterator it = children.begin(); it != end; it++) { | |
602 if (is_hide) (*it)->is_hidden_now = true; | |
603 else (*it)->is_hidden_now = (*it)->is_hidden; | |
604 if ( (*it)->widget) { | |
605 if ((*it)->is_hidden_now) (*it)->widget->deactivate(); | |
606 else (*it)->widget->activate(); | |
607 } | |
608 PicContainer* next = dynamic_cast<PicContainer*>(*it); | |
609 if (next && (!next->children.empty())) next->set_nowhiddenflag(is_hide); | |
610 } | |
611 } | |
612 void PicContainer::RMove(int add_x, int add_y) { // event widget の移動があり得るので子についてもRMoveを呼び出す | |
613 PicBase::RMove(add_x, add_y); | |
614 iterator end = children.end(); | |
615 for (iterator it = children.begin(); it != end; it++) { | |
616 (*it)->RMove(0,0); | |
617 } | |
618 } | |
619 | |
620 PicBase* PicContainer::create_leaf(const Rect& rel_pos, int attr) { | |
621 return new PicBase(rel_pos, this, attr); | |
622 } | |
623 PicContainer* PicContainer::create_node(const Rect& rel_pos, int attr) { | |
624 return new PicContainer(rel_pos, this, attr); | |
625 } | |
626 | |
627 /*************************************************************** | |
628 ** | |
629 ** PicWidget | |
630 */ | |
631 | |
632 PicWidget::PicWidget(void) { | |
633 pic = 0; | |
634 } | |
635 PicWidget::~PicWidget() { | |
636 if (pic) { | |
637 pic->SetEventWidget(0); | |
638 delete pic; | |
639 } | |
640 pic = 0; | |
641 } | |
642 void PicWidget::SetPic(PicBase* new_pic) { | |
643 if (pic) { | |
644 pic->SetEventWidget(0); | |
645 delete pic; | |
646 } | |
647 pic = new_pic; | |
648 if (pic) pic->SetEventWidget(this); | |
649 } | |
650 PicBase* PicWidget::Pic(void) { | |
651 if (pic == 0) { | |
652 fprintf(stderr,"Error: PicWidget::Pic returns zero.\n"); | |
653 } | |
654 return pic; | |
655 } | |
656 PicContainer* PicWidget::PicNode(void) { | |
657 PicContainer* node = dynamic_cast<PicContainer*>(pic); | |
658 if (node == 0) { | |
659 fprintf(stderr,"Error: PicWidget::PicNode returns zero.\n"); | |
660 } | |
661 return node; | |
662 } | |
663 | |
664 /****************************************** | |
665 ** FileToSurface | |
666 */ | |
667 | |
668 #include<list> | |
669 #include<map> | |
670 #include<string> | |
671 using namespace std; | |
672 struct SurfaceIndex { | |
673 typedef list<SurfaceIndex*>::iterator qiterator; | |
674 string filename; | |
675 Surface* surface; | |
676 qiterator qpos; | |
677 int ref_count; | |
678 }; | |
679 | |
680 class FileToSurface { | |
681 typedef list<SurfaceIndex*>::iterator qiterator; | |
682 | |
683 list<SurfaceIndex*> queue; | |
684 map<string, SurfaceIndex*> findex; | |
685 map<Surface*, SurfaceIndex*> mindex; | |
686 int count; | |
687 int count_max; | |
688 const PicRoot& root; | |
689 bool DeleteData(SurfaceIndex* data); | |
690 Surface* LoadSurface(string name, char*& mem); | |
691 public: | |
692 FileToSurface(const PicRoot& root); | |
693 ~FileToSurface(void); | |
694 Surface* Load(string name); | |
695 bool Free(Surface* s); | |
696 }; | |
697 | |
698 FileToSurface::FileToSurface(const PicRoot& _root) : root(_root) { | |
699 count = 0; | |
700 count_max = 32; // キャッシュ量(決め打ち) | |
701 }; | |
702 FileToSurface::~FileToSurface() { | |
703 qiterator it; | |
704 for (it=queue.begin(); it != queue.end(); it++) { | |
705 if ( (*it)->ref_count) { | |
706 fprintf(stderr, "Warning: FileToSurface: delete referenced surface named '%s'\n",(*it)->filename.c_str()); | |
707 } | |
708 root.DeleteSurfaceImpl( (*it)->surface); | |
709 delete *it; | |
710 } | |
711 } | |
712 inline bool FileToSurface::DeleteData(SurfaceIndex* data) { | |
713 if ( data->ref_count) return false; | |
714 findex.erase(data->filename); | |
715 mindex.erase(data->surface); | |
716 queue.erase(data->qpos); | |
717 root.DeleteSurfaceImpl(data->surface); | |
718 delete data; | |
719 count--; | |
720 return true; | |
721 } | |
722 inline Surface* FileToSurface::LoadSurface(string name, char*& mem) { | |
723 ARCINFO* info = file_searcher.Find(FILESEARCH::PDT, name.c_str(),"pdt"); | |
724 if (info == 0) return 0; | |
725 GRPCONV* conv = GRPCONV::AssignConverter(info); | |
726 if (conv == 0) { delete info;return 0;} | |
727 mem = (char*)malloc(conv->Width() * conv->Height() * 4 + 1024); | |
728 Surface* s = 0; | |
729 if (conv->Read(mem)) { | |
730 MaskType is_mask = conv->IsMask() ? ALPHA_MASK : NO_MASK; | |
731 if (is_mask == ALPHA_MASK) { // alpha がすべて 0xff ならマスク無しとする | |
732 int len = conv->Width()*conv->Height(); | |
733 unsigned int* d = (unsigned int*)mem; | |
734 int i; for (i=0; i<len; i++) { | |
735 if ( (*d&0xff000000) != 0xff000000) break; | |
736 d++; | |
737 } | |
738 if (i == len) { | |
739 is_mask = NO_MASK; | |
740 } | |
741 } | |
742 s = root.NewSurfaceFromRGBAData(conv->Width(), conv->Height(), mem, is_mask); | |
743 } | |
744 delete conv; delete info; // delete data; | |
745 return s; | |
746 } | |
747 Surface* FileToSurface::Load(string name) { | |
748 if (findex.find(name) != findex.end()) { | |
749 findex[name]->ref_count++; | |
750 return findex[name]->surface; | |
751 } | |
752 char* mem; | |
753 Surface* surface = LoadSurface(name, mem); | |
754 if (surface == 0) return 0; | |
755 | |
756 while (count >= count_max) { // count_max 以上のデータを可能なら削除する | |
757 qiterator it; | |
758 for (it=queue.begin(); it != queue.end(); it++) { | |
759 if (DeleteData(*it)) break; | |
760 } | |
761 if (it == queue.end()) break; // 全データが使用中なら終了 | |
762 } | |
763 SurfaceIndex* new_index = new SurfaceIndex; | |
764 new_index->filename = name; | |
765 new_index->surface = surface; | |
766 findex[name] = new_index; | |
767 mindex[surface] = new_index; | |
768 queue.push_back(new_index); | |
769 new_index->qpos = queue.end(); new_index->qpos--; | |
770 new_index->ref_count = 1; | |
771 count++; | |
772 return surface; | |
773 } | |
774 bool FileToSurface::Free(Surface* s) { | |
775 if (mindex.find(s) == mindex.end()) { | |
776 return false; | |
777 } | |
778 SurfaceIndex* index = mindex[s]; | |
779 if (index->ref_count == 0) DeleteData(index); | |
780 else index->ref_count--; | |
781 return true; | |
782 } | |
783 | |
784 /****************************************** | |
785 ** PicRoot | |
786 */ | |
787 #include<SDL.h> | |
788 | |
789 #include"surface.h" | |
790 | |
791 #define DefaultRmask 0xff0000 | |
792 #define DefaultGmask 0xff00 | |
793 #define DefaultBmask 0xff | |
794 #define DefaultAmask 0xff000000 | |
795 #define DefaultBpp 32 | |
796 | |
797 PicRoot::PicRoot(void) { | |
798 hw_surface = (Surface*)SDL_GetVideoSurface(); | |
799 SDL_PixelFormat* fmt_SDL = hw_surface->format; | |
800 if (fmt_SDL->BitsPerPixel == DefaultBpp && fmt_SDL->Rmask == DefaultRmask && fmt_SDL->Gmask == DefaultGmask && fmt_SDL->Bmask == DefaultBmask) { | |
801 surface = hw_surface; | |
802 } else { | |
803 surface = (Surface*)SDL_CreateRGBSurface(0, hw_surface->w, hw_surface->h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, 0); | |
804 } | |
805 | |
806 Rect rpos(0, 0, surface->w, surface->h); | |
807 root = new PicContainer(rpos, 0, 0); | |
808 root->InitRoot(this); | |
809 root->show(); | |
810 ftosurface = new FileToSurface(*this); | |
811 width = surface->w; | |
812 height = surface->h; | |
813 return; | |
814 } | |
815 PicRoot::~PicRoot() { | |
816 // if (surface) DeleteSurfaceImpl(surface); // SDL_GetVideoSurface() した surface は開放の必要がないらしい | |
817 surface = 0; | |
818 delete root; | |
819 delete ftosurface; | |
820 } | |
821 void PicRoot::Update(PicBase* pic, const Rect& rpos, const Rect& apos) { | |
822 update_rects.push_back(UpdateItem(pic, rpos, apos)); | |
823 } | |
824 bool PicRoot::UpdateItem::less(const PicRoot::UpdateItem& a, const PicRoot::UpdateItem& b) { | |
825 return a.pic->DistanceRoot() < b.pic->DistanceRoot(); | |
826 } | |
827 void PicRoot::DeleteUpdatePic(PicBase* pic) { | |
828 vector<UpdateItem>::iterator it = update_rects.begin(); | |
829 while(it != update_rects.end()) { | |
830 if (it->pic == pic) { | |
831 update_rects.erase(it); | |
832 it = update_rects.begin(); | |
833 continue; | |
834 } | |
835 it++; | |
836 } | |
837 return; | |
838 } | |
839 void PicRoot::ExecUpdate(void) { | |
840 /* 共通する領域を消去する */ | |
841 sort(update_rects.begin(), update_rects.end(), UpdateItem::less); | |
842 vector<UpdateItem>::iterator it; | |
843 vector<UpdateItem>::iterator end = update_rects.end(); | |
844 if(print_blit){ | |
845 fprintf(stderr,"ExecUpdate Start: \n\t"); | |
846 for (it=update_rects.begin(); it != end; it++) { | |
847 fprintf(stderr,"(%d,%d,%d,%d), ",it->apos.lx,it->apos.ty,it->apos.rx,it->apos.by); | |
848 } | |
849 fprintf(stderr,"\n"); | |
850 } | |
851 for (it=update_rects.begin(); it != end; it++) { | |
852 if (it->rpos.width() == 0) continue; | |
853 | |
854 Rect apos = it->apos; | |
855 PicBase* pic = it->pic; | |
856 | |
857 vector<UpdateItem>::iterator jt = it; jt++; | |
858 for (; jt != end; jt++) { | |
859 if (apos.is_inner(jt->apos)) { | |
860 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 | |
861 jt->rpos = Rect(0,0); // empty rect をセット | |
862 jt->apos = Rect(0,0); | |
863 } | |
864 } else if (jt->apos.is_inner(apos)) { // 相手に自分が包含される | |
865 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 | |
866 it->rpos = Rect(0,0); | |
867 it->apos = Rect(0,0); | |
868 break; | |
869 } | |
870 } | |
871 } | |
872 } | |
873 if(print_blit){ | |
874 fprintf(stderr,"->\t"); | |
875 for (it=update_rects.begin(); it != end; it++) { | |
876 fprintf(stderr,"(%d,%d,%d,%d), ",it->apos.lx,it->apos.ty,it->apos.rx,it->apos.by); | |
877 } | |
878 fprintf(stderr,"\n"); | |
879 } | |
880 | |
881 int num = update_rects.size(); | |
882 SDL_Rect* r = new SDL_Rect[num]; | |
883 Rect confine = Rect(0, 0, surface->w, surface->h); | |
884 int n = 0; | |
885 int i; | |
886 for (i=0; i<num; i++) { | |
887 UpdateItem& item = update_rects[i]; | |
888 Rect& ur = item.apos; | |
889 if (ur.width() == 0) continue; | |
890 if(print_blit)fprintf(stderr,"%08x: %d,%d,%d,%d",item.pic, item.apos.lx, item.apos.ty, item.apos.rx, item.apos.by); | |
891 | |
892 item.pic->ExecReBlit(item.rpos); | |
893 if(print_blit)fprintf(stderr,"\n"); | |
894 ur.intersect(confine); | |
895 r[n].x = ur.lx; | |
896 r[n].y = ur.ty; | |
897 r[n].w = ur.rx - ur.lx; | |
898 r[n].h = ur.by - ur.ty; | |
899 if (surface != hw_surface) SDL_BlitSurface(surface, &r[n], hw_surface, &r[n]); | |
900 n++; | |
901 } | |
902 if(print_blit)fprintf(stderr,"\n"); | |
903 SDL_UpdateRects(hw_surface, n, r); | |
904 delete[] r; update_rects.clear(); | |
905 } | |
906 | |
907 Surface* PicRoot::NewSurface(int w, int h, MaskType with_mask) const { | |
908 Surface* s; | |
909 if (with_mask == ALPHA_MASK) { | |
910 s = (Surface*)SDL_CreateRGBSurface(SDL_SRCALPHA, w, h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, DefaultAmask); | |
911 } else { | |
912 s = (Surface*)SDL_CreateRGBSurface(0, w, h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, 0); | |
913 } | |
914 return s; | |
915 } | |
916 | |
917 Surface* PicRoot::NewSurfaceFromRGBAData(int w, int h, char* data, MaskType with_mask) const { | |
918 int amask = (with_mask == ALPHA_MASK) ? DefaultAmask : 0; | |
919 Surface* s = (Surface*)SDL_CreateRGBSurfaceFrom(data, w, h, DefaultBpp, w*4, DefaultRmask, DefaultGmask, DefaultBmask, amask); | |
920 s->flags &= ~SDL_PREALLOC; | |
921 return s; | |
922 }; | |
923 Surface* PicRoot::NewSurface(const char* f, MaskType with_mask) { | |
924 if (f == 0) return 0; | |
925 Surface* s = ftosurface->Load(f); | |
926 if (s == 0) return 0; | |
927 if (with_mask == COLOR_MASK) { | |
928 SDL_SetColorKey( (SDL_Surface*)s, SDL_SRCCOLORKEY, *(Uint32*)s->pixels); | |
929 } | |
930 /* xkanon の残骸 */ | |
931 if (strcmp(f, "grdat") == 0) | |
932 SDL_SetColorKey(s, SDL_SRCCOLORKEY, 0x55aa66); | |
933 return s; | |
934 } | |
935 Surface* PicRoot::RotZoomSurface(Surface* from, double zoom, double rotate) { | |
936 Surface* ret = (Surface*)rotozoomSurface( (SDL_Surface*)from, rotate, zoom, SMOOTHING_OFF); | |
937 return ret; | |
938 } | |
939 void PicRoot::DeleteSurfaceImpl(Surface* s) const { | |
940 SDL_FreeSurface(s); | |
941 } | |
942 void PicRoot::DeleteSurface(Surface* s) { | |
943 if (!ftosurface->Free(s)) | |
944 DeleteSurfaceImpl(s); | |
945 } | |
946 inline SDL_Rect SDLed(const Rect& rect) { | |
947 SDL_Rect r; | |
948 r.x = rect.lx; | |
949 r.y = rect.ty; | |
950 r.w = rect.rx-rect.lx; | |
951 r.h = rect.by-rect.ty; | |
952 return r; | |
953 } | |
954 | |
955 #ifndef ALPHA_MAX | |
956 #define ALPHA_MAX 255 | |
957 #endif | |
958 void PicRoot::BlitSurface(Surface* src, const Rect& src_r, const unsigned char* alpha, const Rect& alpha_r, Surface* dest, const Rect& dest_r, int attribute) const { | |
959 if (print_blit) fprintf(stderr," s %08x %d:%d:%d:%d;",src, dest_r.lx, dest_r.ty, dest_r.rx, dest_r.by); | |
960 SDL_Rect sr = SDLed(src_r); SDL_Rect dr = SDLed(dest_r); | |
961 special_blit: | |
962 if (attribute & PicBase::BLIT_MULTIPLY) { | |
963 if (print_blit) fprintf(stderr,"M"); | |
964 DSurfaceBlitMultiply(src, src_r, dest, dest_r); | |
965 return; | |
966 } else if (attribute & PicBase::BLIT_SATURATE) { | |
967 if (src->format->Amask != 0) goto normal_blit; | |
968 if (print_blit) fprintf(stderr,"S"); | |
969 unsigned char a = 255; | |
970 if (alpha && alpha_r.width() >= 1 && alpha_r.height() >= 1) a = *alpha; | |
971 DSurfaceBlitSaturate(src, src_r, dest, dest_r, a); | |
972 return; | |
973 } | |
974 normal_blit: | |
975 if (print_blit) fprintf(stderr,"N"); | |
976 if (alpha == 0 || alpha_r.width() == 0) { // simple blit | |
977 if (print_blit) fprintf(stderr,"X"); | |
978 SDL_BlitSurface(src, &sr, dest, &dr); | |
979 return; | |
980 } | |
981 if (alpha_r.width() == 1 && alpha_r.height() == 1) { | |
982 if (*alpha == 255) { | |
983 if (print_blit) fprintf(stderr,"Y"); | |
984 SDL_BlitSurface(src, &sr, dest, &dr); | |
985 return; | |
986 } | |
987 if (src->format->Amask == 0) { // use per-surface alpha | |
988 if (print_blit) fprintf(stderr,"Z"); | |
989 SDL_SetAlpha(src, SDL_SRCALPHA, *alpha); | |
990 SDL_BlitSurface(src, &sr, dest, &dr); | |
991 SDL_SetAlpha(src, 0, 0); | |
992 return; | |
993 } | |
994 } | |
995 // generic alpha blit | |
996 if (print_blit) fprintf(stderr,"W"); | |
997 DSurfaceBlitAlpha(src, src_r, dest, dest_r, alpha, alpha_r); | |
998 return; | |
999 } | |
1000 | |
1001 bool PicRoot::with_mask(Surface* s) { | |
1002 return s->format->Amask != 0; | |
1003 } | |
1004 | |
1005 #if USE_X11 | |
1006 #include<SDL_syswm.h> | |
1007 #include<X11/Xlib.h> | |
1008 #include<X11/Xutil.h> | |
1009 #endif /* USE_X11 */ | |
1010 void PicRoot::SetWindowCaption(const char* caption) { | |
1011 #if USE_X11 | |
1012 // SDL_WM_SetCaption(caption, 0); | |
1013 // SDLの関数では2バイト文字をサポートしてくれないので、同等の内容に修正 | |
1014 SDL_SysWMinfo info; | |
1015 memset(&info,0,sizeof(info)); | |
1016 SDL_VERSION(&(info.version)); | |
1017 if (SDL_GetWMInfo(&info) == 1) { | |
1018 Display* display = info.info.x11.display; | |
1019 Window wm = info.info.x11.wmwindow; | |
1020 if (wm == 0) wm = info.info.x11.window; | |
1021 if (wm != 0) { | |
1022 XTextProperty titleprop; | |
1023 XmbTextListToTextProperty(display, (char**)&caption, 1, XCompoundTextStyle, &titleprop); | |
1024 XSetWMName(display, wm, &titleprop); | |
1025 XSetWMIconName(display, wm, &titleprop); | |
1026 XFree(titleprop.value); | |
1027 } | |
1028 XSync(display, False); | |
1029 } | |
1030 #endif /* USE_X11 */ | |
1031 } | |
1032 | |
1033 /************************************************************ | |
1034 ** PicAnm | |
1035 */ | |
1036 | |
1037 void PicBase::ClearAnm(void) { | |
1038 while(!anm.empty()) { | |
1039 delete anm.back(); | |
1040 } | |
1041 } | |
1042 PicAnm::PicAnm(PicBase* _pic) { | |
1043 pic.push_back(_pic); | |
1044 pic[0]->anm.push_back(this); | |
1045 return; | |
1046 | |
1047 } | |
1048 PicAnm::PicAnm(vector<PicBase*> _pic) : pic(_pic) { | |
1049 if (pic.empty()) return; | |
1050 pic[0]->anm.push_back(this); | |
1051 return; | |
1052 } | |
1053 PicAnm::~PicAnm() { | |
1054 vector<PicAnm*>::iterator it = find(pic[0]->anm.begin(), pic[0]->anm.end(), this); | |
1055 if (it == pic[0]->anm.end()) { | |
1056 fprintf(stderr,"Cannot found this in PicAnm::~PicAnm()"); | |
1057 } else { | |
1058 pic[0]->anm.erase(it); | |
1059 } | |
1060 } |