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